Rollup merge of #139225 - EnzymeAD:rust-lang-enzyme, r=jieyouxu
move autodiff from EnzymeAD/Enzyme to our rust-lang/Enzyme soft-fork
In https://github.com/rust-lang/team/pull/1665 we decided to have a soft-fork of Enzyme, to be able to merge e.g. CI, docs, or cmake improvements if upstream is not interested in them. We don't intend to merge logic/code changes. It also seems generally preferable if we clone submodules from a rust-lang repo, instead of an external org. We don't build or checkout Enzyme yet by default, so this should be a safe rollup.
diff --git a/.gitattributes b/.gitattributes
index d29c15f..8700d5d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -5,6 +5,7 @@
*.h rust
*.rs rust diff=rust
*.fixed linguist-language=Rust
+*.pp linguist-language=Rust
*.mir linguist-language=Rust
src/etc/installer/gfx/* binary
src/vendor/** -text
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2539700..51dd0f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -69,6 +69,8 @@
env:
CI_JOB_NAME: ${{ matrix.name }}
CI_JOB_DOC_URL: ${{ matrix.doc_url }}
+ GITHUB_WORKFLOW_RUN_ID: ${{ github.run_id }}
+ GITHUB_REPOSITORY: ${{ github.repository }}
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
# commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs.
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
diff --git a/Cargo.lock b/Cargo.lock
index 01d7e0b..a5d8d6f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -535,7 +535,7 @@
"termize",
"tokio",
"toml 0.7.8",
- "ui_test 0.29.2",
+ "ui_test",
"walkdir",
]
@@ -2262,7 +2262,7 @@
"smallvec",
"tempfile",
"tikv-jemalloc-sys",
- "ui_test 0.28.0",
+ "ui_test",
"windows-sys 0.52.0",
]
@@ -4300,6 +4300,7 @@
version = "0.0.0"
dependencies = [
"bitflags",
+ "itertools",
"pulldown-cmark 0.11.3",
"rustc_arena",
"rustc_ast",
@@ -5509,32 +5510,6 @@
[[package]]
name = "ui_test"
-version = "0.28.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576"
-dependencies = [
- "annotate-snippets 0.11.5",
- "anyhow",
- "bstr",
- "cargo-platform",
- "cargo_metadata 0.18.1",
- "color-eyre",
- "colored",
- "comma",
- "crossbeam-channel",
- "indicatif",
- "levenshtein",
- "prettydiff",
- "regex",
- "rustc_version",
- "rustfix",
- "serde",
- "serde_json",
- "spanned",
-]
-
-[[package]]
-name = "ui_test"
version = "0.29.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1211b1111c752c73b33073d2958072be08825fd97c9ab4d83444da361a06634b"
diff --git a/RELEASES.md b/RELEASES.md
index 755e73a..0948eb8 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,126 @@
+Version 1.86.0 (2025-04-03)
+==========================
+
+<a id="1.86.0-Language"></a>
+
+Language
+--------
+- [Stabilize upcasting trait objects to supertraits.](https://github.com/rust-lang/rust/pull/134367)
+- [Allow safe functions to be marked with the `#[target_feature]` attribute.](https://github.com/rust-lang/rust/pull/134090)
+- [The `missing_abi` lint now warns-by-default.](https://github.com/rust-lang/rust/pull/132397)
+- Rust now lints about double negations, to catch cases that might have intended to be a prefix decrement operator (`--x`) as written in other languages. This was previously a clippy lint, `clippy::double_neg`, and is [now available directly in Rust as `double_negations`.](https://github.com/rust-lang/rust/pull/126604)
+- [More pointers are now detected as definitely not-null based on their alignment in const eval.](https://github.com/rust-lang/rust/pull/133700)
+- [Empty `repr()` attribute applied to invalid items are now correctly rejected.](https://github.com/rust-lang/rust/pull/133925)
+- [Inner attributes `#![test]` and `#![rustfmt::skip]` are no longer accepted in more places than intended.](https://github.com/rust-lang/rust/pull/134276)
+
+<a id="1.86.0-Compiler"></a>
+
+Compiler
+--------
+- [Debug-assert that raw pointers are non-null on access.](https://github.com/rust-lang/rust/pull/134424)
+- [Change `-O` to mean `-C opt-level=3` instead of `-C opt-level=2` to match Cargo's defaults.](https://github.com/rust-lang/rust/pull/135439)
+- [Fix emission of `overflowing_literals` under certain macro environments.](https://github.com/rust-lang/rust/pull/136393)
+
+<a id="1.86.0-Platform-Support"></a>
+
+Platform Support
+----------------
+- [Replace `i686-unknown-redox` target with `i586-unknown-redox`.](https://github.com/rust-lang/rust/pull/136698)
+- [Increase baseline CPU of `i686-unknown-hurd-gnu` to Pentium 4.](https://github.com/rust-lang/rust/pull/136700)
+- New tier 3 targets:
+ - [`{aarch64-unknown,x86_64-pc}-nto-qnx710_iosock`](https://github.com/rust-lang/rust/pull/133631).
+ For supporting Neutrino QNX 7.1 with `io-socket` network stack.
+ - [`{aarch64-unknown,x86_64-pc}-nto-qnx800`](https://github.com/rust-lang/rust/pull/133631).
+ For supporting Neutrino QNX 8.0 (`no_std`-only).
+ - [`{x86_64,i686}-win7-windows-gnu`](https://github.com/rust-lang/rust/pull/134609).
+ Intended for backwards compatibility with Windows 7. `{x86_64,i686}-win7-windows-msvc` are the Windows MSVC counterparts that already exist as Tier 3 targets.
+ - [`amdgcn-amd-amdhsa`](https://github.com/rust-lang/rust/pull/134740).
+ - [`x86_64-pc-cygwin`](https://github.com/rust-lang/rust/pull/134999).
+ - [`{mips,mipsel}-mti-none-elf`](https://github.com/rust-lang/rust/pull/135074).
+ Initial bare-metal support.
+ - [`m68k-unknown-none-elf`](https://github.com/rust-lang/rust/pull/135085).
+ - [`armv7a-nuttx-{eabi,eabihf}`, `aarch64-unknown-nuttx`, and `thumbv7a-nuttx-{eabi,eabihf}`](https://github.com/rust-lang/rust/pull/135757).
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.86.0-Libraries"></a>
+
+Libraries
+---------
+- The type of `FromBytesWithNulError` in `CStr::from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>` was [changed from an opaque struct to an enum](https://github.com/rust-lang/rust/pull/134143), allowing users to examine why the conversion failed.
+- [Remove `RustcDecodable` and `RustcEncodable`.](https://github.com/rust-lang/rust/pull/134272)
+- [Deprecate libtest's `--logfile` option.](https://github.com/rust-lang/rust/pull/134283)
+- [On recent versions of Windows, `std::fs::remove_file` will now remove read-only files.](https://github.com/rust-lang/rust/pull/134679)
+
+<a id="1.86.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`{float}::next_down`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_down)
+- [`{float}::next_up`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_up)
+- [`<[_]>::get_disjoint_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_mut)
+- [`<[_]>::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_unchecked_mut)
+- [`slice::GetDisjointMutError`](https://doc.rust-lang.org/stable/std/slice/enum.GetDisjointMutError.html)
+- [`HashMap::get_disjoint_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_mut)
+- [`HashMap::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_unchecked_mut)
+- [`NonZero::count_ones`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.count_ones)
+- [`Vec::pop_if`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pop_if)
+- [`sync::Once::wait`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait)
+- [`sync::Once::wait_force`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait_force)
+- [`sync::OnceLock::wait`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html#method.wait)
+
+These APIs are now stable in const contexts:
+
+- [`hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
+- [`io::Cursor::get_mut`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_mut)
+- [`io::Cursor::set_position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.set_position)
+- [`str::is_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.is_char_boundary)
+- [`str::split_at`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at)
+- [`str::split_at_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_checked)
+- [`str::split_at_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut)
+- [`str::split_at_mut_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut_checked)
+
+<a id="1.86.0-Cargo"></a>
+
+Cargo
+-----
+- [When merging, replace rather than combine configuration keys that refer to a program path and its arguments.](https://github.com/rust-lang/cargo/pull/15066/)
+- [Error if both `--package` and `--workspace` are passed but the requested package is missing.](https://github.com/rust-lang/cargo/pull/15071/) This was previously silently ignored, which was considered a bug since missing packages should be reported.
+- [Deprecate the token argument in `cargo login` to avoid shell history leaks.](https://github.com/rust-lang/cargo/pull/15057/)
+- [Simplify the implementation of `SourceID` comparisons.](https://github.com/rust-lang/cargo/pull/14980/) This may potentially change behavior if the canonicalized URL compares differently in alternative registries.
+
+<a id="1.86.0-Rustdoc"></a>
+
+Rustdoc
+-----
+- [Add a sans-serif font setting.](https://github.com/rust-lang/rust/pull/133636)
+
+<a id="1.86.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+- [The `wasm_c_abi` future compatibility warning is now a hard error.](https://github.com/rust-lang/rust/pull/133951)
+ Users of `wasm-bindgen` should upgrade to at least version 0.2.89, otherwise compilation will fail.
+- [Remove long-deprecated no-op attributes `#![no_start]` and `#![crate_id]`.](https://github.com/rust-lang/rust/pull/134300)
+- [The future incompatibility lint `cenum_impl_drop_cast` has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`.
+- [SSE2 is now required for "i686" 32-bit x86 hard-float targets; disabling it causes a warning that will become a hard error eventually.](https://github.com/rust-lang/rust/pull/137037)
+ To compile for pre-SSE2 32-bit x86, use a "i586" target instead.
+
+<a id="1.86.0-Internal-Changes"></a>
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Build the rustc on AArch64 Linux with ThinLTO + PGO.](https://github.com/rust-lang/rust/pull/133807)
+ The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster.
+
+
Version 1.85.1 (2025-03-18)
==========================
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index caffe1a..2a98821 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -28,8 +28,9 @@
# - A new option
# - A change in the default values
#
-# If `change-id` does not match the version that is currently running,
-# `x.py` will inform you about the changes made on bootstrap.
+# If the change-id does not match the version currently in use, x.py will
+# display the changes made to the bootstrap.
+# To suppress these warnings, you can set change-id = "ignore".
#change-id = <latest change id in src/bootstrap/src/utils/change_tracker.rs>
# =============================================================================
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 3f28dc7..843d5ca 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1462,7 +1462,8 @@ pub fn is_sized(&self) -> bool {
!self.is_unsized()
}
- /// Returns `true` if this is a single signed integer scalar
+ /// Returns `true` if this is a single signed integer scalar.
+ /// Sanity check: panics if this is not a scalar type (see PR #70189).
#[inline]
pub fn is_signed(&self) -> bool {
match self {
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 064f05e..33c2060 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3303,9 +3303,6 @@ pub struct Item<K = ItemKind> {
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
- /// The name of the item.
- /// It might be a dummy name in case of anonymous items.
- pub ident: Ident,
pub kind: K,
@@ -3327,23 +3324,23 @@ pub fn span_with_attributes(&self) -> Span {
pub fn opt_generics(&self) -> Option<&Generics> {
match &self.kind {
- ItemKind::ExternCrate(_)
+ ItemKind::ExternCrate(..)
| ItemKind::Use(_)
- | ItemKind::Mod(_, _)
+ | ItemKind::Mod(..)
| ItemKind::ForeignMod(_)
| ItemKind::GlobalAsm(_)
| ItemKind::MacCall(_)
| ItemKind::Delegation(_)
| ItemKind::DelegationMac(_)
- | ItemKind::MacroDef(_) => None,
+ | ItemKind::MacroDef(..) => None,
ItemKind::Static(_) => None,
ItemKind::Const(i) => Some(&i.generics),
ItemKind::Fn(i) => Some(&i.generics),
ItemKind::TyAlias(i) => Some(&i.generics),
- ItemKind::TraitAlias(generics, _)
- | ItemKind::Enum(_, generics)
- | ItemKind::Struct(_, generics)
- | ItemKind::Union(_, generics) => Some(&generics),
+ ItemKind::TraitAlias(_, generics, _)
+ | ItemKind::Enum(_, _, generics)
+ | ItemKind::Struct(_, _, generics)
+ | ItemKind::Union(_, _, generics) => Some(&generics),
ItemKind::Trait(i) => Some(&i.generics),
ItemKind::Impl(i) => Some(&i.generics),
}
@@ -3420,6 +3417,7 @@ fn default() -> FnHeader {
pub struct Trait {
pub safety: Safety,
pub is_auto: IsAuto,
+ pub ident: Ident,
pub generics: Generics,
pub bounds: GenericBounds,
pub items: ThinVec<P<AssocItem>>,
@@ -3465,6 +3463,7 @@ pub struct TyAliasWhereClauses {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct TyAlias {
pub defaultness: Defaultness,
+ pub ident: Ident,
pub generics: Generics,
pub where_clauses: TyAliasWhereClauses,
pub bounds: GenericBounds,
@@ -3493,6 +3492,7 @@ pub struct FnContract {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Fn {
pub defaultness: Defaultness,
+ pub ident: Ident,
pub generics: Generics,
pub sig: FnSig,
pub contract: Option<P<FnContract>>,
@@ -3506,6 +3506,7 @@ pub struct Delegation {
pub id: NodeId,
pub qself: Option<P<QSelf>>,
pub path: Path,
+ pub ident: Ident,
pub rename: Option<Ident>,
pub body: Option<P<Block>>,
/// The item was expanded from a glob delegation item.
@@ -3523,6 +3524,7 @@ pub struct DelegationMac {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct StaticItem {
+ pub ident: Ident,
pub ty: P<Ty>,
pub safety: Safety,
pub mutability: Mutability,
@@ -3533,6 +3535,7 @@ pub struct StaticItem {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ConstItem {
pub defaultness: Defaultness,
+ pub ident: Ident,
pub generics: Generics,
pub ty: P<Ty>,
pub expr: Option<P<Expr>>,
@@ -3545,7 +3548,7 @@ pub enum ItemKind {
/// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
///
/// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
- ExternCrate(Option<Symbol>),
+ ExternCrate(Option<Symbol>, Ident),
/// A use declaration item (`use`).
///
/// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`.
@@ -3567,7 +3570,7 @@ pub enum ItemKind {
/// E.g., `mod foo;` or `mod foo { .. }`.
/// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not
/// semantically by Rust.
- Mod(Safety, ModKind),
+ Mod(Safety, Ident, ModKind),
/// An external module (`extern`).
///
/// E.g., `extern {}` or `extern "C" {}`.
@@ -3581,15 +3584,15 @@ pub enum ItemKind {
/// An enum definition (`enum`).
///
/// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
- Enum(EnumDef, Generics),
+ Enum(Ident, EnumDef, Generics),
/// A struct definition (`struct`).
///
/// E.g., `struct Foo<A> { x: A }`.
- Struct(VariantData, Generics),
+ Struct(Ident, VariantData, Generics),
/// A union definition (`union`).
///
/// E.g., `union Foo<A, B> { x: A, y: B }`.
- Union(VariantData, Generics),
+ Union(Ident, VariantData, Generics),
/// A trait declaration (`trait`).
///
/// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
@@ -3597,7 +3600,7 @@ pub enum ItemKind {
/// Trait alias.
///
/// E.g., `trait Foo = Bar + Quux;`.
- TraitAlias(Generics, GenericBounds),
+ TraitAlias(Ident, Generics, GenericBounds),
/// An implementation.
///
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
@@ -3608,7 +3611,7 @@ pub enum ItemKind {
MacCall(P<MacCall>),
/// A macro definition.
- MacroDef(MacroDef),
+ MacroDef(Ident, MacroDef),
/// A single delegation item (`reuse`).
///
@@ -3620,6 +3623,31 @@ pub enum ItemKind {
}
impl ItemKind {
+ pub fn ident(&self) -> Option<Ident> {
+ match *self {
+ ItemKind::ExternCrate(_, ident)
+ | ItemKind::Static(box StaticItem { ident, .. })
+ | ItemKind::Const(box ConstItem { ident, .. })
+ | ItemKind::Fn(box Fn { ident, .. })
+ | ItemKind::Mod(_, ident, _)
+ | ItemKind::TyAlias(box TyAlias { ident, .. })
+ | ItemKind::Enum(ident, ..)
+ | ItemKind::Struct(ident, ..)
+ | ItemKind::Union(ident, ..)
+ | ItemKind::Trait(box Trait { ident, .. })
+ | ItemKind::TraitAlias(ident, ..)
+ | ItemKind::MacroDef(ident, _)
+ | ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
+
+ ItemKind::Use(_)
+ | ItemKind::ForeignMod(_)
+ | ItemKind::GlobalAsm(_)
+ | ItemKind::Impl(_)
+ | ItemKind::MacCall(_)
+ | ItemKind::DelegationMac(_) => None,
+ }
+ }
+
/// "a" or "an"
pub fn article(&self) -> &'static str {
use ItemKind::*;
@@ -3660,11 +3688,11 @@ pub fn generics(&self) -> Option<&Generics> {
Self::Fn(box Fn { generics, .. })
| Self::TyAlias(box TyAlias { generics, .. })
| Self::Const(box ConstItem { generics, .. })
- | Self::Enum(_, generics)
- | Self::Struct(_, generics)
- | Self::Union(_, generics)
+ | Self::Enum(_, _, generics)
+ | Self::Struct(_, _, generics)
+ | Self::Union(_, _, generics)
| Self::Trait(box Trait { generics, .. })
- | Self::TraitAlias(generics, _)
+ | Self::TraitAlias(_, generics, _)
| Self::Impl(box Impl { generics, .. }) => Some(generics),
_ => None,
}
@@ -3700,6 +3728,17 @@ pub enum AssocItemKind {
}
impl AssocItemKind {
+ pub fn ident(&self) -> Option<Ident> {
+ match *self {
+ AssocItemKind::Const(box ConstItem { ident, .. })
+ | AssocItemKind::Fn(box Fn { ident, .. })
+ | AssocItemKind::Type(box TyAlias { ident, .. })
+ | AssocItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
+
+ AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None,
+ }
+ }
+
pub fn defaultness(&self) -> Defaultness {
match *self {
Self::Const(box ConstItem { defaultness, .. })
@@ -3746,14 +3785,26 @@ fn try_from(item_kind: ItemKind) -> Result<AssocItemKind, ItemKind> {
pub enum ForeignItemKind {
/// A foreign static item (`static FOO: u8`).
Static(Box<StaticItem>),
- /// An foreign function.
+ /// A foreign function.
Fn(Box<Fn>),
- /// An foreign type.
+ /// A foreign type.
TyAlias(Box<TyAlias>),
/// A macro expanding to foreign items.
MacCall(P<MacCall>),
}
+impl ForeignItemKind {
+ pub fn ident(&self) -> Option<Ident> {
+ match *self {
+ ForeignItemKind::Static(box StaticItem { ident, .. })
+ | ForeignItemKind::Fn(box Fn { ident, .. })
+ | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => Some(ident),
+
+ ForeignItemKind::MacCall(_) => None,
+ }
+ }
+}
+
impl From<ForeignItemKind> for ItemKind {
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
match foreign_item_kind {
@@ -3790,21 +3841,21 @@ mod size_asserts {
use super::*;
// tidy-alphabetical-start
- static_assert_size!(AssocItem, 88);
+ static_assert_size!(AssocItem, 80);
static_assert_size!(AssocItemKind, 16);
static_assert_size!(Attribute, 32);
static_assert_size!(Block, 32);
static_assert_size!(Expr, 72);
static_assert_size!(ExprKind, 40);
- static_assert_size!(Fn, 176);
- static_assert_size!(ForeignItem, 88);
+ static_assert_size!(Fn, 184);
+ static_assert_size!(ForeignItem, 80);
static_assert_size!(ForeignItemKind, 16);
static_assert_size!(GenericArg, 24);
static_assert_size!(GenericBound, 88);
static_assert_size!(Generics, 40);
static_assert_size!(Impl, 136);
- static_assert_size!(Item, 136);
- static_assert_size!(ItemKind, 64);
+ static_assert_size!(Item, 144);
+ static_assert_size!(ItemKind, 80);
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 80);
static_assert_size!(MetaItemLit, 40);
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 274fe31..30af6d9 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -41,7 +41,6 @@ fn walk(
&mut self,
span: Span,
id: NodeId,
- ident: &mut Ident,
visibility: &mut Visibility,
ctxt: Self::Ctxt,
visitor: &mut impl MutVisitor,
@@ -963,10 +962,10 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
match kind {
FnKind::Fn(
_ctxt,
- _ident,
_vis,
Fn {
defaultness,
+ ident,
generics,
contract,
body,
@@ -974,8 +973,9 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
define_opaque,
},
) => {
- // Identifier and visibility are visited as a part of the item.
+ // Visibility is visited as a part of the item.
visit_defaultness(vis, defaultness);
+ vis.visit_ident(ident);
vis.visit_fn_header(header);
vis.visit_generics(generics);
vis.visit_fn_decl(decl);
@@ -1233,12 +1233,11 @@ pub fn walk_item_kind<K: WalkItemKind>(
kind: &mut K,
span: Span,
id: NodeId,
- ident: &mut Ident,
visibility: &mut Visibility,
ctxt: K::Ctxt,
vis: &mut impl MutVisitor,
) {
- kind.walk(span, id, ident, visibility, ctxt, vis)
+ kind.walk(span, id, visibility, ctxt, vis)
}
impl WalkItemKind for ItemKind {
@@ -1247,21 +1246,22 @@ fn walk(
&mut self,
span: Span,
id: NodeId,
- ident: &mut Ident,
visibility: &mut Visibility,
_ctxt: Self::Ctxt,
vis: &mut impl MutVisitor,
) {
match self {
- ItemKind::ExternCrate(_orig_name) => {}
+ ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident),
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
ItemKind::Static(box StaticItem {
+ ident,
ty,
safety: _,
mutability: _,
expr,
define_opaque,
}) => {
+ vis.visit_ident(ident);
vis.visit_ty(ty);
visit_opt(expr, |expr| vis.visit_expr(expr));
walk_define_opaques(vis, define_opaque);
@@ -1270,10 +1270,11 @@ fn walk(
walk_const_item(vis, item);
}
ItemKind::Fn(func) => {
- vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id);
+ vis.visit_fn(FnKind::Fn(FnCtxt::Free, visibility, &mut *func), span, id);
}
- ItemKind::Mod(safety, mod_kind) => {
+ ItemKind::Mod(safety, ident, mod_kind) => {
visit_safety(vis, safety);
+ vis.visit_ident(ident);
match mod_kind {
ModKind::Loaded(
items,
@@ -1290,18 +1291,29 @@ fn walk(
}
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
- ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => {
+ ItemKind::TyAlias(box TyAlias {
+ defaultness,
+ ident,
+ generics,
+ where_clauses,
+ bounds,
+ ty,
+ }) => {
visit_defaultness(vis, defaultness);
+ vis.visit_ident(ident);
vis.visit_generics(generics);
visit_bounds(vis, bounds, BoundKind::Bound);
visit_opt(ty, |ty| vis.visit_ty(ty));
walk_ty_alias_where_clauses(vis, where_clauses);
}
- ItemKind::Enum(EnumDef { variants }, generics) => {
+ ItemKind::Enum(ident, EnumDef { variants }, generics) => {
+ vis.visit_ident(ident);
vis.visit_generics(generics);
variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
}
- ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => {
+ ItemKind::Struct(ident, variant_data, generics)
+ | ItemKind::Union(ident, variant_data, generics) => {
+ vis.visit_ident(ident);
vis.visit_generics(generics);
vis.visit_variant_data(variant_data);
}
@@ -1326,22 +1338,28 @@ fn walk(
vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() })
});
}
- ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => {
+ ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => {
visit_safety(vis, safety);
+ vis.visit_ident(ident);
vis.visit_generics(generics);
visit_bounds(vis, bounds, BoundKind::Bound);
items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait));
}
- ItemKind::TraitAlias(generics, bounds) => {
+ ItemKind::TraitAlias(ident, generics, bounds) => {
+ vis.visit_ident(ident);
vis.visit_generics(generics);
visit_bounds(vis, bounds, BoundKind::Bound);
}
ItemKind::MacCall(m) => vis.visit_mac_call(m),
- ItemKind::MacroDef(def) => vis.visit_macro_def(def),
+ ItemKind::MacroDef(ident, def) => {
+ vis.visit_ident(ident);
+ vis.visit_macro_def(def)
+ }
ItemKind::Delegation(box Delegation {
id,
qself,
path,
+ ident,
rename,
body,
from_glob: _,
@@ -1349,6 +1367,7 @@ fn walk(
vis.visit_id(id);
vis.visit_qself(qself);
vis.visit_path(path);
+ vis.visit_ident(ident);
if let Some(rename) = rename {
vis.visit_ident(rename);
}
@@ -1381,7 +1400,6 @@ fn walk(
&mut self,
span: Span,
id: NodeId,
- ident: &mut Ident,
visibility: &mut Visibility,
ctxt: Self::Ctxt,
visitor: &mut impl MutVisitor,
@@ -1391,20 +1409,18 @@ fn walk(
walk_const_item(visitor, item);
}
AssocItemKind::Fn(func) => {
- visitor.visit_fn(
- FnKind::Fn(FnCtxt::Assoc(ctxt), ident, visibility, &mut *func),
- span,
- id,
- );
+ visitor.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &mut *func), span, id);
}
AssocItemKind::Type(box TyAlias {
defaultness,
+ ident,
generics,
where_clauses,
bounds,
ty,
}) => {
visit_defaultness(visitor, defaultness);
+ visitor.visit_ident(ident);
visitor.visit_generics(generics);
visit_bounds(visitor, bounds, BoundKind::Bound);
visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1415,6 +1431,7 @@ fn walk(
id,
qself,
path,
+ ident,
rename,
body,
from_glob: _,
@@ -1422,6 +1439,7 @@ fn walk(
visitor.visit_id(id);
visitor.visit_qself(qself);
visitor.visit_path(path);
+ visitor.visit_ident(ident);
if let Some(rename) = rename {
visitor.visit_ident(rename);
}
@@ -1449,8 +1467,9 @@ fn walk(
}
fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
- let ConstItem { defaultness, generics, ty, expr, define_opaque } = item;
+ let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
visit_defaultness(vis, defaultness);
+ vis.visit_ident(ident);
vis.visit_generics(generics);
vis.visit_ty(ty);
visit_opt(expr, |expr| vis.visit_expr(expr));
@@ -1487,12 +1506,11 @@ fn walk_item_ctxt<K: WalkItemKind>(
item: &mut P<Item<K>>,
ctxt: K::Ctxt,
) {
- let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
+ let Item { attrs, id, kind, vis, span, tokens } = item.deref_mut();
visitor.visit_id(id);
visit_attrs(visitor, attrs);
visitor.visit_vis(vis);
- visitor.visit_ident(ident);
- kind.walk(*span, *id, ident, vis, ctxt, visitor);
+ kind.walk(*span, *id, vis, ctxt, visitor);
visit_lazy_tts(visitor, tokens);
visitor.visit_span(span);
}
@@ -1525,38 +1543,37 @@ fn walk(
&mut self,
span: Span,
id: NodeId,
- ident: &mut Ident,
visibility: &mut Visibility,
_ctxt: Self::Ctxt,
visitor: &mut impl MutVisitor,
) {
match self {
ForeignItemKind::Static(box StaticItem {
+ ident,
ty,
mutability: _,
expr,
safety: _,
define_opaque,
}) => {
+ visitor.visit_ident(ident);
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
walk_define_opaques(visitor, define_opaque);
}
ForeignItemKind::Fn(func) => {
- visitor.visit_fn(
- FnKind::Fn(FnCtxt::Foreign, ident, visibility, &mut *func),
- span,
- id,
- );
+ visitor.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &mut *func), span, id);
}
ForeignItemKind::TyAlias(box TyAlias {
defaultness,
+ ident,
generics,
where_clauses,
bounds,
ty,
}) => {
visit_defaultness(visitor, defaultness);
+ visitor.visit_ident(ident);
visitor.visit_generics(generics);
visit_bounds(visitor, bounds, BoundKind::Bound);
visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1984,8 +2001,7 @@ fn dummy() -> Self {
span: Default::default(),
tokens: Default::default(),
},
- ident: Ident::dummy(),
- kind: ItemKind::ExternCrate(None),
+ kind: ItemKind::ExternCrate(None, Ident::dummy()),
tokens: Default::default(),
}
}
@@ -2052,7 +2068,7 @@ fn dummy() -> Self {
#[derive(Debug)]
pub enum FnKind<'a> {
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
- Fn(FnCtxt, &'a mut Ident, &'a mut Visibility, &'a mut Fn),
+ Fn(FnCtxt, &'a mut Visibility, &'a mut Fn),
/// E.g., `|x, y| body`.
Closure(
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 2716601..1ef92ff 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -66,7 +66,7 @@ pub fn descr(self) -> &'static str {
#[derive(Copy, Clone, Debug)]
pub enum FnKind<'a> {
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
- Fn(FnCtxt, &'a Ident, &'a Visibility, &'a Fn),
+ Fn(FnCtxt, &'a Visibility, &'a Fn),
/// E.g., `|x, y| body`.
Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
@@ -75,21 +75,21 @@ pub enum FnKind<'a> {
impl<'a> FnKind<'a> {
pub fn header(&self) -> Option<&'a FnHeader> {
match *self {
- FnKind::Fn(_, _, _, Fn { sig, .. }) => Some(&sig.header),
+ FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header),
FnKind::Closure(..) => None,
}
}
pub fn ident(&self) -> Option<&Ident> {
match self {
- FnKind::Fn(_, ident, ..) => Some(ident),
+ FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),
_ => None,
}
}
pub fn decl(&self) -> &'a FnDecl {
match self {
- FnKind::Fn(_, _, _, Fn { sig, .. }) => &sig.decl,
+ FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl,
FnKind::Closure(_, _, decl, _) => decl,
}
}
@@ -118,7 +118,6 @@ fn walk<'a, V: Visitor<'a>>(
&'a self,
span: Span,
id: NodeId,
- ident: &'a Ident,
visibility: &'a Visibility,
ctxt: Self::Ctxt,
visitor: &mut V,
@@ -364,63 +363,72 @@ fn walk<'a, V: Visitor<'a>>(
&'a self,
span: Span,
id: NodeId,
- ident: &'a Ident,
vis: &'a Visibility,
_ctxt: Self::Ctxt,
visitor: &mut V,
) -> V::Result {
match self {
- ItemKind::ExternCrate(_rename) => {}
+ ItemKind::ExternCrate(_rename, ident) => try_visit!(visitor.visit_ident(ident)),
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
ItemKind::Static(box StaticItem {
+ ident,
ty,
safety: _,
mutability: _,
expr,
define_opaque,
}) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
try_visit!(walk_define_opaques(visitor, define_opaque));
}
ItemKind::Const(box ConstItem {
defaultness: _,
+ ident,
generics,
ty,
expr,
define_opaque,
}) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
try_visit!(walk_define_opaques(visitor, define_opaque));
}
ItemKind::Fn(func) => {
- let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func);
+ let kind = FnKind::Fn(FnCtxt::Free, vis, &*func);
try_visit!(visitor.visit_fn(kind, span, id));
}
- ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
- ModKind::Loaded(items, _inline, _inner_span, _) => {
- walk_list!(visitor, visit_item, items);
+ ItemKind::Mod(_unsafety, ident, mod_kind) => {
+ try_visit!(visitor.visit_ident(ident));
+ match mod_kind {
+ ModKind::Loaded(items, _inline, _inner_span, _) => {
+ walk_list!(visitor, visit_item, items);
+ }
+ ModKind::Unloaded => {}
}
- ModKind::Unloaded => {}
- },
+ }
ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => {
walk_list!(visitor, visit_foreign_item, items);
}
ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
ItemKind::TyAlias(box TyAlias {
generics,
+ ident,
bounds,
ty,
defaultness: _,
where_clauses: _,
}) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
visit_opt!(visitor, visit_ty, ty);
}
- ItemKind::Enum(enum_definition, generics) => {
+ ItemKind::Enum(ident, enum_definition, generics) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_enum_def(enum_definition));
}
@@ -444,32 +452,47 @@ fn walk<'a, V: Visitor<'a>>(
AssocCtxt::Impl { of_trait: of_trait.is_some() }
);
}
- ItemKind::Struct(struct_definition, generics)
- | ItemKind::Union(struct_definition, generics) => {
+ ItemKind::Struct(ident, struct_definition, generics)
+ | ItemKind::Union(ident, struct_definition, generics) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_variant_data(struct_definition));
}
- ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => {
+ ItemKind::Trait(box Trait {
+ safety: _,
+ is_auto: _,
+ ident,
+ generics,
+ bounds,
+ items,
+ }) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
}
- ItemKind::TraitAlias(generics, bounds) => {
+ ItemKind::TraitAlias(ident, generics, bounds) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
}
ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
- ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)),
+ ItemKind::MacroDef(ident, ts) => {
+ try_visit!(visitor.visit_ident(ident));
+ try_visit!(visitor.visit_mac_def(ts, id))
+ }
ItemKind::Delegation(box Delegation {
id,
qself,
path,
+ ident,
rename,
body,
from_glob: _,
}) => {
try_visit!(visitor.visit_qself(qself));
try_visit!(visitor.visit_path(path, *id));
+ try_visit!(visitor.visit_ident(ident));
visit_opt!(visitor, visit_ident, rename);
visit_opt!(visitor, visit_block, body);
}
@@ -743,34 +766,37 @@ fn walk<'a, V: Visitor<'a>>(
&'a self,
span: Span,
id: NodeId,
- ident: &'a Ident,
vis: &'a Visibility,
_ctxt: Self::Ctxt,
visitor: &mut V,
) -> V::Result {
match self {
ForeignItemKind::Static(box StaticItem {
+ ident,
ty,
mutability: _,
expr,
safety: _,
define_opaque,
}) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
try_visit!(walk_define_opaques(visitor, define_opaque));
}
ForeignItemKind::Fn(func) => {
- let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func);
+ let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func);
try_visit!(visitor.visit_fn(kind, span, id));
}
ForeignItemKind::TyAlias(box TyAlias {
generics,
+ ident,
bounds,
ty,
defaultness: _,
where_clauses: _,
}) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
visit_opt!(visitor, visit_ty, ty);
@@ -917,10 +943,10 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
match kind {
FnKind::Fn(
_ctxt,
- _ident,
_vis,
Fn {
defaultness: _,
+ ident,
sig: FnSig { header, decl, span: _ },
generics,
contract,
@@ -928,7 +954,8 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
define_opaque,
},
) => {
- // Identifier and visibility are visited as a part of the item.
+ // Visibility is visited as a part of the item.
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_fn_header(header));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_fn_decl(decl));
@@ -952,7 +979,6 @@ fn walk<'a, V: Visitor<'a>>(
&'a self,
span: Span,
id: NodeId,
- ident: &'a Ident,
vis: &'a Visibility,
ctxt: Self::Ctxt,
visitor: &mut V,
@@ -960,28 +986,32 @@ fn walk<'a, V: Visitor<'a>>(
match self {
AssocItemKind::Const(box ConstItem {
defaultness: _,
+ ident,
generics,
ty,
expr,
define_opaque,
}) => {
+ try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
try_visit!(walk_define_opaques(visitor, define_opaque));
}
AssocItemKind::Fn(func) => {
- let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func);
+ let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func);
try_visit!(visitor.visit_fn(kind, span, id));
}
AssocItemKind::Type(box TyAlias {
generics,
+ ident,
bounds,
ty,
defaultness: _,
where_clauses: _,
}) => {
try_visit!(visitor.visit_generics(generics));
+ try_visit!(visitor.visit_ident(ident));
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
visit_opt!(visitor, visit_ty, ty);
}
@@ -992,12 +1022,14 @@ fn walk<'a, V: Visitor<'a>>(
id,
qself,
path,
+ ident,
rename,
body,
from_glob: _,
}) => {
try_visit!(visitor.visit_qself(qself));
try_visit!(visitor.visit_path(path, *id));
+ try_visit!(visitor.visit_ident(ident));
visit_opt!(visitor, visit_ident, rename);
visit_opt!(visitor, visit_block, body);
}
@@ -1039,11 +1071,10 @@ fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>(
item: &'a Item<K>,
ctxt: K::Ctxt,
) -> V::Result {
- let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
+ let Item { id, span, vis, attrs, kind, tokens: _ } = item;
walk_list!(visitor, visit_attribute, attrs);
try_visit!(visitor.visit_vis(vis));
- try_visit!(visitor.visit_ident(ident));
- try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor));
+ try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
V::Result::output()
}
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index f7640c6..9899ee0 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -56,6 +56,7 @@
pub(crate) struct DelegationResults<'hir> {
pub body_id: hir::BodyId,
pub sig: hir::FnSig<'hir>,
+ pub ident: Ident,
pub generics: &'hir hir::Generics<'hir>,
}
@@ -104,9 +105,9 @@ pub(crate) fn lower_delegation(
let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
let sig = self.lower_delegation_sig(sig_id, decl, span);
let body_id = self.lower_delegation_body(delegation, param_count, span);
-
+ let ident = self.lower_ident(delegation.ident);
let generics = self.lower_delegation_generics(span);
- DelegationResults { body_id, sig, generics }
+ DelegationResults { body_id, sig, ident, generics }
}
Err(err) => self.generate_delegation_error(err, span),
}
@@ -405,8 +406,9 @@ fn generate_delegation_error(
let header = self.generate_header_error();
let sig = hir::FnSig { decl, header, span };
+ let ident = Ident::dummy();
let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span)));
- DelegationResults { generics, body_id, sig }
+ DelegationResults { ident, generics, body_id, sig }
}
fn generate_header_error(&self) -> hir::FnHeader {
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index 3438959..0de0319 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -323,14 +323,12 @@ fn make_count<'hir>(
/// Generates
///
/// ```text
-/// <core::fmt::rt::Placeholder::new(
-/// …usize, // position
-/// '…', // fill
-/// <core::fmt::rt::Alignment>::…, // alignment
-/// …u32, // flags
-/// <core::fmt::rt::Count::…>, // width
-/// <core::fmt::rt::Count::…>, // precision
-/// )
+/// <core::fmt::rt::Placeholder {
+/// position: …usize,
+/// flags: …u32,
+/// precision: <core::fmt::rt::Count::…>,
+/// width: <core::fmt::rt::Count::…>,
+/// }
/// ```
fn make_format_spec<'hir>(
ctx: &mut LoweringContext<'_, 'hir>,
@@ -384,13 +382,13 @@ fn make_format_spec<'hir>(
let flags = ctx.expr_u32(sp, flags);
let precision = make_count(ctx, sp, precision, argmap);
let width = make_count(ctx, sp, width, argmap);
- let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
- sp,
- hir::LangItem::FormatPlaceholder,
- sym::new,
- ));
- let args = ctx.arena.alloc_from_iter([position, flags, precision, width]);
- ctx.expr_call_mut(sp, format_placeholder_new, args)
+ let position = ctx.expr_field(Ident::new(sym::position, sp), ctx.arena.alloc(position), sp);
+ let flags = ctx.expr_field(Ident::new(sym::flags, sp), ctx.arena.alloc(flags), sp);
+ let precision = ctx.expr_field(Ident::new(sym::precision, sp), ctx.arena.alloc(precision), sp);
+ let width = ctx.expr_field(Ident::new(sym::width, sp), ctx.arena.alloc(width), sp);
+ let placeholder = ctx.arena.alloc(hir::QPath::LangItem(hir::LangItem::FormatPlaceholder, sp));
+ let fields = ctx.arena.alloc_from_iter([position, flags, precision, width]);
+ ctx.expr(sp, hir::ExprKind::Struct(placeholder, fields, hir::StructTailExpr::None))
}
fn expand_format_args<'hir>(
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index c03d5e5..28f596a 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -5,7 +5,7 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
-use rustc_hir::{self as hir, HirId, PredicateOrigin};
+use rustc_hir::{self as hir, HirId, IsAnonInPath, PredicateOrigin};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::edit_distance::find_best_match_for_name;
@@ -107,7 +107,6 @@ fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
}
fn lower_foreign_item(&mut self, item: &ForeignItem) {
- debug_assert_ne!(item.ident.name, kw::Empty);
self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
}
}
@@ -151,7 +150,7 @@ fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
let vis_span = self.lower_span(i.vis.span);
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
- let kind = self.lower_item_kind(i.span, i.id, hir_id, i.ident, attrs, vis_span, &i.kind);
+ let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind);
let item = hir::Item {
owner_id: hir_id.expect_owner(),
kind,
@@ -166,41 +165,44 @@ fn lower_item_kind(
span: Span,
id: NodeId,
hir_id: hir::HirId,
- ident: Ident,
attrs: &'hir [hir::Attribute],
vis_span: Span,
i: &ItemKind,
) -> hir::ItemKind<'hir> {
match i {
- ItemKind::ExternCrate(orig_name) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::ExternCrate(orig_name, ident) => {
+ let ident = self.lower_ident(*ident);
hir::ItemKind::ExternCrate(*orig_name, ident)
}
ItemKind::Use(use_tree) => {
- debug_assert_eq!(ident.name, kw::Empty);
// Start with an empty prefix.
let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
}
ItemKind::Static(box ast::StaticItem {
+ ident,
ty: t,
safety: _,
mutability: m,
expr: e,
define_opaque,
}) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ let ident = self.lower_ident(*ident);
let (ty, body_id) =
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
self.lower_define_opaque(hir_id, define_opaque);
hir::ItemKind::Static(ident, ty, *m, body_id)
}
- ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::Const(box ast::ConstItem {
+ ident,
+ generics,
+ ty,
+ expr,
+ define_opaque,
+ ..
+ }) => {
+ let ident = self.lower_ident(*ident);
let (generics, (ty, body_id)) = self.lower_generics(
generics,
id,
@@ -214,13 +216,13 @@ fn lower_item_kind(
}
ItemKind::Fn(box Fn {
sig: FnSig { decl, header, span: fn_sig_span },
+ ident,
generics,
body,
contract,
define_opaque,
..
}) => {
- debug_assert_ne!(ident.name, kw::Empty);
self.with_new_scopes(*fn_sig_span, |this| {
// Note: we don't need to change the return type from `T` to
// `impl Future<Output = T>` here because lower_body
@@ -248,7 +250,7 @@ fn lower_item_kind(
span: this.lower_span(*fn_sig_span),
};
this.lower_define_opaque(hir_id, define_opaque);
- let ident = this.lower_ident(ident);
+ let ident = this.lower_ident(*ident);
hir::ItemKind::Fn {
ident,
sig,
@@ -258,9 +260,8 @@ fn lower_item_kind(
}
})
}
- ItemKind::Mod(_, mod_kind) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::Mod(_, ident, mod_kind) => {
+ let ident = self.lower_ident(*ident);
match mod_kind {
ModKind::Loaded(items, _, spans, _) => {
hir::ItemKind::Mod(ident, self.lower_mod(items, spans))
@@ -268,24 +269,19 @@ fn lower_item_kind(
ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
}
}
- ItemKind::ForeignMod(fm) => {
- debug_assert_eq!(ident.name, kw::Empty);
- hir::ItemKind::ForeignMod {
- abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
- items: self
- .arena
- .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
- }
- }
+ ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {
+ abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
+ items: self
+ .arena
+ .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+ },
ItemKind::GlobalAsm(asm) => {
- debug_assert_eq!(ident.name, kw::Empty);
let asm = self.lower_inline_asm(span, asm);
let fake_body =
self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
hir::ItemKind::GlobalAsm { asm, fake_body }
}
- ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
- debug_assert_ne!(ident.name, kw::Empty);
+ ItemKind::TyAlias(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
// We lower
//
// type Foo = impl Trait
@@ -294,7 +290,7 @@ fn lower_item_kind(
//
// type Foo = Foo1
// opaque type Foo1: Trait
- let ident = self.lower_ident(ident);
+ let ident = self.lower_ident(*ident);
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
let (generics, ty) = self.lower_generics(
@@ -322,9 +318,8 @@ fn lower_item_kind(
);
hir::ItemKind::TyAlias(ident, ty, generics)
}
- ItemKind::Enum(enum_definition, generics) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::Enum(ident, enum_definition, generics) => {
+ let ident = self.lower_ident(*ident);
let (generics, variants) = self.lower_generics(
generics,
id,
@@ -337,9 +332,8 @@ fn lower_item_kind(
);
hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics)
}
- ItemKind::Struct(struct_def, generics) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::Struct(ident, struct_def, generics) => {
+ let ident = self.lower_ident(*ident);
let (generics, struct_def) = self.lower_generics(
generics,
id,
@@ -348,9 +342,8 @@ fn lower_item_kind(
);
hir::ItemKind::Struct(ident, struct_def, generics)
}
- ItemKind::Union(vdata, generics) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::Union(ident, vdata, generics) => {
+ let ident = self.lower_ident(*ident);
let (generics, vdata) = self.lower_generics(
generics,
id,
@@ -369,7 +362,6 @@ fn lower_item_kind(
self_ty: ty,
items: impl_items,
}) => {
- debug_assert_eq!(ident.name, kw::Empty);
// Lower the "impl header" first. This ordering is important
// for in-band lifetimes! Consider `'a` here:
//
@@ -435,9 +427,8 @@ fn lower_item_kind(
items: new_impl_items,
}))
}
- ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => {
+ let ident = self.lower_ident(*ident);
let (generics, (safety, items, bounds)) = self.lower_generics(
generics,
id,
@@ -456,9 +447,8 @@ fn lower_item_kind(
);
hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items)
}
- ItemKind::TraitAlias(generics, bounds) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::TraitAlias(ident, generics, bounds) => {
+ let ident = self.lower_ident(*ident);
let (generics, bounds) = self.lower_generics(
generics,
id,
@@ -472,9 +462,8 @@ fn lower_item_kind(
);
hir::ItemKind::TraitAlias(ident, generics, bounds)
}
- ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
+ ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
+ let ident = self.lower_ident(*ident);
let body = P(self.lower_delim_args(body));
let def_id = self.local_def_id(id);
let def_kind = self.tcx.def_kind(def_id);
@@ -488,11 +477,9 @@ fn lower_item_kind(
hir::ItemKind::Macro(ident, macro_def, macro_kind)
}
ItemKind::Delegation(box delegation) => {
- debug_assert_ne!(ident.name, kw::Empty);
- let ident = self.lower_ident(ident);
let delegation_results = self.lower_delegation(delegation, id, false);
hir::ItemKind::Fn {
- ident,
+ ident: delegation_results.ident,
sig: delegation_results.sig,
generics: delegation_results.generics,
body: delegation_results.body_id,
@@ -649,61 +636,64 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let owner_id = hir_id.expect_owner();
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
- let item = hir::ForeignItem {
- owner_id,
- ident: self.lower_ident(i.ident),
- kind: match &i.kind {
- ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => {
- let fdec = &sig.decl;
- let itctx = ImplTraitContext::Universal;
- let (generics, (decl, fn_args)) =
- self.lower_generics(generics, i.id, itctx, |this| {
- (
- // Disallow `impl Trait` in foreign items.
- this.lower_fn_decl(
- fdec,
- i.id,
- sig.span,
- FnDeclKind::ExternFn,
- None,
- ),
- this.lower_fn_params_to_names(fdec),
- )
- });
+ let (ident, kind) = match &i.kind {
+ ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => {
+ let fdec = &sig.decl;
+ let itctx = ImplTraitContext::Universal;
+ let (generics, (decl, fn_args)) =
+ self.lower_generics(generics, i.id, itctx, |this| {
+ (
+ // Disallow `impl Trait` in foreign items.
+ this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None),
+ this.lower_fn_params_to_names(fdec),
+ )
+ });
- // Unmarked safety in unsafe block defaults to unsafe.
- let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
+ // Unmarked safety in unsafe block defaults to unsafe.
+ let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
- if define_opaque.is_some() {
- self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
- }
+ if define_opaque.is_some() {
+ self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
+ }
+ (
+ ident,
hir::ForeignItemKind::Fn(
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
fn_args,
generics,
- )
- }
- ForeignItemKind::Static(box StaticItem {
- ty,
- mutability,
- expr: _,
- safety,
- define_opaque,
- }) => {
- let ty = self
- .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
- let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
+ ),
+ )
+ }
+ ForeignItemKind::Static(box StaticItem {
+ ident,
+ ty,
+ mutability,
+ expr: _,
+ safety,
+ define_opaque,
+ }) => {
+ let ty =
+ self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
+ let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
- if define_opaque.is_some() {
- self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
- }
-
- hir::ForeignItemKind::Static(ty, *mutability, safety)
+ // njn: where for this?
+ if define_opaque.is_some() {
+ self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
}
- ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
- ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
- },
+
+ (ident, hir::ForeignItemKind::Static(ty, *mutability, safety))
+ }
+ ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => {
+ (ident, hir::ForeignItemKind::Type)
+ }
+ ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
+ };
+
+ let item = hir::ForeignItem {
+ owner_id,
+ ident: self.lower_ident(*ident),
+ kind,
vis_span: self.lower_span(i.vis.span),
span: self.lower_span(i.span),
};
@@ -713,7 +703,9 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef {
id: hir::ForeignItemId { owner_id: self.owner_id(i.id) },
- ident: self.lower_ident(i.ident),
+ // `unwrap` is safe because `ForeignItemKind::MacCall` is the only foreign item kind
+ // without an identifier and it cannot reach here.
+ ident: self.lower_ident(i.kind.ident().unwrap()),
span: self.lower_span(i.span),
}
}
@@ -800,13 +792,19 @@ pub(super) fn lower_field_def(
}
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
- debug_assert_ne!(i.ident.name, kw::Empty);
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
let trait_item_def_id = hir_id.expect_owner();
- let (generics, kind, has_default) = match &i.kind {
- AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => {
+ let (ident, generics, kind, has_default) = match &i.kind {
+ AssocItemKind::Const(box ConstItem {
+ ident,
+ generics,
+ ty,
+ expr,
+ define_opaque,
+ ..
+ }) => {
let (generics, kind) = self.lower_generics(
generics,
i.id,
@@ -831,9 +829,11 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
}
}
- (generics, kind, expr.is_some())
+ (*ident, generics, kind, expr.is_some())
}
- AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
+ AssocItemKind::Fn(box Fn {
+ sig, ident, generics, body: None, define_opaque, ..
+ }) => {
// FIXME(contracts): Deny contract here since it won't apply to
// any impl method or callees.
let names = self.lower_fn_params_to_names(&sig.decl);
@@ -851,10 +851,16 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
"only trait methods with default bodies can define opaque types",
);
}
- (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
+ (
+ *ident,
+ generics,
+ hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)),
+ false,
+ )
}
AssocItemKind::Fn(box Fn {
sig,
+ ident,
generics,
body: Some(body),
contract,
@@ -880,9 +886,16 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
attrs,
);
self.lower_define_opaque(hir_id, &define_opaque);
- (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
+ (
+ *ident,
+ generics,
+ hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
+ true,
+ )
}
- AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
+ AssocItemKind::Type(box TyAlias {
+ ident, generics, where_clauses, bounds, ty, ..
+ }) => {
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
let (generics, kind) = self.lower_generics(
@@ -905,7 +918,7 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
)
},
);
- (generics, kind, ty.is_some())
+ (*ident, generics, kind, ty.is_some())
}
AssocItemKind::Delegation(box delegation) => {
let delegation_results = self.lower_delegation(delegation, i.id, false);
@@ -913,7 +926,7 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
delegation_results.sig,
hir::TraitFn::Provided(delegation_results.body_id),
);
- (delegation_results.generics, item_kind, true)
+ (delegation.ident, delegation_results.generics, item_kind, true)
}
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
panic!("macros should have been expanded by now")
@@ -922,7 +935,7 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let item = hir::TraitItem {
owner_id: trait_item_def_id,
- ident: self.lower_ident(i.ident),
+ ident: self.lower_ident(ident),
generics,
kind,
span: self.lower_span(i.span),
@@ -932,15 +945,20 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
}
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
- let kind = match &i.kind {
- AssocItemKind::Const(..) => hir::AssocItemKind::Const,
- AssocItemKind::Type(..) => hir::AssocItemKind::Type,
- AssocItemKind::Fn(box Fn { sig, .. }) => {
- hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
+ let (ident, kind) = match &i.kind {
+ AssocItemKind::Const(box ConstItem { ident, .. }) => {
+ (*ident, hir::AssocItemKind::Const)
}
- AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
- has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false),
- },
+ AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, hir::AssocItemKind::Type),
+ AssocItemKind::Fn(box Fn { ident, sig, .. }) => {
+ (*ident, hir::AssocItemKind::Fn { has_self: sig.decl.has_self() })
+ }
+ AssocItemKind::Delegation(box delegation) => (
+ delegation.ident,
+ hir::AssocItemKind::Fn {
+ has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false),
+ },
+ ),
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
panic!("macros should have been expanded by now")
}
@@ -948,7 +966,7 @@ fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
let id = hir::TraitItemId { owner_id: self.owner_id(i.id) };
hir::TraitItemRef {
id,
- ident: self.lower_ident(i.ident),
+ ident: self.lower_ident(ident),
span: self.lower_span(i.span),
kind,
}
@@ -964,16 +982,23 @@ fn lower_impl_item(
i: &AssocItem,
is_in_trait_impl: bool,
) -> &'hir hir::ImplItem<'hir> {
- debug_assert_ne!(i.ident.name, kw::Empty);
// Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
- let (generics, kind) = match &i.kind {
- AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self
- .lower_generics(
+ let (ident, (generics, kind)) = match &i.kind {
+ AssocItemKind::Const(box ConstItem {
+ ident,
+ generics,
+ ty,
+ expr,
+ define_opaque,
+ ..
+ }) => (
+ *ident,
+ self.lower_generics(
generics,
i.id,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
@@ -982,11 +1007,19 @@ fn lower_impl_item(
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = this.lower_const_body(i.span, expr.as_deref());
this.lower_define_opaque(hir_id, &define_opaque);
-
hir::ImplItemKind::Const(ty, body)
},
),
- AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
+ ),
+ AssocItemKind::Fn(box Fn {
+ sig,
+ ident,
+ generics,
+ body,
+ contract,
+ define_opaque,
+ ..
+ }) => {
let body_id = self.lower_maybe_coroutine_body(
sig.span,
i.span,
@@ -1007,44 +1040,50 @@ fn lower_impl_item(
);
self.lower_define_opaque(hir_id, &define_opaque);
- (generics, hir::ImplItemKind::Fn(sig, body_id))
+ (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id)))
}
- AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
+ AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
- self.lower_generics(
- &generics,
- i.id,
- ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
- |this| match ty {
- None => {
- let guar = this.dcx().span_delayed_bug(
- i.span,
- "expected to lower associated type, but it was missing",
- );
- let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
- hir::ImplItemKind::Type(ty)
- }
- Some(ty) => {
- let ty = this.lower_ty(
- ty,
- ImplTraitContext::OpaqueTy {
- origin: hir::OpaqueTyOrigin::TyAlias {
- parent: this.local_def_id(i.id),
- in_assoc_ty: true,
+ (
+ *ident,
+ self.lower_generics(
+ &generics,
+ i.id,
+ ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
+ |this| match ty {
+ None => {
+ let guar = this.dcx().span_delayed_bug(
+ i.span,
+ "expected to lower associated type, but it was missing",
+ );
+ let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
+ hir::ImplItemKind::Type(ty)
+ }
+ Some(ty) => {
+ let ty = this.lower_ty(
+ ty,
+ ImplTraitContext::OpaqueTy {
+ origin: hir::OpaqueTyOrigin::TyAlias {
+ parent: this.local_def_id(i.id),
+ in_assoc_ty: true,
+ },
},
- },
- );
- hir::ImplItemKind::Type(ty)
- }
- },
+ );
+ hir::ImplItemKind::Type(ty)
+ }
+ },
+ ),
)
}
AssocItemKind::Delegation(box delegation) => {
let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl);
(
- delegation_results.generics,
- hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
+ delegation.ident,
+ (
+ delegation_results.generics,
+ hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
+ ),
)
}
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
@@ -1054,7 +1093,7 @@ fn lower_impl_item(
let item = hir::ImplItem {
owner_id: hir_id.expect_owner(),
- ident: self.lower_ident(i.ident),
+ ident: self.lower_ident(ident),
generics,
kind,
vis_span: self.lower_span(i.vis.span),
@@ -1067,7 +1106,9 @@ fn lower_impl_item(
fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef {
hir::ImplItemRef {
id: hir::ImplItemId { owner_id: self.owner_id(i.id) },
- ident: self.lower_ident(i.ident),
+ // `unwrap` is safe because `AssocItemKind::{MacCall,DelegationMac}` are the only
+ // assoc item kinds without an identifier and they cannot reach here.
+ ident: self.lower_ident(i.kind.ident().unwrap()),
span: self.lower_span(i.span),
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
@@ -1823,7 +1864,7 @@ pub(super) fn lower_generic_bound_predicate(
}
GenericParamKind::Lifetime => {
let lt_id = self.next_node_id();
- let lifetime = self.new_named_lifetime(id, lt_id, ident);
+ let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No);
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
lifetime,
bounds,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index ced9064..d5d6dcd 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -55,7 +55,8 @@
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::{
- self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate,
+ self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName,
+ TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
@@ -1755,7 +1756,11 @@ fn lower_param_bound(
}
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
- self.new_named_lifetime(l.id, l.id, l.ident)
+ self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No)
+ }
+
+ fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime {
+ self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes)
}
#[instrument(level = "debug", skip(self))]
@@ -1764,28 +1769,43 @@ fn new_named_lifetime(
id: NodeId,
new_id: NodeId,
ident: Ident,
+ is_anon_in_path: IsAnonInPath,
) -> &'hir hir::Lifetime {
+ debug_assert_ne!(ident.name, kw::Empty);
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
let res = match res {
LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param),
LifetimeRes::Fresh { param, .. } => {
+ debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
let param = self.local_def_id(param);
hir::LifetimeName::Param(param)
}
- LifetimeRes::Infer => hir::LifetimeName::Infer,
- LifetimeRes::Static { .. } => hir::LifetimeName::Static,
+ LifetimeRes::Infer => {
+ debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+ hir::LifetimeName::Infer
+ }
+ LifetimeRes::Static { .. } => {
+ debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
+ hir::LifetimeName::Static
+ }
LifetimeRes::Error => hir::LifetimeName::Error,
LifetimeRes::ElidedAnchor { .. } => {
panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span);
}
};
+ #[cfg(debug_assertions)]
+ if is_anon_in_path == IsAnonInPath::Yes {
+ debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+ }
+
debug!(?res);
- self.arena.alloc(hir::Lifetime {
- hir_id: self.lower_node_id(new_id),
- ident: self.lower_ident(ident),
+ self.arena.alloc(hir::Lifetime::new(
+ self.lower_node_id(new_id),
+ self.lower_ident(ident),
res,
- })
+ is_anon_in_path,
+ ))
}
fn lower_generic_params_mut(
@@ -2369,11 +2389,12 @@ fn ty_path(&mut self, mut hir_id: HirId, span: Span, qpath: hir::QPath<'hir>) ->
/// when the bound is written, even if it is written with `'_` like in
/// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked.
fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
- let r = hir::Lifetime {
- hir_id: self.next_id(),
- ident: Ident::new(kw::Empty, self.lower_span(span)),
- res: hir::LifetimeName::ImplicitObjectLifetimeDefault,
- };
+ let r = hir::Lifetime::new(
+ self.next_id(),
+ Ident::new(kw::UnderscoreLifetime, self.lower_span(span)),
+ hir::LifetimeName::ImplicitObjectLifetimeDefault,
+ IsAnonInPath::No,
+ );
debug!("elided_dyn_bound: r={:?}", r);
self.arena.alloc(r)
}
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index d00c797..c464c15 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -7,7 +7,7 @@
use rustc_hir::def_id::DefId;
use rustc_middle::span_bug;
use rustc_session::parse::add_feature_diagnostics;
-use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
+use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
@@ -450,10 +450,7 @@ fn maybe_insert_elided_lifetimes_in_path(
0,
(start.as_u32()..end.as_u32()).map(|i| {
let id = NodeId::from_u32(i);
- let l = self.lower_lifetime(&Lifetime {
- id,
- ident: Ident::new(kw::Empty, elided_lifetime_span),
- });
+ let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span);
GenericArg::Lifetime(l)
}),
);
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index a1487ca..839d5d3 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -334,8 +334,7 @@ fn check_decl_attrs(&self, fn_decl: &FnDecl) {
.filter(|attr| {
let arr = [
sym::allow,
- sym::cfg,
- sym::cfg_attr,
+ sym::cfg_trace,
sym::cfg_attr_trace,
sym::deny,
sym::expect,
@@ -608,7 +607,7 @@ fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) {
fn deny_items(&self, trait_items: &[P<AssocItem>], ident: Span) {
if !trait_items.is_empty() {
- let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
+ let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect();
let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident });
}
@@ -818,8 +817,10 @@ fn visit_item(&mut self, item: &'a Item) {
self.has_proc_macro_decls = true;
}
- if attr::contains_name(&item.attrs, sym::no_mangle) {
- self.check_nomangle_item_asciionly(item.ident, item.span);
+ if let Some(ident) = item.kind.ident()
+ && attr::contains_name(&item.attrs, sym::no_mangle)
+ {
+ self.check_nomangle_item_asciionly(ident, item.span);
}
match &item.kind {
@@ -853,7 +854,6 @@ fn visit_item(&mut self, item: &'a Item) {
}
this.visit_vis(&item.vis);
- this.visit_ident(&item.ident);
let disallowed = matches!(constness, Const::No)
.then(|| TildeConstReason::TraitImpl { span: item.span });
this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
@@ -907,7 +907,6 @@ fn visit_item(&mut self, item: &'a Item) {
}
this.visit_vis(&item.vis);
- this.visit_ident(&item.ident);
this.with_tilde_const(
Some(TildeConstReason::Impl { span: item.span }),
|this| this.visit_generics(generics),
@@ -919,8 +918,15 @@ fn visit_item(&mut self, item: &'a Item) {
return; // Avoid visiting again.
}
ItemKind::Fn(
- func
- @ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ },
+ func @ box Fn {
+ defaultness,
+ ident,
+ generics: _,
+ sig,
+ contract: _,
+ body,
+ define_opaque: _,
+ },
) => {
self.check_defaultness(item.span, *defaultness);
@@ -950,8 +956,8 @@ fn visit_item(&mut self, item: &'a Item) {
}
self.visit_vis(&item.vis);
- self.visit_ident(&item.ident);
- let kind = FnKind::Fn(FnCtxt::Free, &item.ident, &item.vis, &*func);
+ self.visit_ident(ident);
+ let kind = FnKind::Fn(FnCtxt::Free, &item.vis, &*func);
self.visit_fn(kind, item.span, item.id);
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
@@ -987,7 +993,7 @@ fn visit_item(&mut self, item: &'a Item) {
});
return; // Avoid visiting again.
}
- ItemKind::Enum(def, _) => {
+ ItemKind::Enum(_, def, _) => {
for variant in &def.variants {
self.visibility_not_permitted(
&variant.vis,
@@ -1001,22 +1007,22 @@ fn visit_item(&mut self, item: &'a Item) {
}
}
}
- ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
+ ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => {
let is_const_trait =
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
self.with_in_trait(item.span, is_const_trait, |this| {
if *is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
- this.deny_generic_params(generics, item.ident.span);
- this.deny_super_traits(bounds, item.ident.span);
- this.deny_where_clause(&generics.where_clause, item.ident.span);
- this.deny_items(items, item.ident.span);
+ this.deny_generic_params(generics, ident.span);
+ this.deny_super_traits(bounds, ident.span);
+ this.deny_where_clause(&generics.where_clause, ident.span);
+ this.deny_items(items, ident.span);
}
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
// context for the supertraits.
this.visit_vis(&item.vis);
- this.visit_ident(&item.ident);
+ this.visit_ident(ident);
let disallowed = is_const_trait
.is_none()
.then(|| TildeConstReason::Trait { span: item.span });
@@ -1029,7 +1035,7 @@ fn visit_item(&mut self, item: &'a Item) {
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again
}
- ItemKind::Mod(safety, mod_kind) => {
+ ItemKind::Mod(safety, ident, mod_kind) => {
if let &Safety::Unsafe(span) = safety {
self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
}
@@ -1037,13 +1043,13 @@ fn visit_item(&mut self, item: &'a Item) {
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _))
&& !attr::contains_name(&item.attrs, sym::path)
{
- self.check_mod_file_item_asciionly(item.ident);
+ self.check_mod_file_item_asciionly(*ident);
}
}
- ItemKind::Struct(vdata, generics) => match vdata {
+ ItemKind::Struct(ident, vdata, generics) => match vdata {
VariantData::Struct { fields, .. } => {
self.visit_vis(&item.vis);
- self.visit_ident(&item.ident);
+ self.visit_ident(ident);
self.visit_generics(generics);
// Permit `Anon{Struct,Union}` as field type.
walk_list!(self, visit_struct_field_def, fields);
@@ -1052,14 +1058,14 @@ fn visit_item(&mut self, item: &'a Item) {
}
_ => {}
},
- ItemKind::Union(vdata, generics) => {
+ ItemKind::Union(ident, vdata, generics) => {
if vdata.fields().is_empty() {
self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
}
match vdata {
VariantData::Struct { fields, .. } => {
self.visit_vis(&item.vis);
- self.visit_ident(&item.ident);
+ self.visit_ident(ident);
self.visit_generics(generics);
// Permit `Anon{Struct,Union}` as field type.
walk_list!(self, visit_struct_field_def, fields);
@@ -1122,14 +1128,15 @@ fn visit_item(&mut self, item: &'a Item) {
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
match &fi.kind {
- ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
+ ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => {
self.check_defaultness(fi.span, *defaultness);
- self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
+ self.check_foreign_fn_bodyless(*ident, body.as_deref());
self.check_foreign_fn_headerless(sig.header);
- self.check_foreign_item_ascii_only(fi.ident);
+ self.check_foreign_item_ascii_only(*ident);
}
ForeignItemKind::TyAlias(box TyAlias {
defaultness,
+ ident,
generics,
where_clauses,
bounds,
@@ -1137,15 +1144,15 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
..
}) => {
self.check_defaultness(fi.span, *defaultness);
- self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
+ self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span));
self.check_type_no_bounds(bounds, "`extern` blocks");
self.check_foreign_ty_genericless(generics, where_clauses);
- self.check_foreign_item_ascii_only(fi.ident);
+ self.check_foreign_item_ascii_only(*ident);
}
- ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => {
+ ForeignItemKind::Static(box StaticItem { ident, safety, expr, .. }) => {
self.check_item_safety(fi.span, *safety);
- self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
- self.check_foreign_item_ascii_only(fi.ident);
+ self.check_foreign_kind_bodyless(*ident, "static", expr.as_ref().map(|b| b.span));
+ self.check_foreign_item_ascii_only(*ident);
}
ForeignItemKind::MacCall(..) => {}
}
@@ -1354,7 +1361,6 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
if let FnKind::Fn(
_,
_,
- _,
Fn {
sig: FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. },
..
@@ -1365,7 +1371,7 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
}
// Functions without bodies cannot have patterns.
- if let FnKind::Fn(ctxt, _, _, Fn { body: None, sig, .. }) = fk {
+ if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk {
Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
if let Some(ident) = ident {
@@ -1399,15 +1405,17 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
.is_some();
let disallowed = (!tilde_const_allowed).then(|| match fk {
- FnKind::Fn(_, ident, _, _) => TildeConstReason::Function { ident: ident.span },
+ FnKind::Fn(_, _, f) => TildeConstReason::Function { ident: f.ident.span },
FnKind::Closure(..) => TildeConstReason::Closure,
});
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
- if attr::contains_name(&item.attrs, sym::no_mangle) {
- self.check_nomangle_item_asciionly(item.ident, item.span);
+ if let Some(ident) = item.kind.ident()
+ && attr::contains_name(&item.attrs, sym::no_mangle)
+ {
+ self.check_nomangle_item_asciionly(ident, item.span);
}
if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() {
@@ -1467,8 +1475,8 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
}
}
- if let AssocItemKind::Const(..) = item.kind {
- self.check_item_named(item.ident, "const");
+ if let AssocItemKind::Const(ci) = &item.kind {
+ self.check_item_named(ci.ident, "const");
}
let parent_is_const =
@@ -1481,8 +1489,8 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
|| matches!(func.sig.header.constness, Const::Yes(_)) =>
{
self.visit_vis(&item.vis);
- self.visit_ident(&item.ident);
- let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, &item.vis, &*func);
+ self.visit_ident(&func.ident);
+ let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.vis, &*func);
walk_list!(self, visit_attribute, &item.attrs);
self.visit_fn(kind, item.span, item.id);
}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 31ff102..ea60e08 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -99,6 +99,13 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
}
visit::walk_ty(self, ty);
}
+
+ fn visit_anon_const(&mut self, _: &ast::AnonConst) -> Self::Result {
+ // We don't walk the anon const because it crosses a conceptual boundary: We're no
+ // longer "inside" the original type.
+ // Brittle: We assume that the callers of `check_impl_trait` will later recurse into
+ // the items found in the AnonConst to look for nested TyAliases.
+ }
}
ImplTraitVisitor { vis: self, in_associated_ty }.visit_ty(ty);
}
@@ -229,7 +236,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
gate!(&self, trait_alias, i.span, "trait aliases are experimental");
}
- ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
+ ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => {
let msg = "`macro` is experimental";
gate!(&self, decl_macro, i.span, msg);
}
@@ -483,7 +490,6 @@ macro_rules! gate_all {
half_open_range_patterns_in_slices,
"half-open range patterns in slices are unstable"
);
- gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete");
gate_all!(yeet_expr, "`do yeet` expression is experimental");
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index cdb1817..3dbfc19 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -593,7 +593,7 @@ fn print_either_attributes(
}
fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool {
- if attr.has_name(sym::cfg_attr_trace) {
+ if attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) {
// It's not a valid identifier, so avoid printing it
// to keep the printed code reasonably parse-able.
return false;
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index d406a56..653bd77 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -28,23 +28,24 @@ fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]
}
fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
- let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+ let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
self.ann.pre(self, AnnNode::SubItem(id));
self.hardbreak_if_not_bol();
self.maybe_print_comment(span.lo());
self.print_outer_attributes(attrs);
match kind {
ast::ForeignItemKind::Fn(func) => {
- self.print_fn_full(ident, vis, attrs, &*func);
+ self.print_fn_full(vis, attrs, &*func);
}
ast::ForeignItemKind::Static(box ast::StaticItem {
+ ident,
ty,
mutability,
expr,
safety,
define_opaque,
}) => self.print_item_const(
- ident,
+ *ident,
Some(*mutability),
&ast::Generics::default(),
ty,
@@ -56,13 +57,14 @@ fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
),
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
defaultness,
+ ident,
generics,
where_clauses,
bounds,
ty,
}) => {
self.print_associated_type(
- ident,
+ *ident,
generics,
*where_clauses,
bounds,
@@ -162,7 +164,7 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
self.print_outer_attributes(&item.attrs);
self.ann.pre(self, AnnNode::Item(item));
match &item.kind {
- ast::ItemKind::ExternCrate(orig_name) => {
+ ast::ItemKind::ExternCrate(orig_name, ident) => {
self.head(visibility_qualified(&item.vis, "extern crate"));
if let &Some(orig_name) = orig_name {
self.print_name(orig_name);
@@ -170,7 +172,7 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
self.word("as");
self.space();
}
- self.print_ident(item.ident);
+ self.print_ident(*ident);
self.word(";");
self.end(); // end inner head-block
self.end(); // end outer head-block
@@ -182,6 +184,7 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
self.word(";");
}
ast::ItemKind::Static(box StaticItem {
+ ident,
ty,
safety,
mutability: mutbl,
@@ -190,7 +193,7 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
}) => {
self.print_safety(*safety);
self.print_item_const(
- item.ident,
+ *ident,
Some(*mutbl),
&ast::Generics::default(),
ty,
@@ -203,13 +206,14 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
}
ast::ItemKind::Const(box ast::ConstItem {
defaultness,
+ ident,
generics,
ty,
expr,
define_opaque,
}) => {
self.print_item_const(
- item.ident,
+ *ident,
None,
generics,
ty,
@@ -221,15 +225,15 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
);
}
ast::ItemKind::Fn(func) => {
- self.print_fn_full(item.ident, &item.vis, &item.attrs, &*func);
+ self.print_fn_full(&item.vis, &item.attrs, &*func);
}
- ast::ItemKind::Mod(safety, mod_kind) => {
+ ast::ItemKind::Mod(safety, ident, mod_kind) => {
self.head(Self::to_string(|s| {
s.print_visibility(&item.vis);
s.print_safety(*safety);
s.word("mod");
}));
- self.print_ident(item.ident);
+ self.print_ident(*ident);
match mod_kind {
ModKind::Loaded(items, ..) => {
@@ -273,13 +277,14 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
}
ast::ItemKind::TyAlias(box ast::TyAlias {
defaultness,
+ ident,
generics,
where_clauses,
bounds,
ty,
}) => {
self.print_associated_type(
- item.ident,
+ *ident,
generics,
*where_clauses,
bounds,
@@ -288,16 +293,16 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
*defaultness,
);
}
- ast::ItemKind::Enum(enum_definition, params) => {
- self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
+ ast::ItemKind::Enum(ident, enum_definition, params) => {
+ self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis);
}
- ast::ItemKind::Struct(struct_def, generics) => {
+ ast::ItemKind::Struct(ident, struct_def, generics) => {
self.head(visibility_qualified(&item.vis, "struct"));
- self.print_struct(struct_def, generics, item.ident, item.span, true);
+ self.print_struct(struct_def, generics, *ident, item.span, true);
}
- ast::ItemKind::Union(struct_def, generics) => {
+ ast::ItemKind::Union(ident, struct_def, generics) => {
self.head(visibility_qualified(&item.vis, "union"));
- self.print_struct(struct_def, generics, item.ident, item.span, true);
+ self.print_struct(struct_def, generics, *ident, item.span, true);
}
ast::ItemKind::Impl(box ast::Impl {
safety,
@@ -347,19 +352,19 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
self.bclose(item.span, empty);
}
ast::ItemKind::Trait(box ast::Trait {
- is_auto,
safety,
+ is_auto,
+ ident,
generics,
bounds,
items,
- ..
}) => {
self.head("");
self.print_visibility(&item.vis);
self.print_safety(*safety);
self.print_is_auto(*is_auto);
self.word_nbsp("trait");
- self.print_ident(item.ident);
+ self.print_ident(*ident);
self.print_generic_params(&generics.params);
if !bounds.is_empty() {
self.word_nbsp(":");
@@ -375,9 +380,9 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
let empty = item.attrs.is_empty() && items.is_empty();
self.bclose(item.span, empty);
}
- ast::ItemKind::TraitAlias(generics, bounds) => {
+ ast::ItemKind::TraitAlias(ident, generics, bounds) => {
self.head(visibility_qualified(&item.vis, "trait"));
- self.print_ident(item.ident);
+ self.print_ident(*ident);
self.print_generic_params(&generics.params);
self.nbsp();
if !bounds.is_empty() {
@@ -395,8 +400,8 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
self.word(";");
}
}
- ast::ItemKind::MacroDef(macro_def) => {
- self.print_mac_def(macro_def, &item.ident, item.span, |state| {
+ ast::ItemKind::MacroDef(ident, macro_def) => {
+ self.print_mac_def(macro_def, &ident, item.span, |state| {
state.print_visibility(&item.vis)
});
}
@@ -549,24 +554,25 @@ pub(crate) fn print_variant(&mut self, v: &ast::Variant) {
}
fn print_assoc_item(&mut self, item: &ast::AssocItem) {
- let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+ let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
self.ann.pre(self, AnnNode::SubItem(id));
self.hardbreak_if_not_bol();
self.maybe_print_comment(span.lo());
self.print_outer_attributes(attrs);
match kind {
ast::AssocItemKind::Fn(func) => {
- self.print_fn_full(ident, vis, attrs, &*func);
+ self.print_fn_full(vis, attrs, &*func);
}
ast::AssocItemKind::Const(box ast::ConstItem {
defaultness,
+ ident,
generics,
ty,
expr,
define_opaque,
}) => {
self.print_item_const(
- ident,
+ *ident,
None,
generics,
ty,
@@ -579,13 +585,14 @@ fn print_assoc_item(&mut self, item: &ast::AssocItem) {
}
ast::AssocItemKind::Type(box ast::TyAlias {
defaultness,
+ ident,
generics,
where_clauses,
bounds,
ty,
}) => {
self.print_associated_type(
- ident,
+ *ident,
generics,
*where_clauses,
bounds,
@@ -671,14 +678,8 @@ fn print_delegation(
}
}
- fn print_fn_full(
- &mut self,
- name: Ident,
- vis: &ast::Visibility,
- attrs: &[ast::Attribute],
- func: &ast::Fn,
- ) {
- let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
+ fn print_fn_full(&mut self, vis: &ast::Visibility, attrs: &[ast::Attribute], func: &ast::Fn) {
+ let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque } = func;
self.print_define_opaques(define_opaque.as_deref());
@@ -687,7 +688,7 @@ fn print_fn_full(
}
self.print_visibility(vis);
self.print_defaultness(*defaultness);
- self.print_fn(&sig.decl, sig.header, Some(name), generics);
+ self.print_fn(&sig.decl, sig.header, Some(*ident), generics);
if let Some(contract) = &contract {
self.nbsp();
self.print_contract(contract);
@@ -734,13 +735,13 @@ pub(crate) fn print_fn(
&mut self,
decl: &ast::FnDecl,
header: ast::FnHeader,
- name: Option<Ident>,
+ ident: Option<Ident>,
generics: &ast::Generics,
) {
self.print_fn_header_info(header);
- if let Some(name) = name {
+ if let Some(ident) = ident {
self.nbsp();
- self.print_ident(name);
+ self.print_ident(ident);
}
self.print_generic_params(&generics.params);
self.print_fn_params_and_ret(decl, false);
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 5a89f7c..45cdd23 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -1,7 +1,7 @@
//! This file provides API for compiler consumers.
use rustc_hir::def_id::LocalDefId;
-use rustc_index::{IndexSlice, IndexVec};
+use rustc_index::IndexVec;
use rustc_middle::mir::{Body, Promoted};
use rustc_middle::ty::TyCtxt;
@@ -100,8 +100,5 @@ pub fn get_body_with_borrowck_facts(
def: LocalDefId,
options: ConsumerOptions,
) -> BodyWithBorrowckFacts<'_> {
- let (input_body, promoted) = tcx.mir_promoted(def);
- let input_body: &Body<'_> = &input_body.borrow();
- let promoted: &IndexSlice<_, _> = &promoted.borrow();
- *super::do_mir_borrowck(tcx, input_body, promoted, Some(options)).1.unwrap()
+ *super::do_mir_borrowck(tcx, def, Some(options)).1.unwrap()
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 6b11f1a..50a18b0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -513,14 +513,14 @@ pub(crate) fn report_region_error(
ty::VarianceDiagInfo::Invariant { ty, param_index } => {
let (desc, note) = match ty.kind() {
ty::RawPtr(ty, mutbl) => {
- assert_eq!(*mutbl, rustc_hir::Mutability::Mut);
+ assert_eq!(*mutbl, hir::Mutability::Mut);
(
format!("a mutable pointer to `{}`", ty),
"mutable pointers are invariant over their type parameter".to_string(),
)
}
ty::Ref(_, inner_ty, mutbl) => {
- assert_eq!(*mutbl, rustc_hir::Mutability::Mut);
+ assert_eq!(*mutbl, hir::Mutability::Mut);
(
format!("a mutable reference to `{inner_ty}`"),
"mutable references are invariant over their type parameter"
@@ -887,7 +887,7 @@ fn add_static_impl_trait_suggestion(
// Skip `async` desugaring `impl Future`.
}
if let TyKind::TraitObject(_, lt) = alias_ty.kind {
- if lt.ident.name == kw::Empty {
+ if lt.res == hir::LifetimeName::ImplicitObjectLifetimeDefault {
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
} else {
spans_suggs.push((lt.ident.span, "'a".to_string()));
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 84b7b8c..7f0ee28 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -103,11 +103,8 @@ pub fn provide(providers: &mut Providers) {
}
fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
- let (input_body, promoted) = tcx.mir_promoted(def);
- debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
-
+ let (input_body, _) = tcx.mir_promoted(def);
let input_body: &Body<'_> = &input_body.borrow();
-
if input_body.should_skip() || input_body.tainted_by_errors.is_some() {
debug!("Skipping borrowck because of injected body or tainted body");
// Let's make up a borrowck result! Fun times!
@@ -120,7 +117,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
return tcx.arena.alloc(result);
}
- let borrowck_result = do_mir_borrowck(tcx, input_body, &*promoted.borrow(), None).0;
+ let borrowck_result = do_mir_borrowck(tcx, def, None).0;
debug!("mir_borrowck done");
tcx.arena.alloc(borrowck_result)
@@ -131,15 +128,16 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
/// Use `consumer_options: None` for the default behavior of returning
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
/// to the given [`ConsumerOptions`].
-#[instrument(skip(tcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
+#[instrument(skip(tcx), level = "debug")]
fn do_mir_borrowck<'tcx>(
tcx: TyCtxt<'tcx>,
- input_body: &Body<'tcx>,
- input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
+ def: LocalDefId,
consumer_options: Option<ConsumerOptions>,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
- let def = input_body.source.def_id().expect_local();
let infcx = BorrowckInferCtxt::new(tcx, def);
+ let (input_body, promoted) = tcx.mir_promoted(def);
+ let input_body: &Body<'_> = &input_body.borrow();
+ let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
if let Some(e) = input_body.tainted_by_errors {
infcx.set_tainted_by_errors(e);
}
@@ -499,7 +497,8 @@ fn register_predefined_opaques_for_next_solver(&self, def_id: LocalDefId) {
)
});
- self.inject_new_hidden_type_unchecked(key, hidden_ty);
+ let prev = self.register_hidden_type_in_storage(key, hidden_ty);
+ assert_eq!(prev, None);
}
}
}
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index d0bd364..8e7b6f0 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -1,9 +1,9 @@
//! The entry point of the NLL borrow checker.
+use std::io;
use std::path::PathBuf;
use std::rc::Rc;
use std::str::FromStr;
-use std::{env, io};
use polonius_engine::{Algorithm, Output};
use rustc_index::IndexSlice;
@@ -162,9 +162,8 @@ pub(crate) fn compute_regions<'a, 'tcx>(
}
if polonius_output {
- let algorithm =
- env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
- let algorithm = Algorithm::from_str(&algorithm).unwrap();
+ let algorithm = infcx.tcx.env_var("POLONIUS_ALGORITHM").unwrap_or("Hybrid");
+ let algorithm = Algorithm::from_str(algorithm).unwrap();
debug!("compute_regions: using polonius algorithm {:?}", algorithm);
let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis");
Some(Box::new(Output::compute(polonius_facts, algorithm, false)))
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 1c1b2c8..ea406e7 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -21,15 +21,15 @@ pub(crate) fn expand(
// Allow using `#[alloc_error_handler]` on an item statement
// FIXME - if we get deref patterns, use them to reduce duplication here
- let (item, is_stmt, sig_span) = if let Annotatable::Item(item) = &item
+ let (item, ident, is_stmt, sig_span) = if let Annotatable::Item(item) = &item
&& let ItemKind::Fn(fn_kind) = &item.kind
{
- (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ (item, fn_kind.ident, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
} else if let Annotatable::Stmt(stmt) = &item
&& let StmtKind::Item(item) = &stmt.kind
&& let ItemKind::Fn(fn_kind) = &item.kind
{
- (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ (item, fn_kind.ident, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
} else {
ecx.dcx().emit_err(errors::AllocErrorMustBeFn { span: item.span() });
return vec![orig_item];
@@ -39,7 +39,7 @@ pub(crate) fn expand(
let span = ecx.with_def_site_ctxt(item.span);
// Generate item statements for the allocator methods.
- let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)];
+ let stmts = thin_vec![generate_handler(ecx, ident, span, sig_span)];
// Generate anonymous constant serving as container for the allocator methods.
let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
@@ -85,6 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
let kind = ItemKind::Fn(Box::new(Fn {
defaultness: ast::Defaultness::Final,
sig,
+ ident: Ident::from_str_and_span("__rg_oom", span),
generics: Generics::default(),
contract: None,
body,
@@ -93,6 +94,6 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
- let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
+ let item = cx.item(span, attrs, kind);
cx.stmt_item(sig_span, item)
}
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index eb5b345..3e8ddb8 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -10,7 +10,7 @@
use rustc_parse::exp;
use rustc_parse::parser::{ExpKeywordPair, Parser};
use rustc_session::lint;
-use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw};
+use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw};
use rustc_target::asm::InlineAsmArch;
use smallvec::smallvec;
use {rustc_ast as ast, rustc_parse_format as parse};
@@ -888,7 +888,6 @@ pub(super) fn expand_global_asm<'cx>(
};
match mac {
Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item {
- ident: Ident::empty(),
attrs: ast::AttrVec::new(),
id: ast::DUMMY_NODE_ID,
kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index a949ab9..ea7248c 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -112,7 +112,6 @@ fn build_initial_imports(&self) -> Stmt {
self.span,
self.cx.item(
self.span,
- Ident::empty(),
thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
ItemKind::Use(UseTree {
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index be11711..8937d35 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -146,26 +146,26 @@ pub(crate) fn expand(
}
let dcx = ecx.sess.dcx();
// first get the annotable item:
- let (sig, is_impl): (FnSig, bool) = match &item {
+ let (primal, sig, is_impl): (Ident, FnSig, bool) = match &item {
Annotatable::Item(iitem) => {
- let sig = match &iitem.kind {
- ItemKind::Fn(box ast::Fn { sig, .. }) => sig,
+ let (ident, sig) = match &iitem.kind {
+ ItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
_ => {
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
return vec![item];
}
};
- (sig.clone(), false)
+ (*ident, sig.clone(), false)
}
Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => {
- let sig = match &assoc_item.kind {
- ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig,
+ let (ident, sig) = match &assoc_item.kind {
+ ast::AssocItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
_ => {
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
return vec![item];
}
};
- (sig.clone(), true)
+ (*ident, sig.clone(), true)
}
_ => {
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
@@ -184,11 +184,9 @@ pub(crate) fn expand(
let has_ret = has_ret(&sig.decl.output);
let sig_span = ecx.with_call_site_ctxt(sig.span);
- let (vis, primal) = match &item {
- Annotatable::Item(iitem) => (iitem.vis.clone(), iitem.ident.clone()),
- Annotatable::AssocItem(assoc_item, _) => {
- (assoc_item.vis.clone(), assoc_item.ident.clone())
- }
+ let vis = match &item {
+ Annotatable::Item(iitem) => iitem.vis.clone(),
+ Annotatable::AssocItem(assoc_item, _) => assoc_item.vis.clone(),
_ => {
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
return vec![item];
@@ -237,12 +235,12 @@ pub(crate) fn expand(
let d_body = gen_enzyme_body(
ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored,
);
- let d_ident = first_ident(&meta_item_vec[0]);
// The first element of it is the name of the function to be generated
let asdf = Box::new(ast::Fn {
defaultness: ast::Defaultness::Final,
sig: d_sig,
+ ident: first_ident(&meta_item_vec[0]),
generics: Generics::default(),
contract: None,
body: Some(d_body),
@@ -323,14 +321,12 @@ fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool {
id: ast::DUMMY_NODE_ID,
span,
vis,
- ident: d_ident,
kind: assoc_item,
tokens: None,
});
Annotatable::AssocItem(d_fn, Impl { of_trait: false })
} else {
- let mut d_fn =
- ecx.item(span, d_ident, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
+ let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
d_fn.vis = vis;
Annotatable::Item(d_fn)
};
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index c3656e8..44cf215 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone(
let is_simple;
match item {
Annotatable::Item(annitem) => match &annitem.kind {
- ItemKind::Struct(_, Generics { params, .. })
- | ItemKind::Enum(_, Generics { params, .. }) => {
+ ItemKind::Struct(_, _, Generics { params, .. })
+ | ItemKind::Enum(_, _, Generics { params, .. }) => {
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
if has_derive_copy
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 7958e03..aa01da3 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord(
// Order in which to perform matching
let discr_then_data = if let Annotatable::Item(item) = item
- && let ItemKind::Enum(def, _) = &item.kind
+ && let ItemKind::Enum(_, def, _) = &item.kind
{
let dataful: Vec<bool> = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect();
match dataful.iter().filter(|&&b| b).count() {
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 46b79e0..446d8af 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
item.visit_with(&mut DetectNonGenericPointeeAttr { cx });
let (name_ident, generics) = if let Annotatable::Item(aitem) = item
- && let ItemKind::Struct(struct_data, g) = &aitem.kind
+ && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind
{
if !matches!(
struct_data,
@@ -40,7 +40,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
cx.dcx().emit_err(RequireOneField { span });
return;
}
- (aitem.ident, g)
+ (*ident, g)
} else {
cx.dcx().emit_err(RequireTransparent { span });
return;
@@ -108,7 +108,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
push(Annotatable::Item(
cx.item(
span,
- Ident::empty(),
attrs.clone(),
ast::ItemKind::Impl(Box::new(ast::Impl {
safety: ast::Safety::Default,
@@ -153,7 +152,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
let trait_ref = cx.trait_ref(trait_path);
let item = cx.item(
span,
- Ident::empty(),
attrs.clone(),
ast::ItemKind::Impl(Box::new(ast::Impl {
safety: ast::Safety::Default,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 03ee59d..b9197be 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -487,28 +487,28 @@ pub(crate) fn expand_ext(
);
let newitem = match &item.kind {
- ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
+ ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def(
cx,
struct_def,
- item.ident,
+ *ident,
generics,
from_scratch,
is_packed,
),
- ast::ItemKind::Enum(enum_def, generics) => {
+ ast::ItemKind::Enum(ident, enum_def, generics) => {
// We ignore `is_packed` here, because `repr(packed)`
// enums cause an error later on.
//
// This can only cause further compilation errors
// downstream in blatantly illegal code, so it is fine.
- self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
+ self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch)
}
- ast::ItemKind::Union(struct_def, generics) => {
+ ast::ItemKind::Union(ident, struct_def, generics) => {
if self.supports_unions {
self.expand_struct_def(
cx,
struct_def,
- item.ident,
+ *ident,
generics,
from_scratch,
is_packed,
@@ -596,7 +596,6 @@ fn create_derived_impl(
P(ast::AssocItem {
id: ast::DUMMY_NODE_ID,
span: self.span,
- ident,
vis: ast::Visibility {
span: self.span.shrink_to_lo(),
kind: ast::VisibilityKind::Inherited,
@@ -605,6 +604,7 @@ fn create_derived_impl(
attrs: ast::AttrVec::new(),
kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
defaultness: ast::Defaultness::Final,
+ ident,
generics: Generics::default(),
where_clauses: ast::TyAliasWhereClauses::default(),
bounds: Vec::new(),
@@ -789,7 +789,6 @@ fn create_derived_impl(
cx.item(
self.span,
- Ident::empty(),
attrs,
ast::ItemKind::Impl(Box::new(ast::Impl {
safety: ast::Safety::Default,
@@ -1033,10 +1032,10 @@ fn create_method(
kind: ast::VisibilityKind::Inherited,
tokens: None,
},
- ident: method_ident,
kind: ast::AssocItemKind::Fn(Box::new(ast::Fn {
defaultness,
sig,
+ ident: method_ident,
generics: fn_generics,
contract: None,
body: Some(body_block),
diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs
index b39c986..ccfcc30 100644
--- a/compiler/rustc_builtin_macros/src/edition_panic.rs
+++ b/compiler/rustc_builtin_macros/src/edition_panic.rs
@@ -74,11 +74,11 @@ pub(crate) fn use_panic_2021(mut span: Span) -> bool {
// (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
loop {
let expn = span.ctxt().outer_expn_data();
- if let Some(features) = expn.allow_internal_unstable {
- if features.iter().any(|&f| f == sym::edition_panic) {
- span = expn.call_site;
- continue;
- }
+ if let Some(features) = expn.allow_internal_unstable
+ && features.contains(&sym::edition_panic)
+ {
+ span = expn.call_site;
+ continue;
}
break expn.edition >= Edition::Edition2021;
}
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 90d7923..4b1958b 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -25,15 +25,15 @@ pub(crate) fn expand(
// Allow using `#[global_allocator]` on an item statement
// FIXME - if we get deref patterns, use them to reduce duplication here
- let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item
- && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind
+ let (item, ident, is_stmt, ty_span) = if let Annotatable::Item(item) = &item
+ && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind
{
- (item, false, ecx.with_def_site_ctxt(ty.span))
+ (item, *ident, false, ecx.with_def_site_ctxt(ty.span))
} else if let Annotatable::Stmt(stmt) = &item
&& let StmtKind::Item(item) = &stmt.kind
- && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind
+ && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind
{
- (item, true, ecx.with_def_site_ctxt(ty.span))
+ (item, *ident, true, ecx.with_def_site_ctxt(ty.span))
} else {
ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() });
return vec![orig_item];
@@ -41,7 +41,7 @@ pub(crate) fn expand(
// Generate a bunch of new items using the AllocFnFactory
let span = ecx.with_def_site_ctxt(item.span);
- let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx };
+ let f = AllocFnFactory { span, ty_span, global: ident, cx: ecx };
// Generate item statements for the allocator methods.
let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
@@ -80,17 +80,13 @@ fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
let kind = ItemKind::Fn(Box::new(Fn {
defaultness: ast::Defaultness::Final,
sig,
+ ident: Ident::from_str_and_span(&global_fn_name(method.name), self.span),
generics: Generics::default(),
contract: None,
body,
define_opaque: None,
}));
- let item = self.cx.item(
- self.span,
- Ident::from_str_and_span(&global_fn_name(method.name), self.span),
- self.attrs(),
- kind,
- );
+ let item = self.cx.item(self.span, self.attrs(), kind);
self.cx.stmt_item(self.ty_span, item)
}
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index ee6475c..8862965 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -92,7 +92,12 @@ fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
}
}
- fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
+ fn collect_custom_derive(
+ &mut self,
+ item: &'a ast::Item,
+ function_name: Ident,
+ attr: &'a ast::Attribute,
+ ) {
let Some((trait_name, proc_attrs)) =
parse_macro_name_and_helper_attrs(self.dcx, attr, "derive")
else {
@@ -104,7 +109,7 @@ fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribut
id: item.id,
span: item.span,
trait_name,
- function_name: item.ident,
+ function_name,
attrs: proc_attrs,
}));
} else {
@@ -118,12 +123,12 @@ fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribut
}
}
- fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
+ fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) {
if self.in_root && item.vis.kind.is_pub() {
self.macros.push(ProcMacro::Attr(ProcMacroDef {
id: item.id,
span: item.span,
- function_name: item.ident,
+ function_name,
}));
} else {
let msg = if !self.in_root {
@@ -136,12 +141,12 @@ fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
}
}
- fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
+ fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) {
if self.in_root && item.vis.kind.is_pub() {
self.macros.push(ProcMacro::Bang(ProcMacroDef {
id: item.id,
span: item.span,
- function_name: item.ident,
+ function_name,
}));
} else {
let msg = if !self.in_root {
@@ -165,12 +170,6 @@ fn visit_item(&mut self, item: &'a ast::Item) {
}
}
- // First up, make sure we're checking a bare function. If we're not then
- // we're just not interested in this item.
- //
- // If we find one, try to locate a `#[proc_macro_derive]` attribute on it.
- let is_fn = matches!(item.kind, ast::ItemKind::Fn(..));
-
let mut found_attr: Option<&'a ast::Attribute> = None;
for attr in &item.attrs {
@@ -214,7 +213,11 @@ fn visit_item(&mut self, item: &'a ast::Item) {
return;
};
- if !is_fn {
+ // Make sure we're checking a bare function. If we're not then we're
+ // just not interested any further in this item.
+ let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind {
+ fn_.ident
+ } else {
self.dcx
.create_err(errors::AttributeOnlyBeUsedOnBareFunctions {
span: attr.span,
@@ -222,7 +225,7 @@ fn visit_item(&mut self, item: &'a ast::Item) {
})
.emit();
return;
- }
+ };
if self.is_test_crate {
return;
@@ -238,12 +241,13 @@ fn visit_item(&mut self, item: &'a ast::Item) {
return;
}
+ // Try to locate a `#[proc_macro_derive]` attribute.
if attr.has_name(sym::proc_macro_derive) {
- self.collect_custom_derive(item, attr);
+ self.collect_custom_derive(item, fn_ident, attr);
} else if attr.has_name(sym::proc_macro_attribute) {
- self.collect_attr_proc_macro(item);
+ self.collect_attr_proc_macro(item, fn_ident);
} else if attr.has_name(sym::proc_macro) {
- self.collect_bang_proc_macro(item);
+ self.collect_bang_proc_macro(item, fn_ident);
};
let prev_in_root = mem::replace(&mut self.in_root, false);
@@ -278,7 +282,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
let proc_macro = Ident::new(sym::proc_macro, span);
- let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
+ let krate = cx.item(span, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, proc_macro));
let bridge = Ident::new(sym::bridge, span);
let client = Ident::new(sym::client, span);
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index ba63b18..a1ee53b 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -43,9 +43,8 @@ pub fn inject(
let item = cx.item(
span,
- Ident::new(name, ident_span),
thin_vec![cx.attr_word(sym::macro_use, span)],
- ast::ItemKind::ExternCrate(None),
+ ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)),
);
krate.items.insert(0, item);
@@ -68,7 +67,6 @@ pub fn inject(
// Inject the relevant crate's prelude.
let use_item = cx.item(
span,
- Ident::empty(),
thin_vec![cx.attr_word(sym::prelude_import, span)],
ast::ItemKind::Use(ast::UseTree {
prefix: cx.path(span, import_path),
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 239f865..1cef4f9 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -51,21 +51,28 @@ pub(crate) fn expand_test_case(
return vec![];
}
};
- item = item.map(|mut item| {
- let test_path_symbol = Symbol::intern(&item_path(
- // skip the name of the root module
- &ecx.current_expansion.module.mod_path[1..],
- &item.ident,
- ));
- item.vis = ast::Visibility {
- span: item.vis.span,
- kind: ast::VisibilityKind::Public,
- tokens: None,
- };
- item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
- item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
- item
- });
+
+ // `#[test_case]` is valid on functions, consts, and statics. Only modify
+ // the item in those cases.
+ match &mut item.kind {
+ ast::ItemKind::Fn(box ast::Fn { ident, .. })
+ | ast::ItemKind::Const(box ast::ConstItem { ident, .. })
+ | ast::ItemKind::Static(box ast::StaticItem { ident, .. }) => {
+ ident.span = ident.span.with_ctxt(sp.ctxt());
+ let test_path_symbol = Symbol::intern(&item_path(
+ // skip the name of the root module
+ &ecx.current_expansion.module.mod_path[1..],
+ ident,
+ ));
+ item.vis = ast::Visibility {
+ span: item.vis.span,
+ kind: ast::VisibilityKind::Public,
+ tokens: None,
+ };
+ item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
+ }
+ _ => {}
+ }
let ret = if is_stmt {
Annotatable::Stmt(P(ecx.stmt_item(item.span, item)))
@@ -162,17 +169,17 @@ pub(crate) fn expand_test_or_bench(
let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span());
let attr_sp = cx.with_def_site_ctxt(attr_sp);
- let test_id = Ident::new(sym::test, attr_sp);
+ let test_ident = Ident::new(sym::test, attr_sp);
// creates test::$name
- let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
+ let test_path = |name| cx.path(ret_ty_sp, vec![test_ident, Ident::from_str_and_span(name, sp)]);
// creates test::ShouldPanic::$name
let should_panic_path = |name| {
cx.path(
sp,
vec![
- test_id,
+ test_ident,
Ident::from_str_and_span("ShouldPanic", sp),
Ident::from_str_and_span(name, sp),
],
@@ -184,7 +191,7 @@ pub(crate) fn expand_test_or_bench(
cx.path(
sp,
vec![
- test_id,
+ test_ident,
Ident::from_str_and_span("TestType", sp),
Ident::from_str_and_span(name, sp),
],
@@ -223,7 +230,7 @@ pub(crate) fn expand_test_or_bench(
// super::$test_fn(b)
cx.expr_call(
ret_ty_sp,
- cx.expr_path(cx.path(sp, vec![item.ident])),
+ cx.expr_path(cx.path(sp, vec![fn_.ident])),
thin_vec![cx.expr_ident(sp, b)],
),
],
@@ -249,7 +256,7 @@ pub(crate) fn expand_test_or_bench(
// $test_fn()
cx.expr_call(
ret_ty_sp,
- cx.expr_path(cx.path(sp, vec![item.ident])),
+ cx.expr_path(cx.path(sp, vec![fn_.ident])),
ThinVec::new(),
), // )
],
@@ -262,15 +269,14 @@ pub(crate) fn expand_test_or_bench(
let test_path_symbol = Symbol::intern(&item_path(
// skip the name of the root module
&cx.current_expansion.module.mod_path[1..],
- &item.ident,
+ &fn_.ident,
));
- let location_info = get_location_info(cx, &item);
+ let location_info = get_location_info(cx, &fn_);
let mut test_const =
cx.item(
sp,
- Ident::new(item.ident.name, sp),
thin_vec![
// #[cfg(test)]
cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
@@ -283,6 +289,7 @@ pub(crate) fn expand_test_or_bench(
ast::ItemKind::Const(
ast::ConstItem {
defaultness: ast::Defaultness::Final,
+ ident: Ident::new(fn_.ident.name, sp),
generics: ast::Generics::default(),
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
define_opaque: None,
@@ -380,7 +387,8 @@ pub(crate) fn expand_test_or_bench(
});
// extern crate test
- let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
+ let test_extern =
+ cx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident));
debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
@@ -434,8 +442,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
.emit();
}
-fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) {
- let span = item.ident.span;
+fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize, usize, usize) {
+ let span = fn_.ident.span;
let (source_file, lo_line, lo_col, hi_line, hi_col) =
cx.sess.source_map().span_to_location_info(span);
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 768b459..56a67b0 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -134,7 +134,8 @@ fn visit_item(&mut self, item: &mut P<ast::Item>) {
if let Some(name) = get_test_name(&item) {
debug!("this is a test item");
- let test = Test { span: item.span, ident: item.ident, name };
+ // `unwrap` is ok because only functions, consts, and static should reach here.
+ let test = Test { span: item.span, ident: item.kind.ident().unwrap(), name };
self.tests.push(test);
}
@@ -142,19 +143,12 @@ fn visit_item(&mut self, item: &mut P<ast::Item>) {
// mods or tests inside of functions will break things
if let ast::ItemKind::Mod(
_,
+ _,
ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _),
) = item.kind
{
let prev_tests = mem::take(&mut self.tests);
- walk_item_kind(
- &mut item.kind,
- item.span,
- item.id,
- &mut item.ident,
- &mut item.vis,
- (),
- self,
- );
+ walk_item_kind(&mut item.kind, item.span, item.id, &mut item.vis, (), self);
self.add_test_cases(item.id, span, prev_tests);
} else {
// But in those cases, we emit a lint to warn the user of these missing tests.
@@ -181,9 +175,9 @@ fn visit_item(&mut self, i: &'a ast::Item) {
}
fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType {
- match item.kind {
- ast::ItemKind::Fn(..) => {
- rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name))
+ match &item.kind {
+ ast::ItemKind::Fn(fn_) => {
+ rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(fn_.ident.name))
}
_ => EntryPointType::None,
}
@@ -295,7 +289,7 @@ fn generate_test_harness(
fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
let sp = cx.def_site;
let ecx = &cx.ext_cx;
- let test_id = Ident::new(sym::test, sp);
+ let test_ident = Ident::new(sym::test, sp);
let runner_name = match cx.panic_strategy {
PanicStrategy::Unwind => "test_main_static",
@@ -303,10 +297,9 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
};
// test::test_main_static(...)
- let mut test_runner = cx
- .test_runner
- .clone()
- .unwrap_or_else(|| ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)]));
+ let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| {
+ ecx.path(sp, vec![test_ident, Ident::from_str_and_span(runner_name, sp)])
+ });
test_runner.span = sp;
@@ -317,7 +310,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
// extern crate test
let test_extern_stmt = ecx.stmt_item(
sp,
- ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)),
+ ecx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)),
);
// #[rustc_main]
@@ -340,23 +333,24 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty));
let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
let defaultness = ast::Defaultness::Final;
+
+ // Honor the reexport_test_harness_main attribute
+ let main_ident = match cx.reexport_test_harness_main {
+ Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
+ None => Ident::new(sym::main, sp),
+ };
+
let main = ast::ItemKind::Fn(Box::new(ast::Fn {
defaultness,
sig,
+ ident: main_ident,
generics: ast::Generics::default(),
contract: None,
body: Some(main_body),
define_opaque: None,
}));
- // Honor the reexport_test_harness_main attribute
- let main_id = match cx.reexport_test_harness_main {
- Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
- None => Ident::new(sym::main, sp),
- };
-
let main = P(ast::Item {
- ident: main_id,
attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr],
id: ast::DUMMY_NODE_ID,
kind: main,
diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml
index 1ec99eb..ee5de8b 100644
--- a/compiler/rustc_codegen_cranelift/.cirrus.yml
+++ b/compiler/rustc_codegen_cranelift/.cirrus.yml
@@ -1,20 +1,21 @@
-task:
- name: freebsd
- freebsd_instance:
- image: freebsd-13-2-release-amd64
- setup_rust_script:
- - pkg install -y git-tiny binutils
- - curl https://sh.rustup.rs -sSf --output rustup.sh
- - sh rustup.sh --default-toolchain none -y --profile=minimal
- target_cache:
- folder: build/cg_clif
- prepare_script:
- - . $HOME/.cargo/env
- - ./y.sh prepare
- test_script:
- - . $HOME/.cargo/env
- # Disabling incr comp reduces cache size and incr comp doesn't save as much
- # on CI anyway.
- - export CARGO_BUILD_INCREMENTAL=false
- # Skip rand as it fails on FreeBSD due to rust-random/rand#1355
- - ./y.sh test --skip-test test.rust-random/rand
+# FIXME re-enable once https://github.com/rust-lang/rust/issues/134863 is fixed.
+# task:
+# name: freebsd
+# freebsd_instance:
+# image: freebsd-13-2-release-amd64
+# setup_rust_script:
+# - pkg install -y git-tiny binutils
+# - curl https://sh.rustup.rs -sSf --output rustup.sh
+# - sh rustup.sh --default-toolchain none -y --profile=minimal
+# target_cache:
+# folder: build/cg_clif
+# prepare_script:
+# - . $HOME/.cargo/env
+# - ./y.sh prepare
+# test_script:
+# - . $HOME/.cargo/env
+# # Disabling incr comp reduces cache size and incr comp doesn't save as much
+# # on CI anyway.
+# - export CARGO_BUILD_INCREMENTAL=false
+# # Skip rand as it fails on FreeBSD due to rust-random/rand#1355
+# - ./y.sh test --skip-test test.rust-random/rand
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md b/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md
deleted file mode 100644
index c70ba8f..0000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# github-release
-
-An action used to publish GitHub releases for `wasmtime`.
-
-As of the time of this writing there's a few actions floating around which
-perform github releases but they all tend to have their set of drawbacks.
-Additionally nothing handles deleting releases which we need for our rolling
-`dev` release.
-
-To handle all this this action rolls-its-own implementation using the
-actions/toolkit repository and packages published there. These run in a Docker
-container and take various inputs to orchestrate the release from the build.
-
-More comments can be found in `main.js`.
-
-Testing this is really hard. If you want to try though run `npm install` and
-then `node main.js`. You'll have to configure a bunch of env vars though to get
-anything reasonably working.
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml b/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml
deleted file mode 100644
index 36e5209..0000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-name: 'rustc_codegen_cranelift github releases'
-description: 'rustc_codegen_cranelift github releases'
-inputs:
- token:
- description: ''
- required: true
- files:
- description: ''
- required: true
-runs:
- using: 'node16'
- main: 'main.js'
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js b/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js
deleted file mode 100644
index 1eb2b7f..0000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js
+++ /dev/null
@@ -1,162 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-const core = require('@actions/core');
-const path = require("path");
-const fs = require("fs");
-const github = require('@actions/github');
-const glob = require('glob');
-
-function sleep(milliseconds) {
- return new Promise(resolve => setTimeout(resolve, milliseconds))
-}
-
-async function runOnce() {
- // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*`
- const files = core.getInput('files');
- const token = core.getInput('token');
- const slug = process.env.GITHUB_REPOSITORY;
- const owner = slug.split('/')[0];
- const repo = slug.split('/')[1];
- const sha = process.env.GITHUB_SHA;
- let name = 'dev';
- if (process.env.GITHUB_REF.startsWith('refs/tags/v')) {
- name = process.env.GITHUB_REF.substring(10);
- }
-
- core.info(`files: ${files}`);
- core.info(`name: ${name}`);
- core.info(`token: ${token}`);
-
- const octokit = github.getOctokit(token);
-
- // For the `dev` release we may need to update the tag to point to the new
- // commit on this branch. All other names should already have tags associated
- // with them.
- if (name == 'dev') {
- let tag = null;
- try {
- tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name });
- core.info(`found existing tag`);
- console.log("tag: ", JSON.stringify(tag.data, null, 2));
- } catch (e) {
- // ignore if this tag doesn't exist
- core.info(`no existing tag found`);
- }
-
- if (tag === null || tag.data.object.sha !== sha) {
- core.info(`updating existing tag or creating new one`);
-
- try {
- core.info(`updating dev tag`);
- await octokit.rest.git.updateRef({
- owner,
- repo,
- ref: 'tags/dev',
- sha,
- force: true,
- });
- } catch (e) {
- console.log("ERROR: ", JSON.stringify(e.response, null, 2));
- core.info(`creating dev tag`);
- try {
- await octokit.rest.git.createRef({
- owner,
- repo,
- ref: 'refs/tags/dev',
- sha,
- });
- } catch (e) {
- // we might race with others, so assume someone else has created the
- // tag by this point.
- console.log("failed to create tag: ", JSON.stringify(e.response, null, 2));
- }
- }
-
- console.log("double-checking tag is correct");
- tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name });
- if (tag.data.object.sha !== sha) {
- console.log("tag: ", JSON.stringify(tag.data, null, 2));
- throw new Error("tag didn't work");
- }
- } else {
- core.info(`existing tag works`);
- }
- }
-
- // Delete a previous release
- try {
- core.info(`fetching release`);
- let release = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag: name });
- console.log("found release: ", JSON.stringify(release.data, null, 2));
- await octokit.rest.repos.deleteRelease({
- owner,
- repo,
- release_id: release.data.id,
- });
- console.log("deleted release");
- } catch (e) {
- console.log("ERROR: ", JSON.stringify(e, null, 2));
- }
-
- console.log("creating a release");
- let release = await octokit.rest.repos.createRelease({
- owner,
- repo,
- tag_name: name,
- prerelease: name === 'dev',
- });
-
- // Delete all assets from a previous run
- for (const asset of release.data.assets) {
- console.log(`deleting prior asset ${asset.id}`);
- await octokit.rest.repos.deleteReleaseAsset({
- owner,
- repo,
- asset_id: asset.id,
- });
- }
-
- // Upload all the relevant assets for this release as just general blobs.
- for (const file of glob.sync(files)) {
- const size = fs.statSync(file).size;
- const name = path.basename(file);
- core.info(`upload ${file}`);
- await octokit.rest.repos.uploadReleaseAsset({
- data: fs.createReadStream(file),
- headers: { 'content-length': size, 'content-type': 'application/octet-stream' },
- name,
- url: release.data.upload_url,
- });
- }
-}
-
-async function run() {
- const retries = 10;
- for (let i = 0; i < retries; i++) {
- try {
- await runOnce();
- break;
- } catch (e) {
- if (i === retries - 1)
- throw e;
- logError(e);
- console.log("RETRYING after 10s");
- await sleep(10000)
- }
- }
-}
-
-function logError(e) {
- console.log("ERROR: ", e.message);
- try {
- console.log(JSON.stringify(e, null, 2));
- } catch (e) {
- // ignore json errors for now
- }
- console.log(e.stack);
-}
-
-run().catch(err => {
- logError(err);
- core.setFailed(err.message);
-});
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json
deleted file mode 100644
index dd3b2a0..0000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json
+++ /dev/null
@@ -1,571 +0,0 @@
-{
- "name": "rustc_codegen_cranelift-github-release",
- "version": "0.0.0",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "name": "rustc_codegen_cranelift-github-release",
- "version": "0.0.0",
- "dependencies": {
- "@actions/core": "^1.9.1",
- "@actions/github": "^5.1.0",
- "glob": "^7.1.5"
- }
- },
- "node_modules/@actions/core": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
- "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
- "dependencies": {
- "@actions/http-client": "^2.0.1",
- "uuid": "^8.3.2"
- }
- },
- "node_modules/@actions/github": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
- "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
- "dependencies": {
- "@actions/http-client": "^2.0.1",
- "@octokit/core": "^3.6.0",
- "@octokit/plugin-paginate-rest": "^2.17.0",
- "@octokit/plugin-rest-endpoint-methods": "^5.13.0"
- }
- },
- "node_modules/@actions/http-client": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
- "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
- "dependencies": {
- "tunnel": "^0.0.6"
- }
- },
- "node_modules/@octokit/auth-token": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
- "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
- "dependencies": {
- "@octokit/types": "^6.0.3"
- }
- },
- "node_modules/@octokit/core": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
- "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
- "dependencies": {
- "@octokit/auth-token": "^2.4.4",
- "@octokit/graphql": "^4.5.8",
- "@octokit/request": "^5.6.3",
- "@octokit/request-error": "^2.0.5",
- "@octokit/types": "^6.0.3",
- "before-after-hook": "^2.2.0",
- "universal-user-agent": "^6.0.0"
- }
- },
- "node_modules/@octokit/endpoint": {
- "version": "6.0.12",
- "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
- "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
- "dependencies": {
- "@octokit/types": "^6.0.3",
- "is-plain-object": "^5.0.0",
- "universal-user-agent": "^6.0.0"
- }
- },
- "node_modules/@octokit/graphql": {
- "version": "4.8.0",
- "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
- "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
- "dependencies": {
- "@octokit/request": "^5.6.0",
- "@octokit/types": "^6.0.3",
- "universal-user-agent": "^6.0.0"
- }
- },
- "node_modules/@octokit/openapi-types": {
- "version": "12.11.0",
- "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
- "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
- },
- "node_modules/@octokit/plugin-paginate-rest": {
- "version": "2.21.3",
- "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
- "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
- "dependencies": {
- "@octokit/types": "^6.40.0"
- },
- "peerDependencies": {
- "@octokit/core": ">=2"
- }
- },
- "node_modules/@octokit/plugin-rest-endpoint-methods": {
- "version": "5.16.2",
- "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
- "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
- "dependencies": {
- "@octokit/types": "^6.39.0",
- "deprecation": "^2.3.1"
- },
- "peerDependencies": {
- "@octokit/core": ">=3"
- }
- },
- "node_modules/@octokit/request": {
- "version": "5.6.3",
- "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
- "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
- "dependencies": {
- "@octokit/endpoint": "^6.0.1",
- "@octokit/request-error": "^2.1.0",
- "@octokit/types": "^6.16.1",
- "is-plain-object": "^5.0.0",
- "node-fetch": "^2.6.7",
- "universal-user-agent": "^6.0.0"
- }
- },
- "node_modules/@octokit/request-error": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
- "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
- "dependencies": {
- "@octokit/types": "^6.0.3",
- "deprecation": "^2.0.0",
- "once": "^1.4.0"
- }
- },
- "node_modules/@octokit/types": {
- "version": "6.41.0",
- "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
- "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
- "dependencies": {
- "@octokit/openapi-types": "^12.11.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "node_modules/before-after-hook": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
- "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
- },
- "node_modules/deprecation": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
- "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "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"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/is-plain-object": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
- "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/node-fetch": {
- "version": "2.6.7",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
- "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
- "dependencies": {
- "whatwg-url": "^5.0.0"
- },
- "engines": {
- "node": "4.x || >=6.0.0"
- },
- "peerDependencies": {
- "encoding": "^0.1.0"
- },
- "peerDependenciesMeta": {
- "encoding": {
- "optional": true
- }
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
- },
- "node_modules/tunnel": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
- "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
- "engines": {
- "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
- }
- },
- "node_modules/universal-user-agent": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
- "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
- },
- "node_modules/uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
- },
- "node_modules/whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dependencies": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
- }
- },
- "dependencies": {
- "@actions/core": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
- "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
- "requires": {
- "@actions/http-client": "^2.0.1",
- "uuid": "^8.3.2"
- }
- },
- "@actions/github": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
- "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
- "requires": {
- "@actions/http-client": "^2.0.1",
- "@octokit/core": "^3.6.0",
- "@octokit/plugin-paginate-rest": "^2.17.0",
- "@octokit/plugin-rest-endpoint-methods": "^5.13.0"
- }
- },
- "@actions/http-client": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
- "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
- "requires": {
- "tunnel": "^0.0.6"
- }
- },
- "@octokit/auth-token": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
- "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
- "requires": {
- "@octokit/types": "^6.0.3"
- }
- },
- "@octokit/core": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
- "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
- "requires": {
- "@octokit/auth-token": "^2.4.4",
- "@octokit/graphql": "^4.5.8",
- "@octokit/request": "^5.6.3",
- "@octokit/request-error": "^2.0.5",
- "@octokit/types": "^6.0.3",
- "before-after-hook": "^2.2.0",
- "universal-user-agent": "^6.0.0"
- }
- },
- "@octokit/endpoint": {
- "version": "6.0.12",
- "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
- "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
- "requires": {
- "@octokit/types": "^6.0.3",
- "is-plain-object": "^5.0.0",
- "universal-user-agent": "^6.0.0"
- }
- },
- "@octokit/graphql": {
- "version": "4.8.0",
- "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
- "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
- "requires": {
- "@octokit/request": "^5.6.0",
- "@octokit/types": "^6.0.3",
- "universal-user-agent": "^6.0.0"
- }
- },
- "@octokit/openapi-types": {
- "version": "12.11.0",
- "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
- "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
- },
- "@octokit/plugin-paginate-rest": {
- "version": "2.21.3",
- "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
- "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
- "requires": {
- "@octokit/types": "^6.40.0"
- }
- },
- "@octokit/plugin-rest-endpoint-methods": {
- "version": "5.16.2",
- "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
- "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
- "requires": {
- "@octokit/types": "^6.39.0",
- "deprecation": "^2.3.1"
- }
- },
- "@octokit/request": {
- "version": "5.6.3",
- "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
- "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
- "requires": {
- "@octokit/endpoint": "^6.0.1",
- "@octokit/request-error": "^2.1.0",
- "@octokit/types": "^6.16.1",
- "is-plain-object": "^5.0.0",
- "node-fetch": "^2.6.7",
- "universal-user-agent": "^6.0.0"
- }
- },
- "@octokit/request-error": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
- "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
- "requires": {
- "@octokit/types": "^6.0.3",
- "deprecation": "^2.0.0",
- "once": "^1.4.0"
- }
- },
- "@octokit/types": {
- "version": "6.41.0",
- "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
- "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
- "requires": {
- "@octokit/openapi-types": "^12.11.0"
- }
- },
- "balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "before-after-hook": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
- "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
- },
- "deprecation": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
- "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
- },
- "glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "is-plain-object": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
- "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
- },
- "minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "node-fetch": {
- "version": "2.6.7",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
- "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
- "requires": {
- "whatwg-url": "^5.0.0"
- }
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "requires": {
- "wrappy": "1"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
- },
- "tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
- },
- "tunnel": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
- "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
- },
- "universal-user-agent": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
- "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
- },
- "uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
- },
- "webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
- },
- "whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "requires": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
- }
- }
-}
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json
deleted file mode 100644
index d9c23f8..0000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name": "rustc_codegen_cranelift-github-release",
- "version": "0.0.0",
- "license": "Apache-2.0 WITH LLVM-exception",
- "main": "main.js",
- "dependencies": {
- "@actions/core": "^1.9.1",
- "@actions/github": "^5.1.0",
- "glob": "^7.1.5"
- }
-}
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
index 30dc5cb..6ad041a 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
@@ -25,7 +25,10 @@
- os: ubuntu-latest
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- - os: macos-latest
+ - os: ubuntu-24.04-arm
+ env:
+ TARGET_TRIPLE: aarch64-unknown-linux-gnu
+ - os: macos-13
env:
TARGET_TRIPLE: x86_64-apple-darwin
- os: macos-latest
@@ -56,13 +59,6 @@
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: rustup set default-host x86_64-pc-windows-gnu
- - name: Use x86_64 compiler on macOS
- if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
- run: rustup set default-host x86_64-apple-darwin
-
- - name: Prepare dependencies
- run: ./y.sh prepare
-
- name: Build
run: ./y.sh build --sysroot none
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index 61a4c12..6fd288d 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -53,13 +53,12 @@
- os: ubuntu-latest
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- - os: macos-latest
- env:
- TARGET_TRIPLE: x86_64-apple-darwin
- - os: ubuntu-latest
+ - os: ubuntu-24.04-arm
env:
TARGET_TRIPLE: aarch64-unknown-linux-gnu
- apt_deps: gcc-aarch64-linux-gnu qemu-user
+ - os: macos-13
+ env:
+ TARGET_TRIPLE: x86_64-apple-darwin
- os: macos-latest
env:
TARGET_TRIPLE: aarch64-apple-darwin
@@ -95,10 +94,6 @@
if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: rustup set default-host x86_64-pc-windows-gnu
- - name: Use x86_64 compiler on macOS
- if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
- run: rustup set default-host x86_64-apple-darwin
-
- name: Install toolchain and emulator
if: matrix.apt_deps != null
run: |
@@ -170,9 +165,6 @@
sudo apt update
sudo apt install -y hyperfine
- - name: Prepare dependencies
- run: ./y.sh prepare
-
- name: Build
run: ./y.sh build --sysroot none
@@ -192,7 +184,10 @@
- os: ubuntu-22.04
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- - os: macos-latest
+ - os: ubuntu-24.04-arm
+ env:
+ TARGET_TRIPLE: aarch64-unknown-linux-gnu
+ - os: macos-13
env:
TARGET_TRIPLE: x86_64-apple-darwin
- os: macos-latest
@@ -218,13 +213,6 @@
if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: rustup set default-host x86_64-pc-windows-gnu
- - name: Use x86_64 compiler on macOS
- if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
- run: rustup set default-host x86_64-apple-darwin
-
- - name: Prepare dependencies
- run: ./y.sh prepare
-
- name: Build backend
run: ./y.sh build --sysroot none
@@ -273,12 +261,9 @@
rmdir artifacts/ # verify all artifacts are represented in release/
ls -R release/
- - run: npm install --production
- working-directory: .github/actions/github-release
-
- - name: Publish Release
- uses: ./.github/actions/github-release
- with:
- files: "release/*"
- token: ${{ github.token }}
- continue-on-error: true
+ - name: Publish release
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ gh release delete --cleanup-tag -y dev || true
+ gh release create --target $GITHUB_SHA --prerelease dev release/*
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
index 70c214c..9253ab9 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
@@ -22,9 +22,6 @@
path: build/cg_clif
key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }}
- - name: Prepare dependencies
- run: ./y.sh prepare
-
- name: Test
run: ./scripts/test_bootstrap.sh
@@ -50,8 +47,5 @@
sudo apt update
sudo apt install -y ripgrep
- - name: Prepare dependencies
- run: ./y.sh prepare
-
- name: Test
run: ./scripts/test_rustc_tests.sh
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index 491646c..68bd93a 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -1,42 +1,41 @@
{
"editor.formatOnSave": true,
-
// in case rustc.source is disabled for performance reasons; disable the errors about this
- "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"],
+ "rust-analyzer.diagnostics.disabled": [
+ "unresolved-extern-crate",
+ "unresolved-macro-call"
+ ],
"rust-analyzer.rustc.source": "discover",
"rust-analyzer.imports.granularity.enforce": true,
"rust-analyzer.imports.granularity.group": "module",
"rust-analyzer.imports.prefix": "crate",
- "rust-analyzer.cargo.features": ["unstable-features"],
+ "rust-analyzer.cargo.features": [
+ "unstable-features"
+ ],
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
"./build_system/Cargo.toml",
{
+ "sysroot_src": "./build/stdlib/library",
"crates": [
{
"root_module": "./example/mini_core.rs",
- "edition": "2018",
+ "edition": "2015",
"deps": [],
"cfg": [],
},
{
"root_module": "./example/mini_core_hello_world.rs",
- "edition": "2018",
- "deps": [{ "crate": 0, "name": "mini_core" }],
+ "edition": "2015",
+ "deps": [
+ {
+ "crate": 0,
+ "name": "mini_core"
+ }
+ ],
"cfg": [],
},
{
- "root_module": "./example/mod_bench.rs",
- "edition": "2018",
- "deps": [],
- "cfg": [],
- },
- ]
- },
- {
- "sysroot_src": "./build/stdlib/library",
- "crates": [
- {
"root_module": "./example/std_example.rs",
"edition": "2015",
"deps": [],
diff --git a/compiler/rustc_codegen_cranelift/.zed/settings.json b/compiler/rustc_codegen_cranelift/.zed/settings.json
index e93bed3..4338a34 100644
--- a/compiler/rustc_codegen_cranelift/.zed/settings.json
+++ b/compiler/rustc_codegen_cranelift/.zed/settings.json
@@ -5,7 +5,10 @@
"initialization_options": {
"diagnostics": {
// in case rustc.source is disabled for performance reasons; disable the errors about this
- "disabled": ["unresolved-extern-crate", "unresolved-macro-call"]
+ "disabled": [
+ "unresolved-extern-crate",
+ "unresolved-macro-call"
+ ]
},
"rustc": {
"source": "discover"
@@ -18,22 +21,25 @@
"prefix": "crate"
},
"cargo": {
- "features": ["unstable-features"]
+ "features": [
+ "unstable-features"
+ ]
},
"linkedProjects": [
"./Cargo.toml",
"./build_system/Cargo.toml",
{
+ "sysroot_src": "./build/stdlib/library",
"crates": [
{
"root_module": "./example/mini_core.rs",
- "edition": "2018",
+ "edition": "2015",
"deps": [],
"cfg": []
},
{
"root_module": "./example/mini_core_hello_world.rs",
- "edition": "2018",
+ "edition": "2015",
"deps": [
{
"crate": 0,
@@ -43,17 +49,6 @@
"cfg": []
},
{
- "root_module": "./example/mod_bench.rs",
- "edition": "2018",
- "deps": [],
- "cfg": []
- }
- ]
- },
- {
- "sysroot_src": "./build/stdlib/library",
- "crates": [
- {
"root_module": "./example/std_example.rs",
"edition": "2015",
"deps": [],
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index ca66ec5..e5f1896 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -42,27 +42,43 @@
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
-name = "cranelift-bforest"
-version = "0.116.1"
+name = "cranelift-assembler-x64"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e15d04a0ce86cb36ead88ad68cf693ffd6cda47052b9e0ac114bc47fd9cd23c4"
+checksum = "3e4b56ebe316895d3fa37775d0a87b0c889cc933f5c8b253dbcc7c7bcb7fe7e4"
+dependencies = [
+ "cranelift-assembler-x64-meta",
+]
+
+[[package]]
+name = "cranelift-assembler-x64-meta"
+version = "0.118.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95cabbc01dfbd7dcd6c329ca44f0212910309c221797ac736a67a5bc8857fe1b"
+
+[[package]]
+name = "cranelift-bforest"
+version = "0.118.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76ffe46df300a45f1dc6f609dc808ce963f0e3a2e971682c479a2d13e3b9b8ef"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-bitset"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c6e3969a7ce267259ce244b7867c5d3bc9e65b0a87e81039588dfdeaede9f34"
+checksum = "b265bed7c51e1921fdae6419791d31af77d33662ee56d7b0fa0704dc8d231cab"
[[package]]
name = "cranelift-codegen"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c22032c4cb42558371cf516bb47f26cdad1819d3475c133e93c49f50ebf304e"
+checksum = "e606230a7e3a6897d603761baee0d19f88d077f17b996bb5089488a29ae96e41"
dependencies = [
"bumpalo",
+ "cranelift-assembler-x64",
"cranelift-bforest",
"cranelift-bitset",
"cranelift-codegen-meta",
@@ -71,7 +87,7 @@
"cranelift-entity",
"cranelift-isle",
"gimli",
- "hashbrown 0.14.5",
+ "hashbrown",
"log",
"regalloc2",
"rustc-hash",
@@ -82,42 +98,43 @@
[[package]]
name = "cranelift-codegen-meta"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c904bc71c61b27fc57827f4a1379f29de64fe95653b620a3db77d59655eee0b8"
+checksum = "8a63bffafc23bc60969ad528e138788495999d935f0adcfd6543cb151ca8637d"
dependencies = [
+ "cranelift-assembler-x64",
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40180f5497572f644ce88c255480981ae2ec1d7bb4d8e0c0136a13b87a2f2ceb"
+checksum = "af50281b67324b58e843170a6a5943cf6d387c06f7eeacc9f5696e4ab7ae7d7e"
[[package]]
name = "cranelift-control"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d132c6d0bd8a489563472afc171759da0707804a65ece7ceb15a8c6d7dd5ef"
+checksum = "8c20c1b38d1abfbcebb0032e497e71156c0e3b8dcb3f0a92b9863b7bcaec290c"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b2d0d9618275474fbf679dd018ac6e009acbd6ae6850f6a67be33fb3b00b323"
+checksum = "0c2c67d95507c51b4a1ff3f3555fe4bfec36b9e13c1b684ccc602736f5d5f4a2"
dependencies = [
"cranelift-bitset",
]
[[package]]
name = "cranelift-frontend"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fac41e16729107393174b0c9e3730fb072866100e1e64e80a1a963b2e484d57"
+checksum = "4e002691cc69c38b54fc7ec93e5be5b744f627d027031d991cc845d1d512d0ce"
dependencies = [
"cranelift-codegen",
"log",
@@ -127,15 +144,15 @@
[[package]]
name = "cranelift-isle"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ca20d576e5070044d0a72a9effc2deacf4d6aa650403189d8ea50126483944d"
+checksum = "e93588ed1796cbcb0e2ad160403509e2c5d330d80dd6e0014ac6774c7ebac496"
[[package]]
name = "cranelift-jit"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e65c42755a719b09662b00c700daaf76cc35d5ace1f5c002ad404b591ff1978"
+checksum = "17f6682f0b193d6b7873cc8e7ed67e8776a8a26f50eeabf88534e9be618b9a03"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -153,9 +170,9 @@
[[package]]
name = "cranelift-module"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d55612bebcf16ff7306c8a6f5bdb6d45662b8aa1ee058ecce8807ad87db719b"
+checksum = "ff19784c6de05116e63e6a34791012bd927b2a4eac56233039c46f1b6a4edac8"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -164,9 +181,9 @@
[[package]]
name = "cranelift-native"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8dee82f3f1f2c4cba9177f1cc5e350fe98764379bcd29340caa7b01f85076c7"
+checksum = "e5b09bdd6407bf5d89661b80cf926ce731c9e8cc184bf49102267a2369a8358e"
dependencies = [
"cranelift-codegen",
"libc",
@@ -175,9 +192,9 @@
[[package]]
name = "cranelift-object"
-version = "0.116.1"
+version = "0.118.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aad5a6d3e379493c3f8b35dc61c93d0bf5f27003bbe20614e0200b0ec372ef52"
+checksum = "685e8661a30d1cb69509f589ac643adeee79c5f63c0da316431b9fad29e6d3b4"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -228,12 +245,6 @@
[[package]]
name = "hashbrown"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
-
-[[package]]
-name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
@@ -248,7 +259,7 @@
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [
"equivalent",
- "hashbrown 0.15.2",
+ "hashbrown",
]
[[package]]
@@ -295,7 +306,7 @@
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"crc32fast",
- "hashbrown 0.15.2",
+ "hashbrown",
"indexmap",
"memchr",
]
@@ -326,7 +337,7 @@
dependencies = [
"allocator-api2",
"bumpalo",
- "hashbrown 0.15.2",
+ "hashbrown",
"log",
"rustc-hash",
"smallvec",
@@ -425,9 +436,9 @@
[[package]]
name = "wasmtime-jit-icache-coherence"
-version = "29.0.1"
+version = "31.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec5e8552e01692e6c2e5293171704fed8abdec79d1a6995a0870ab190e5747d1"
+checksum = "a54f6c6c7e9d7eeee32dfcc10db7f29d505ee7dd28d00593ea241d5f70698e64"
dependencies = [
"anyhow",
"cfg-if",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index 670d6f4..08b60de 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,12 +8,12 @@
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { version = "0.116.0", default-features = false, features = ["std", "unwind", "all-native-arch"] }
-cranelift-frontend = { version = "0.116.0" }
-cranelift-module = { version = "0.116.0" }
-cranelift-native = { version = "0.116.0" }
-cranelift-jit = { version = "0.116.0", optional = true }
-cranelift-object = { version = "0.116.0" }
+cranelift-codegen = { version = "0.118.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
+cranelift-frontend = { version = "0.118.0" }
+cranelift-module = { version = "0.118.0" }
+cranelift-native = { version = "0.118.0" }
+cranelift-jit = { version = "0.118.0", optional = true }
+cranelift-object = { version = "0.118.0" }
target-lexicon = "0.13"
gimli = { version = "0.31", default-features = false, features = ["write"] }
object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
@@ -24,12 +24,12 @@
[patch.crates-io]
# Uncomment to use an unreleased version of cranelift
-#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
+#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
# Uncomment to use local checkout of cranelift
#cranelift-codegen = { path = "../wasmtime/cranelift/codegen" }
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 18a840f..28edb57 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -49,13 +49,13 @@
```bash
$ git clone https://github.com/rust-lang/rustc_codegen_cranelift
$ cd rustc_codegen_cranelift
-$ ./y.sh prepare
$ ./y.sh build
```
To run the test suite replace the last command with:
```bash
+$ ./y.sh prepare # only needs to be run the first time
$ ./test.sh
```
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index 11f73bd..ba5cc9a 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -91,6 +91,13 @@ pub(crate) const fn source_dir(&self) -> RelPath {
fn verify_checksum(&self, dirs: &Dirs) {
let download_dir = self.download_dir(dirs);
+ if !download_dir.exists() {
+ eprintln!(
+ "Missing directory {download_dir}: Please run ./y.sh prepare to download.",
+ download_dir = download_dir.display(),
+ );
+ std::process::exit(1);
+ }
let actual_hash = format!("{:016x}", hash_dir(&download_dir));
if actual_hash != self.content_hash {
eprintln!(
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index ea7e94c..122b541 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -1,5 +1,4 @@
use std::ffi::OsStr;
-use std::fs;
use std::path::PathBuf;
use std::process::Command;
@@ -126,9 +125,9 @@ const fn jit_bin(config: &'static str, source: &'static str, args: &'static str)
static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_SRC, "portable-simd_target");
-static LIBCORE_TESTS_SRC: RelPath = RelPath::build("coretests");
+static SYSROOT_TESTS_SRC: RelPath = RelPath::build("sysroot_tests");
-static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "coretests_target");
+static SYSROOT_TESTS: CargoProject = CargoProject::new(&SYSROOT_TESTS_SRC, "sysroot_tests_target");
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
TestCase::custom("test.rust-random/rand", &|runner| {
@@ -147,28 +146,24 @@ const fn jit_bin(config: &'static str, source: &'static str, args: &'static str)
spawn_and_wait(build_cmd);
}
}),
- TestCase::custom("test.libcore", &|runner| {
+ TestCase::custom("test.sysroot", &|runner| {
apply_patches(
&runner.dirs,
- "coretests",
- &runner.stdlib_source.join("library/coretests"),
- &LIBCORE_TESTS_SRC.to_path(&runner.dirs),
+ "sysroot_tests",
+ &runner.stdlib_source.join("library"),
+ &SYSROOT_TESTS_SRC.to_path(&runner.dirs),
);
- let source_lockfile = runner.dirs.source_dir.join("patches/coretests-lock.toml");
- let target_lockfile = LIBCORE_TESTS_SRC.to_path(&runner.dirs).join("Cargo.lock");
- fs::copy(source_lockfile, target_lockfile).unwrap();
-
- LIBCORE_TESTS.clean(&runner.dirs);
+ SYSROOT_TESTS.clean(&runner.dirs);
if runner.is_native {
- let mut test_cmd = LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs);
- test_cmd.arg("--").arg("-q");
+ let mut test_cmd = SYSROOT_TESTS.test(&runner.target_compiler, &runner.dirs);
+ test_cmd.args(["-p", "coretests", "-p", "alloctests", "--", "-q"]);
spawn_and_wait(test_cmd);
} else {
eprintln!("Cross-Compiling: Not running tests");
- let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
- build_cmd.arg("--tests");
+ let mut build_cmd = SYSROOT_TESTS.build(&runner.target_compiler, &runner.dirs);
+ build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]);
spawn_and_wait(build_cmd);
}
}),
@@ -330,10 +325,8 @@ fn new(
target_compiler.rustflags.extend(rustflags_from_env("RUSTFLAGS"));
target_compiler.rustdocflags.extend(rustflags_from_env("RUSTDOCFLAGS"));
- let jit_supported = use_unstable_features
- && is_native
- && target_compiler.triple.contains("x86_64")
- && !target_compiler.triple.contains("windows");
+ let jit_supported =
+ use_unstable_features && is_native && !target_compiler.triple.contains("windows");
Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source }
}
@@ -374,21 +367,7 @@ fn run_testsuite(&self, tests: &[TestCase]) {
TestCaseCmd::JitBin { source, args } => {
let mut jit_cmd = self.rustc_command([
"-Zunstable-options",
- "-Cllvm-args=mode=jit",
- "-Cprefer-dynamic",
- source,
- "--cfg",
- "jit",
- ]);
- if !args.is_empty() {
- jit_cmd.env("CG_CLIF_JIT_ARGS", args);
- }
- spawn_and_wait(jit_cmd);
-
- eprintln!("[JIT-lazy] {testname}");
- let mut jit_cmd = self.rustc_command([
- "-Zunstable-options",
- "-Cllvm-args=mode=jit-lazy",
+ "-Cllvm-args=jit-mode",
"-Cprefer-dynamic",
source,
"--cfg",
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index f578cbe..714414f 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -35,6 +35,6 @@
testsuite.extended_sysroot
test.rust-random/rand
-test.libcore
+test.sysroot
test.regex
test.portable-simd
diff --git a/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md
index 135a51c..dbe3610 100644
--- a/compiler/rustc_codegen_cranelift/docs/usage.md
+++ b/compiler/rustc_codegen_cranelift/docs/usage.md
@@ -38,14 +38,7 @@
or
```bash
-$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
-```
-
-There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
-first called.
-
-```bash
-$ $cg_clif_dir/dist/cargo-clif lazy-jit
+$ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs
```
## Shell
@@ -54,7 +47,7 @@
```bash
function jit_naked() {
- echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic
+ echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode-Cprefer-dynamic
}
function jit() {
diff --git a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs
index 25bfe54..de9a3d5 100644
--- a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs
+++ b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs
@@ -6,16 +6,25 @@
#![feature(gen_blocks)]
fn foo() -> impl Iterator<Item = u32> {
- gen { yield 42; for x in 3..6 { yield x } }
+ gen {
+ yield 42;
+ for x in 3..6 {
+ yield x
+ }
+ }
}
fn moved() -> impl Iterator<Item = u32> {
let mut x = "foo".to_string();
gen move {
yield 42;
- if x == "foo" { return }
+ if x == "foo" {
+ return;
+ }
x.clear();
- for x in 3..6 { yield x }
+ for x in 3..6 {
+ yield x
+ }
}
}
@@ -32,5 +41,4 @@ fn main() {
let mut iter = moved();
assert_eq!(iter.next(), Some(42));
assert_eq!(iter.next(), None);
-
}
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch
similarity index 84%
rename from compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
rename to compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch
index 4a06dc3..16c8488 100644
--- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch
@@ -10,20 +10,20 @@
library/core/tests/atomic.rs | 4 ---
4 files changed, 4 insertions(+), 50 deletions(-)
-diff --git a/tests/lib.rs b/tests/lib.rs
+diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs
index 1e336bf..35e6f54 100644
---- a/tests/lib.rs
-+++ b/tests/lib.rs
+--- a/coretests/tests/lib.rs
++++ b/coretests/tests/lib.rs
@@ -2,5 +2,4 @@
// tidy-alphabetical-start
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
#![cfg_attr(test, feature(cfg_match))]
#![feature(alloc_layout_extra)]
#![feature(array_chunks)]
-diff --git a/tests/atomic.rs b/tests/atomic.rs
+diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs
index b735957..ea728b6 100644
---- a/tests/atomic.rs
-+++ b/tests/atomic.rs
+--- a/coretests/tests/atomic.rs
++++ b/coretests/tests/atomic.rs
@@ -185,10 +185,6 @@ fn atomic_alignment() {
assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
#[cfg(target_has_atomic = "64")]
diff --git a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch
deleted file mode 100644
index f5ae66c..0000000
--- a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Fri, 3 Dec 2021 12:16:30 +0100
-Subject: [PATCH] Disable long running tests
-
----
- library/core/tests/slice.rs | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/tests/slice.rs b/tests/slice.rs
-index 8402833..84592e0 100644
---- a/tests/slice.rs
-+++ b/tests/slice.rs
-@@ -1809,6 +1809,7 @@ fn sort_unstable() {
- }
- }
-
-+/*
- #[test]
- #[cfg(not(target_arch = "wasm32"))]
- #[cfg_attr(miri, ignore)] // Miri is too slow
-@@ -1914,6 +1915,7 @@ fn select_nth_unstable() {
- v.select_nth_unstable(0);
- assert!(v == [0xDEADBEEF]);
- }
-+*/
-
- #[test]
- #[should_panic(expected = "index 0 greater than length of slice")]
-@@ -2462,6 +2462,7 @@ take_tests! {
- #[cfg(not(miri))] // unused in Miri
- const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
-
-+/*
- // can't be a constant due to const mutability rules
- #[cfg(not(miri))] // unused in Miri
- macro_rules! empty_max_mut {
-@@ -2485,6 +2486,7 @@ take_tests! {
- (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
- (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
- }
-+*/
-
- #[test]
- fn test_slice_from_ptr_range() {
---
-2.26.2.7.g19db9cfb68
-
diff --git a/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch
new file mode 100644
index 0000000..357b8d3
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch
@@ -0,0 +1,105 @@
+From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Fri, 3 Dec 2021 12:16:30 +0100
+Subject: [PATCH] Disable long running tests
+
+---
+ library/coretests/tests/slice.rs | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/coretests/tests/slice.rs b/coretests/tests/slice.rs
+index 8402833..84592e0 100644
+--- a/coretests/tests/slice.rs
++++ b/coretests/tests/slice.rs
+@@ -1809,6 +1809,7 @@ fn sort_unstable() {
+ }
+ }
+
++/*
+ #[test]
+ #[cfg(not(target_arch = "wasm32"))]
+ #[cfg_attr(miri, ignore)] // Miri is too slow
+@@ -1914,6 +1915,7 @@ fn select_nth_unstable() {
+ v.select_nth_unstable(0);
+ assert!(v == [0xDEADBEEF]);
+ }
++*/
+
+ #[test]
+ #[should_panic(expected = "index 0 greater than length of slice")]
+@@ -2462,6 +2462,7 @@ take_tests! {
+ #[cfg(not(miri))] // unused in Miri
+ const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
+
++/*
+ // can't be a constant due to const mutability rules
+ #[cfg(not(miri))] // unused in Miri
+ macro_rules! empty_max_mut {
+@@ -2485,6 +2486,7 @@ take_tests! {
+ (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
+ (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
+ }
++*/
+
+ #[test]
+ fn test_slice_from_ptr_range() {
+diff --git a/alloctests/tests/sort/tests.rs b/alloctests/tests/sort/tests.rs
+index d321f8d..8b2040a 100644
+--- a/alloctests/tests/sort/tests.rs
++++ b/alloctests/tests/sort/tests.rs
+@@ -1,3 +1,5 @@
++#![cfg(any())]
++
+ use std::cell::Cell;
+ use std::cmp::Ordering;
+ use std::fmt::Debug;
+diff --git a/alloctests/tests/str.rs b/alloctests/tests/str.rs
+index 906fa2d..b82fa99 100644
+--- a/alloctests/tests/str.rs
++++ b/alloctests/tests/str.rs
+@@ -2234,7 +2234,7 @@ fn const_str_ptr() {
+ const C: *const u8 = B as *const u8;
+
+ // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
+- #[cfg(not(miri))]
++ #[cfg(any())]
+ {
+ let foo = &A as *const u8;
+ assert_eq!(foo, C);
+diff --git a/alloctests/tests/task.rs b/alloctests/tests/task.rs
+index 390dec1..87df6e6 100644
+--- a/alloctests/tests/task.rs
++++ b/alloctests/tests/task.rs
+@@ -4,7 +4,7 @@ use alloc::task::{LocalWake, Wake};
+ use core::task::{LocalWaker, Waker};
+
+ #[test]
+-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
+ fn test_waker_will_wake_clone() {
+ struct NoopWaker;
+
+@@ -20,7 +20,7 @@ fn test_waker_will_wake_clone() {
+ }
+
+ #[test]
+-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
+ fn test_local_waker_will_wake_clone() {
+ struct NoopWaker;
+
+diff --git a/alloctests/tests/vec.rs b/alloctests/tests/vec.rs
+index f430d97..cfbd3cb 100644
+--- a/alloctests/tests/vec.rs
++++ b/alloctests/tests/vec.rs
+@@ -762,6 +762,7 @@ fn test_drain_inclusive_range() {
+ }
+
+ #[test]
++#[ignore]
+ fn test_drain_max_vec_size() {
+ let mut v = Vec::<()>::with_capacity(usize::MAX);
+ unsafe {
+--
+2.26.2.7.g19db9cfb68
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
deleted file mode 100644
index 34249ea..0000000
--- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 175d52c5e1779764b66777db1e6f172c2dc365ff Mon Sep 17 00:00:00 2001
-From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
-Date: Fri, 9 Aug 2024 15:44:51 +0000
-Subject: [PATCH] Disable f16 and f128 in compiler-builtins
-
----
- library/liballoc/Cargo.toml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/library/liballoc/Cargo.toml b/library/liballoc/Cargo.toml
-index 7165c3e48af..968552ad435 100644
---- a/library/alloc/Cargo.toml
-+++ b/library/alloc/Cargo.toml
-@@ -11,7 +11,7 @@ test = { path = "../test" }
- bench = false
-
- [dependencies]
- core = { path = "../core", public = true }
--compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std', 'no-f16-f128'] }
-
- [features]
- compiler-builtins-mem = ['compiler_builtins/mem']
---
-2.34.1
-
diff --git a/compiler/rustc_codegen_cranelift/patches/coretests-lock.toml b/compiler/rustc_codegen_cranelift/patches/coretests-lock.toml
deleted file mode 100644
index af8f28a..0000000
--- a/compiler/rustc_codegen_cranelift/patches/coretests-lock.toml
+++ /dev/null
@@ -1,35 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "coretests"
-version = "0.0.0"
-dependencies = [
- "rand",
- "rand_xorshift",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-
-[[package]]
-name = "rand_xorshift"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
-dependencies = [
- "rand_core",
-]
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index 481903c..ceff15b 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,4 +1,4 @@
[toolchain]
-channel = "nightly-2025-02-15"
+channel = "nightly-2025-03-30"
components = ["rust-src", "rustc-dev", "llvm-tools"]
profile = "minimal"
diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml
index f31fa9c..35c9266 100644
--- a/compiler/rustc_codegen_cranelift/rustfmt.toml
+++ b/compiler/rustc_codegen_cranelift/rustfmt.toml
@@ -1,7 +1,3 @@
-ignore = [
- "example/gen_block_iterate.rs", # uses edition 2024
-]
-
# Matches rustfmt.toml of rustc
style_edition = "2024"
use_small_heuristics = "Max"
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
index ebbb687..e6c63bf 100644
--- a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
@@ -50,19 +50,7 @@ fn main() {
.chain([
"--".to_string(),
"-Zunstable-options".to_string(),
- "-Cllvm-args=mode=jit".to_string(),
- ])
- .collect()
- }
- Some("lazy-jit") => {
- rustflags.push("-Cprefer-dynamic".to_owned());
- args.remove(0);
- IntoIterator::into_iter(["rustc".to_string()])
- .chain(args)
- .chain([
- "--".to_string(),
- "-Zunstable-options".to_string(),
- "-Cllvm-args=mode=jit-lazy".to_string(),
+ "-Cllvm-args=jit-mode".to_string(),
])
.collect()
}
diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
index 0252d5b..4595063 100755
--- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
@@ -4,7 +4,7 @@
pushd $(dirname "$0")/../
RUSTC="$(pwd)/dist/rustc-clif"
popd
-PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
+PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=jit-mode -Cprefer-dynamic $0
#*/
//! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh
index 3552829..152c243 100755
--- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh
@@ -64,7 +64,7 @@
cg_clif=$(pwd)
pushd ../rust
git fetch origin master
- git checkout "$RUST_VERS"
+ git -c advice.detachedHead=false checkout "$RUST_VERS"
"$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust
popd
git merge sync_from_rust -m "Sync from rust $RUST_VERS"
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index 54f6baf..ca6426f 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -43,8 +43,31 @@
# disabled bootstrap will crash trying to copy llvm tools for the bootstrap
# compiler.
llvm-tools = false
+std-features = ["panic-unwind", "compiler-builtins-no-f16-f128"]
EOF
+
+cat <<EOF | git apply -
+diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
+index cf4ef4ee310..fe78560fcaf 100644
+--- a/src/bootstrap/src/core/config/config.rs
++++ b/src/bootstrap/src/core/config/config.rs
+@@ -3138,13 +3138,6 @@ fn parse_download_ci_llvm(
+ );
+ }
+
+- if b && self.is_running_on_ci {
+- // On CI, we must always rebuild LLVM if there were any modifications to it
+- panic!(
+- "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
+- );
+- }
+-
+ // If download-ci-llvm=true we also want to check that CI llvm is available
+ b && llvm::is_ci_llvm_available_for_target(self, asserts)
+ }
+EOF
+
popd
# Allow the testsuite to use llvm tools
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 55230a0..95a4302 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -27,7 +27,6 @@
git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
git checkout -- tests/ui/proc-macro/pretty-print-hack/
git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs
-rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
# missing features
# ================
@@ -57,7 +56,6 @@
rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported
rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes
rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo
-rm tests/ui/simd-abi-checks.rs # vector types >128bits not yet supported
# requires LTO
rm -r tests/run-make/cdylib
@@ -120,6 +118,7 @@
rm tests/ui/consts/issue-33537.rs # same
rm tests/ui/consts/const-mut-refs-crate.rs # same
rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift
+rm tests/ui/abi/simd-abi-checks-avx.rs # attempts to declare function with two different signatures
# doesn't work due to the way the rustc test suite is invoked.
# should work when using ./x.py test the way it is intended
@@ -136,7 +135,6 @@
# ============
rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort
-rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold
# bugs in the test suite
# ======================
@@ -150,48 +148,8 @@
rm tests/ui/process/process-panic-after-fork.rs # same
cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist
-cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/
-# prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by
-# rustdoc-clif
cat <<EOF | git apply -
-diff --git a/tests/run-make/tools.mk b/tests/run-make/tools.mk
-index ea06b620c4c..b969d0009c6 100644
---- a/tests/run-make/tools.mk
-+++ b/tests/run-make/tools.mk
-@@ -9,7 +9,7 @@ RUSTC_ORIGINAL := \$(RUSTC)
- BARE_RUSTC := \$(HOST_RPATH_ENV) '\$(RUSTC)'
- BARE_RUSTDOC := \$(HOST_RPATH_ENV) '\$(RUSTDOC)'
- RUSTC := \$(BARE_RUSTC) --out-dir \$(TMPDIR) -L \$(TMPDIR) \$(RUSTFLAGS) -Ainternal_features
--RUSTDOC := \$(BARE_RUSTDOC) -L \$(TARGET_RPATH_DIR)
-+RUSTDOC := \$(BARE_RUSTDOC)
- ifdef RUSTC_LINKER
- RUSTC := \$(RUSTC) -Clinker='\$(RUSTC_LINKER)'
- RUSTDOC := \$(RUSTDOC) -Clinker='\$(RUSTC_LINKER)'
-diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
-index 9607ff02f96..b7d97caf9a2 100644
---- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
-+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
-@@ -34,7 +34,6 @@ pub fn bare() -> Self {
- #[track_caller]
- pub fn new() -> Self {
- let mut cmd = setup_common();
-- cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR"));
- Self { cmd }
- }
-
-diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
-index e7ae773ffa1d3..04bc2d7787da7 100644
---- a/src/tools/compiletest/src/runtest/run_make.rs
-+++ b/src/tools/compiletest/src/runtest/run_make.rs
-@@ -329,7 +329,6 @@ impl TestCx<'_> {
- .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
- .arg("--edition=2021")
- .arg(&self.testpaths.file.join("rmake.rs"))
-- .arg("-Cprefer-dynamic")
- // Provide necessary library search paths for rustc.
- .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap());
-
diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs
index 30387af428c..f7895b12961 100644
--- a/tests/run-make/linker-warning/rmake.rs
@@ -205,7 +163,19 @@
regex::escape(run_make_support::build_root().to_str().unwrap()),
"/build-root",
)
- .run();
+ .normalize(r#""[^"]*\/symbols.o""#, "\\"/symbols.o\\"")
+diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
+index 073116933bd..c3e4578204d 100644
+--- a/src/tools/compiletest/src/runtest/run_make.rs
++++ b/src/tools/compiletest/src/runtest/run_make.rs
+@@ -109,7 +109,6 @@ pub(super) fn run_rmake_test(&self) {
+ // library or compiler features. Here, we force the stage 0 rustc to consider itself as
+ // a stable-channel compiler via \`RUSTC_BOOTSTRAP=-1\` to prevent *any* unstable
+ // library/compiler usages, even if stage 0 rustc is *actually* a nightly rustc.
+- .env("RUSTC_BOOTSTRAP", "-1")
+ .arg("-o")
+ .arg(&recipe_bin)
+ // Specify library search paths for \`run_make_support\`.
EOF
echo "[TEST] rustc test suite"
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 125a920..adaa754 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -729,8 +729,10 @@ fn codegen_stmt<'tcx>(
let to_ty = fx.monomorphize(to_ty);
fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
- ty.builtin_deref(true)
- .is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
+ ty.builtin_deref(true).is_some_and(|pointee_ty| {
+ fx.tcx
+ .type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized())
+ })
}
if is_wide_ptr(fx, from_ty) {
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 766278d..abe2972 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -71,7 +71,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
},
ty::FnPtr(..) => pointer_ty(tcx),
ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
- if has_ptr_meta(tcx, *pointee_ty) {
+ if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) {
return None;
} else {
pointer_ty(tcx)
@@ -91,7 +91,7 @@ fn clif_pair_type_from_ty<'tcx>(
(clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?)
}
ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
- if has_ptr_meta(tcx, *pointee_ty) {
+ if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) {
(pointer_ty(tcx), pointer_ty(tcx))
} else {
return None;
@@ -101,20 +101,6 @@ fn clif_pair_type_from_ty<'tcx>(
})
}
-/// Is a pointer to this type a wide ptr?
-pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
- if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) {
- return false;
- }
-
- let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized());
- match tail.kind() {
- ty::Foreign(..) => false,
- ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
- _ => bug!("unexpected unsized tail: {:?}", tail),
- }
-}
-
pub(crate) fn codegen_icmp_imm(
fx: &mut FunctionCx<'_, '_, '_>,
intcc: IntCC,
diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs
index d784f6e..d328b33 100644
--- a/compiler/rustc_codegen_cranelift/src/config.rs
+++ b/compiler/rustc_codegen_cranelift/src/config.rs
@@ -1,21 +1,10 @@
-/// The mode to use for compilation.
-#[derive(Copy, Clone, Debug)]
-pub enum CodegenMode {
- /// AOT compile the crate. This is the default.
- Aot,
- /// JIT compile and execute the crate.
- Jit,
- /// JIT compile and execute the crate, but only compile functions the first time they are used.
- JitLazy,
-}
-
/// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars.
#[derive(Clone, Debug)]
pub struct BackendConfig {
/// Should the crate be AOT compiled or JIT executed.
///
- /// Defaults to AOT compilation. Can be set using `-Cllvm-args=mode=...`.
- pub codegen_mode: CodegenMode,
+ /// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`.
+ pub jit_mode: bool,
/// When JIT mode is enable pass these arguments to the program.
///
@@ -27,7 +16,7 @@ impl BackendConfig {
/// Parse the configuration passed in using `-Cllvm-args`.
pub fn from_opts(opts: &[String]) -> Result<Self, String> {
let mut config = BackendConfig {
- codegen_mode: CodegenMode::Aot,
+ jit_mode: false,
jit_args: match std::env::var("CG_CLIF_JIT_ARGS") {
Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
Err(std::env::VarError::NotPresent) => vec![],
@@ -43,20 +32,9 @@ pub fn from_opts(opts: &[String]) -> Result<Self, String> {
// testing cg_clif.
continue;
}
- if let Some((name, value)) = opt.split_once('=') {
- match name {
- "mode" => {
- config.codegen_mode = match value {
- "aot" => CodegenMode::Aot,
- "jit" => CodegenMode::Jit,
- "jit-lazy" => CodegenMode::JitLazy,
- _ => return Err(format!("Unknown codegen mode `{}`", value)),
- };
- }
- _ => return Err(format!("Unknown option `{}`", name)),
- }
- } else {
- return Err(format!("Invalid option `{}`", opt));
+ match &**opt {
+ "jit-mode" => config.jit_mode = true,
+ _ => return Err(format!("Unknown option `{}`", opt)),
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
index 017d778..25b922c 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
@@ -6,7 +6,7 @@
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use crate::{DebugContext, FullyMonomorphizedLayoutCx, has_ptr_meta};
+use crate::{DebugContext, FullyMonomorphizedLayoutCx};
#[derive(Default)]
pub(crate) struct TypeDebugContext<'tcx> {
@@ -129,7 +129,7 @@ fn pointer_type<'tcx>(
let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true);
- if !has_ptr_meta(tcx, ptr_type) {
+ if !tcx.type_has_metadata(ptr_type, ty::TypingEnv::fully_monomorphized()) {
let pointer_type_id =
self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type);
let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id);
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index fb7864a..444dc44 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -331,7 +331,7 @@ fn produce_final_output_artifacts(
}
fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
- let isa = crate::build_isa(sess);
+ let isa = crate::build_isa(sess, false);
let mut builder =
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 57c88f4..41f8bb9 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -1,75 +1,27 @@
//! The JIT driver uses [`cranelift_jit`] to JIT execute programs without writing any object
//! files.
-use std::cell::RefCell;
use std::ffi::CString;
use std::os::raw::{c_char, c_int};
-use std::sync::{Mutex, OnceLock, mpsc};
-use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use cranelift_jit::{JITBuilder, JITModule};
use rustc_codegen_ssa::CrateInfo;
use rustc_middle::mir::mono::MonoItem;
use rustc_session::Session;
use rustc_span::sym;
+use crate::CodegenCx;
use crate::debuginfo::TypeDebugContext;
use crate::prelude::*;
use crate::unwind_module::UnwindModule;
-use crate::{CodegenCx, CodegenMode};
-struct JitState {
- jit_module: UnwindModule<JITModule>,
-}
-
-thread_local! {
- static LAZY_JIT_STATE: RefCell<Option<JitState>> = const { RefCell::new(None) };
-}
-
-/// The Sender owned by the rustc thread
-static GLOBAL_MESSAGE_SENDER: OnceLock<Mutex<mpsc::Sender<UnsafeMessage>>> = OnceLock::new();
-
-/// A message that is sent from the jitted runtime to the rustc thread.
-/// Senders are responsible for upholding `Send` semantics.
-enum UnsafeMessage {
- /// Request that the specified `Instance` be lazily jitted.
- ///
- /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after
- /// this message is sent.
- JitFn {
- instance_ptr: *const Instance<'static>,
- trampoline_ptr: *const u8,
- tx: mpsc::Sender<*const u8>,
- },
-}
-unsafe impl Send for UnsafeMessage {}
-
-impl UnsafeMessage {
- /// Send the message.
- fn send(self) {
- thread_local! {
- /// The Sender owned by the local thread
- static LOCAL_MESSAGE_SENDER: mpsc::Sender<UnsafeMessage> =
- GLOBAL_MESSAGE_SENDER
- .get().unwrap()
- .lock().unwrap()
- .clone();
- }
- LOCAL_MESSAGE_SENDER.with(|sender| {
- sender.send(self).expect("rustc thread hung up before lazy JIT request was sent")
- })
- }
-}
-
-fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>, CodegenCx) {
+fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
- let isa = crate::build_isa(tcx.sess);
+ let isa = crate::build_isa(tcx.sess, true);
let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
- jit_builder.hotswap(hotswap);
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
- jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
@@ -79,7 +31,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>
(jit_module, cx)
}
-pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<String>) -> ! {
+pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
if !tcx.sess.opts.output_types.should_codegen() {
tcx.dcx().fatal("JIT mode doesn't work with `cargo check`");
}
@@ -88,8 +40,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
tcx.dcx().fatal("can't jit non-executable crate");
}
- let (mut jit_module, mut cx) =
- create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy));
+ let (mut jit_module, mut cx) = create_jit_module(tcx);
let mut cached_context = Context::new();
let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
@@ -105,21 +56,15 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
super::predefine_mono_items(tcx, &mut jit_module, &mono_items);
for (mono_item, _) in mono_items {
match mono_item {
- MonoItem::Fn(inst) => match codegen_mode {
- CodegenMode::Aot => unreachable!(),
- CodegenMode::Jit => {
- codegen_and_compile_fn(
- tcx,
- &mut cx,
- &mut cached_context,
- &mut jit_module,
- inst,
- );
- }
- CodegenMode::JitLazy => {
- codegen_shim(tcx, &mut cached_context, &mut jit_module, inst)
- }
- },
+ MonoItem::Fn(inst) => {
+ codegen_and_compile_fn(
+ tcx,
+ &mut cx,
+ &mut cached_context,
+ &mut jit_module,
+ inst,
+ );
+ }
MonoItem::Static(def_id) => {
crate::constant::codegen_static(tcx, &mut jit_module, def_id);
}
@@ -161,41 +106,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id);
- LAZY_JIT_STATE.with(|lazy_jit_state| {
- let mut lazy_jit_state = lazy_jit_state.borrow_mut();
- assert!(lazy_jit_state.is_none());
- *lazy_jit_state = Some(JitState { jit_module });
- });
-
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
unsafe { ::std::mem::transmute(finalized_start) };
- let (tx, rx) = mpsc::channel();
- GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap();
+ let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
- // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages
- // (eg to lazily JIT further functions as required)
- std::thread::spawn(move || {
- let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
+ // Push a null pointer as a terminating argument. This is required by POSIX and
+ // useful as some dynamic linkers use it as a marker to jump over.
+ argv.push(std::ptr::null());
- // Push a null pointer as a terminating argument. This is required by POSIX and
- // useful as some dynamic linkers use it as a marker to jump over.
- argv.push(std::ptr::null());
-
- let ret = f(args.len() as c_int, argv.as_ptr());
- std::process::exit(ret);
- });
-
- // Handle messages
- loop {
- match rx.recv().unwrap() {
- // lazy JIT compilation request - compile requested instance and return pointer to result
- UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => {
- tx.send(jit_fn(instance_ptr, trampoline_ptr))
- .expect("jitted runtime hung up before response to lazy JIT request was sent");
- }
- }
- }
+ let ret = f(args.len() as c_int, argv.as_ptr());
+ std::process::exit(ret);
}
pub(crate) fn codegen_and_compile_fn<'tcx>(
@@ -227,58 +148,6 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
});
}
-extern "C" fn clif_jit_fn(
- instance_ptr: *const Instance<'static>,
- trampoline_ptr: *const u8,
-) -> *const u8 {
- // send the JIT request to the rustc thread, with a channel for the response
- let (tx, rx) = mpsc::channel();
- UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }.send();
-
- // block on JIT compilation result
- rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request")
-}
-
-fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 {
- rustc_middle::ty::tls::with(|tcx| {
- // lift is used to ensure the correct lifetime for instance.
- let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();
-
- LAZY_JIT_STATE.with(|lazy_jit_state| {
- let mut lazy_jit_state = lazy_jit_state.borrow_mut();
- let lazy_jit_state = lazy_jit_state.as_mut().unwrap();
- let jit_module = &mut lazy_jit_state.jit_module;
-
- let name = tcx.symbol_name(instance).name;
- let sig = crate::abi::get_function_sig(
- tcx,
- jit_module.target_config().default_call_conv,
- instance,
- );
- let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
-
- let current_ptr = jit_module.module.read_got_entry(func_id);
-
- // If the function's GOT entry has already been updated to point at something other
- // than the shim trampoline, don't re-jit but just return the new pointer instead.
- // This does not need synchronization as this code is executed only by a sole rustc
- // thread.
- if current_ptr != trampoline_ptr {
- return current_ptr;
- }
-
- jit_module.module.prepare_for_function_redefine(func_id).unwrap();
-
- let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
- codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
-
- assert!(cx.global_asm.is_empty());
- jit_module.finalize_definitions();
- jit_module.module.get_finalized_function(func_id)
- })
- })
-}
-
fn dep_symbol_lookup_fn(
sess: &Session,
crate_info: CrateInfo,
@@ -326,57 +195,3 @@ fn dep_symbol_lookup_fn(
None
})
}
-
-fn codegen_shim<'tcx>(
- tcx: TyCtxt<'tcx>,
- cached_context: &mut Context,
- module: &mut UnwindModule<JITModule>,
- inst: Instance<'tcx>,
-) {
- let pointer_type = module.target_config().pointer_type();
-
- let name = tcx.symbol_name(inst).name;
- let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
- let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
-
- let instance_ptr = Box::into_raw(Box::new(inst));
-
- let jit_fn = module
- .declare_function(
- "__clif_jit_fn",
- Linkage::Import,
- &Signature {
- call_conv: module.target_config().default_call_conv,
- params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)],
- returns: vec![AbiParam::new(pointer_type)],
- },
- )
- .unwrap();
-
- let context = cached_context;
- context.clear();
- let trampoline = &mut context.func;
- trampoline.signature = sig.clone();
-
- let mut builder_ctx = FunctionBuilderContext::new();
- let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx);
-
- let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func);
- let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func);
- let sig_ref = trampoline_builder.func.import_signature(sig);
-
- let entry_block = trampoline_builder.create_block();
- trampoline_builder.append_block_params_for_function_params(entry_block);
- let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec();
-
- trampoline_builder.switch_to_block(entry_block);
- let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
- let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn);
- let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]);
- let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
- let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
- let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
- trampoline_builder.ins().return_(&ret_vals);
-
- module.define_function(func_id, context).unwrap();
-}
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 310b226..fbc33a6 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -612,6 +612,15 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
generated_asm.push_str(".att_syntax\n");
}
+ if self.arch == InlineAsmArch::AArch64 {
+ for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features {
+ if feature.name == sym::neon {
+ continue;
+ }
+ writeln!(generated_asm, ".arch_extension {}", feature.name).unwrap();
+ }
+ }
+
// The actual inline asm
for piece in self.template {
match piece {
@@ -652,6 +661,20 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
.emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier)
.unwrap(),
},
+ InlineAsmArch::AArch64 => match reg {
+ InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
+ // rustc emits v0 rather than q0
+ reg.emit(
+ &mut generated_asm,
+ InlineAsmArch::AArch64,
+ Some(modifier.unwrap_or('q')),
+ )
+ .unwrap()
+ }
+ _ => reg
+ .emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier)
+ .unwrap(),
+ },
_ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(),
}
}
@@ -665,6 +688,15 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
}
generated_asm.push('\n');
+ if self.arch == InlineAsmArch::AArch64 {
+ for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features {
+ if feature.name == sym::neon {
+ continue;
+ }
+ writeln!(generated_asm, ".arch_extension no{}", feature.name).unwrap();
+ }
+ }
+
if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
generated_asm.push_str(".intel_syntax noprefix\n");
}
@@ -809,7 +841,13 @@ fn save_register(
}
InlineAsmArch::AArch64 => {
generated_asm.push_str(" str ");
- reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
+ match reg {
+ InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
+ // rustc emits v0 rather than q0
+ reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap()
+ }
+ _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(),
+ }
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
}
InlineAsmArch::RiscV64 => {
@@ -851,7 +889,13 @@ fn restore_register(
}
InlineAsmArch::AArch64 => {
generated_asm.push_str(" ldr ");
- reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
+ match reg {
+ InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
+ // rustc emits v0 rather than q0
+ reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap()
+ }
+ _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(),
+ }
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
}
InlineAsmArch::RiscV64 => {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 720a0d8..eb0dfbb 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -54,6 +54,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
);
}
+ "llvm.fptosi.sat.v4i32.v4f32" => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+ fx.bcx.ins().fcvt_to_sint_sat(types::I32, lane)
+ });
+ }
+
_ => {
fx.tcx
.dcx()
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
index 4c59c81..387c87d 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -1,5 +1,9 @@
//! Emulate AArch64 LLVM intrinsics
+use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_target::asm::*;
+
+use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner};
use crate::intrinsics::*;
use crate::prelude::*;
@@ -17,7 +21,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
fx.bcx.ins().fence();
}
- "llvm.aarch64.neon.ld1x4.v16i8.p0i8" => {
+ "llvm.aarch64.neon.ld1x4.v16i8.p0" => {
intrinsic_args!(fx, args => (ptr); intrinsic);
let ptr = ptr.load_scalar(fx);
@@ -49,6 +53,121 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
});
}
+ "llvm.aarch64.neon.fcvtns.v4i32.v4f32" => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ // Note: Using inline asm instead of fcvt_to_sint as the latter rounds to zero rather than to nearest
+
+ let a_ptr = a.force_stack(fx).0.get_addr(fx);
+ let res_place = CPlace::new_stack_slot(fx, ret.layout());
+ let res_ptr = res_place.to_ptr().get_addr(fx);
+
+ codegen_inline_asm_inner(
+ fx,
+ &[InlineAsmTemplatePiece::String(
+ "ldr q0, [x0]
+ fcvtns v0.4s, v0.4s
+ str q0, [x1]"
+ .into(),
+ )],
+ &[
+ CInlineAsmOperand::In {
+ reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+ AArch64InlineAsmReg::x0,
+ )),
+ value: a_ptr,
+ },
+ CInlineAsmOperand::In {
+ reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+ AArch64InlineAsmReg::x1,
+ )),
+ value: res_ptr,
+ },
+ ],
+ InlineAsmOptions::NOSTACK,
+ );
+ let res = res_place.to_cvalue(fx);
+ ret.write_cvalue_transmute(fx, res);
+ }
+
+ "llvm.aarch64.neon.frecpe.v4f32" => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ let a_ptr = a.force_stack(fx).0.get_addr(fx);
+ let res_place = CPlace::new_stack_slot(fx, ret.layout());
+ let res_ptr = res_place.to_ptr().get_addr(fx);
+
+ codegen_inline_asm_inner(
+ fx,
+ &[InlineAsmTemplatePiece::String(
+ "ldr q0, [x0]
+ frecpe v0.4s, v0.4s
+ str q0, [x1]"
+ .into(),
+ )],
+ &[
+ CInlineAsmOperand::In {
+ reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+ AArch64InlineAsmReg::x0,
+ )),
+ value: a_ptr,
+ },
+ CInlineAsmOperand::In {
+ reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+ AArch64InlineAsmReg::x1,
+ )),
+ value: res_ptr,
+ },
+ ],
+ InlineAsmOptions::NOSTACK,
+ );
+ let res = res_place.to_cvalue(fx);
+ ret.write_cvalue_transmute(fx, res);
+ }
+
+ "llvm.aarch64.neon.frecps.v4f32" => {
+ intrinsic_args!(fx, args => (a, b); intrinsic);
+
+ let a_ptr = a.force_stack(fx).0.get_addr(fx);
+ let b_ptr = b.force_stack(fx).0.get_addr(fx);
+ let res_place = CPlace::new_stack_slot(fx, ret.layout());
+ let res_ptr = res_place.to_ptr().get_addr(fx);
+
+ codegen_inline_asm_inner(
+ fx,
+ &[InlineAsmTemplatePiece::String(
+ "ldr q0, [x0]
+ ldr q1, [x1]
+ frecps v0.4s, v0.4s, v1.4s
+ str q0, [x2]"
+ .into(),
+ )],
+ &[
+ CInlineAsmOperand::In {
+ reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+ AArch64InlineAsmReg::x0,
+ )),
+ value: a_ptr,
+ },
+ CInlineAsmOperand::In {
+ reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+ AArch64InlineAsmReg::x1,
+ )),
+ value: b_ptr,
+ },
+ CInlineAsmOperand::In {
+ reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+ AArch64InlineAsmReg::x2,
+ )),
+ value: res_ptr,
+ },
+ ],
+ InlineAsmOptions::NOSTACK,
+ );
+ let res = res_place.to_cvalue(fx);
+ ret.write_cvalue_transmute(fx, res);
+ }
+
_ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v")
|| intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") =>
{
@@ -134,7 +253,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
}
let res = CValue::by_val(
fx.bcx.ins().uextend(types::I32, res_val),
- fx.layout_of(fx.tcx.types.u32),
+ fx.layout_of(fx.tcx.types.i32),
);
ret.write_cvalue(fx, res);
}
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index ab3386a..e7afaff 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -42,7 +42,6 @@
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};
use rustc_codegen_ssa::CodegenResults;
-use rustc_codegen_ssa::back::versioned_llvm_target;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -214,15 +213,14 @@ fn codegen_crate(
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
.unwrap_or_else(|err| tcx.sess.dcx().fatal(err))
});
- match config.codegen_mode {
- CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module),
- CodegenMode::Jit | CodegenMode::JitLazy => {
- #[cfg(feature = "jit")]
- driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args);
+ if config.jit_mode {
+ #[cfg(feature = "jit")]
+ driver::jit::run_jit(tcx, config.jit_args);
- #[cfg(not(feature = "jit"))]
- tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
- }
+ #[cfg(not(feature = "jit"))]
+ tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
+ } else {
+ driver::aot::run_aot(tcx, metadata, need_metadata_module)
}
}
@@ -247,21 +245,19 @@ fn enable_verifier(sess: &Session) -> bool {
}
fn target_triple(sess: &Session) -> target_lexicon::Triple {
- // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS.
- // See <https://github.com/bytecodealliance/target-lexicon/pull/113>
- match versioned_llvm_target(sess).parse() {
+ match sess.target.llvm_target.parse() {
Ok(triple) => triple,
Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)),
}
}
-fn build_isa(sess: &Session) -> Arc<dyn TargetIsa + 'static> {
+fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
use target_lexicon::BinaryFormat;
let target_triple = crate::target_triple(sess);
let mut flags_builder = settings::builder();
- flags_builder.enable("is_pic").unwrap();
+ flags_builder.set("is_pic", if jit { "false" } else { "true" }).unwrap();
let enable_verifier = if enable_verifier(sess) { "true" } else { "false" };
flags_builder.set("enable_verifier", enable_verifier).unwrap();
flags_builder.set("regalloc_checker", enable_verifier).unwrap();
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index f44e245..2a4d1e3 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -395,8 +395,12 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>,
) -> CValue<'tcx> {
- let is_thin_ptr =
- in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true);
+ let is_thin_ptr = in_lhs
+ .layout()
+ .ty
+ .builtin_deref(true)
+ .map(|ty| !fx.tcx.type_has_metadata(ty, ty::TypingEnv::fully_monomorphized()))
+ .unwrap_or(true);
if is_thin_ptr {
match bin_op {
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index cc739fe..f8a1958 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -746,7 +746,7 @@ pub(crate) fn place_field(
};
let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field);
- if has_ptr_meta(fx.tcx, field_layout.ty) {
+ if fx.tcx.type_has_metadata(field_layout.ty, ty::TypingEnv::fully_monomorphized()) {
CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
} else {
CPlace::for_ptr(field_ptr, field_layout)
@@ -832,7 +832,7 @@ pub(crate) fn place_index(
pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> {
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap());
- if has_ptr_meta(fx.tcx, inner_layout.ty) {
+ if fx.tcx.type_has_metadata(inner_layout.ty, ty::TypingEnv::fully_monomorphized()) {
let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
} else {
@@ -845,7 +845,7 @@ pub(crate) fn place_ref(
fx: &mut FunctionCx<'_, '_, 'tcx>,
layout: TyAndLayout<'tcx>,
) -> CValue<'tcx> {
- if has_ptr_meta(fx.tcx, self.layout().ty) {
+ if fx.tcx.type_has_metadata(self.layout().ty, ty::TypingEnv::fully_monomorphized()) {
let (ptr, extra) = self.to_ptr_unsized();
CValue::by_val_pair(ptr.get_addr(fx), extra, layout)
} else {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index c514b7a..474475f 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -364,6 +364,7 @@ pub fn const_alloc_to_gcc<'gcc>(
llvals.push(cx.const_bytes(bytes));
}
+ // FIXME(bjorn3) avoid wrapping in a struct when there is only a single element.
cx.const_struct(&llvals, true)
}
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 62fa288..7675e75 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -129,7 +129,12 @@ fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>(
append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, range);
}
- cx.const_struct(&llvals, true)
+ // Avoid wrapping in a struct if there is only a single value. This ensures
+ // that LLVM is able to perform the string merging optimization if the constant
+ // is a valid C string. LLVM only considers bare arrays for this optimization,
+ // not arrays wrapped in a struct. LLVM handles this at:
+ // https://github.com/rust-lang/llvm-project/blob/acaea3d2bb8f351b740db7ebce7d7a40b9e21488/llvm/lib/Target/TargetLoweringObjectFile.cpp#L249-L280
+ if let &[data] = &*llvals { data } else { cx.const_struct(&llvals, true) }
}
fn codegen_static_initializer<'ll, 'tcx>(
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 4a166b0..4e85286 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -274,7 +274,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("arm", "fp16") => Some(LLVMFeature::new("fullfp16")),
// In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single
// feature called `fast-unaligned-access`. In LLVM 19, it was split back out.
- ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => {
+ ("riscv32" | "riscv64", "unaligned-scalar-mem" | "unaligned-vector-mem")
+ if get_version().0 == 18 =>
+ {
Some(LLVMFeature::new("fast-unaligned-access"))
}
// Filter out features that are not supported by the current LLVM version
@@ -298,6 +300,13 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")),
("sparc", "v8plus") if get_version().0 < 19 => None,
("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")),
+ // These new `amx` variants and `movrs` were introduced in LLVM20
+ ("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose")
+ if get_version().0 < 20 =>
+ {
+ None
+ }
+ ("x86", "movrs") if get_version().0 < 20 => None,
(_, s) => Some(LLVMFeature::new(s)),
}
}
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 95912b0..954a601 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -10,8 +10,6 @@
codegen_ssa_apple_deployment_target_too_low =
deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min}
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
-
codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error}
codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
@@ -391,8 +389,6 @@
codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
-codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-
codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]`
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
@@ -402,3 +398,20 @@
codegen_ssa_version_script_write_failure = failed to write version script: {$error}
codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
+
+codegen_ssa_xcrun_command_line_tools_insufficient =
+ when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode
+
+codegen_ssa_xcrun_failed_invoking = invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error}
+
+codegen_ssa_xcrun_found_developer_dir = found active developer directory at "{$developer_dir}"
+
+# `xcrun` already outputs a message about missing Xcode installation, so we only augment it with details about env vars.
+codegen_ssa_xcrun_no_developer_dir =
+ pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable
+
+codegen_ssa_xcrun_sdk_path_warning = output of `xcrun` while finding {$sdk_name}.sdk
+ .note = {$stderr}
+
+codegen_ssa_xcrun_unsuccessful = failed running `{$command_formatted}` to find {$sdk_name}.sdk
+ .note = {$stdout}{$stderr}
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index bfa7635..2c8b0ec 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -1,16 +1,40 @@
use std::env;
+use std::ffi::OsString;
use std::fmt::{Display, from_fn};
use std::num::ParseIntError;
+use std::path::PathBuf;
+use std::process::Command;
+use itertools::Itertools;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::Session;
use rustc_target::spec::Target;
+use tracing::debug;
-use crate::errors::AppleDeploymentTarget;
+use crate::errors::{AppleDeploymentTarget, XcrunError, XcrunSdkPathWarning};
+use crate::fluent_generated as fluent;
#[cfg(test)]
mod tests;
+/// The canonical name of the desired SDK for a given target.
+pub(super) fn sdk_name(target: &Target) -> &'static str {
+ match (&*target.os, &*target.abi) {
+ ("macos", "") => "MacOSX",
+ ("ios", "") => "iPhoneOS",
+ ("ios", "sim") => "iPhoneSimulator",
+ // Mac Catalyst uses the macOS SDK
+ ("ios", "macabi") => "MacOSX",
+ ("tvos", "") => "AppleTVOS",
+ ("tvos", "sim") => "AppleTVSimulator",
+ ("visionos", "") => "XROS",
+ ("visionos", "sim") => "XRSimulator",
+ ("watchos", "") => "WatchOS",
+ ("watchos", "sim") => "WatchSimulator",
+ (os, abi) => unreachable!("invalid os '{os}' / abi '{abi}' combination for Apple target"),
+ }
+}
+
pub(super) fn macho_platform(target: &Target) -> u32 {
match (&*target.os, &*target.abi) {
("macos", _) => object::macho::PLATFORM_MACOS,
@@ -253,3 +277,131 @@ pub(super) fn add_version_to_llvm_target(
format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}")
}
}
+
+pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> {
+ let sdk_name = sdk_name(&sess.target);
+
+ match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) {
+ Ok((path, stderr)) => {
+ // Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning.
+ if !stderr.is_empty() {
+ sess.dcx().emit_warn(XcrunSdkPathWarning { sdk_name, stderr });
+ }
+ Some(path)
+ }
+ Err(err) => {
+ let mut diag = sess.dcx().create_err(err);
+
+ // Recognize common error cases, and give more Rust-specific error messages for those.
+ if let Some(developer_dir) = xcode_select_developer_dir() {
+ diag.arg("developer_dir", &developer_dir);
+ diag.note(fluent::codegen_ssa_xcrun_found_developer_dir);
+ if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") {
+ if sdk_name != "MacOSX" {
+ diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient);
+ }
+ }
+ } else {
+ diag.help(fluent::codegen_ssa_xcrun_no_developer_dir);
+ }
+
+ diag.emit();
+ None
+ }
+ }
+}
+
+/// Invoke `xcrun --sdk $sdk_name --show-sdk-path` to get the SDK path.
+///
+/// The exact logic that `xcrun` uses is unspecified (see `man xcrun` for a few details), and may
+/// change between macOS and Xcode versions, but it roughly boils down to finding the active
+/// developer directory, and then invoking `xcodebuild -sdk $sdk_name -version` to get the SDK
+/// details.
+///
+/// Finding the developer directory is roughly done by looking at, in order:
+/// - The `DEVELOPER_DIR` environment variable.
+/// - The `/var/db/xcode_select_link` symlink (set by `xcode-select --switch`).
+/// - `/Applications/Xcode.app` (hardcoded fallback path).
+/// - `/Library/Developer/CommandLineTools` (hardcoded fallback path).
+///
+/// Note that `xcrun` caches its result, but with a cold cache this whole operation can be quite
+/// slow, especially so the first time it's run after a reboot.
+fn xcrun_show_sdk_path(
+ sdk_name: &'static str,
+ verbose: bool,
+) -> Result<(PathBuf, String), XcrunError> {
+ let mut cmd = Command::new("xcrun");
+ if verbose {
+ cmd.arg("--verbose");
+ }
+ // The `--sdk` parameter is the same as in xcodebuild, namely either an absolute path to an SDK,
+ // or the (lowercase) canonical name of an SDK.
+ cmd.arg("--sdk");
+ cmd.arg(&sdk_name.to_lowercase());
+ cmd.arg("--show-sdk-path");
+
+ // We do not stream stdout/stderr lines directly to the user, since whether they are warnings or
+ // errors depends on the status code at the end.
+ let output = cmd.output().map_err(|error| XcrunError::FailedInvoking {
+ sdk_name,
+ command_formatted: format!("{cmd:?}"),
+ error,
+ })?;
+
+ // It is fine to do lossy conversion here, non-UTF-8 paths are quite rare on macOS nowadays
+ // (only possible with the HFS+ file system), and we only use it for error messages.
+ let stderr = String::from_utf8_lossy_owned(output.stderr);
+ if !stderr.is_empty() {
+ debug!(stderr, "original xcrun stderr");
+ }
+
+ // Some versions of `xcodebuild` output beefy errors when invoked via `xcrun`,
+ // but these are usually red herrings.
+ let stderr = stderr
+ .lines()
+ .filter(|line| {
+ !line.contains("Writing error result bundle")
+ && !line.contains("Requested but did not find extension point with identifier")
+ })
+ .join("\n");
+
+ if output.status.success() {
+ Ok((stdout_to_path(output.stdout), stderr))
+ } else {
+ // Output both stdout and stderr, since shims of `xcrun` (such as the one provided by
+ // nixpkgs), do not always use stderr for errors.
+ let stdout = String::from_utf8_lossy_owned(output.stdout).trim().to_string();
+ Err(XcrunError::Unsuccessful {
+ sdk_name,
+ command_formatted: format!("{cmd:?}"),
+ stdout,
+ stderr,
+ })
+ }
+}
+
+/// Invoke `xcode-select --print-path`, and return the current developer directory.
+///
+/// NOTE: We don't do any error handling here, this is only used as a canary in diagnostics (`xcrun`
+/// will have already emitted the relevant error information).
+fn xcode_select_developer_dir() -> Option<PathBuf> {
+ let mut cmd = Command::new("xcode-select");
+ cmd.arg("--print-path");
+ let output = cmd.output().ok()?;
+ if !output.status.success() {
+ return None;
+ }
+ Some(stdout_to_path(output.stdout))
+}
+
+fn stdout_to_path(mut stdout: Vec<u8>) -> PathBuf {
+ // Remove trailing newline.
+ if let Some(b'\n') = stdout.last() {
+ let _ = stdout.pop().unwrap();
+ }
+ #[cfg(unix)]
+ let path = <OsString as std::os::unix::ffi::OsStringExt>::from_vec(stdout);
+ #[cfg(not(unix))] // Unimportant, this is only used on macOS
+ let path = OsString::from(String::from_utf8(stdout).unwrap());
+ PathBuf::from(path)
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs
index 7ccda5a..8df740a 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs
@@ -1,4 +1,4 @@
-use super::{add_version_to_llvm_target, parse_version};
+use super::*;
#[test]
fn test_add_version_to_llvm_target() {
@@ -19,3 +19,69 @@ fn test_parse_version() {
assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6)));
assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99)));
}
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcode-select is only available on macOS")]
+fn lookup_developer_dir() {
+ let _developer_dir = xcode_select_developer_dir().unwrap();
+}
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
+fn lookup_sdk() {
+ let (sdk_path, stderr) = xcrun_show_sdk_path("MacOSX", false).unwrap();
+ // Check that the found SDK is valid.
+ assert!(sdk_path.join("SDKSettings.plist").exists());
+ assert_eq!(stderr, "");
+
+ // Test that the SDK root is a subdir of the developer directory.
+ if let Some(developer_dir) = xcode_select_developer_dir() {
+ // Only run this test if SDKROOT is not set (otherwise xcrun may look up via. that).
+ if std::env::var_os("SDKROOT").is_some() {
+ assert!(sdk_path.starts_with(&developer_dir));
+ }
+ }
+}
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
+fn lookup_sdk_verbose() {
+ let (_, stderr) = xcrun_show_sdk_path("MacOSX", true).unwrap();
+ // Newer xcrun versions should emit something like this:
+ //
+ // xcrun: note: looking up SDK with 'xcodebuild -sdk macosx -version Path'
+ // xcrun: note: xcrun_db = '/var/.../xcrun_db'
+ // xcrun: note: lookup resolved to: '...'
+ // xcrun: note: database key is: ...
+ //
+ // Or if the value is already cached, something like this:
+ //
+ // xcrun: note: database key is: ...
+ // xcrun: note: lookup resolved in '/var/.../xcrun_db' : '...'
+ assert!(
+ stderr.contains("xcrun: note: lookup resolved"),
+ "stderr should contain lookup note: {stderr}",
+ );
+}
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
+fn try_lookup_invalid_sdk() {
+ // As a proxy for testing all the different ways that `xcrun` can fail,
+ // test the case where an SDK was not found.
+ let err = xcrun_show_sdk_path("invalid", false).unwrap_err();
+ let XcrunError::Unsuccessful { stderr, .. } = err else {
+ panic!("unexpected error kind: {err:?}");
+ };
+ // Either one of (depending on if using Command Line Tools or full Xcode):
+ // xcrun: error: SDK "invalid" cannot be located
+ // xcodebuild: error: SDK "invalid" cannot be located.
+ assert!(
+ stderr.contains(r#"error: SDK "invalid" cannot be located"#),
+ "stderr should contain xcodebuild note: {stderr}",
+ );
+ assert!(
+ stderr.contains("xcrun: error: unable to lookup item 'Path' in SDK 'invalid'"),
+ "stderr should contain xcrun note: {stderr}",
+ );
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index a564e0e..7d41108 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -294,7 +294,7 @@ fn link_rlib<'a>(
let (metadata, metadata_position) = create_wrapper_file(
sess,
".rmeta".to_string(),
- codegen_results.metadata.raw_data(),
+ codegen_results.metadata.stub_or_full(),
);
let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME);
match metadata_position {
@@ -1560,17 +1560,13 @@ fn print_native_static_libs(
match out {
OutFileName::Real(path) => {
out.overwrite(&lib_args.join(" "), sess);
- if !lib_args.is_empty() {
- sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
- }
+ sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
}
OutFileName::Stdout => {
- if !lib_args.is_empty() {
- sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts);
- // Prefix for greppability
- // Note: This must not be translated as tools are allowed to depend on this exact string.
- sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" ")));
- }
+ sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts);
+ // Prefix for greppability
+ // Note: This must not be translated as tools are allowed to depend on this exact string.
+ sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" ")));
}
}
}
@@ -3205,9 +3201,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
}
fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> {
- let arch = &sess.target.arch;
let os = &sess.target.os;
- let llvm_target = &sess.target.llvm_target;
if sess.target.vendor != "apple"
|| !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos")
|| !matches!(flavor, LinkerFlavor::Darwin(..))
@@ -3219,37 +3213,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
return None;
}
- let sdk_name = match (arch.as_ref(), os.as_ref()) {
- ("aarch64", "tvos") if llvm_target.ends_with("-simulator") => "appletvsimulator",
- ("aarch64", "tvos") => "appletvos",
- ("x86_64", "tvos") => "appletvsimulator",
- ("arm", "ios") => "iphoneos",
- ("aarch64", "ios") if llvm_target.contains("macabi") => "macosx",
- ("aarch64", "ios") if llvm_target.ends_with("-simulator") => "iphonesimulator",
- ("aarch64", "ios") => "iphoneos",
- ("x86", "ios") => "iphonesimulator",
- ("x86_64", "ios") if llvm_target.contains("macabi") => "macosx",
- ("x86_64", "ios") => "iphonesimulator",
- ("x86_64", "watchos") => "watchsimulator",
- ("arm64_32", "watchos") => "watchos",
- ("aarch64", "watchos") if llvm_target.ends_with("-simulator") => "watchsimulator",
- ("aarch64", "watchos") => "watchos",
- ("aarch64", "visionos") if llvm_target.ends_with("-simulator") => "xrsimulator",
- ("aarch64", "visionos") => "xros",
- ("arm", "watchos") => "watchos",
- (_, "macos") => "macosx",
- _ => {
- sess.dcx().emit_err(errors::UnsupportedArch { arch, os });
- return None;
- }
- };
- let sdk_root = match get_apple_sdk_root(sdk_name) {
- Ok(s) => s,
- Err(e) => {
- sess.dcx().emit_err(e);
- return None;
- }
- };
+ let sdk_root = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
match flavor {
LinkerFlavor::Darwin(Cc::Yes, _) => {
@@ -3259,28 +3223,32 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
// This is admittedly a bit strange, as on most targets
// `-isysroot` only applies to include header files, but on Apple
// targets this also applies to libraries and frameworks.
- cmd.cc_args(&["-isysroot", &sdk_root]);
+ cmd.cc_arg("-isysroot");
+ cmd.cc_arg(&sdk_root);
}
LinkerFlavor::Darwin(Cc::No, _) => {
- cmd.link_args(&["-syslibroot", &sdk_root]);
+ cmd.link_arg("-syslibroot");
+ cmd.link_arg(&sdk_root);
}
_ => unreachable!(),
}
- Some(sdk_root.into())
+ Some(sdk_root)
}
-fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootError<'_>> {
- // Following what clang does
- // (https://github.com/llvm/llvm-project/blob/
- // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
- // to allow the SDK path to be set. (For clang, xcrun sets
- // SDKROOT; for rustc, the user or build system can set it, or we
- // can fall back to checking for xcrun on PATH.)
+fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
if let Ok(sdkroot) = env::var("SDKROOT") {
- let p = Path::new(&sdkroot);
- match sdk_name {
- // Ignore `SDKROOT` if it's clearly set for the wrong platform.
+ let p = PathBuf::from(&sdkroot);
+
+ // Ignore invalid SDKs, similar to what clang does:
+ // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.6/clang/lib/Driver/ToolChains/Darwin.cpp#L2212-L2229
+ //
+ // NOTE: Things are complicated here by the fact that `rustc` can be run by Cargo to compile
+ // build scripts and proc-macros for the host, and thus we need to ignore SDKROOT if it's
+ // clearly set for the wrong platform.
+ //
+ // FIXME(madsmtm): Make this more robust (maybe read `SDKSettings.json` like Clang does?).
+ match &*apple::sdk_name(&sess.target).to_lowercase() {
"appletvos"
if sdkroot.contains("TVSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {}
@@ -3307,26 +3275,11 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro
if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
// Ignore `SDKROOT` if it's not a valid path.
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
- _ => return Ok(sdkroot),
+ _ => return Some(p),
}
}
- let res =
- Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
- |output| {
- if output.status.success() {
- Ok(String::from_utf8(output.stdout).unwrap())
- } else {
- let error = String::from_utf8(output.stderr);
- let error = format!("process exit with error: {}", error.unwrap());
- Err(io::Error::new(io::ErrorKind::Other, &error[..]))
- }
- },
- );
- match res {
- Ok(output) => Ok(output.trim().to_string()),
- Err(error) => Err(errors::AppleSdkRootError::SdkPath { sdk_name, error }),
- }
+ apple::get_sdk_root(sess)
}
/// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 68b453f..ac9ac9b 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -540,8 +540,8 @@ pub fn create_compressed_metadata_file(
symbol_name: &str,
) -> Vec<u8> {
let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec();
- packed_metadata.write_all(&(metadata.raw_data().len() as u64).to_le_bytes()).unwrap();
- packed_metadata.extend(metadata.raw_data());
+ packed_metadata.write_all(&(metadata.stub_or_full().len() as u64).to_le_bytes()).unwrap();
+ packed_metadata.extend(metadata.stub_or_full());
let Some(mut file) = create_object_file(sess) else {
if sess.target.is_like_wasm {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 216a18e..ccc0273 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -2186,7 +2186,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
// indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve
// these, but it currently does not do so.
let can_have_static_objects =
- tcx.sess.lto() == Lto::Thin || tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib);
+ tcx.sess.lto() == Lto::Thin || tcx.crate_types().contains(&CrateType::Rlib);
tcx.sess.target.is_like_windows &&
can_have_static_objects &&
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index d16d4ed..a85d032 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -604,7 +604,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
if let Some((name, _)) = lang_items::extract(attrs)
&& let Some(lang_item) = LangItem::from_name(name)
{
- if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) {
+ if WEAK_LANG_ITEMS.contains(&lang_item) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
}
if let Some(link_name) = lang_item.link_name() {
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 0b7cad0..f52d29b 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -739,13 +739,6 @@ pub enum ExtractBundledLibsError<'a> {
}
#[derive(Diagnostic)]
-#[diag(codegen_ssa_unsupported_arch)]
-pub(crate) struct UnsupportedArch<'a> {
- pub arch: &'a str,
- pub os: &'a str,
-}
-
-#[derive(Diagnostic)]
pub(crate) enum AppleDeploymentTarget {
#[diag(codegen_ssa_apple_deployment_target_invalid)]
Invalid { env_var: &'static str, error: ParseIntError },
@@ -754,12 +747,6 @@ pub(crate) enum AppleDeploymentTarget {
}
#[derive(Diagnostic)]
-pub(crate) enum AppleSdkRootError<'a> {
- #[diag(codegen_ssa_apple_sdk_error_sdk_path)]
- SdkPath { sdk_name: &'a str, error: Error },
-}
-
-#[derive(Diagnostic)]
#[diag(codegen_ssa_read_file)]
pub(crate) struct ReadFileError {
pub message: std::io::Error,
@@ -1334,3 +1321,26 @@ pub(crate) struct MixedExportNameAndNoMangle {
#[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
pub removal_span: Span,
}
+
+#[derive(Diagnostic, Debug)]
+pub(crate) enum XcrunError {
+ #[diag(codegen_ssa_xcrun_failed_invoking)]
+ FailedInvoking { sdk_name: &'static str, command_formatted: String, error: std::io::Error },
+
+ #[diag(codegen_ssa_xcrun_unsuccessful)]
+ #[note]
+ Unsuccessful {
+ sdk_name: &'static str,
+ command_formatted: String,
+ stdout: String,
+ stderr: String,
+ },
+}
+
+#[derive(Diagnostic, Debug)]
+#[diag(codegen_ssa_xcrun_sdk_path_warning)]
+#[note]
+pub(crate) struct XcrunSdkPathWarning {
+ pub sdk_name: &'static str,
+ pub stderr: String,
+}
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 93c34a2..d26d6ed 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -13,6 +13,7 @@
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(rustdoc_internals)]
+#![feature(string_from_utf8_lossy_owned)]
#![feature(trait_alias)]
#![feature(try_blocks)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index ffbe54d..3a64c92 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -564,6 +564,8 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
}
}
+impl_stable_traits_for_trivial_type!(::std::ffi::OsStr);
+
impl_stable_traits_for_trivial_type!(::std::path::Path);
impl_stable_traits_for_trivial_type!(::std::path::PathBuf);
diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs
index 8485d70..f09c2ed 100644
--- a/compiler/rustc_errors/src/snippet.rs
+++ b/compiler/rustc_errors/src/snippet.rs
@@ -159,11 +159,7 @@ pub(crate) fn is_line(&self) -> bool {
/// Length of this annotation as displayed in the stderr output
pub(crate) fn len(&self) -> usize {
// Account for usize underflows
- if self.end_col.display > self.start_col.display {
- self.end_col.display - self.start_col.display
- } else {
- self.start_col.display - self.end_col.display
- }
+ self.end_col.display.abs_diff(self.start_col.display)
}
pub(crate) fn has_label(&self) -> bool {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 990d0f2..d14e476 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1424,12 +1424,11 @@ pub fn parse_macro_name_and_helper_attrs(
/// See #73345 and #83125 for more details.
/// FIXME(#73933): Remove this eventually.
fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
- let name = item.ident.name;
- if name == sym::ProceduralMasqueradeDummyType
- && let ast::ItemKind::Enum(enum_def, _) = &item.kind
+ if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind
+ && ident.name == sym::ProceduralMasqueradeDummyType
&& let [variant] = &*enum_def.variants
&& variant.ident.name == sym::Input
- && let FileName::Real(real) = psess.source_map().span_to_filename(item.ident.span)
+ && let FileName::Real(real) = psess.source_map().span_to_filename(ident.span)
&& let Some(c) = real
.local_path()
.unwrap_or(Path::new(""))
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 89a750b..f68172c 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -662,15 +662,8 @@ pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<as
P(ast::FnDecl { inputs, output })
}
- pub fn item(
- &self,
- span: Span,
- name: Ident,
- attrs: ast::AttrVec,
- kind: ast::ItemKind,
- ) -> P<ast::Item> {
+ pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P<ast::Item> {
P(ast::Item {
- ident: name,
attrs,
id: ast::DUMMY_NODE_ID,
kind,
@@ -687,17 +680,17 @@ pub fn item(
pub fn item_static(
&self,
span: Span,
- name: Ident,
+ ident: Ident,
ty: P<ast::Ty>,
mutability: ast::Mutability,
expr: P<ast::Expr>,
) -> P<ast::Item> {
self.item(
span,
- name,
AttrVec::new(),
ast::ItemKind::Static(
ast::StaticItem {
+ ident,
ty,
safety: ast::Safety::Default,
mutability,
@@ -712,18 +705,18 @@ pub fn item_static(
pub fn item_const(
&self,
span: Span,
- name: Ident,
+ ident: Ident,
ty: P<ast::Ty>,
expr: P<ast::Expr>,
) -> P<ast::Item> {
let defaultness = ast::Defaultness::Final;
self.item(
span,
- name,
AttrVec::new(),
ast::ItemKind::Const(
ast::ConstItem {
defaultness,
+ ident,
// FIXME(generic_const_items): Pass the generics as a parameter.
generics: ast::Generics::default(),
ty,
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index ada49ee..bcc2703 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -156,6 +156,19 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec
.collect()
}
+pub(crate) fn attr_into_trace(mut attr: Attribute, trace_name: Symbol) -> Attribute {
+ match &mut attr.kind {
+ AttrKind::Normal(normal) => {
+ let NormalAttr { item, tokens } = &mut **normal;
+ item.path.segments[0].ident.name = trace_name;
+ // This makes the trace attributes unobservable to token-based proc macros.
+ *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
+ }
+ AttrKind::DocComment(..) => unreachable!(),
+ }
+ attr
+}
+
#[macro_export]
macro_rules! configure {
($this:ident, $node:ident) => {
@@ -280,16 +293,7 @@ pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> V
// A trace attribute left in AST in place of the original `cfg_attr` attribute.
// It can later be used by lints or other diagnostics.
- let mut trace_attr = cfg_attr.clone();
- match &mut trace_attr.kind {
- AttrKind::Normal(normal) => {
- let NormalAttr { item, tokens } = &mut **normal;
- item.path.segments[0].ident.name = sym::cfg_attr_trace;
- // This makes the trace attributes unobservable to token-based proc macros.
- *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
- }
- AttrKind::DocComment(..) => unreachable!(),
- }
+ let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace);
let Some((cfg_predicate, expanded_attrs)) =
rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index d0bd8a8..bca846d 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -33,7 +33,7 @@
use smallvec::SmallVec;
use crate::base::*;
-use crate::config::StripUnconfigured;
+use crate::config::{StripUnconfigured, attr_into_trace};
use crate::errors::{
EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
@@ -744,6 +744,7 @@ fn expand_invoc(
item_inner.kind,
ItemKind::Mod(
_,
+ _,
ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _),
)
) =>
@@ -911,7 +912,7 @@ struct GateProcMacroInput<'a> {
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
fn visit_item(&mut self, item: &'ast ast::Item) {
match &item.kind {
- ItemKind::Mod(_, mod_kind)
+ ItemKind::Mod(_, _, mod_kind)
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) =>
{
feature_err(
@@ -1221,9 +1222,8 @@ fn wrap_flat_map_node_walk_flat_map(
}
// Work around borrow checker not seeing through `P`'s deref.
- let (ident, span, mut attrs) = (node.ident, node.span, mem::take(&mut node.attrs));
- let ItemKind::Mod(_, mod_kind) = &mut node.kind else { unreachable!() };
-
+ let (span, mut attrs) = (node.span, mem::take(&mut node.attrs));
+ let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() };
let ecx = &mut collector.cx;
let (file_path, dir_path, dir_ownership) = match mod_kind {
ModKind::Loaded(_, inline, _, _) => {
@@ -1305,6 +1305,7 @@ fn wrap_flat_map_node_walk_flat_map(
collector.cx.current_expansion.module = orig_module;
res
}
+
fn declared_names(&self) -> Vec<Ident> {
if let ItemKind::Use(ut) = &self.kind {
fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
@@ -1324,7 +1325,7 @@ fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
return idents;
}
- vec![self.ident]
+ if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] }
}
}
@@ -1844,11 +1845,11 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>(
id: ast::DUMMY_NODE_ID,
span: if from_glob { item_span } else { ident.span },
vis: item.vis.clone(),
- ident: rename.unwrap_or(ident),
kind: Node::delegation_item_kind(Box::new(ast::Delegation {
id: ast::DUMMY_NODE_ID,
qself: deleg.qself.clone(),
path,
+ ident: rename.unwrap_or(ident),
rename,
body: deleg.body.clone(),
from_glob,
@@ -2003,7 +2004,7 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
let attr_name = attr.ident().unwrap().name;
// `#[cfg]` and `#[cfg_attr]` are special - they are
// eagerly evaluated.
- if attr_name != sym::cfg && attr_name != sym::cfg_attr_trace {
+ if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace {
self.cx.sess.psess.buffer_lint(
UNUSED_ATTRIBUTES,
attr.span,
@@ -2027,11 +2028,10 @@ fn expand_cfg_true(
) -> (bool, Option<ast::MetaItem>) {
let (res, meta_item) = self.cfg().cfg_true(&attr);
if res {
- // FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
- // and some tools like rustdoc and clippy rely on that. Find a way to remove them
- // while keeping the tools working.
- self.cx.expanded_inert_attrs.mark(&attr);
- node.visit_attrs(|attrs| attrs.insert(pos, attr));
+ // A trace attribute left in AST in place of the original `cfg` attribute.
+ // It can later be used by lints or other diagnostics.
+ let trace_attr = attr_into_trace(attr, sym::cfg_trace);
+ node.visit_attrs(|attrs| attrs.insert(pos, trace_attr));
}
(res, meta_item)
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index a60a872..0136292 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -26,7 +26,7 @@ fn mac_placeholder() -> P<ast::MacCall> {
})
}
- let ident = Ident::empty();
+ let ident = Ident::dummy();
let attrs = ast::AttrVec::new();
let vis = vis.unwrap_or(ast::Visibility {
span: DUMMY_SP,
@@ -62,7 +62,6 @@ fn mac_placeholder() -> P<ast::MacCall> {
AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
id,
span,
- ident,
vis,
attrs,
kind: ast::ItemKind::MacCall(mac_placeholder()),
@@ -71,7 +70,6 @@ fn mac_placeholder() -> P<ast::MacCall> {
AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
id,
span,
- ident,
vis,
attrs,
kind: ast::AssocItemKind::MacCall(mac_placeholder()),
@@ -80,7 +78,6 @@ fn mac_placeholder() -> P<ast::MacCall> {
AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
id,
span,
- ident,
vis,
attrs,
kind: ast::AssocItemKind::MacCall(mac_placeholder()),
@@ -90,7 +87,6 @@ fn mac_placeholder() -> P<ast::MacCall> {
AstFragment::TraitImplItems(smallvec![P(ast::AssocItem {
id,
span,
- ident,
vis,
attrs,
kind: ast::AssocItemKind::MacCall(mac_placeholder()),
@@ -101,7 +97,6 @@ fn mac_placeholder() -> P<ast::MacCall> {
AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
id,
span,
- ident,
vis,
attrs,
kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index fd93645..1e33e2e 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -760,10 +760,14 @@ pub struct BuiltinAttribute {
template!(Word, List: r#""...""#), DuplicatesOk,
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
),
- // Trace that is left when a `cfg_attr` attribute is expanded.
- // The attribute is not gated, to avoid stability errors, but it cannot be used in stable or
- // unstable code directly because `sym::cfg_attr_trace` is not a valid identifier, it can only
- // be generated by the compiler.
+ // Traces that are left when `cfg` and `cfg_attr` attributes are expanded.
+ // The attributes are not gated, to avoid stability errors, but they cannot be used in stable
+ // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they
+ // can only be generated by the compiler.
+ ungated!(
+ cfg_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
+ EncodeCrossCrate::No
+ ),
ungated!(
cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
EncodeCrossCrate::No
@@ -1083,9 +1087,9 @@ pub struct BuiltinAttribute {
WarnFollowing, EncodeCrossCrate::No
),
rustc_attr!(
- TEST, rustc_error, Normal,
- template!(Word, List: "delayed_bug_from_inside_query"),
- WarnFollowingWordOnly, EncodeCrossCrate::Yes
+ TEST, rustc_delayed_bug_from_inside_query, Normal,
+ template!(Word),
+ WarnFollowing, EncodeCrossCrate::No
),
rustc_attr!(
TEST, rustc_dump_user_args, Normal, template!(Word),
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 47e4f9a..6ba7b22 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -142,6 +142,9 @@ macro_rules! declare_features {
/// Allows inferring `'static` outlives requirements (RFC 2093).
(removed, infer_static_outlives_requirements, "1.63.0", Some(54185),
Some("removed as it caused some confusion and discussion was inactive for years")),
+ /// Allow anonymous constants from an inline `const` block in pattern position
+ (removed, inline_const_pat, "CURRENT_RUSTC_VERSION", Some(76001),
+ Some("removed due to implementation concerns as it requires significant refactorings")),
/// Lazily evaluate constants. This allows constants to depend on type parameters.
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
/// Changes `impl Trait` to capture all lifetimes in scope.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 72468dd..87b88bb 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -324,6 +324,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, loongarch_target_feature, "1.73.0", Some(44839)),
(unstable, m68k_target_feature, "1.85.0", Some(134328)),
(unstable, mips_target_feature, "1.27.0", Some(44839)),
+ (unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)),
(unstable, powerpc_target_feature, "1.27.0", Some(44839)),
(unstable, prfchw_target_feature, "1.78.0", Some(44839)),
(unstable, riscv_target_feature, "1.45.0", Some(44839)),
@@ -531,8 +532,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, import_trait_associated_functions, "1.86.0", Some(134691)),
/// Allows associated types in inherent impls.
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
- /// Allow anonymous constants from an inline `const` block in pattern position
- (unstable, inline_const_pat, "1.58.0", Some(76001)),
/// Allows using `pointer` and `reference` in intra-doc links
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
// Allows using the `kl` and `widekl` target features and the associated intrinsics
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 5f8941d..dc00b52 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -294,7 +294,7 @@ pub fn def_path_data(self, name: Option<Symbol>) -> DefPathData {
DefKind::GlobalAsm => DefPathData::GlobalAsm,
DefKind::Impl { .. } => DefPathData::Impl,
DefKind::Closure => DefPathData::Closure,
- DefKind::SyntheticCoroutineBody => DefPathData::Closure,
+ DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody,
}
}
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 61f5efd..c52954a 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -291,6 +291,8 @@ pub enum DefPathData {
/// An existential `impl Trait` type node.
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
OpaqueTy,
+ /// A synthetic body for a coroutine's by-move body.
+ SyntheticCoroutineBody,
}
impl Definitions {
@@ -415,8 +417,16 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
- Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
- | OpaqueTy => None,
+ Impl
+ | ForeignMod
+ | CrateRoot
+ | Use
+ | GlobalAsm
+ | Closure
+ | Ctor
+ | AnonConst
+ | OpaqueTy
+ | SyntheticCoroutineBody => None,
}
}
@@ -441,6 +451,7 @@ pub fn name(&self) -> DefPathDataName {
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
+ SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
}
}
}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 751c379..e3e9689 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -35,20 +35,60 @@
pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
use crate::intravisit::{FnKind, VisitorExt};
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
+pub enum IsAnonInPath {
+ No,
+ Yes,
+}
+
+/// A lifetime. The valid field combinations are non-obvious. The following
+/// example shows some of them. See also the comments on `LifetimeName`.
+/// ```
+/// #[repr(C)]
+/// struct S<'a>(&'a u32); // res=Param, name='a, IsAnonInPath::No
+/// unsafe extern "C" {
+/// fn f1(s: S); // res=Param, name='_, IsAnonInPath::Yes
+/// fn f2(s: S<'_>); // res=Param, name='_, IsAnonInPath::No
+/// fn f3<'a>(s: S<'a>); // res=Param, name='a, IsAnonInPath::No
+/// }
+///
+/// struct St<'a> { x: &'a u32 } // res=Param, name='a, IsAnonInPath::No
+/// fn f() {
+/// _ = St { x: &0 }; // res=Infer, name='_, IsAnonInPath::Yes
+/// _ = St::<'_> { x: &0 }; // res=Infer, name='_, IsAnonInPath::No
+/// }
+///
+/// struct Name<'a>(&'a str); // res=Param, name='a, IsAnonInPath::No
+/// const A: Name = Name("a"); // res=Static, name='_, IsAnonInPath::Yes
+/// const B: &str = ""; // res=Static, name='_, IsAnonInPath::No
+/// static C: &'_ str = ""; // res=Static, name='_, IsAnonInPath::No
+/// static D: &'static str = ""; // res=Static, name='static, IsAnonInPath::No
+///
+/// trait Tr {}
+/// fn tr(_: Box<dyn Tr>) {} // res=ImplicitObjectLifetimeDefault, name='_, IsAnonInPath::No
+///
+/// // (commented out because these cases trigger errors)
+/// // struct S1<'a>(&'a str); // res=Param, name='a, IsAnonInPath::No
+/// // struct S2(S1); // res=Error, name='_, IsAnonInPath::Yes
+/// // struct S3(S1<'_>); // res=Error, name='_, IsAnonInPath::No
+/// // struct S4(S1<'a>); // res=Error, name='a, IsAnonInPath::No
+/// ```
#[derive(Debug, Copy, Clone, HashStable_Generic)]
pub struct Lifetime {
#[stable_hasher(ignore)]
pub hir_id: HirId,
- /// Either "`'a`", referring to a named lifetime definition,
- /// `'_` referring to an anonymous lifetime (either explicitly `'_` or `&type`),
- /// or "``" (i.e., `kw::Empty`) when appearing in path.
- ///
- /// See `Lifetime::suggestion_position` for practical use.
+ /// Either a named lifetime definition (e.g. `'a`, `'static`) or an
+ /// anonymous lifetime (`'_`, either explicitly written, or inserted for
+ /// things like `&type`).
pub ident: Ident,
/// Semantics of this lifetime.
pub res: LifetimeName,
+
+ /// Is the lifetime anonymous and in a path? Used only for error
+ /// suggestions. See `Lifetime::suggestion` for example use.
+ pub is_anon_in_path: IsAnonInPath,
}
#[derive(Debug, Copy, Clone, HashStable_Generic)]
@@ -111,11 +151,12 @@ pub enum LifetimeName {
/// that was already reported.
Error,
- /// User wrote an anonymous lifetime, either `'_` or nothing.
- /// The semantics of this lifetime should be inferred by typechecking code.
+ /// User wrote an anonymous lifetime, either `'_` or nothing (which gets
+ /// converted to `'_`). The semantics of this lifetime should be inferred
+ /// by typechecking code.
Infer,
- /// User wrote `'static`.
+ /// User wrote `'static` or nothing (which gets converted to `'_`).
Static,
}
@@ -135,59 +176,57 @@ fn is_elided(&self) -> bool {
impl fmt::Display for Lifetime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) }
+ self.ident.name.fmt(f)
}
}
-pub enum LifetimeSuggestionPosition {
- /// The user wrote `'a` or `'_`.
- Normal,
- /// The user wrote `&type` or `&mut type`.
- Ampersand,
- /// The user wrote `Path` and omitted the `<'_>`.
- ElidedPath,
- /// The user wrote `Path<T>`, and omitted the `'_,`.
- ElidedPathArgument,
- /// The user wrote `dyn Trait` and omitted the `+ '_`.
- ObjectDefault,
-}
-
impl Lifetime {
+ pub fn new(
+ hir_id: HirId,
+ ident: Ident,
+ res: LifetimeName,
+ is_anon_in_path: IsAnonInPath,
+ ) -> Lifetime {
+ let lifetime = Lifetime { hir_id, ident, res, is_anon_in_path };
+
+ // Sanity check: elided lifetimes form a strict subset of anonymous lifetimes.
+ #[cfg(debug_assertions)]
+ match (lifetime.is_elided(), lifetime.is_anonymous()) {
+ (false, false) => {} // e.g. `'a`
+ (false, true) => {} // e.g. explicit `'_`
+ (true, true) => {} // e.g. `&x`
+ (true, false) => panic!("bad Lifetime"),
+ }
+
+ lifetime
+ }
+
pub fn is_elided(&self) -> bool {
self.res.is_elided()
}
pub fn is_anonymous(&self) -> bool {
- self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime
- }
-
- pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) {
- if self.ident.name == kw::Empty {
- if self.ident.span.is_empty() {
- (LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span)
- } else {
- (LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi())
- }
- } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault {
- (LifetimeSuggestionPosition::ObjectDefault, self.ident.span)
- } else if self.ident.span.is_empty() {
- (LifetimeSuggestionPosition::Ampersand, self.ident.span)
- } else {
- (LifetimeSuggestionPosition::Normal, self.ident.span)
- }
+ self.ident.name == kw::UnderscoreLifetime
}
pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
debug_assert!(new_lifetime.starts_with('\''));
- let (pos, span) = self.suggestion_position();
- let code = match pos {
- LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"),
- LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "),
- LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"),
- LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "),
- LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"),
- };
- (span, code)
+
+ match (self.is_anon_in_path, self.ident.span.is_empty()) {
+ // The user wrote `Path<T>`, and omitted the `'_,`.
+ (IsAnonInPath::Yes, true) => (self.ident.span, format!("{new_lifetime}, ")),
+
+ // The user wrote `Path` and omitted the `<'_>`.
+ (IsAnonInPath::Yes, false) => {
+ (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>"))
+ }
+
+ // The user wrote `&type` or `&mut type`.
+ (IsAnonInPath::No, true) => (self.ident.span, format!("{new_lifetime} ")),
+
+ // The user wrote `'a` or `'_`.
+ (IsAnonInPath::No, false) => (self.ident.span, format!("{new_lifetime}")),
+ }
}
}
diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs
index f75b966..62ef02d 100644
--- a/compiler/rustc_hir/src/hir/tests.rs
+++ b/compiler/rustc_hir/src/hir/tests.rs
@@ -58,6 +58,7 @@ fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
hir_id: HirId::INVALID,
ident: Ident::new(sym::name, DUMMY_SP),
res: LifetimeName::Static,
+ is_anon_in_path: IsAnonInPath::No,
}
},
syntax,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index d63165f..32a582a 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -29,6 +29,7 @@ enum NonAsmTypeReason<'tcx> {
Invalid(Ty<'tcx>),
InvalidElement(DefId, Ty<'tcx>),
NotSizedPtr(Ty<'tcx>),
+ EmptySIMDArray(Ty<'tcx>),
}
impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
@@ -102,6 +103,9 @@ fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result<InlineAsmType, NonAsmTypeReason<'tc
}
ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
+ if fields.is_empty() {
+ return Err(NonAsmTypeReason::EmptySIMDArray(ty));
+ }
let field = &fields[FieldIdx::ZERO];
let elem_ty = field.ty(self.tcx(), args);
@@ -226,6 +230,10 @@ fn check_asm_operand_type(
can be used as arguments for inline assembly",
).emit();
}
+ NonAsmTypeReason::EmptySIMDArray(ty) => {
+ let msg = format!("use of empty SIMD vector `{ty}`");
+ self.infcx.dcx().struct_span_err(expr.span, msg).emit();
+ }
}
return None;
}
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 255f5fe..cf66ab7 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -8,7 +8,6 @@
use std::mem;
-use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -23,12 +22,11 @@
#[derive(Debug, Copy, Clone)]
struct Context {
- /// The scope that contains any new variables declared, plus its depth in
- /// the scope tree.
- var_parent: Option<(Scope, ScopeDepth)>,
+ /// The scope that contains any new variables declared.
+ var_parent: Option<Scope>,
- /// Region parent of expressions, etc., plus its depth in the scope tree.
- parent: Option<(Scope, ScopeDepth)>,
+ /// Region parent of expressions, etc.
+ parent: Option<Scope>,
}
struct ScopeResolutionVisitor<'tcx> {
@@ -46,28 +44,6 @@ struct ScopeResolutionVisitor<'tcx> {
scope_tree: ScopeTree,
cx: Context,
-
- /// `terminating_scopes` is a set containing the ids of each
- /// statement, or conditional/repeating expression. These scopes
- /// are calling "terminating scopes" because, when attempting to
- /// find the scope of a temporary, by default we search up the
- /// enclosing scopes until we encounter the terminating scope. A
- /// conditional/repeating expression is one which is not
- /// guaranteed to execute exactly once upon entering the parent
- /// scope. This could be because the expression only executes
- /// conditionally, such as the expression `b` in `a && b`, or
- /// because the expression may execute many times, such as a loop
- /// body. The reason that we distinguish such expressions is that,
- /// upon exiting the parent scope, we cannot statically know how
- /// many times the expression executed, and thus if the expression
- /// creates temporaries we cannot know statically how many such
- /// temporaries we would have to cleanup. Therefore, we ensure that
- /// the temporaries never outlast the conditional/repeating
- /// expression, preventing the need for dynamic checks and/or
- /// arbitrary amounts of stack space. Terminating scopes end
- /// up being contained in a DestructionScope that contains the
- /// destructor's execution.
- terminating_scopes: FxHashSet<hir::ItemLocalId>,
}
/// Records the lifetime of a local variable as `cx.var_parent`
@@ -78,11 +54,15 @@ fn record_var_lifetime(visitor: &mut ScopeResolutionVisitor<'_>, var_id: hir::It
//
// extern fn isalnum(c: c_int) -> c_int
}
- Some((parent_scope, _)) => visitor.scope_tree.record_var_scope(var_id, parent_scope),
+ Some(parent_scope) => visitor.scope_tree.record_var_scope(var_id, parent_scope),
}
}
-fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hir::Block<'tcx>) {
+fn resolve_block<'tcx>(
+ visitor: &mut ScopeResolutionVisitor<'tcx>,
+ blk: &'tcx hir::Block<'tcx>,
+ terminating: bool,
+) {
debug!("resolve_block(blk.hir_id={:?})", blk.hir_id);
let prev_cx = visitor.cx;
@@ -112,7 +92,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
// `other_argument()` has run and also the call to `quux(..)`
// itself has returned.
- visitor.enter_node_scope_with_dtor(blk.hir_id.local_id);
+ visitor.enter_node_scope_with_dtor(blk.hir_id.local_id, terminating);
visitor.cx.var_parent = visitor.cx.parent;
{
@@ -141,8 +121,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
// the sequence of visits agree with the order in the default
// `hir::intravisit` visitor.
mem::swap(&mut prev_cx, &mut visitor.cx);
- visitor.terminating_scopes.insert(els.hir_id.local_id);
- visitor.visit_block(els);
+ resolve_block(visitor, els, true);
// From now on, we continue normally.
visitor.cx = prev_cx;
}
@@ -170,12 +149,12 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
if let Some(tail_expr) = blk.expr {
let local_id = tail_expr.hir_id.local_id;
let edition = blk.span.edition();
- if edition.at_least_rust_2024() {
- visitor.terminating_scopes.insert(local_id);
- } else if !visitor
- .tcx
- .lints_that_dont_need_to_run(())
- .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER))
+ let terminating = edition.at_least_rust_2024();
+ if !terminating
+ && !visitor
+ .tcx
+ .lints_that_dont_need_to_run(())
+ .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER))
{
// If this temporary scope will be changing once the codebase adopts Rust 2024,
// and we are linting about possible semantic changes that would result,
@@ -186,7 +165,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
.backwards_incompatible_scope
.insert(local_id, Scope { local_id, data: ScopeData::Node });
}
- visitor.visit_expr(tail_expr);
+ resolve_expr(visitor, tail_expr, terminating);
}
}
@@ -204,25 +183,19 @@ fn has_let_expr(expr: &Expr<'_>) -> bool {
let prev_cx = visitor.cx;
- visitor.terminating_scopes.insert(arm.hir_id.local_id);
-
- visitor.enter_node_scope_with_dtor(arm.hir_id.local_id);
+ visitor.enter_node_scope_with_dtor(arm.hir_id.local_id, true);
visitor.cx.var_parent = visitor.cx.parent;
- if let Some(expr) = arm.guard
- && !has_let_expr(expr)
- {
- visitor.terminating_scopes.insert(expr.hir_id.local_id);
+ resolve_pat(visitor, arm.pat);
+ if let Some(guard) = arm.guard {
+ resolve_expr(visitor, guard, !has_let_expr(guard));
}
-
- intravisit::walk_arm(visitor, arm);
+ resolve_expr(visitor, arm.body, false);
visitor.cx = prev_cx;
}
fn resolve_pat<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
- visitor.record_child_scope(Scope { local_id: pat.hir_id.local_id, data: ScopeData::Node });
-
// If this is a binding then record the lifetime of that binding.
if let PatKind::Binding(..) = pat.kind {
record_var_lifetime(visitor, pat.hir_id.local_id);
@@ -246,126 +219,24 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi
// associated destruction scope that represents the scope of the
// statement plus its destructors, and thus the scope for which
// regions referenced by the destructors need to survive.
- visitor.terminating_scopes.insert(stmt_id);
let prev_parent = visitor.cx.parent;
- visitor.enter_node_scope_with_dtor(stmt_id);
+ visitor.enter_node_scope_with_dtor(stmt_id, true);
intravisit::walk_stmt(visitor, stmt);
visitor.cx.parent = prev_parent;
}
-fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+fn resolve_expr<'tcx>(
+ visitor: &mut ScopeResolutionVisitor<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ terminating: bool,
+) {
debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr);
let prev_cx = visitor.cx;
- visitor.enter_node_scope_with_dtor(expr.hir_id.local_id);
-
- {
- let terminating_scopes = &mut visitor.terminating_scopes;
- let mut terminating = |id: hir::ItemLocalId| {
- terminating_scopes.insert(id);
- };
- match expr.kind {
- // Conditional or repeating scopes are always terminating
- // scopes, meaning that temporaries cannot outlive them.
- // This ensures fixed size stacks.
- hir::ExprKind::Binary(
- source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
- l,
- r,
- ) => {
- // expr is a short circuiting operator (|| or &&). As its
- // functionality can't be overridden by traits, it always
- // processes bool sub-expressions. bools are Copy and thus we
- // can drop any temporaries in evaluation (read) order
- // (with the exception of potentially failing let expressions).
- // We achieve this by enclosing the operands in a terminating
- // scope, both the LHS and the RHS.
-
- // We optimize this a little in the presence of chains.
- // Chains like a && b && c get lowered to AND(AND(a, b), c).
- // In here, b and c are RHS, while a is the only LHS operand in
- // that chain. This holds true for longer chains as well: the
- // leading operand is always the only LHS operand that is not a
- // binop itself. Putting a binop like AND(a, b) into a
- // terminating scope is not useful, thus we only put the LHS
- // into a terminating scope if it is not a binop.
-
- let terminate_lhs = match l.kind {
- // let expressions can create temporaries that live on
- hir::ExprKind::Let(_) => false,
- // binops already drop their temporaries, so there is no
- // need to put them into a terminating scope.
- // This is purely an optimization to reduce the number of
- // terminating scopes.
- hir::ExprKind::Binary(
- source_map::Spanned {
- node: hir::BinOpKind::And | hir::BinOpKind::Or, ..
- },
- ..,
- ) => false,
- // otherwise: mark it as terminating
- _ => true,
- };
- if terminate_lhs {
- terminating(l.hir_id.local_id);
- }
-
- // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries
- // should live beyond the immediate expression
- if !matches!(r.kind, hir::ExprKind::Let(_)) {
- terminating(r.hir_id.local_id);
- }
- }
- hir::ExprKind::If(_, then, Some(otherwise)) => {
- terminating(then.hir_id.local_id);
- terminating(otherwise.hir_id.local_id);
- }
-
- hir::ExprKind::If(_, then, None) => {
- terminating(then.hir_id.local_id);
- }
-
- hir::ExprKind::Loop(body, _, _, _) => {
- terminating(body.hir_id.local_id);
- }
-
- hir::ExprKind::DropTemps(expr) => {
- // `DropTemps(expr)` does not denote a conditional scope.
- // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`.
- terminating(expr.hir_id.local_id);
- }
-
- hir::ExprKind::AssignOp(..)
- | hir::ExprKind::Index(..)
- | hir::ExprKind::Unary(..)
- | hir::ExprKind::Call(..)
- | hir::ExprKind::MethodCall(..) => {
- // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls
- //
- // The lifetimes for a call or method call look as follows:
- //
- // call.id
- // - arg0.id
- // - ...
- // - argN.id
- // - call.callee_id
- //
- // The idea is that call.callee_id represents *the time when
- // the invoked function is actually running* and call.id
- // represents *the time to prepare the arguments and make the
- // call*. See the section "Borrows in Calls" borrowck/README.md
- // for an extended explanation of why this distinction is
- // important.
- //
- // record_superlifetime(new_cx, expr.callee_id);
- }
-
- _ => {}
- }
- }
+ visitor.enter_node_scope_with_dtor(expr.hir_id.local_id, terminating);
let prev_pessimistic = visitor.pessimistic_yield;
@@ -420,6 +291,53 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
// properly, we can't miss any types.
match expr.kind {
+ // Conditional or repeating scopes are always terminating
+ // scopes, meaning that temporaries cannot outlive them.
+ // This ensures fixed size stacks.
+ hir::ExprKind::Binary(
+ source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+ left,
+ right,
+ ) => {
+ // expr is a short circuiting operator (|| or &&). As its
+ // functionality can't be overridden by traits, it always
+ // processes bool sub-expressions. bools are Copy and thus we
+ // can drop any temporaries in evaluation (read) order
+ // (with the exception of potentially failing let expressions).
+ // We achieve this by enclosing the operands in a terminating
+ // scope, both the LHS and the RHS.
+
+ // We optimize this a little in the presence of chains.
+ // Chains like a && b && c get lowered to AND(AND(a, b), c).
+ // In here, b and c are RHS, while a is the only LHS operand in
+ // that chain. This holds true for longer chains as well: the
+ // leading operand is always the only LHS operand that is not a
+ // binop itself. Putting a binop like AND(a, b) into a
+ // terminating scope is not useful, thus we only put the LHS
+ // into a terminating scope if it is not a binop.
+
+ let terminate_lhs = match left.kind {
+ // let expressions can create temporaries that live on
+ hir::ExprKind::Let(_) => false,
+ // binops already drop their temporaries, so there is no
+ // need to put them into a terminating scope.
+ // This is purely an optimization to reduce the number of
+ // terminating scopes.
+ hir::ExprKind::Binary(
+ source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+ ..,
+ ) => false,
+ // otherwise: mark it as terminating
+ _ => true,
+ };
+
+ // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries
+ // should live beyond the immediate expression
+ let terminate_rhs = !matches!(right.kind, hir::ExprKind::Let(_));
+
+ resolve_expr(visitor, left, terminate_lhs);
+ resolve_expr(visitor, right, terminate_rhs);
+ }
// Manually recurse over closures, because they are nested bodies
// that share the parent environment. We handle const blocks in
// `visit_inline_const`.
@@ -488,9 +406,9 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
visitor.cx.var_parent = visitor.cx.parent;
visitor.visit_expr(cond);
- visitor.visit_expr(then);
+ resolve_expr(visitor, then, true);
visitor.cx = expr_cx;
- visitor.visit_expr(otherwise);
+ resolve_expr(visitor, otherwise, true);
}
hir::ExprKind::If(cond, then, None) => {
@@ -503,10 +421,20 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
visitor.cx.var_parent = visitor.cx.parent;
visitor.visit_expr(cond);
- visitor.visit_expr(then);
+ resolve_expr(visitor, then, true);
visitor.cx = expr_cx;
}
+ hir::ExprKind::Loop(body, _, _, _) => {
+ resolve_block(visitor, body, true);
+ }
+
+ hir::ExprKind::DropTemps(expr) => {
+ // `DropTemps(expr)` does not denote a conditional scope.
+ // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`.
+ resolve_expr(visitor, expr, true);
+ }
+
_ => intravisit::walk_expr(visitor, expr),
}
@@ -541,7 +469,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
// Keep traversing up while we can.
match visitor.scope_tree.parent_map.get(&scope) {
// Don't cross from closure bodies to their parent.
- Some(&(superscope, _)) => match superscope.data {
+ Some(&superscope) => match superscope.data {
ScopeData::CallSite => break,
_ => scope = superscope,
},
@@ -560,7 +488,7 @@ fn resolve_local<'tcx>(
) {
debug!("resolve_local(pat={:?}, init={:?})", pat, init);
- let blk_scope = visitor.cx.var_parent.map(|(p, _)| p);
+ let blk_scope = visitor.cx.var_parent;
// As an exception to the normal rules governing temporary
// lifetimes, initializers in a let have a temporary lifetime
@@ -625,10 +553,7 @@ fn resolve_local<'tcx>(
if is_binding_pat(pat) {
visitor.scope_tree.record_rvalue_candidate(
expr.hir_id,
- RvalueCandidateType::Pattern {
- target: expr.hir_id.local_id,
- lifetime: blk_scope,
- },
+ RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope },
);
}
}
@@ -733,10 +658,7 @@ fn record_rvalue_scope_if_borrow_expr<'tcx>(
record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
visitor.scope_tree.record_rvalue_candidate(
subexpr.hir_id,
- RvalueCandidateType::Borrow {
- target: subexpr.hir_id.local_id,
- lifetime: blk_id,
- },
+ RvalueCandidate { target: subexpr.hir_id.local_id, lifetime: blk_id },
);
}
hir::ExprKind::Struct(_, fields, _) => {
@@ -783,28 +705,24 @@ fn record_rvalue_scope_if_borrow_expr<'tcx>(
impl<'tcx> ScopeResolutionVisitor<'tcx> {
/// Records the current parent (if any) as the parent of `child_scope`.
- /// Returns the depth of `child_scope`.
- fn record_child_scope(&mut self, child_scope: Scope) -> ScopeDepth {
+ fn record_child_scope(&mut self, child_scope: Scope) {
let parent = self.cx.parent;
self.scope_tree.record_scope_parent(child_scope, parent);
- // If `child_scope` has no parent, it must be the root node, and so has
- // a depth of 1. Otherwise, its depth is one more than its parent's.
- parent.map_or(1, |(_p, d)| d + 1)
}
/// Records the current parent (if any) as the parent of `child_scope`,
/// and sets `child_scope` as the new current parent.
fn enter_scope(&mut self, child_scope: Scope) {
- let child_depth = self.record_child_scope(child_scope);
- self.cx.parent = Some((child_scope, child_depth));
+ self.record_child_scope(child_scope);
+ self.cx.parent = Some(child_scope);
}
- fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) {
+ fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId, terminating: bool) {
// If node was previously marked as a terminating scope during the
// recursive visit of its parent node in the HIR, then we need to
// account for the destruction scope representing the scope of
// the destructors that run immediately after it completes.
- if self.terminating_scopes.contains(&id) {
+ if terminating {
self.enter_scope(Scope { local_id: id, data: ScopeData::Destruction });
}
self.enter_scope(Scope { local_id: id, data: ScopeData::Node });
@@ -816,13 +734,11 @@ fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) {
// visited the body.
let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
let outer_cx = self.cx;
- let outer_ts = mem::take(&mut self.terminating_scopes);
// The 'pessimistic yield' flag is set to true when we are
// processing a `+=` statement and have to make pessimistic
// control flow assumptions. This doesn't apply to nested
// bodies within the `+=` statements. See #69307.
let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
- self.terminating_scopes.insert(hir_id.local_id);
self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::CallSite });
self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::Arguments });
@@ -832,14 +748,13 @@ fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) {
// Restore context we had at the start.
self.expr_and_pat_count = outer_ec;
self.cx = outer_cx;
- self.terminating_scopes = outer_ts;
self.pessimistic_yield = outer_pessimistic_yield;
}
}
impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
fn visit_block(&mut self, b: &'tcx Block<'tcx>) {
- resolve_block(self, b);
+ resolve_block(self, b, false);
}
fn visit_body(&mut self, body: &hir::Body<'tcx>) {
@@ -857,14 +772,13 @@ fn visit_body(&mut self, body: &hir::Body<'tcx>) {
self.enter_body(body.value.hir_id, |this| {
if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() {
// The arguments and `self` are parented to the fn.
- this.cx.var_parent = this.cx.parent.take();
+ this.cx.var_parent = this.cx.parent;
for param in body.params {
this.visit_pat(param.pat);
}
// The body of the every fn is a root scope.
- this.cx.parent = this.cx.var_parent;
- this.visit_expr(body.value)
+ resolve_expr(this, body.value, true);
} else {
// Only functions have an outer terminating (drop) scope, while
// temporaries in constant initializers may be 'static, but only
@@ -885,6 +799,10 @@ fn visit_body(&mut self, body: &hir::Body<'tcx>) {
// (i.e., `'static`), which means that after `g` returns, it drops,
// and all the associated destruction scope rules apply.
this.cx.var_parent = None;
+ this.enter_scope(Scope {
+ local_id: body.value.hir_id.local_id,
+ data: ScopeData::Destruction,
+ });
resolve_local(this, None, Some(body.value));
}
})
@@ -900,7 +818,7 @@ fn visit_stmt(&mut self, s: &'tcx Stmt<'tcx>) {
resolve_stmt(self, s);
}
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
- resolve_expr(self, ex);
+ resolve_expr(self, ex, false);
}
fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) {
resolve_local(self, Some(l.pat), l.init)
@@ -930,7 +848,6 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
scope_tree: ScopeTree::default(),
expr_and_pat_count: 0,
cx: Context { parent: None, var_parent: None },
- terminating_scopes: Default::default(),
pessimistic_yield: false,
fixup_scopes: vec![],
};
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 952af59..83d095a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -188,10 +188,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
/// definition itself. For example, this definition would be illegal:
///
/// ```rust
-/// struct Ref<'a, T> { x: &'a T }
+/// struct StaticRef<T> { x: &'static T }
/// ```
///
-/// because the type did not declare that `T:'a`.
+/// because the type did not declare that `T: 'static`.
///
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 5588631..8e62dce 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -86,6 +86,7 @@ pub(super) fn prohibit_or_lint_bare_trait_object_ty(
"expected a type, found a trait"
);
if self_ty.span.can_be_used_for_suggestions()
+ && poly_trait_ref.trait_ref.trait_def_id().is_some()
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
&& !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag)
{
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index ddaca89..1c23761 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1193,7 +1193,8 @@ fn print_expr_struct(
wth: hir::StructTailExpr<'_>,
) {
self.print_qpath(qpath, true);
- self.word("{");
+ self.nbsp();
+ self.word_space("{");
self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span);
match wth {
hir::StructTailExpr::Base(expr) => {
@@ -1215,20 +1216,13 @@ fn print_expr_struct(
self.word("..");
self.end();
}
- hir::StructTailExpr::None => {
- if !fields.is_empty() {
- self.word(",");
- }
- }
+ hir::StructTailExpr::None => {}
}
-
+ self.space();
self.word("}");
}
fn print_expr_field(&mut self, field: &hir::ExprField<'_>) {
- if self.attrs(field.hir_id).is_empty() {
- self.space();
- }
self.cbox(INDENT_UNIT);
self.print_attrs_as_outer(self.attrs(field.hir_id));
if !field.is_shorthand {
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 4cbc42b..f42ca3a 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -41,8 +41,8 @@
use rustc_attr_parsing::InlineAttr;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, struct_span_code_err};
+use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir, LangItem};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer::relate::RelateResult;
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
@@ -55,7 +55,7 @@
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
};
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -592,63 +592,6 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe
// Create an obligation for `Source: CoerceUnsized<Target>`.
let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
- let root_obligation = Obligation::new(
- self.tcx,
- cause.clone(),
- self.fcx.param_env,
- ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]),
- );
-
- // If the root `Source: CoerceUnsized<Target>` obligation can't possibly hold,
- // we don't have to assume that this is unsizing coercion (it will always lead to an error)
- //
- // However, we don't want to bail early all the time, since the unholdable obligations
- // may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id<This = U>`),
- // so we only bail if there (likely) is another way to convert the types.
- if !self.infcx.predicate_may_hold(&root_obligation) {
- if let Some(dyn_metadata_adt_def_id) = self.tcx.lang_items().get(LangItem::DynMetadata)
- && let Some(metadata_type_def_id) = self.tcx.lang_items().get(LangItem::Metadata)
- {
- self.probe(|_| {
- let ocx = ObligationCtxt::new(&self.infcx);
-
- // returns `true` if `<ty as Pointee>::Metadata` is `DynMetadata<_>`
- let has_dyn_trait_metadata = |ty| {
- let metadata_ty: Result<_, _> = ocx.structurally_normalize_ty(
- &ObligationCause::dummy(),
- self.fcx.param_env,
- Ty::new_alias(
- self.tcx,
- ty::AliasTyKind::Projection,
- AliasTy::new(self.tcx, metadata_type_def_id, [ty]),
- ),
- );
-
- metadata_ty.is_ok_and(|metadata_ty| {
- metadata_ty
- .ty_adt_def()
- .is_some_and(|d| d.did() == dyn_metadata_adt_def_id)
- })
- };
-
- // If both types are raw pointers to a (wrapper over a) trait object,
- // this might be a cast like `*const W<dyn Trait> -> *const dyn Trait`.
- // So it's better to bail and try that. (even if the cast is not possible, for
- // example due to vtables not matching, cast diagnostic will likely still be better)
- //
- // N.B. use `target`, not `coerce_target` (the latter is a var)
- if let &ty::RawPtr(source_pointee, _) = coerce_source.kind()
- && let &ty::RawPtr(target_pointee, _) = target.kind()
- && has_dyn_trait_metadata(source_pointee)
- && has_dyn_trait_metadata(target_pointee)
- {
- return Err(TypeError::Mismatch);
- }
-
- Ok(())
- })?;
- }
- }
// Use a FIFO queue for this custom fulfillment procedure.
//
@@ -657,7 +600,12 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe
// and almost never more than 3. By using a SmallVec we avoid an
// allocation, at the (very small) cost of (occasionally) having to
// shift subsequent elements down when removing the front element.
- let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![root_obligation];
+ let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new(
+ self.tcx,
+ cause,
+ self.fcx.param_env,
+ ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
+ )];
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index c71a5ea..6fb2892 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -1,6 +1,9 @@
//! A different sort of visitor for walking fn bodies. Unlike the
//! normal visitor, which just walks the entire body in one shot, the
//! `ExprUseVisitor` determines how expressions are being used.
+//!
+//! In the compiler, this is only used for upvar inference, but there
+//! are many uses within clippy.
use std::cell::{Ref, RefCell};
use std::ops::Deref;
@@ -25,7 +28,7 @@
use rustc_middle::{bug, span_bug};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::infer::InferCtxtExt;
-use tracing::{debug, trace};
+use tracing::{debug, instrument, trace};
use crate::fn_ctxt::FnCtxt;
@@ -35,11 +38,8 @@ pub trait Delegate<'tcx> {
/// The value found at `place` is moved, depending
/// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
///
- /// Use of a `Copy` type in a ByValue context is considered a use
- /// by `ImmBorrow` and `borrow` is called instead. This is because
- /// a shared borrow is the "minimum access" that would be needed
- /// to perform a copy.
- ///
+ /// If the value is `Copy`, [`copy`][Self::copy] is called instead, which
+ /// by default falls back to [`borrow`][Self::borrow].
///
/// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
/// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
@@ -73,6 +73,10 @@ fn borrow(
/// The value found at `place` is being copied.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
+ ///
+ /// If an implementation is not provided, use of a `Copy` type in a ByValue context is instead
+ /// considered a use by `ImmBorrow` and `borrow` is called instead. This is because a shared
+ /// borrow is the "minimum access" that would be needed to perform a copy.
fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
// In most cases, copying data from `x` is equivalent to doing `*&x`, so by default
// we treat a copy of `x` as a borrow of `x`.
@@ -141,6 +145,8 @@ fn fake_read(
}
}
+/// This trait makes `ExprUseVisitor` usable with both [`FnCtxt`]
+/// and [`LateContext`], depending on where in the compiler it is used.
pub trait TypeInformationCtxt<'tcx> {
type TypeckResults<'a>: Deref<Target = ty::TypeckResults<'tcx>>
where
@@ -154,7 +160,7 @@ pub trait TypeInformationCtxt<'tcx> {
fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
- fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error;
+ fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error;
fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error>;
@@ -189,7 +195,7 @@ fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
(**self).try_structurally_resolve_type(sp, ty)
}
- fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error {
+ fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error {
self.dcx().span_delayed_bug(span, msg.to_string())
}
@@ -239,7 +245,7 @@ fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
t
}
- fn report_error(&self, span: Span, msg: impl ToString) -> ! {
+ fn report_bug(&self, span: Span, msg: impl ToString) -> ! {
span_bug!(span, "{}", msg.to_string())
}
@@ -268,9 +274,9 @@ fn tcx(&self) -> TyCtxt<'tcx> {
}
}
-/// The ExprUseVisitor type
+/// A visitor that reports how each expression is being used.
///
-/// This is the code that actually walks the tree.
+/// See [module-level docs][self] and [`Delegate`] for details.
pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> {
cx: Cx,
/// We use a `RefCell` here so that delegates can mutate themselves, but we can
@@ -314,9 +320,8 @@ pub fn consume_body(&self, body: &hir::Body<'_>) -> Result<(), Cx::Error> {
Ok(())
}
+ #[instrument(skip(self), level = "debug")]
fn consume_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
- debug!("delegate_consume(place_with_id={:?})", place_with_id);
-
if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
} else {
@@ -324,9 +329,8 @@ fn consume_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: Hi
}
}
+ #[instrument(skip(self), level = "debug")]
pub fn consume_clone_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
- debug!("delegate_consume_or_clone(place_with_id={:?})", place_with_id);
-
// `x.use` will do one of the following
// * if it implements `Copy`, it will be a copy
// * if it implements `UseCloned`, it will be a call to `clone`
@@ -351,18 +355,16 @@ fn consume_exprs(&self, exprs: &[hir::Expr<'_>]) -> Result<(), Cx::Error> {
}
// FIXME: It's suspicious that this is public; clippy should probably use `walk_expr`.
+ #[instrument(skip(self), level = "debug")]
pub fn consume_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
- debug!("consume_expr(expr={:?})", expr);
-
let place_with_id = self.cat_expr(expr)?;
self.consume_or_copy(&place_with_id, place_with_id.hir_id);
self.walk_expr(expr)?;
Ok(())
}
+ #[instrument(skip(self), level = "debug")]
pub fn consume_or_clone_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
- debug!("consume_or_clone_expr(expr={:?})", expr);
-
let place_with_id = self.cat_expr(expr)?;
self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id);
self.walk_expr(expr)?;
@@ -376,17 +378,15 @@ fn mutate_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
Ok(())
}
+ #[instrument(skip(self), level = "debug")]
fn borrow_expr(&self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) -> Result<(), Cx::Error> {
- debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk);
-
let place_with_id = self.cat_expr(expr)?;
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
self.walk_expr(expr)
}
+ #[instrument(skip(self), level = "debug")]
pub fn walk_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
- debug!("walk_expr(expr={:?})", expr);
-
self.walk_adjustment(expr)?;
match expr.kind {
@@ -733,9 +733,8 @@ fn walk_local<F>(
/// Indicates that the value of `blk` will be consumed, meaning either copied or moved
/// depending on its type.
+ #[instrument(skip(self), level = "debug")]
fn walk_block(&self, blk: &hir::Block<'_>) -> Result<(), Cx::Error> {
- debug!("walk_block(blk.hir_id={})", blk.hir_id);
-
for stmt in blk.stmts {
self.walk_stmt(stmt)?;
}
@@ -861,7 +860,7 @@ fn walk_adjustment(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
}
/// Walks the autoref `autoref` applied to the autoderef'd
- /// `expr`. `base_place` is the mem-categorized form of `expr`
+ /// `expr`. `base_place` is `expr` represented as a place,
/// after all relevant autoderefs have occurred.
fn walk_autoref(
&self,
@@ -942,14 +941,13 @@ fn walk_irrefutable_pat(
}
/// The core driver for walking a pattern
+ #[instrument(skip(self), level = "debug")]
fn walk_pat(
&self,
discr_place: &PlaceWithHirId<'tcx>,
pat: &hir::Pat<'_>,
has_guard: bool,
) -> Result<(), Cx::Error> {
- debug!("walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})", discr_place, pat, has_guard);
-
let tcx = self.cx.tcx();
self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
match pat.kind {
@@ -1042,6 +1040,7 @@ fn walk_pat(
///
/// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
/// closure as the DefId.
+ #[instrument(skip(self), level = "debug")]
fn walk_captures(&self, closure_expr: &hir::Closure<'_>) -> Result<(), Cx::Error> {
fn upvar_is_local_variable(
upvars: Option<&FxIndexMap<HirId, hir::Upvar>>,
@@ -1051,8 +1050,6 @@ fn upvar_is_local_variable(
upvars.map(|upvars| !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure)
}
- debug!("walk_captures({:?})", closure_expr);
-
let tcx = self.cx.tcx();
let closure_def_id = closure_expr.def_id;
// For purposes of this function, coroutine and closures are equivalent.
@@ -1164,55 +1161,17 @@ fn upvar_is_local_variable(
}
}
-/// The job of the categorization methods is to analyze an expression to
-/// determine what kind of memory is used in evaluating it (for example,
-/// where dereferences occur and what kind of pointer is dereferenced;
-/// whether the memory is mutable, etc.).
+/// The job of the methods whose name starts with `cat_` is to analyze
+/// expressions and construct the corresponding [`Place`]s. The `cat`
+/// stands for "categorize", this is a leftover from long ago when
+/// places were called "categorizations".
///
-/// Categorization effectively transforms all of our expressions into
-/// expressions of the following forms (the actual enum has many more
-/// possibilities, naturally, but they are all variants of these base
-/// forms):
-/// ```ignore (not-rust)
-/// E = rvalue // some computed rvalue
-/// | x // address of a local variable or argument
-/// | *E // deref of a ptr
-/// | E.comp // access to an interior component
-/// ```
-/// Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
-/// address where the result is to be found. If Expr is a place, then this
-/// is the address of the place. If `Expr` is an rvalue, this is the address of
-/// some temporary spot in memory where the result is stored.
-///
-/// Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)`
-/// as follows:
-///
-/// - `cat`: what kind of expression was this? This is a subset of the
-/// full expression forms which only includes those that we care about
-/// for the purpose of the analysis.
-/// - `mutbl`: mutability of the address `A`.
-/// - `ty`: the type of data found at the address `A`.
-///
-/// The resulting categorization tree differs somewhat from the expressions
-/// themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is
-/// decomposed into two operations: a dereference to reach the array data and
-/// then an index to jump forward to the relevant item.
-///
-/// ## By-reference upvars
-///
-/// One part of the codegen which may be non-obvious is that we translate
-/// closure upvars into the dereference of a borrowed pointer; this more closely
-/// resembles the runtime codegen. So, for example, if we had:
-///
-/// let mut x = 3;
-/// let y = 5;
-/// let inc = || x += y;
-///
-/// Then when we categorize `x` (*within* the closure) we would yield a
-/// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
-/// tied to `x`. The type of `x'` will be a borrowed pointer.
+/// Note that a [`Place`] differs somewhat from the expression itself. For
+/// example, auto-derefs are explicit. Also, an index `a[b]` is decomposed into
+/// two operations: a dereference to reach the array data and then an index to
+/// jump forward to the relevant item.
impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
- fn resolve_type_vars_or_error(
+ fn resolve_type_vars_or_bug(
&self,
id: HirId,
ty: Option<Ty<'tcx>>,
@@ -1222,10 +1181,10 @@ fn resolve_type_vars_or_error(
let ty = self.cx.resolve_vars_if_possible(ty);
self.cx.error_reported_in_ty(ty)?;
if ty.is_ty_var() {
- debug!("resolve_type_vars_or_error: infer var from {:?}", ty);
+ debug!("resolve_type_vars_or_bug: infer var from {:?}", ty);
Err(self
.cx
- .report_error(self.cx.tcx().hir().span(id), "encountered type variable"))
+ .report_bug(self.cx.tcx().hir().span(id), "encountered type variable"))
} else {
Ok(ty)
}
@@ -1233,24 +1192,21 @@ fn resolve_type_vars_or_error(
None => {
// FIXME: We shouldn't be relying on the infcx being tainted.
self.cx.tainted_by_errors()?;
- bug!(
- "no type for node {} in mem_categorization",
- self.cx.tcx().hir_id_to_string(id)
- );
+ bug!("no type for node {} in ExprUseVisitor", self.cx.tcx().hir_id_to_string(id));
}
}
}
fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, Cx::Error> {
- self.resolve_type_vars_or_error(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
+ self.resolve_type_vars_or_bug(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
}
fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
- self.resolve_type_vars_or_error(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
+ self.resolve_type_vars_or_bug(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
}
fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
- self.resolve_type_vars_or_error(
+ self.resolve_type_vars_or_bug(
expr.hir_id,
self.cx.typeck_results().expr_ty_adjusted_opt(expr),
)
@@ -1285,7 +1241,7 @@ fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
self.pat_ty_unadjusted(pat)
}
- /// Like `TypeckResults::pat_ty`, but ignores implicit `&` patterns.
+ /// Like [`Self::pat_ty_adjusted`], but ignores implicit `&` patterns.
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
let base_ty = self.node_ty(pat.hir_id)?;
trace!(?base_ty);
@@ -1315,7 +1271,7 @@ fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
debug!("By-ref binding of non-derefable type");
Err(self
.cx
- .report_error(pat.span, "by-ref binding of non-derefable type"))
+ .report_bug(pat.span, "by-ref binding of non-derefable type"))
}
}
} else {
@@ -1511,7 +1467,7 @@ fn cat_res(
}
}
- def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def),
+ def => span_bug!(span, "unexpected definition in ExprUseVisitor: {:?}", def),
}
}
@@ -1604,7 +1560,7 @@ fn cat_deref(
Some(ty) => ty,
None => {
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
- return Err(self.cx.report_error(
+ return Err(self.cx.report_bug(
self.cx.tcx().hir().span(node),
"explicit deref of non-derefable type",
));
@@ -1629,7 +1585,7 @@ fn variant_index_for_adt(
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
return Err(self
.cx
- .report_error(span, "struct or tuple struct pattern not applied to an ADT"));
+ .report_bug(span, "struct or tuple struct pattern not applied to an ADT"));
};
match res {
@@ -1675,7 +1631,7 @@ fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> Result<usize,
let ty = self.cx.typeck_results().node_type(pat_hir_id);
match self.cx.try_structurally_resolve_type(span, ty).kind() {
ty::Tuple(args) => Ok(args.len()),
- _ => Err(self.cx.report_error(span, "tuple pattern not applied to a tuple")),
+ _ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")),
}
}
@@ -1854,7 +1810,7 @@ fn cat_pattern<F>(
debug!("explicit index of non-indexable type {:?}", place_with_id);
return Err(self
.cx
- .report_error(pat.span, "explicit index of non-indexable type"));
+ .report_bug(pat.span, "explicit index of non-indexable type"));
};
let elt_place = self.cat_projection(
pat.hir_id,
diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
index 98d7f77..973dc71 100644
--- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
@@ -2,7 +2,7 @@
use hir::def_id::DefId;
use rustc_hir as hir;
use rustc_middle::bug;
-use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree};
+use rustc_middle::middle::region::{RvalueCandidate, Scope, ScopeTree};
use rustc_middle::ty::RvalueScopes;
use tracing::debug;
@@ -55,15 +55,11 @@ fn record_rvalue_scope_rec(
fn record_rvalue_scope(
rvalue_scopes: &mut RvalueScopes,
expr: &hir::Expr<'_>,
- candidate: &RvalueCandidateType,
+ candidate: &RvalueCandidate,
) {
debug!("resolve_rvalue_scope(expr={expr:?}, candidate={candidate:?})");
- match candidate {
- RvalueCandidateType::Borrow { lifetime, .. }
- | RvalueCandidateType::Pattern { lifetime, .. } => {
- record_rvalue_scope_rec(rvalue_scopes, expr, *lifetime)
- } // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments
- }
+ record_rvalue_scope_rec(rvalue_scopes, expr, candidate.lifetime)
+ // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments
}
pub(crate) fn resolve_rvalue_scopes<'a, 'tcx>(
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index fc98a60..d07bfad 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -18,12 +18,12 @@
//! from there).
//!
//! The fact that we are inferring borrow kinds as we go results in a
-//! semi-hacky interaction with mem-categorization. In particular,
-//! mem-categorization will query the current borrow kind as it
-//! categorizes, and we'll return the *current* value, but this may get
+//! semi-hacky interaction with the way `ExprUseVisitor` is computing
+//! `Place`s. In particular, it will query the current borrow kind as it
+//! goes, and we'll return the *current* value, but this may get
//! adjusted later. Therefore, in this module, we generally ignore the
-//! borrow kind (and derived mutabilities) that are returned from
-//! mem-categorization, since they may be inaccurate. (Another option
+//! borrow kind (and derived mutabilities) that `ExprUseVisitor` returns
+//! within `Place`s, since they may be inaccurate. (Another option
//! would be to use a unification scheme, where instead of returning a
//! concrete borrow kind like `ty::ImmBorrow`, we return a
//! `ty::InferBorrow(upvar_id)` or something like that, but this would
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 215b133..d9297fb 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -198,13 +198,12 @@ fn register_hidden_type(
/// it hasn't previously been defined. This does not emit any
/// constraints and it's the responsibility of the caller to make
/// sure that the item bounds of the opaque are checked.
- pub fn inject_new_hidden_type_unchecked(
+ pub fn register_hidden_type_in_storage(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
hidden_ty: OpaqueHiddenType<'tcx>,
- ) {
- let prev = self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty);
- assert_eq!(prev, None);
+ ) -> Option<Ty<'tcx>> {
+ self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty)
}
/// Insert a hidden type into the opaque type storage, equating it
diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index ffbe708..4b9c71d 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -50,11 +50,5 @@
interface_proc_macro_crate_panic_abort =
building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
-interface_rustc_error_fatal =
- fatal error triggered by #[rustc_error]
-
-interface_rustc_error_unexpected_annotation =
- unexpected annotation used with `#[rustc_error(...)]`!
-
interface_temps_dir_error =
failed to find or create the directory specified by `--temps-dir`
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index ef0235b..6b39b4f 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -74,20 +74,6 @@ pub struct GeneratedFileConflictsWithDirectory<'a> {
pub struct OutDirError;
#[derive(Diagnostic)]
-#[diag(interface_rustc_error_fatal)]
-pub struct RustcErrorFatal {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(interface_rustc_error_unexpected_annotation)]
-pub struct RustcErrorUnexpectedAnnotation {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(interface_failed_writing_file)]
pub struct FailedWritingFile<'a> {
pub path: &'a Path,
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 8be7ba7..93013c8 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1,5 +1,5 @@
use std::any::Any;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
use std::io::{self, BufWriter, Write};
use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock, OnceLock};
@@ -361,6 +361,31 @@ const fn as_str(self) -> &'static str {
)
}
+fn env_var_os<'tcx>(tcx: TyCtxt<'tcx>, key: &'tcx OsStr) -> Option<&'tcx OsStr> {
+ let value = env::var_os(key);
+
+ let value_tcx = value.as_ref().map(|value| {
+ let encoded_bytes = tcx.arena.alloc_slice(value.as_encoded_bytes());
+ debug_assert_eq!(value.as_encoded_bytes(), encoded_bytes);
+ // SAFETY: The bytes came from `as_encoded_bytes`, and we assume that
+ // `alloc_slice` is implemented correctly, and passes the same bytes
+ // back (debug asserted above).
+ unsafe { OsStr::from_encoded_bytes_unchecked(encoded_bytes) }
+ });
+
+ // Also add the variable to Cargo's dependency tracking
+ //
+ // NOTE: This only works for passes run before `write_dep_info`. See that
+ // for extension points for configuring environment variables to be
+ // properly change-tracked.
+ tcx.sess.psess.env_depinfo.borrow_mut().insert((
+ Symbol::intern(&key.to_string_lossy()),
+ value.as_ref().and_then(|value| value.to_str()).map(|value| Symbol::intern(&value)),
+ ));
+
+ value_tcx
+}
+
// Returns all the paths that correspond to generated files.
fn generated_output_paths(
tcx: TyCtxt<'_>,
@@ -725,6 +750,7 @@ pub fn write_dep_info(tcx: TyCtxt<'_>) {
|tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
providers.early_lint_checks = early_lint_checks;
+ providers.env_var_os = env_var_os;
limits::provide(providers);
proc_macro_decls::provide(providers);
rustc_const_eval::provide(providers);
@@ -1041,48 +1067,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
});
}
-/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
-/// to write UI tests that actually test that compilation succeeds without reporting
-/// an error.
-fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
- let Some((def_id, _)) = tcx.entry_fn(()) else { return };
- for attr in tcx.get_attrs(def_id, sym::rustc_error) {
- match attr.meta_item_list() {
- // Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
- Some(list)
- if list.iter().any(|list_item| {
- matches!(
- list_item.ident().map(|i| i.name),
- Some(sym::delayed_bug_from_inside_query)
- )
- }) =>
- {
- tcx.ensure_ok().trigger_delayed_bug(def_id);
- }
-
- // Bare `#[rustc_error]`.
- None => {
- tcx.dcx().emit_fatal(errors::RustcErrorFatal { span: tcx.def_span(def_id) });
- }
-
- // Some other attribute.
- Some(_) => {
- tcx.dcx().emit_warn(errors::RustcErrorUnexpectedAnnotation {
- span: tcx.def_span(def_id),
- });
- }
- }
- }
-}
-
/// Runs the codegen backend, after which the AST and analysis can
/// be discarded.
pub(crate) fn start_codegen<'tcx>(
codegen_backend: &dyn CodegenBackend,
tcx: TyCtxt<'tcx>,
) -> Box<dyn Any> {
- // Hook for UI tests.
- check_for_rustc_errors_attr(tcx);
+ // Hook for tests.
+ if let Some((def_id, _)) = tcx.entry_fn(())
+ && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query)
+ {
+ tcx.ensure_ok().trigger_delayed_bug(def_id);
+ }
// Don't run this test assertions when not doing codegen. Compiletest tries to build
// build-fail tests in check mode first and expects it to not give an error in that case.
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index b44be17..4592e01 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -787,6 +787,7 @@ macro_rules! tracked {
tracked!(direct_access_external_data, Some(true));
tracked!(dual_proc_macros, true);
tracked!(dwarf_version, Some(5));
+ tracked!(embed_metadata, false);
tracked!(embed_source, true);
tracked!(emit_thin_lto, false);
tracked!(emscripten_wasm_eh, true);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 333786f..83d8093 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -18,7 +18,7 @@
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMapInputs;
-use rustc_span::{Symbol, sym};
+use rustc_span::{SessionGlobals, Symbol, sym};
use rustc_target::spec::Target;
use tracing::info;
@@ -188,26 +188,11 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
// On deadlock, creates a new thread and forwards information in thread
// locals to it. The new thread runs the deadlock handler.
- // Get a `GlobalCtxt` reference from `CurrentGcx` as we cannot rely on having a
- // `TyCtxt` TLS reference here.
- let query_map = current_gcx2.access(|gcx| {
- tls::enter_context(&tls::ImplicitCtxt::new(gcx), || {
- tls::with(|tcx| {
- match QueryCtxt::new(tcx).collect_active_jobs() {
- Ok(query_map) => query_map,
- Err(_) => {
- // There was an unexpected error collecting all active jobs, which we need
- // to find cycles to break.
- // We want to avoid panicking in the deadlock handler, so we abort instead.
- eprintln!("internal compiler error: failed to get query map in deadlock handler, aborting process");
- process::abort();
- }
- }
- })
- })
- });
- let query_map = FromDyn::from(query_map);
+ let current_gcx2 = current_gcx2.clone();
let registry = rayon_core::Registry::current();
+ let session_globals = rustc_span::with_session_globals(|session_globals| {
+ session_globals as *const SessionGlobals as usize
+ });
thread::Builder::new()
.name("rustc query cycle handler".to_string())
.spawn(move || {
@@ -217,7 +202,24 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
// otherwise the compiler could just hang,
process::abort();
});
- break_query_cycles(query_map.into_inner(), ®istry);
+
+ // Get a `GlobalCtxt` reference from `CurrentGcx` as we cannot rely on having a
+ // `TyCtxt` TLS reference here.
+ current_gcx2.access(|gcx| {
+ tls::enter_context(&tls::ImplicitCtxt::new(gcx), || {
+ tls::with(|tcx| {
+ // Accessing session globals is sound as they outlive `GlobalCtxt`.
+ // They are needed to hash query keys containing spans or symbols.
+ let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || {
+ // Ensure there was no errors collecting all active jobs.
+ // We need the complete map to ensure we find a cycle to break.
+ QueryCtxt::new(tcx).collect_active_jobs().ok().expect("failed to collect active queries in deadlock handler")
+ });
+ break_query_cycles(query_map, ®istry);
+ })
+ })
+ });
+
on_panic.disable();
})
.unwrap();
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index d518658..782d328 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -456,6 +456,10 @@
lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable
+lint_invalid_null_arguments = calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ .origin = null pointer originates from here
+ .doc = for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
.label = casting happened here
@@ -680,15 +684,6 @@
lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope
.label = names from parent modules are not accessible without an explicit import
-lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false
- .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
- .label = expression has type `{$orig_ty}`
-
-lint_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false
-
-lint_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false
- .label = expression has type `{$orig_ty}`
-
lint_query_instability = using `{$query}` can result in unstable query results
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
@@ -799,6 +794,9 @@
lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
.note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
+lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
+ .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
+
lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing
.label = argument has type `{$arg_ty}`
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value
@@ -978,6 +976,15 @@
lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result
+lint_useless_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false
+ .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+ .label = expression has type `{$orig_ty}`
+
+lint_useless_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false
+
+lint_useless_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false
+ .label = expression has type `{$orig_ty}`
+
lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
lint_variant_size_differences =
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9dccd4a..c56dbc2 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -330,7 +330,6 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast
if let FnKind::Fn(
ctxt,
_,
- _,
ast::Fn {
sig: ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. },
body,
@@ -3116,6 +3115,7 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
for item in &krate.items {
if let ast::ItemKind::Mod(
_,
+ ident,
ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _),
) = item.kind
{
@@ -3123,7 +3123,7 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
continue;
}
- match item.ident.name.as_str() {
+ match ident.name.as_str() {
"lib" => cx.emit_span_lint(
SPECIAL_MODULE_NAME,
item.span,
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index b359ee7..1d4be24 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -1,24 +1,21 @@
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
//! Clippy.
-use rustc_ast as ast;
+use rustc_hir::HirId;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
-use rustc_hir::{
- AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat,
- PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Ty, TyKind,
-};
use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::{Span, sym};
use tracing::debug;
+use {rustc_ast as ast, rustc_hir as hir};
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
- UntranslatableDiag,
+ TypeIrTraitUsage, UntranslatableDiag,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@@ -37,9 +34,12 @@
declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
impl LateLintPass<'_> for DefaultHashTypes {
- fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
+ fn check_path(&mut self, cx: &LateContext<'_>, path: &hir::Path<'_>, hir_id: HirId) {
let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return };
- if matches!(cx.tcx.hir_node(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) {
+ if matches!(
+ cx.tcx.hir_node(hir_id),
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. })
+ ) {
// Don't lint imports, only actual usages.
return;
}
@@ -60,10 +60,10 @@ fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
/// get the `DefId` and `GenericArgsRef` of the function.
fn typeck_results_of_method_fn<'tcx>(
cx: &LateContext<'tcx>,
- expr: &Expr<'_>,
+ expr: &hir::Expr<'_>,
) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> {
match expr.kind {
- ExprKind::MethodCall(segment, ..)
+ hir::ExprKind::MethodCall(segment, ..)
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
{
Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id)))
@@ -102,7 +102,7 @@ fn typeck_results_of_method_fn<'tcx>(
declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
impl LateLintPass<'_> for QueryStability {
- fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args)
{
@@ -164,21 +164,25 @@ fn check_path(
}
}
- fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) {
+ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) {
match &ty.kind {
- TyKind::Path(QPath::Resolved(_, path)) => {
+ hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
if lint_ty_kind_usage(cx, &path.res) {
let span = match cx.tcx.parent_hir_node(ty.hir_id) {
- Node::PatExpr(PatExpr { kind: PatExprKind::Path(qpath), .. })
- | Node::Pat(Pat {
- kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..),
+ hir::Node::PatExpr(hir::PatExpr {
+ kind: hir::PatExprKind::Path(qpath),
..
})
- | Node::Expr(
- Expr { kind: ExprKind::Path(qpath), .. }
- | &Expr { kind: ExprKind::Struct(qpath, ..), .. },
+ | hir::Node::Pat(hir::Pat {
+ kind:
+ hir::PatKind::TupleStruct(qpath, ..) | hir::PatKind::Struct(qpath, ..),
+ ..
+ })
+ | hir::Node::Expr(
+ hir::Expr { kind: hir::ExprKind::Path(qpath), .. }
+ | &hir::Expr { kind: hir::ExprKind::Struct(qpath, ..), .. },
) => {
- if let QPath::TypeRelative(qpath_ty, ..) = qpath
+ if let hir::QPath::TypeRelative(qpath_ty, ..) = qpath
&& qpath_ty.hir_id == ty.hir_id
{
Some(path.span)
@@ -223,7 +227,7 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, res: &Res) -> bool {
}
}
-fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
+fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &hir::Path<'_>) -> Option<String> {
match &path.res {
Res::Def(_, def_id) => {
if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(*def_id) {
@@ -244,13 +248,17 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
None
}
-fn gen_args(segment: &PathSegment<'_>) -> String {
+fn gen_args(segment: &hir::PathSegment<'_>) -> String {
if let Some(args) = &segment.args {
let lifetimes = args
.args
.iter()
.filter_map(|arg| {
- if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None }
+ if let hir::GenericArg::Lifetime(lt) = arg {
+ Some(lt.ident.to_string())
+ } else {
+ None
+ }
})
.collect::<Vec<_>>();
@@ -272,7 +280,7 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
}
declare_tool_lint! {
- /// The `usage_of_type_ir_inherent` lint detects usage `rustc_type_ir::inherent`.
+ /// The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`.
///
/// This module should only be used within the trait solver.
pub rustc::USAGE_OF_TYPE_IR_INHERENT,
@@ -281,10 +289,43 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
report_in_external_macro: true
}
-declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]);
+declare_tool_lint! {
+ /// The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`,
+ /// or `rustc_infer::InferCtxtLike`.
+ ///
+ /// Methods of this trait should only be used within the type system abstraction layer,
+ /// and in the generic next trait solver implementation. Look for an analogously named
+ /// method on `TyCtxt` or `InferCtxt` (respectively).
+ pub rustc::USAGE_OF_TYPE_IR_TRAITS,
+ Allow,
+ "usage `rustc_type_ir`-specific abstraction traits outside of trait system",
+ report_in_external_macro: true
+}
+
+declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]);
impl<'tcx> LateLintPass<'tcx> for TypeIr {
- fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+ let res_def_id = match expr.kind {
+ hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => path.res.opt_def_id(),
+ hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::MethodCall(..) => {
+ cx.typeck_results().type_dependent_def_id(expr.hir_id)
+ }
+ _ => return,
+ };
+ let Some(res_def_id) = res_def_id else {
+ return;
+ };
+ if let Some(assoc_item) = cx.tcx.opt_associated_item(res_def_id)
+ && let Some(trait_def_id) = assoc_item.trait_container(cx.tcx)
+ && (cx.tcx.is_diagnostic_item(sym::type_ir_interner, trait_def_id)
+ | cx.tcx.is_diagnostic_item(sym::type_ir_infer_ctxt_like, trait_def_id))
+ {
+ cx.emit_span_lint(USAGE_OF_TYPE_IR_TRAITS, expr.span, TypeIrTraitUsage);
+ }
+ }
+
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
@@ -394,15 +435,15 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
impl LateLintPass<'_> for Diagnostics {
- fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
- let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| {
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
+ let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| {
let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
result
};
// Only check function calls and method calls.
let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind {
- ExprKind::Call(callee, args) => {
+ hir::ExprKind::Call(callee, args) => {
match cx.typeck_results().node_type(callee.hir_id).kind() {
&ty::FnDef(def_id, fn_gen_args) => {
(callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false))
@@ -410,7 +451,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
_ => return, // occurs for fns passed as args
}
}
- ExprKind::MethodCall(_segment, _recv, args, _span) => {
+ hir::ExprKind::MethodCall(_segment, _recv, args, _span) => {
let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr)
else {
return;
@@ -514,8 +555,8 @@ fn diagnostic_outside_of_impl<'cx>(
let mut is_inside_appropriate_impl = false;
for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) {
debug!(?parent);
- if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent
- && let Impl { of_trait: Some(of_trait), .. } = impl_
+ if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent
+ && let hir::Impl { of_trait: Some(of_trait), .. } = impl_
&& let Some(def_id) = of_trait.trait_def_id()
&& let Some(name) = cx.tcx.get_diagnostic_name(def_id)
&& matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
@@ -543,8 +584,8 @@ fn diagnostic_outside_of_impl<'cx>(
declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]);
impl LateLintPass<'_> for BadOptAccess {
- fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
- let ExprKind::Field(base, target) = expr.kind else { return };
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
+ let hir::ExprKind::Field(base, target) = expr.kind else { return };
let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return };
// Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be
// avoided.
@@ -581,9 +622,12 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
- if let ExprKind::Binary(BinOp { node: BinOpKind::Eq | BinOpKind::Ne, .. }, lhs, rhs) =
- expr.kind
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
+ if let hir::ExprKind::Binary(
+ hir::BinOp { node: hir::BinOpKind::Eq | hir::BinOpKind::Ne, .. },
+ lhs,
+ rhs,
+ ) = expr.kind
{
if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
@@ -592,9 +636,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
}
}
-fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
match &expr.kind {
- ExprKind::MethodCall(..) => cx
+ hir::ExprKind::MethodCall(..) => cx
.typeck_results()
.type_dependent_def_id(expr.hir_id)
.is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)),
@@ -617,11 +661,11 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
- if let ExprKind::Call(path, [arg]) = expr.kind
- && let ExprKind::Path(ref qpath) = path.kind
+ if let hir::ExprKind::Call(path, [arg]) = expr.kind
+ && let hir::ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
- && let ExprKind::Lit(kind) = arg.kind
+ && let hir::ExprKind::Lit(kind) = arg.kind
&& let rustc_ast::LitKind::Str(_, _) = kind.node
{
cx.emit_span_lint(
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c38a754..25878c7 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -80,6 +80,7 @@
mod unit_bindings;
mod unqualified_local_imports;
mod unused;
+mod utils;
use async_closures::AsyncClosureUsage;
use async_fn_in_trait::AsyncFnInTrait;
@@ -645,6 +646,7 @@ fn register_internals(store: &mut LintStore) {
LintId::of(USAGE_OF_QUALIFIED_TY),
LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
LintId::of(USAGE_OF_TYPE_IR_INHERENT),
+ LintId::of(USAGE_OF_TYPE_IR_TRAITS),
LintId::of(BAD_OPT_ACCESS),
LintId::of(SPAN_USE_EQ_CTXT),
],
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 0058630..55d010e 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -591,24 +591,40 @@ pub(crate) struct ExpectationNote {
// ptr_nulls.rs
#[derive(LintDiagnostic)]
-pub(crate) enum PtrNullChecksDiag<'a> {
- #[diag(lint_ptr_null_checks_fn_ptr)]
- #[help(lint_help)]
+pub(crate) enum UselessPtrNullChecksDiag<'a> {
+ #[diag(lint_useless_ptr_null_checks_fn_ptr)]
+ #[help]
FnPtr {
orig_ty: Ty<'a>,
#[label]
label: Span,
},
- #[diag(lint_ptr_null_checks_ref)]
+ #[diag(lint_useless_ptr_null_checks_ref)]
Ref {
orig_ty: Ty<'a>,
#[label]
label: Span,
},
- #[diag(lint_ptr_null_checks_fn_ret)]
+ #[diag(lint_useless_ptr_null_checks_fn_ret)]
FnRet { fn_name: Ident },
}
+#[derive(LintDiagnostic)]
+pub(crate) enum InvalidNullArgumentsDiag {
+ #[diag(lint_invalid_null_arguments)]
+ #[help(lint_doc)]
+ NullPtrInline {
+ #[label(lint_origin)]
+ null_span: Span,
+ },
+ #[diag(lint_invalid_null_arguments)]
+ #[help(lint_doc)]
+ NullPtrThroughBinding {
+ #[note(lint_origin)]
+ null_span: Span,
+ },
+}
+
// for_loops_over_fallibles.rs
#[derive(LintDiagnostic)]
#[diag(lint_for_loops_over_fallibles)]
@@ -944,6 +960,11 @@ pub(crate) struct TyQualified {
pub(crate) struct TypeIrInherentUsage;
#[derive(LintDiagnostic)]
+#[diag(lint_type_ir_trait_usage)]
+#[note]
+pub(crate) struct TypeIrTraitUsage;
+
+#[derive(LintDiagnostic)]
#[diag(lint_non_glob_import_type_ir_inherent)]
pub(crate) struct NonGlobImportTypeIrInherent {
#[suggestion(code = "{snippet}", applicability = "maybe-incorrect")]
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index f8e0a94..9ed11d9 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -104,8 +104,10 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
// determining if we are in a doctest context can't currently be determined
// by the code itself (there are no specific attributes), but fortunately rustdoc
// sets a perma-unstable env var for libtest so we just reuse that for now
- let is_at_toplevel_doctest =
- || self.body_depth == 2 && std::env::var("UNSTABLE_RUSTDOC_TEST_PATH").is_ok();
+ let is_at_toplevel_doctest = || {
+ self.body_depth == 2
+ && cx.tcx.env_var_os("UNSTABLE_RUSTDOC_TEST_PATH".as_ref()).is_some()
+ };
match item.kind {
ItemKind::Impl(impl_) => {
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 752636c..df567e8 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -172,20 +172,22 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
}
match &it.kind {
- ast::ItemKind::TyAlias(..)
- | ast::ItemKind::Enum(..)
- | ast::ItemKind::Struct(..)
- | ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident),
- ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident),
- ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident),
+ ast::ItemKind::TyAlias(box ast::TyAlias { ident, .. })
+ | ast::ItemKind::Enum(ident, ..)
+ | ast::ItemKind::Struct(ident, ..)
+ | ast::ItemKind::Union(ident, ..) => self.check_case(cx, "type", ident),
+ ast::ItemKind::Trait(box ast::Trait { ident, .. }) => {
+ self.check_case(cx, "trait", ident)
+ }
+ ast::ItemKind::TraitAlias(ident, _, _) => self.check_case(cx, "trait alias", ident),
// N.B. This check is only for inherent associated types, so that we don't lint against
// trait impls where we should have warned for the trait definition already.
ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => {
for it in items {
// FIXME: this doesn't respect `#[allow(..)]` on the item itself.
- if let ast::AssocItemKind::Type(..) = it.kind {
- self.check_case(cx, "associated type", &it.ident);
+ if let ast::AssocItemKind::Type(alias) = &it.kind {
+ self.check_case(cx, "associated type", &alias.ident);
}
}
}
@@ -194,8 +196,8 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
}
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
- if let ast::AssocItemKind::Type(..) = it.kind {
- self.check_case(cx, "associated type", &it.ident);
+ if let ast::AssocItemKind::Type(alias) = &it.kind {
+ self.check_case(cx, "associated type", &alias.ident);
}
}
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index 1489f9d..826bce2 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -1,9 +1,11 @@
use rustc_ast::LitKind;
use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
+use rustc_middle::ty::RawPtr;
use rustc_session::{declare_lint, declare_lint_pass};
-use rustc_span::sym;
+use rustc_span::{Span, sym};
-use crate::lints::PtrNullChecksDiag;
+use crate::lints::{InvalidNullArgumentsDiag, UselessPtrNullChecksDiag};
+use crate::utils::peel_casts;
use crate::{LateContext, LateLintPass, LintContext};
declare_lint! {
@@ -31,17 +33,40 @@
"useless checking of non-null-typed pointer"
}
-declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]);
+declare_lint! {
+ /// The `invalid_null_arguments` lint checks for invalid usage of null pointers in arguments.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// # use std::{slice, ptr};
+ /// // Undefined behavior
+ /// # let _slice: &[u8] =
+ /// unsafe { slice::from_raw_parts(ptr::null(), 0) };
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Calling methods whos safety invariants requires non-null ptr with a null pointer
+ /// is [Undefined Behavior](https://doc.rust-lang.org/reference/behavior-considered-undefined.html)!
+ INVALID_NULL_ARGUMENTS,
+ Deny,
+ "invalid null pointer in arguments"
+}
+
+declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS, INVALID_NULL_ARGUMENTS]);
/// This function checks if the expression is from a series of consecutive casts,
/// ie. `(my_fn as *const _ as *mut _).cast_mut()` and whether the original expression is either
/// a fn ptr, a reference, or a function call whose definition is
/// annotated with `#![rustc_never_returns_null_ptr]`.
/// If this situation is present, the function returns the appropriate diagnostic.
-fn incorrect_check<'a, 'tcx: 'a>(
+fn useless_check<'a, 'tcx: 'a>(
cx: &'a LateContext<'tcx>,
mut e: &'a Expr<'a>,
-) -> Option<PtrNullChecksDiag<'tcx>> {
+) -> Option<UselessPtrNullChecksDiag<'tcx>> {
let mut had_at_least_one_cast = false;
loop {
e = e.peel_blocks();
@@ -50,14 +75,14 @@ fn incorrect_check<'a, 'tcx: 'a>(
&& cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr)
&& let Some(fn_name) = cx.tcx.opt_item_ident(def_id)
{
- return Some(PtrNullChecksDiag::FnRet { fn_name });
+ return Some(UselessPtrNullChecksDiag::FnRet { fn_name });
} else if let ExprKind::Call(path, _args) = e.kind
&& let ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr)
&& let Some(fn_name) = cx.tcx.opt_item_ident(def_id)
{
- return Some(PtrNullChecksDiag::FnRet { fn_name });
+ return Some(UselessPtrNullChecksDiag::FnRet { fn_name });
}
e = if let ExprKind::Cast(expr, t) = e.kind
&& let TyKind::Ptr(_) = t.kind
@@ -73,9 +98,9 @@ fn incorrect_check<'a, 'tcx: 'a>(
} else if had_at_least_one_cast {
let orig_ty = cx.typeck_results().expr_ty(e);
return if orig_ty.is_fn() {
- Some(PtrNullChecksDiag::FnPtr { orig_ty, label: e.span })
+ Some(UselessPtrNullChecksDiag::FnPtr { orig_ty, label: e.span })
} else if orig_ty.is_ref() {
- Some(PtrNullChecksDiag::Ref { orig_ty, label: e.span })
+ Some(UselessPtrNullChecksDiag::Ref { orig_ty, label: e.span })
} else {
None
};
@@ -85,6 +110,25 @@ fn incorrect_check<'a, 'tcx: 'a>(
}
}
+/// Checks if the given expression is a null pointer (modulo casting)
+fn is_null_ptr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Span> {
+ let (expr, _) = peel_casts(cx, expr);
+
+ if let ExprKind::Call(path, []) = expr.kind
+ && let ExprKind::Path(ref qpath) = path.kind
+ && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+ && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+ {
+ (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut).then_some(expr.span)
+ } else if let ExprKind::Lit(spanned) = expr.kind
+ && let LitKind::Int(v, _) = spanned.node
+ {
+ (v == 0).then_some(expr.span)
+ } else {
+ None
+ }
+}
+
impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
match expr.kind {
@@ -97,12 +141,68 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
cx.tcx.get_diagnostic_name(def_id),
Some(sym::ptr_const_is_null | sym::ptr_is_null)
)
- && let Some(diag) = incorrect_check(cx, arg) =>
+ && let Some(diag) = useless_check(cx, arg) =>
{
cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
}
// Catching:
+ // <path>(arg...) where `arg` is null-ptr and `path` is a fn that expect non-null-ptr
+ ExprKind::Call(path, args)
+ if let ExprKind::Path(ref qpath) = path.kind
+ && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+ && let Some(diag_name) = cx.tcx.get_diagnostic_name(def_id) =>
+ {
+ // `arg` positions where null would cause U.B and whenever ZST are allowed.
+ //
+ // We should probably have a `rustc` attribute, but checking them is costly,
+ // maybe if we checked for null ptr first, it would be acceptable?
+ let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name {
+ sym::ptr_read
+ | sym::ptr_read_unaligned
+ | sym::ptr_read_volatile
+ | sym::ptr_replace
+ | sym::ptr_write
+ | sym::ptr_write_bytes
+ | sym::ptr_write_unaligned
+ | sym::ptr_write_volatile => (&[0], true),
+ sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false),
+ sym::ptr_copy
+ | sym::ptr_copy_nonoverlapping
+ | sym::ptr_swap
+ | sym::ptr_swap_nonoverlapping => (&[0, 1], true),
+ _ => return,
+ };
+
+ for &arg_idx in arg_indices {
+ if let Some(arg) = args.get(arg_idx)
+ && let Some(null_span) = is_null_ptr(cx, arg)
+ && let Some(ty) = cx.typeck_results().expr_ty_opt(arg)
+ && let RawPtr(ty, _mutbl) = ty.kind()
+ {
+ // If ZST are fine, don't lint on them
+ let typing_env = cx.typing_env();
+ if are_zsts_allowed
+ && cx
+ .tcx
+ .layout_of(typing_env.as_query_input(*ty))
+ .is_ok_and(|layout| layout.is_1zst())
+ {
+ break;
+ }
+
+ let diag = if arg.span.contains(null_span) {
+ InvalidNullArgumentsDiag::NullPtrInline { null_span }
+ } else {
+ InvalidNullArgumentsDiag::NullPtrThroughBinding { null_span }
+ };
+
+ cx.emit_span_lint(INVALID_NULL_ARGUMENTS, expr.span, diag)
+ }
+ }
+ }
+
+ // Catching:
// (fn_ptr as *<const/mut> <ty>).is_null()
ExprKind::MethodCall(_, receiver, _, _)
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
@@ -110,18 +210,18 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
cx.tcx.get_diagnostic_name(def_id),
Some(sym::ptr_const_is_null | sym::ptr_is_null)
)
- && let Some(diag) = incorrect_check(cx, receiver) =>
+ && let Some(diag) = useless_check(cx, receiver) =>
{
cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
}
ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
let to_check: &Expr<'_>;
- let diag: PtrNullChecksDiag<'_>;
- if let Some(ddiag) = incorrect_check(cx, left) {
+ let diag: UselessPtrNullChecksDiag<'_>;
+ if let Some(ddiag) = useless_check(cx, left) {
to_check = right;
diag = ddiag;
- } else if let Some(ddiag) = incorrect_check(cx, right) {
+ } else if let Some(ddiag) = useless_check(cx, right) {
to_check = left;
diag = ddiag;
} else {
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 7c6656f..1d4d380 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -6,6 +6,7 @@
use rustc_span::sym;
use crate::lints::InvalidReferenceCastingDiag;
+use crate::utils::peel_casts;
use crate::{LateContext, LateLintPass, LintContext};
declare_lint! {
@@ -235,46 +236,3 @@ fn is_cast_to_bigger_memory_layout<'tcx>(
None
}
}
-
-fn peel_casts<'tcx>(cx: &LateContext<'tcx>, mut e: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
- let mut gone_trough_unsafe_cell_raw_get = false;
-
- loop {
- e = e.peel_blocks();
- // <expr> as ...
- e = if let ExprKind::Cast(expr, _) = e.kind {
- expr
- // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
- } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
- && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
- && matches!(
- cx.tcx.get_diagnostic_name(def_id),
- Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const)
- )
- {
- expr
- // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _>(<expr>)
- } else if let ExprKind::Call(path, [arg]) = e.kind
- && let ExprKind::Path(ref qpath) = path.kind
- && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
- && matches!(
- cx.tcx.get_diagnostic_name(def_id),
- Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute)
- )
- {
- if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
- gone_trough_unsafe_cell_raw_get = true;
- }
- arg
- } else {
- let init = cx.expr_or_init(e);
- if init.hir_id != e.hir_id {
- init
- } else {
- break;
- }
- };
- }
-
- (e, gone_trough_unsafe_cell_raw_get)
-}
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 7109fef..6966985 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1634,6 +1634,9 @@ fn check_arg_for_power_alignment<'tcx>(
return true;
} else if let Adt(adt_def, _) = ty.kind()
&& adt_def.is_struct()
+ && adt_def.repr().c()
+ && !adt_def.repr().packed()
+ && adt_def.repr().align.is_none()
{
let struct_variant = adt_def.variant(VariantIdx::ZERO);
// Within a nested struct, all fields are examined to correctly
@@ -1655,8 +1658,11 @@ fn check_struct_for_power_alignment<'tcx>(
item: &'tcx hir::Item<'tcx>,
) {
let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id());
+ // repr(C) structs also with packed or aligned representation
+ // should be ignored.
if adt_def.repr().c()
&& !adt_def.repr().packed()
+ && adt_def.repr().align.is_none()
&& cx.tcx.sess.target.os == "aix"
&& !adt_def.all_fields().next().is_none()
{
diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs
new file mode 100644
index 0000000..a7295d9
--- /dev/null
+++ b/compiler/rustc_lint/src/utils.rs
@@ -0,0 +1,55 @@
+use rustc_hir::{Expr, ExprKind};
+use rustc_span::sym;
+
+use crate::LateContext;
+
+/// Given an expression, peel all of casts (`<expr> as ...`, `<expr>.cast{,_mut,_const}()`,
+/// `ptr::from_ref(<expr>)`, ...) and init expressions.
+///
+/// Returns the innermost expression and a boolean representing if one of the casts was
+/// `UnsafeCell::raw_get(<expr>)`
+pub(crate) fn peel_casts<'tcx>(
+ cx: &LateContext<'tcx>,
+ mut e: &'tcx Expr<'tcx>,
+) -> (&'tcx Expr<'tcx>, bool) {
+ let mut gone_trough_unsafe_cell_raw_get = false;
+
+ loop {
+ e = e.peel_blocks();
+ // <expr> as ...
+ e = if let ExprKind::Cast(expr, _) = e.kind {
+ expr
+ // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
+ } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
+ && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+ && matches!(
+ cx.tcx.get_diagnostic_name(def_id),
+ Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const)
+ )
+ {
+ expr
+ // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _>(<expr>)
+ } else if let ExprKind::Call(path, [arg]) = e.kind
+ && let ExprKind::Path(ref qpath) = path.kind
+ && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+ && matches!(
+ cx.tcx.get_diagnostic_name(def_id),
+ Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute)
+ )
+ {
+ if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
+ gone_trough_unsafe_cell_raw_get = true;
+ }
+ arg
+ } else {
+ let init = cx.expr_or_init(e);
+ if init.hir_id != e.hir_id {
+ init
+ } else {
+ break;
+ }
+ };
+ }
+
+ (e, gone_trough_unsafe_cell_raw_get)
+}
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 86f1bcc..257bdc0 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -855,10 +855,15 @@
}
if (LintIR) {
- PipelineStartEPCallbacks.push_back(
- [](ModulePassManager &MPM, OptimizationLevel Level) {
- MPM.addPass(createModuleToFunctionPassAdaptor(LintPass()));
- });
+ PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM,
+ OptimizationLevel Level) {
+#if LLVM_VERSION_GE(21, 0)
+ MPM.addPass(
+ createModuleToFunctionPassAdaptor(LintPass(/*AbortOnError=*/true)));
+#else
+ MPM.addPass(createModuleToFunctionPassAdaptor(LintPass()));
+#endif
+ });
}
if (InstrumentCoverage) {
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 9adbcab..d997ba1 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -97,6 +97,10 @@
found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
.help = please recompile that crate using --crate-type lib
+metadata_full_metadata_not_found =
+ only metadata stub found for `{$flavor}` dependency `{$crate_name}`
+ please provide path to the corresponding .rmeta file with full metadata
+
metadata_global_alloc_required =
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index b7f13e0..16f87ab 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -1032,14 +1032,19 @@ fn inject_profiler_runtime(&mut self) {
}
fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
- self.cstore.has_global_allocator = match &*global_allocator_spans(krate) {
- [span1, span2, ..] => {
- self.dcx().emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
- true
- }
- spans => !spans.is_empty(),
- };
- self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) {
+ self.cstore.has_global_allocator =
+ match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) {
+ [span1, span2, ..] => {
+ self.dcx()
+ .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
+ true
+ }
+ spans => !spans.is_empty(),
+ };
+ self.cstore.has_alloc_error_handler = match &*fn_spans(
+ krate,
+ Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)),
+ ) {
[span1, span2, ..] => {
self.dcx()
.emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
@@ -1310,17 +1315,14 @@ pub fn process_extern_crate(
definitions: &Definitions,
) -> Option<CrateNum> {
match item.kind {
- ast::ItemKind::ExternCrate(orig_name) => {
- debug!(
- "resolving extern crate stmt. ident: {} orig_name: {:?}",
- item.ident, orig_name
- );
+ ast::ItemKind::ExternCrate(orig_name, ident) => {
+ debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name);
let name = match orig_name {
Some(orig_name) => {
validate_crate_name(self.sess, orig_name, Some(item.span));
orig_name
}
- None => item.ident.name,
+ None => ident.name,
};
let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
CrateDepKind::MacrosOnly
@@ -1368,14 +1370,15 @@ pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
}
}
-fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
+fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec<Span> {
struct Finder {
name: Symbol,
spans: Vec<Span>,
}
impl<'ast> visit::Visitor<'ast> for Finder {
fn visit_item(&mut self, item: &'ast ast::Item) {
- if item.ident.name == self.name
+ if let Some(ident) = item.kind.ident()
+ && ident.name == self.name
&& attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
{
self.spans.push(item.span);
@@ -1384,29 +1387,6 @@ fn visit_item(&mut self, item: &'ast ast::Item) {
}
}
- let name = Symbol::intern(&global_fn_name(sym::alloc));
- let mut f = Finder { name, spans: Vec::new() };
- visit::walk_crate(&mut f, krate);
- f.spans
-}
-
-fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
- struct Finder {
- name: Symbol,
- spans: Vec<Span>,
- }
- impl<'ast> visit::Visitor<'ast> for Finder {
- fn visit_item(&mut self, item: &'ast ast::Item) {
- if item.ident.name == self.name
- && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
- {
- self.spans.push(item.span);
- }
- visit::walk_item(self, item)
- }
- }
-
- let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global));
let mut f = Finder { name, spans: Vec::new() };
visit::walk_crate(&mut f, krate);
f.spans
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 0c54628..c45daed 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -526,6 +526,15 @@ fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
}
#[derive(Diagnostic)]
+#[diag(metadata_full_metadata_not_found)]
+pub(crate) struct FullMetadataNotFound {
+ #[primary_span]
+ pub span: Span,
+ pub flavor: CrateFlavor,
+ pub crate_name: Symbol,
+}
+
+#[derive(Diagnostic)]
#[diag(metadata_symbol_conflicts_current, code = E0519)]
pub struct SymbolConflictsCurrent {
#[primary_span]
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index 4450d05..c4e1e0f 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -3,7 +3,7 @@
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{OutFileName, OutputType};
+use rustc_session::config::{CrateType, OutFileName, OutputType};
use rustc_session::output::filename_for_metadata;
use rustc_session::{MetadataKind, Session};
use tempfile::Builder as TempFileBuilder;
@@ -50,7 +50,14 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
.tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailedCreateTempdir { err }));
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
- let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME);
+ let metadata_filename = metadata_tmpdir.as_ref().join("full.rmeta");
+ let metadata_stub_filename = if !tcx.sess.opts.unstable_opts.embed_metadata
+ && !tcx.crate_types().contains(&CrateType::ProcMacro)
+ {
+ Some(metadata_tmpdir.as_ref().join("stub.rmeta"))
+ } else {
+ None
+ };
// Always create a file at `metadata_filename`, even if we have nothing to write to it.
// This simplifies the creation of the output `out_filename` when requested.
@@ -60,9 +67,15 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
});
+ if let Some(metadata_stub_filename) = &metadata_stub_filename {
+ std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| {
+ tcx.dcx()
+ .emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err });
+ });
+ }
}
MetadataKind::Uncompressed | MetadataKind::Compressed => {
- encode_metadata(tcx, &metadata_filename);
+ encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref())
}
};
@@ -100,9 +113,10 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
// Load metadata back to memory: codegen may need to include it in object files.
let metadata =
- EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
- tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err });
- });
+ EncodedMetadata::from_path(metadata_filename, metadata_stub_filename, metadata_tmpdir)
+ .unwrap_or_else(|err| {
+ tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err });
+ });
let need_metadata_module = metadata_kind == MetadataKind::Compressed;
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index d5dd505..112954e 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -654,7 +654,24 @@ fn extract_one(
continue;
}
}
- *slot = Some((hash, metadata, lib.clone()));
+
+ // We error eagerly here. If we're locating a rlib, then in theory the full metadata
+ // could still be in a (later resolved) dylib. In practice, if the rlib and dylib
+ // were produced in a way where one has full metadata and the other hasn't, it would
+ // mean that they were compiled using different compiler flags and probably also have
+ // a different SVH value.
+ if metadata.get_header().is_stub {
+ // `is_stub` should never be true for .rmeta files.
+ assert_ne!(flavor, CrateFlavor::Rmeta);
+
+ // Because rmeta files are resolved before rlib/dylib files, if this is a stub and
+ // we haven't found a slot already, it means that the full metadata is missing.
+ if slot.is_none() {
+ return Err(CrateError::FullMetadataNotFound(self.crate_name, flavor));
+ }
+ } else {
+ *slot = Some((hash, metadata, lib.clone()));
+ }
ret = Some((lib, kind));
}
@@ -728,37 +745,25 @@ fn find_commandline_library(&mut self) -> Result<Option<Library>, CrateError> {
let Some(file) = loc_orig.file_name().and_then(|s| s.to_str()) else {
return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone()));
};
- // FnMut cannot return reference to captured value, so references
- // must be taken outside the closure.
- let rlibs = &mut rlibs;
- let rmetas = &mut rmetas;
- let dylibs = &mut dylibs;
- let type_via_filename = (|| {
- if file.starts_with("lib") {
- if file.ends_with(".rlib") {
- return Some(rlibs);
- }
- if file.ends_with(".rmeta") {
- return Some(rmetas);
- }
+ if file.starts_with("lib") {
+ if file.ends_with(".rlib") {
+ rlibs.insert(loc_canon.clone(), PathKind::ExternFlag);
+ continue;
}
- let dll_prefix = self.target.dll_prefix.as_ref();
- let dll_suffix = self.target.dll_suffix.as_ref();
- if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) {
- return Some(dylibs);
- }
- None
- })();
- match type_via_filename {
- Some(type_via_filename) => {
- type_via_filename.insert(loc_canon.clone(), PathKind::ExternFlag);
- }
- None => {
- self.crate_rejections
- .via_filename
- .push(CrateMismatch { path: loc_orig.clone(), got: String::new() });
+ if file.ends_with(".rmeta") {
+ rmetas.insert(loc_canon.clone(), PathKind::ExternFlag);
+ continue;
}
}
+ let dll_prefix = self.target.dll_prefix.as_ref();
+ let dll_suffix = self.target.dll_suffix.as_ref();
+ if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) {
+ dylibs.insert(loc_canon.clone(), PathKind::ExternFlag);
+ continue;
+ }
+ self.crate_rejections
+ .via_filename
+ .push(CrateMismatch { path: loc_orig.clone(), got: String::new() });
}
// Extract the dylib/rlib/rmeta triple.
@@ -928,6 +933,7 @@ pub(crate) enum CrateError {
ExternLocationNotExist(Symbol, PathBuf),
ExternLocationNotFile(Symbol, PathBuf),
MultipleCandidates(Symbol, CrateFlavor, Vec<PathBuf>),
+ FullMetadataNotFound(Symbol, CrateFlavor),
SymbolConflictsCurrent(Symbol),
StableCrateIdCollision(Symbol, Symbol),
DlOpen(String, String),
@@ -978,6 +984,9 @@ pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
dcx.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates });
}
+ CrateError::FullMetadataNotFound(crate_name, flavor) => {
+ dcx.emit_err(errors::FullMetadataNotFound { span, crate_name, flavor });
+ }
CrateError::SymbolConflictsCurrent(root_name) => {
dcx.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name });
}
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 7ab3d43..386d3d3 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -701,6 +701,7 @@ macro_rules! stat {
triple: tcx.sess.opts.target_triple.clone(),
hash: tcx.crate_hash(LOCAL_CRATE),
is_proc_macro_crate: proc_macro_data.is_some(),
+ is_stub: false,
},
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
@@ -2231,8 +2232,12 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
// generated regardless of trailing bytes that end up in it.
pub struct EncodedMetadata {
- // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
- mmap: Option<Mmap>,
+ // The declaration order matters because `full_metadata` should be dropped
+ // before `_temp_dir`.
+ full_metadata: Option<Mmap>,
+ // This is an optional stub metadata containing only the crate header.
+ // The header should be very small, so we load it directly into memory.
+ stub_metadata: Option<Vec<u8>>,
// We need to carry MaybeTempDir to avoid deleting the temporary
// directory while accessing the Mmap.
_temp_dir: Option<MaybeTempDir>,
@@ -2240,33 +2245,50 @@ pub struct EncodedMetadata {
impl EncodedMetadata {
#[inline]
- pub fn from_path(path: PathBuf, temp_dir: Option<MaybeTempDir>) -> std::io::Result<Self> {
+ pub fn from_path(
+ path: PathBuf,
+ stub_path: Option<PathBuf>,
+ temp_dir: Option<MaybeTempDir>,
+ ) -> std::io::Result<Self> {
let file = std::fs::File::open(&path)?;
let file_metadata = file.metadata()?;
if file_metadata.len() == 0 {
- return Ok(Self { mmap: None, _temp_dir: None });
+ return Ok(Self { full_metadata: None, stub_metadata: None, _temp_dir: None });
}
- let mmap = unsafe { Some(Mmap::map(file)?) };
- Ok(Self { mmap, _temp_dir: temp_dir })
+ let full_mmap = unsafe { Some(Mmap::map(file)?) };
+
+ let stub =
+ if let Some(stub_path) = stub_path { Some(std::fs::read(stub_path)?) } else { None };
+
+ Ok(Self { full_metadata: full_mmap, stub_metadata: stub, _temp_dir: temp_dir })
}
#[inline]
- pub fn raw_data(&self) -> &[u8] {
- self.mmap.as_deref().unwrap_or_default()
+ pub fn full(&self) -> &[u8] {
+ &self.full_metadata.as_deref().unwrap_or_default()
+ }
+
+ #[inline]
+ pub fn stub_or_full(&self) -> &[u8] {
+ self.stub_metadata.as_deref().unwrap_or(self.full())
}
}
impl<S: Encoder> Encodable<S> for EncodedMetadata {
fn encode(&self, s: &mut S) {
- let slice = self.raw_data();
+ self.stub_metadata.encode(s);
+
+ let slice = self.full();
slice.encode(s)
}
}
impl<D: Decoder> Decodable<D> for EncodedMetadata {
fn decode(d: &mut D) -> Self {
+ let stub = <Option<Vec<u8>>>::decode(d);
+
let len = d.read_usize();
- let mmap = if len > 0 {
+ let full_metadata = if len > 0 {
let mut mmap = MmapMut::map_anon(len).unwrap();
mmap.copy_from_slice(d.read_raw_bytes(len));
Some(mmap.make_read_only().unwrap())
@@ -2274,11 +2296,11 @@ fn decode(d: &mut D) -> Self {
None
};
- Self { mmap, _temp_dir: None }
+ Self { full_metadata, stub_metadata: stub, _temp_dir: None }
}
}
-pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
+pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2292,6 +2314,42 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
}
+ with_encode_metadata_header(tcx, path, |ecx| {
+ // Encode all the entries and extra information in the crate,
+ // culminating in the `CrateRoot` which points to all of it.
+ let root = ecx.encode_crate_root();
+
+ // Flush buffer to ensure backing file has the correct size.
+ ecx.opaque.flush();
+ // Record metadata size for self-profiling
+ tcx.prof.artifact_size(
+ "crate_metadata",
+ "crate_metadata",
+ ecx.opaque.file().metadata().unwrap().len(),
+ );
+
+ root.position.get()
+ });
+
+ if let Some(ref_path) = ref_path {
+ with_encode_metadata_header(tcx, ref_path, |ecx| {
+ let header: LazyValue<CrateHeader> = ecx.lazy(CrateHeader {
+ name: tcx.crate_name(LOCAL_CRATE),
+ triple: tcx.sess.opts.target_triple.clone(),
+ hash: tcx.crate_hash(LOCAL_CRATE),
+ is_proc_macro_crate: false,
+ is_stub: true,
+ });
+ header.position.get()
+ });
+ }
+}
+
+fn with_encode_metadata_header(
+ tcx: TyCtxt<'_>,
+ path: &Path,
+ f: impl FnOnce(&mut EncodeContext<'_, '_>) -> usize,
+) {
let mut encoder = opaque::FileEncoder::new(path)
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err }));
encoder.emit_raw_bytes(METADATA_HEADER);
@@ -2326,9 +2384,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
// Encode the rustc version string in a predictable location.
rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
- // Encode all the entries and extra information in the crate,
- // culminating in the `CrateRoot` which points to all of it.
- let root = ecx.encode_crate_root();
+ let root_position = f(&mut ecx);
// Make sure we report any errors from writing to the file.
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2338,12 +2394,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
}
let file = ecx.opaque.file();
- if let Err(err) = encode_root_position(file, root.position.get()) {
+ if let Err(err) = encode_root_position(file, root_position) {
tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err });
}
-
- // Record metadata size for self-profiling
- tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len());
}
fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index dc453b1..f4cf338 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -56,7 +56,7 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
/// Metadata encoding version.
/// N.B., increment this if you change the format of metadata such that
/// the rustc version can't be found to compare with `rustc_version()`.
-const METADATA_VERSION: u8 = 9;
+const METADATA_VERSION: u8 = 10;
/// Metadata header which includes `METADATA_VERSION`.
///
@@ -221,6 +221,12 @@ pub(crate) struct CrateHeader {
/// This is separate from [`ProcMacroData`] to avoid having to update [`METADATA_VERSION`] every
/// time ProcMacroData changes.
pub(crate) is_proc_macro_crate: bool,
+ /// Whether this crate metadata section is just a stub.
+ /// Stubs do not contain the full metadata (it will be typically stored
+ /// in a separate rmeta file).
+ ///
+ /// This is used inside rlibs and dylibs when using `-Zembed-metadata=no`.
+ pub(crate) is_stub: bool,
}
/// Serialized `.rmeta` data for a crate.
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index 316ad80..60ce854 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -53,7 +53,10 @@ pub struct Projection<'tcx> {
pub kind: ProjectionKind,
}
-/// A `Place` represents how a value is located in memory.
+/// A `Place` represents how a value is located in memory. This does not
+/// always correspond to a syntactic place expression. For example, when
+/// processing a pattern, a `Place` can be used to refer to the sub-value
+/// currently being inspected.
///
/// This is an HIR version of [`rustc_middle::mir::Place`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
@@ -67,7 +70,10 @@ pub struct Place<'tcx> {
pub projections: Vec<Projection<'tcx>>,
}
-/// A `PlaceWithHirId` represents how a value is located in memory.
+/// A `PlaceWithHirId` represents how a value is located in memory. This does not
+/// always correspond to a syntactic place expression. For example, when
+/// processing a pattern, a `Place` can be used to refer to the sub-value
+/// currently being inspected.
///
/// This is an HIR version of [`rustc_middle::mir::Place`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 0cc72a2..00da1a6 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -172,6 +172,8 @@ pub const fn new() -> CodegenFnAttrs {
/// * `#[no_mangle]` is present
/// * `#[export_name(...)]` is present
/// * `#[linkage]` is present
+ ///
+ /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
pub fn contains_extern_indicator(&self) -> bool {
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
|| self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 6686151..ba31f77 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -199,8 +199,6 @@ pub fn span(&self, tcx: TyCtxt<'_>, scope_tree: &ScopeTree) -> Span {
}
}
-pub type ScopeDepth = u32;
-
/// The region scope tree encodes information about region relationships.
#[derive(Default, Debug, HashStable)]
pub struct ScopeTree {
@@ -213,7 +211,7 @@ pub struct ScopeTree {
/// conditional expression or repeating block. (Note that the
/// enclosing scope ID for the block associated with a closure is
/// the closure itself.)
- pub parent_map: FxIndexMap<Scope, (Scope, ScopeDepth)>,
+ pub parent_map: FxIndexMap<Scope, Scope>,
/// Maps from a variable or binding ID to the block in which that
/// variable is declared.
@@ -224,7 +222,7 @@ pub struct ScopeTree {
/// and not the enclosing *statement*. Expressions that are not present in this
/// table are not rvalue candidates. The set of rvalue candidates is computed
/// during type check based on a traversal of the AST.
- pub rvalue_candidates: HirIdMap<RvalueCandidateType>,
+ pub rvalue_candidates: HirIdMap<RvalueCandidate>,
/// Backwards incompatible scoping that will be introduced in future editions.
/// This information is used later for linting to identify locals and
@@ -308,15 +306,14 @@ pub struct ScopeTree {
pub yield_in_scope: UnordMap<Scope, Vec<YieldData>>,
}
-/// Identifies the reason that a given expression is an rvalue candidate
-/// (see the `rvalue_candidates` field for more information what rvalue
-/// candidates in general). In constants, the `lifetime` field is None
-/// to indicate that certain expressions escape into 'static and
-/// should have no local cleanup scope.
+/// See the `rvalue_candidates` field for more information on rvalue
+/// candidates in general.
+/// The `lifetime` field is None to indicate that certain expressions escape
+/// into 'static and should have no local cleanup scope.
#[derive(Debug, Copy, Clone, HashStable)]
-pub enum RvalueCandidateType {
- Borrow { target: hir::ItemLocalId, lifetime: Option<Scope> },
- Pattern { target: hir::ItemLocalId, lifetime: Option<Scope> },
+pub struct RvalueCandidate {
+ pub target: hir::ItemLocalId,
+ pub lifetime: Option<Scope>,
}
#[derive(Debug, Copy, Clone, HashStable)]
@@ -329,7 +326,7 @@ pub struct YieldData {
}
impl ScopeTree {
- pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, ScopeDepth)>) {
+ pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
debug!("{:?}.parent = {:?}", child, parent);
if let Some(p) = parent {
@@ -344,21 +341,17 @@ pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
self.var_map.insert(var, lifetime);
}
- pub fn record_rvalue_candidate(&mut self, var: HirId, candidate_type: RvalueCandidateType) {
- debug!("record_rvalue_candidate(var={var:?}, type={candidate_type:?})");
- match &candidate_type {
- RvalueCandidateType::Borrow { lifetime: Some(lifetime), .. }
- | RvalueCandidateType::Pattern { lifetime: Some(lifetime), .. } => {
- assert!(var.local_id != lifetime.local_id)
- }
- _ => {}
+ pub fn record_rvalue_candidate(&mut self, var: HirId, candidate: RvalueCandidate) {
+ debug!("record_rvalue_candidate(var={var:?}, candidate={candidate:?})");
+ if let Some(lifetime) = &candidate.lifetime {
+ assert!(var.local_id != lifetime.local_id)
}
- self.rvalue_candidates.insert(var, candidate_type);
+ self.rvalue_candidates.insert(var, candidate);
}
/// Returns the narrowest scope that encloses `id`, if any.
pub fn opt_encl_scope(&self, id: Scope) -> Option<Scope> {
- self.parent_map.get(&id).cloned().map(|(p, _)| p)
+ self.parent_map.get(&id).cloned()
}
/// Returns the lifetime of the local variable `var_id`, if any.
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 83ada5c..1ffe958 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -150,6 +150,7 @@ pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
// If the function is #[naked] or contains any other attribute that requires exactly-once
// instantiation:
+ // We emit an unused_attributes lint for this case, which should be kept in sync if possible.
let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 4f86703..6d6e6a1 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -334,14 +334,19 @@ pub enum StatementKind<'tcx> {
/// See [`Rvalue`] documentation for details on each of those.
Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
- /// This represents all the reading that a pattern match may do (e.g., inspecting constants and
- /// discriminant values), and the kind of pattern it comes from. This is in order to adapt
- /// potential error messages to these specific patterns.
+ /// When executed at runtime, this is a nop.
///
- /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
- /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
+ /// During static analysis, a fake read:
+ /// - requires that the value being read is initialized (or, in the case
+ /// of closures, that it was fully initialized at some point in the past)
+ /// - constitutes a use of a value for the purposes of NLL (i.e. if the
+ /// value being fake-read is a reference, the lifetime of that reference
+ /// will be extended to cover the `FakeRead`)
+ /// - but, unlike an actual read, does *not* invalidate any exclusive
+ /// borrows.
///
- /// When executed at runtime this is a nop.
+ /// See [`FakeReadCause`] for more details on the situations in which a
+ /// `FakeRead` is emitted.
///
/// Disallowed after drop elaboration.
FakeRead(Box<(FakeReadCause, Place<'tcx>)>),
@@ -518,28 +523,59 @@ pub enum RetagKind {
/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)]
pub enum FakeReadCause {
- /// Inject a fake read of the borrowed input at the end of each guards
- /// code.
+ /// A fake read injected into a match guard to ensure that the discriminants
+ /// that are being matched on aren't modified while the match guard is being
+ /// evaluated.
+ ///
+ /// At the beginning of each match guard, a [fake borrow][FakeBorrowKind] is
+ /// inserted for each discriminant accessed in the entire `match` statement.
+ ///
+ /// Then, at the end of the match guard, a `FakeRead(ForMatchGuard)` is
+ /// inserted to keep the fake borrows alive until that point.
///
/// This should ensure that you cannot change the variant for an enum while
/// you are in the midst of matching on it.
ForMatchGuard,
- /// `let x: !; match x {}` doesn't generate any read of x so we need to
- /// generate a read of x to check that it is initialized and safe.
+ /// Fake read of the scrutinee of a `match` or destructuring `let`
+ /// (i.e. `let` with non-trivial pattern).
///
- /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
- /// FakeRead for that Place outside the closure, in such a case this option would be
- /// Some(closure_def_id).
- /// Otherwise, the value of the optional LocalDefId will be None.
+ /// In `match x { ... }`, we generate a `FakeRead(ForMatchedPlace, x)`
+ /// and insert it into the `otherwise_block` (which is supposed to be
+ /// unreachable for irrefutable pattern-matches like `match` or `let`).
+ ///
+ /// This is necessary because `let x: !; match x {}` doesn't generate any
+ /// actual read of x, so we need to generate a `FakeRead` to check that it
+ /// is initialized.
+ ///
+ /// If the `FakeRead(ForMatchedPlace)` is being performed with a closure
+ /// that doesn't capture the required upvars, the `FakeRead` within the
+ /// closure is omitted entirely.
+ ///
+ /// To make sure that this is still sound, if a closure matches against
+ /// a Place starting with an Upvar, we hoist the `FakeRead` to the
+ /// definition point of the closure.
+ ///
+ /// If the `FakeRead` comes from being hoisted out of a closure like this,
+ /// we record the `LocalDefId` of the closure. Otherwise, the `Option` will be `None`.
//
// We can use LocalDefId here since fake read statements are removed
// before codegen in the `CleanupNonCodegenStatements` pass.
ForMatchedPlace(Option<LocalDefId>),
- /// A fake read of the RefWithinGuard version of a bind-by-value variable
- /// in a match guard to ensure that its value hasn't change by the time
- /// we create the OutsideGuard version.
+ /// A fake read injected into a match guard to ensure that the places
+ /// bound by the pattern are immutable for the duration of the match guard.
+ ///
+ /// Within a match guard, references are created for each place that the
+ /// pattern creates a binding for — this is known as the `RefWithinGuard`
+ /// version of the variables. To make sure that the references stay
+ /// alive until the end of the match guard, and properly prevent the
+ /// places in question from being modified, a `FakeRead(ForGuardBinding)`
+ /// is inserted at the end of the match guard.
+ ///
+ /// For details on how these references are created, see the extensive
+ /// documentation on `bind_matched_candidate_for_guard` in
+ /// `rustc_mir_build`.
ForGuardBinding,
/// Officially, the semantics of
@@ -552,22 +588,42 @@ pub enum FakeReadCause {
/// However, if we see the simple pattern `let var = <expr>`, we optimize this to
/// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
/// but in some cases it can affect the borrow checker, as in #53695.
- /// Therefore, we insert a "fake read" here to ensure that we get
- /// appropriate errors.
///
- /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
- /// FakeRead for that Place outside the closure, in such a case this option would be
- /// Some(closure_def_id).
- /// Otherwise, the value of the optional DefId will be None.
+ /// Therefore, we insert a `FakeRead(ForLet)` immediately after each `let`
+ /// with a trivial pattern.
+ ///
+ /// FIXME: `ExprUseVisitor` has an entirely different opinion on what `FakeRead(ForLet)`
+ /// is supposed to mean. If it was accurate to what MIR lowering does,
+ /// would it even make sense to hoist these out of closures like
+ /// `ForMatchedPlace`?
ForLet(Option<LocalDefId>),
- /// If we have an index expression like
+ /// Currently, index expressions overloaded through the `Index` trait
+ /// get lowered differently than index expressions with builtin semantics
+ /// for arrays and slices — the latter will emit code to perform
+ /// bound checks, and then return a MIR place that will only perform the
+ /// indexing "for real" when it gets incorporated into an instruction.
///
- /// (*x)[1][{ x = y; 4}]
+ /// This is observable in the fact that the following compiles:
///
- /// then the first bounds check is invalidated when we evaluate the second
- /// index expression. Thus we create a fake borrow of `x` across the second
- /// indexer, which will cause a borrow check error.
+ /// ```
+ /// fn f(x: &mut [&mut [u32]], i: usize) {
+ /// x[i][x[i].len() - 1] += 1;
+ /// }
+ /// ```
+ ///
+ /// However, we need to be careful to not let the user invalidate the
+ /// bound check with an expression like
+ ///
+ /// `(*x)[1][{ x = y; 4}]`
+ ///
+ /// Here, the first bounds check would be invalidated when we evaluate the
+ /// second index expression. To make sure that this doesn't happen, we
+ /// create a fake borrow of `x` and hold it while we evaluate the second
+ /// index.
+ ///
+ /// This borrow is kept alive by a `FakeRead(ForIndex)` at the end of its
+ /// scope.
ForIndex,
}
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 7bbaa04..6c6b9a5 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -1,3 +1,4 @@
+use std::ffi::OsStr;
use std::intrinsics::transmute_unchecked;
use std::mem::MaybeUninit;
@@ -67,6 +68,10 @@ impl<T> EraseType for &'_ [T] {
type Result = [u8; size_of::<&'static [()]>()];
}
+impl EraseType for &'_ OsStr {
+ type Result = [u8; size_of::<&'static OsStr>()];
+}
+
impl<T> EraseType for &'_ ty::List<T> {
type Result = [u8; size_of::<&'static ty::List<()>>()];
}
@@ -174,6 +179,10 @@ impl<T> EraseType for Option<&'_ [T]> {
type Result = [u8; size_of::<Option<&'static [()]>>()];
}
+impl EraseType for Option<&'_ OsStr> {
+ type Result = [u8; size_of::<Option<&'static OsStr>>()];
+}
+
impl EraseType for Option<mir::DestructuredConstant<'_>> {
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
}
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 98314b5..c382bcd 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -1,5 +1,7 @@
//! Defines the set of legal keys that can be used in queries.
+use std::ffi::OsStr;
+
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
use rustc_hir::hir_id::{HirId, OwnerId};
use rustc_query_system::dep_graph::DepNodeIndex;
@@ -498,6 +500,14 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
}
}
+impl<'tcx> Key for &'tcx OsStr {
+ type Cache<V> = DefaultCache<Self, V>;
+
+ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
+ DUMMY_SP
+ }
+}
+
/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 527c18a..d7ed703 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -6,6 +6,7 @@
#![allow(unused_parens)]
+use std::ffi::OsStr;
use std::mem;
use std::path::PathBuf;
use std::sync::Arc;
@@ -30,7 +31,9 @@
use rustc_lint_defs::LintId;
use rustc_macros::rustc_queries;
use rustc_query_system::ich::StableHashingContext;
-use rustc_query_system::query::{QueryCache, QueryMode, QueryState, try_get_cached};
+use rustc_query_system::query::{
+ QueryCache, QueryMode, QueryStackDeferred, QueryState, try_get_cached,
+};
use rustc_session::Limits;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::cstore::{
@@ -119,6 +122,21 @@
desc { "perform lints prior to AST lowering" }
}
+ /// Tracked access to environment variables.
+ ///
+ /// Useful for the implementation of `std::env!`, `proc-macro`s change
+ /// detection and other changes in the compiler's behaviour that is easier
+ /// to control with an environment variable than a flag.
+ ///
+ /// NOTE: This currently does not work with dependency info in the
+ /// analysis, codegen and linking passes, place extra code at the top of
+ /// `rustc_interface::passes::write_dep_info` to make that work.
+ query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> {
+ // Environment variables are global state
+ eval_always
+ desc { "get the value of an environment variable" }
+ }
+
query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
no_hash
desc { "getting the resolver outputs" }
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 4834444..a099f77 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -488,7 +488,7 @@ pub struct DynamicQueries<'tcx> {
#[derive(Default)]
pub struct QueryStates<'tcx> {
$(
- pub $name: QueryState<$($K)*>,
+ pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>,
)*
}
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 811bd8f..aa2ee75 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -95,10 +95,16 @@
/// parameter environment.
#[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)]
pub enum SelectionCandidate<'tcx> {
+ /// A built-in implementation for the `Sized` trait. This is preferred
+ /// over all other candidates.
+ SizedCandidate {
+ has_nested: bool,
+ },
+
/// A builtin implementation for some specific traits, used in cases
/// where we cannot rely an ordinary library implementations.
///
- /// The most notable examples are `sized`, `Copy` and `Clone`. This is also
+ /// The most notable examples are `Copy` and `Clone`. This is also
/// used for the `DiscriminantKind` and `Pointee` trait, both of which have
/// an associated type.
BuiltinCandidate {
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 72263d8..2f21d19 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -33,7 +33,7 @@ pub enum ValTreeKind<'tcx> {
/// The fields of any kind of aggregate. Structs, tuples and arrays are represented by
/// listing their fields' values in order.
///
- /// Enums are represented by storing their discriminant as a field, followed by all
+ /// Enums are represented by storing their variant index as a u32 field, followed by all
/// the fields of the variant.
///
/// ZST types are represented as an empty slice.
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 834d1f2..618a65a 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -7,6 +7,8 @@
use std::assert_matches::{assert_matches, debug_assert_matches};
use std::borrow::Borrow;
use std::cmp::Ordering;
+use std::env::VarError;
+use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::ops::{Bound, Deref};
@@ -1883,6 +1885,15 @@ pub fn adjust_target_feature_sig(
}
None
}
+
+ /// Helper to get a tracked environment variable via. [`TyCtxt::env_var_os`] and converting to
+ /// UTF-8 like [`std::env::var`].
+ pub fn env_var<K: ?Sized + AsRef<OsStr>>(self, key: &'tcx K) -> Result<&'tcx str, VarError> {
+ match self.env_var_os(key.as_ref()) {
+ Some(value) => value.to_str().ok_or_else(|| VarError::NotUnicode(value.to_os_string())),
+ None => Err(VarError::NotPresent),
+ }
+ }
}
impl<'tcx> TyCtxtAt<'tcx> {
@@ -1919,10 +1930,10 @@ pub fn create_def(
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
// comp. engine itself.
//
- // This call also writes to the value of `source_span` and `expn_that_defined` queries.
+ // This call also writes to the value of the `source_span` query.
// This is fine because:
- // - those queries are `eval_always` so we won't miss their result changing;
- // - this write will have happened before these queries are called.
+ // - that query is `eval_always` so we won't miss its result changing;
+ // - this write will have happened before that query is called.
let def_id = self.untracked.definitions.write().create_def(parent, data);
// This function modifies `self.definitions` using a side-effect.
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 85d9db7..d4cc562 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -73,9 +73,7 @@ pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion {
pub fn is_anonymous_lifetime(&self) -> bool {
match self.kind {
- GenericParamDefKind::Lifetime => {
- self.name == kw::UnderscoreLifetime || self.name == kw::Empty
- }
+ GenericParamDefKind::Lifetime => self.name == kw::UnderscoreLifetime,
_ => false,
}
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6bdd0a0..0ffaef8 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -457,7 +457,7 @@ impl EarlyParamRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
pub fn has_name(&self) -> bool {
- self.name != kw::UnderscoreLifetime && self.name != kw::Empty
+ self.name != kw::UnderscoreLifetime
}
}
@@ -953,7 +953,7 @@ fn outer_exclusive_binder(&self) -> DebruijnIndex {
/// environment. `ParamEnv` is the type that represents this information. See the
/// [dev guide chapter][param_env_guide] for more information.
///
-/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html
+/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(HashStable, TypeVisitable, TypeFoldable)]
pub struct ParamEnv<'tcx> {
@@ -977,7 +977,7 @@ impl<'tcx> ParamEnv<'tcx> {
/// to use an empty environment. See the [dev guide section][param_env_guide]
/// for information on what a `ParamEnv` is and how to acquire one.
///
- /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html
+ /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
#[inline]
pub fn empty() -> Self {
Self::new(ListWithCachedTypeInfo::empty())
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index dc2040a..5904dea 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -139,8 +139,7 @@ fn default_print_def_path(
match key.disambiguated_data.data {
DefPathData::Closure => {
- // FIXME(async_closures): This is somewhat ugly.
- // We need to additionally print the `kind` field of a closure if
+ // We need to additionally print the `kind` field of a coroutine if
// it is desugared from a coroutine-closure.
if let Some(hir::CoroutineKind::Desugared(
_,
@@ -156,6 +155,10 @@ fn default_print_def_path(
// Closures' own generics are only captures, don't print them.
}
}
+ DefPathData::SyntheticCoroutineBody => {
+ // Synthetic coroutine bodies have no distinct generics, since like
+ // closures they're all just internal state of the coroutine.
+ }
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
// Anon consts doesn't have their own generics, and inline consts' own
// generics are their inferred types, so don't print them.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 3ef8ecc..3281cb41 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2591,11 +2591,9 @@ pub fn pretty_print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), fm
// to fit that into a short string. Hence the recommendation to use
// `explain_region()` or `note_and_explain_region()`.
match *region {
- ty::ReEarlyParam(ref data) => {
- if data.name != kw::Empty {
- p!(write("{}", data.name));
- return Ok(());
- }
+ ty::ReEarlyParam(data) => {
+ p!(write("{}", data.name));
+ return Ok(());
}
ty::ReLateParam(ty::LateParamRegion { kind, .. }) => {
if let Some(name) = kind.get_name() {
@@ -2834,7 +2832,7 @@ fn name_by_region_index(
(name, ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name))
}
- ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime | kw::Empty) => {
+ ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime) => {
let name = next_name(self);
if let Some(lt_idx) = lifetime_idx {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index fb52cf9..c78306f 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -400,9 +400,7 @@ pub fn from_bound(var: BoundVar, br: BoundRegionKind) -> LateParamRegionKind {
pub fn is_named(&self) -> bool {
match *self {
- LateParamRegionKind::Named(_, name) => {
- name != kw::UnderscoreLifetime && name != kw::Empty
- }
+ LateParamRegionKind::Named(_, name) => name != kw::UnderscoreLifetime,
_ => false,
}
}
@@ -475,7 +473,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl BoundRegionKind {
pub fn is_named(&self) -> bool {
match *self {
- BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime && name != kw::Empty,
+ BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime,
_ => false,
}
}
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index b00c816..9bf6e3a 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -38,7 +38,7 @@ pub fn temporary_scope(
let mut id = Scope { local_id: expr_id, data: ScopeData::Node };
let mut backwards_incompatible = None;
- while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) {
+ while let Some(&p) = region_scope_tree.parent_map.get(&id) {
match p.data {
ScopeData::Destruction => {
debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]");
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index 7dda68b..c4357fa 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -49,7 +49,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
pub fn trigger_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) {
tcx.dcx().span_delayed_bug(
tcx.def_span(key),
- "delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]",
+ "delayed bug triggered by #[rustc_delayed_bug_from_inside_query]",
);
}
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 9450ce7..39fcc68 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -88,7 +88,7 @@ fn from_cycle_error(
if info.query.dep_kind == dep_kinds::representability
&& let Some(field_id) = info.query.def_id
&& let Some(field_id) = field_id.as_local()
- && let Some(DefKind::Field) = info.query.def_kind
+ && let Some(DefKind::Field) = info.query.info.def_kind
{
let parent_id = tcx.parent(field_id.to_def_id());
let item_id = match tcx.def_kind(parent_id) {
@@ -216,7 +216,7 @@ fn from_cycle_error(
continue;
};
let frame_span =
- frame.query.default_span(cycle[(i + 1) % cycle.len()].span);
+ frame.query.info.default_span(cycle[(i + 1) % cycle.len()].span);
if frame_span.is_dummy() {
continue;
}
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index e56c0ae..e42336a 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -1496,7 +1496,7 @@ fn build_scope_drops<'tcx>(
// path, then don't generate the drop. (We only take this into
// account for non-unwind paths so as not to disturb the
// caching mechanism.)
- if scope.moved_locals.iter().any(|&o| o == local) {
+ if scope.moved_locals.contains(&local) {
continue;
}
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 89a306c..dd0e07f 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -219,6 +219,8 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id()));
dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(()));
+ // Feed HIR because we try to access this body's attrs in the inliner.
+ body_def.feed_hir();
// Inherited from the by-ref coroutine.
body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
body_def.coverage_attr_on(tcx.coverage_attr_on(coroutine_def_id));
diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs
index d83c0d4..73bd2d0 100644
--- a/compiler/rustc_mir_transform/src/coverage/mappings.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs
@@ -96,7 +96,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>(
}
} else {
// Extract coverage spans from MIR statements/terminators as normal.
- extract_refined_covspans(mir_body, hir_info, graph, &mut code_mappings);
+ extract_refined_covspans(tcx, mir_body, hir_info, graph, &mut code_mappings);
}
branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, graph));
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 8befe9c..f57a158 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,7 +1,9 @@
use std::collections::VecDeque;
+use std::iter;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir;
+use rustc_middle::ty::TyCtxt;
use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
use tracing::{debug, debug_span, instrument};
@@ -11,8 +13,9 @@
mod from_mir;
-pub(super) fn extract_refined_covspans(
- mir_body: &mir::Body<'_>,
+pub(super) fn extract_refined_covspans<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ mir_body: &mir::Body<'tcx>,
hir_info: &ExtractedHirInfo,
graph: &CoverageGraph,
code_mappings: &mut impl Extend<mappings::CodeMapping>,
@@ -50,7 +53,7 @@ pub(super) fn extract_refined_covspans(
// First, perform the passes that need macro information.
covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb));
remove_unwanted_expansion_spans(&mut covspans);
- split_visible_macro_spans(&mut covspans);
+ shrink_visible_macro_spans(tcx, &mut covspans);
// We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::<Vec<_>>();
@@ -83,9 +86,7 @@ pub(super) fn extract_refined_covspans(
// Split the covspans into separate buckets that don't overlap any holes.
let buckets = divide_spans_into_buckets(covspans, &holes);
- for mut covspans in buckets {
- // Make sure each individual bucket is internally sorted.
- covspans.sort_by(compare_covspans);
+ for covspans in buckets {
let _span = debug_span!("processing bucket", ?covspans).entered();
let mut covspans = remove_unwanted_overlapping_spans(covspans);
@@ -129,82 +130,50 @@ fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
}
/// When a span corresponds to a macro invocation that is visible from the
-/// function body, split it into two parts. The first part covers just the
-/// macro name plus `!`, and the second part covers the rest of the macro
-/// invocation. This seems to give better results for code that uses macros.
-fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
- let mut extra_spans = vec![];
+/// function body, truncate it to just the macro name plus `!`.
+/// This seems to give better results for code that uses macros.
+fn shrink_visible_macro_spans(tcx: TyCtxt<'_>, covspans: &mut Vec<SpanFromMir>) {
+ let source_map = tcx.sess.source_map();
- covspans.retain(|covspan| {
- let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else {
- return true;
- };
-
- let split_len = visible_macro.as_str().len() as u32 + 1;
- let (before, after) = covspan.span.split_at(split_len);
- if !covspan.span.contains(before) || !covspan.span.contains(after) {
- // Something is unexpectedly wrong with the split point.
- // The debug assertion in `split_at` will have already caught this,
- // but in release builds it's safer to do nothing and maybe get a
- // bug report for unexpected coverage, rather than risk an ICE.
- return true;
+ for covspan in covspans {
+ if matches!(covspan.expn_kind, Some(ExpnKind::Macro(MacroKind::Bang, _))) {
+ covspan.span = source_map.span_through_char(covspan.span, '!');
}
-
- extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb));
- extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb));
- false // Discard the original covspan that we just split.
- });
-
- // The newly-split spans are added at the end, so any previous sorting
- // is not preserved.
- covspans.extend(extra_spans);
+ }
}
/// Uses the holes to divide the given covspans into buckets, such that:
-/// - No span in any hole overlaps a bucket (truncating the spans if necessary).
+/// - No span in any hole overlaps a bucket (discarding spans if necessary).
/// - The spans in each bucket are strictly after all spans in previous buckets,
/// and strictly before all spans in subsequent buckets.
///
-/// The resulting buckets are sorted relative to each other, but might not be
-/// internally sorted.
+/// The lists of covspans and holes must be sorted.
+/// The resulting buckets are sorted relative to each other, and each bucket's
+/// contents are sorted.
#[instrument(level = "debug")]
fn divide_spans_into_buckets(input_covspans: Vec<Covspan>, holes: &[Hole]) -> Vec<Vec<Covspan>> {
debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
- // Now we're ready to start carving holes out of the initial coverage spans,
- // and grouping them in buckets separated by the holes.
+ // Now we're ready to start grouping spans into buckets separated by holes.
let mut input_covspans = VecDeque::from(input_covspans);
- let mut fragments = vec![];
// For each hole:
// - Identify the spans that are entirely or partly before the hole.
- // - Put those spans in a corresponding bucket, truncated to the start of the hole.
- // - If one of those spans also extends after the hole, put the rest of it
- // in a "fragments" vector that is processed by the next hole.
+ // - Discard any that overlap with the hole.
+ // - Add the remaining identified spans to the corresponding bucket.
let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
for (hole, bucket) in holes.iter().zip(&mut buckets) {
- let fragments_from_prev = std::mem::take(&mut fragments);
-
- // Only inspect spans that precede or overlap this hole,
- // leaving the rest to be inspected by later holes.
- // (This relies on the spans and holes both being sorted.)
- let relevant_input_covspans =
- drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi());
-
- for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) {
- let (before, after) = covspan.split_around_hole_span(hole.span);
- bucket.extend(before);
- fragments.extend(after);
- }
+ bucket.extend(
+ drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi())
+ .filter(|c| !c.span.overlaps(hole.span)),
+ );
}
- // After finding the spans before each hole, any remaining fragments/spans
- // form their own final bucket, after the final hole.
+ // Any remaining spans form their own final bucket, after the final hole.
// (If there were no holes, this will just be all of the initial spans.)
- fragments.extend(input_covspans);
- buckets.push(fragments);
+ buckets.push(Vec::from(input_covspans));
buckets
}
@@ -215,7 +184,7 @@ fn drain_front_while<'a, T>(
queue: &'a mut VecDeque<T>,
mut pred_fn: impl FnMut(&T) -> bool,
) -> impl Iterator<Item = T> {
- std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
+ iter::from_fn(move || queue.pop_front_if(|x| pred_fn(x)))
}
/// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines"
@@ -258,22 +227,6 @@ struct Covspan {
}
impl Covspan {
- /// Splits this covspan into 0-2 parts:
- /// - The part that is strictly before the hole span, if any.
- /// - The part that is strictly after the hole span, if any.
- fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
- let before = try {
- let span = self.span.trim_end(hole_span)?;
- Self { span, ..*self }
- };
- let after = try {
- let span = self.span.trim_start(hole_span)?;
- Self { span, ..*self }
- };
-
- (before, after)
- }
-
/// If `self` and `other` can be merged (i.e. they have the same BCB),
/// mutates `self.span` to also include `other.span` and returns true.
///
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index 1faa217..804cd8a 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -120,22 +120,20 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
// an `if condition { block }` has a span that includes the executed block, if true,
// but for coverage, the code region executed, up to *and* through the SwitchInt,
// actually stops before the if's block.)
- TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG
+ TerminatorKind::Unreachable
| TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. }
| TerminatorKind::SwitchInt { .. }
- // For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`.
| TerminatorKind::FalseEdge { .. }
| TerminatorKind::Goto { .. } => None,
// Call `func` operand can have a more specific span when part of a chain of calls
- TerminatorKind::Call { ref func, .. }
- | TerminatorKind::TailCall { ref func, .. } => {
+ TerminatorKind::Call { ref func, .. } | TerminatorKind::TailCall { ref func, .. } => {
let mut span = terminator.source_info.span;
- if let mir::Operand::Constant(box constant) = func {
- if constant.span.lo() > span.lo() {
- span = span.with_lo(constant.span.lo());
- }
+ if let mir::Operand::Constant(constant) = func
+ && span.contains(constant.span)
+ {
+ span = constant.span;
}
Some(span)
}
@@ -147,9 +145,7 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
| TerminatorKind::Yield { .. }
| TerminatorKind::CoroutineDrop
| TerminatorKind::FalseUnwind { .. }
- | TerminatorKind::InlineAsm { .. } => {
- Some(terminator.source_info.span)
- }
+ | TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span),
}
}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 205d388..c372b77 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -12,6 +12,7 @@
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]
+#![feature(vec_deque_pop_if)]
#![feature(yeet_expr)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 231d7c2..e7930f0 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -12,6 +12,7 @@
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion;
+use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance,
};
@@ -56,7 +57,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
ty::Coroutine(..) => ExternAbi::Rust,
// No need to do MIR validation on error bodies
ty::Error(_) => return,
- _ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"),
+ _ => span_bug!(body.span, "unexpected body ty: {body_ty}"),
};
ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
@@ -543,7 +544,13 @@ pub(super) fn validate_types<'tcx>(
caller_body: &Body<'tcx>,
) -> Vec<(Location, String)> {
let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() };
- type_checker.visit_body(body);
+ // The type checker formats a bunch of strings with type names in it, but these strings
+ // are not always going to be encountered on the error path since the inliner also uses
+ // the validator, and there are certain kinds of inlining (even for valid code) that
+ // can cause validation errors (mostly around where clauses and rigid projections).
+ with_no_trimmed_paths!({
+ type_checker.visit_body(body);
+ });
type_checker.failures
}
@@ -655,7 +662,7 @@ fn visit_projection_elem(
ProjectionElem::Index(index) => {
let index_ty = self.body.local_decls[index].ty;
if index_ty != self.tcx.types.usize {
- self.fail(location, format!("bad index ({index_ty:?} != usize)"))
+ self.fail(location, format!("bad index ({index_ty} != usize)"))
}
}
ProjectionElem::Deref
@@ -664,10 +671,7 @@ fn visit_projection_elem(
let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
if base_ty.is_box() {
- self.fail(
- location,
- format!("{base_ty:?} dereferenced after ElaborateBoxDerefs"),
- )
+ self.fail(location, format!("{base_ty} dereferenced after ElaborateBoxDerefs"))
}
}
ProjectionElem::Field(f, ty) => {
@@ -680,7 +684,7 @@ fn visit_projection_elem(
this.fail(
location,
format!(
- "Field projection `{place_ref:?}.{f:?}` specified type `{ty:?}`, but actual type is `{f_ty:?}`"
+ "Field projection `{place_ref:?}.{f:?}` specified type `{ty}`, but actual type is `{f_ty}`"
)
)
}
@@ -806,7 +810,7 @@ fn visit_projection_elem(
self.fail(
location,
format!(
- "Failed subtyping {ty:#?} and {:#?}",
+ "Failed subtyping {ty} and {}",
place_ref.ty(&self.body.local_decls, self.tcx).ty
),
)
@@ -826,7 +830,7 @@ fn visit_projection_elem(
self.fail(
location,
format!(
- "Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty:?}"
+ "Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty}"
),
);
}
@@ -841,7 +845,7 @@ fn visit_var_debug_info(&mut self, debuginfo: &VarDebugInfo<'tcx>) {
if ty.is_union() || ty.is_enum() {
self.fail(
START_BLOCK.start_location(),
- format!("invalid type {ty:?} in debuginfo for {:?}", debuginfo.name),
+ format!("invalid type {ty} in debuginfo for {:?}", debuginfo.name),
);
}
if projection.is_empty() {
@@ -1064,15 +1068,13 @@ macro_rules! check_kinds {
if !self.mir_assign_valid_types(a, b) {
self.fail(
location,
- format!("Cannot {op:?} compare incompatible types {a:?} and {b:?}"),
+ format!("Cannot {op:?} compare incompatible types {a} and {b}"),
);
}
} else if a != b {
self.fail(
location,
- format!(
- "Cannot perform binary op {op:?} on unequal types {a:?} and {b:?}"
- ),
+ format!("Cannot perform binary op {op:?} on unequal types {a} and {b}"),
);
}
}
@@ -1081,7 +1083,7 @@ macro_rules! check_kinds {
Offset => {
check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
if b != self.tcx.types.isize && b != self.tcx.types.usize {
- self.fail(location, format!("Cannot offset by non-isize type {b:?}"));
+ self.fail(location, format!("Cannot offset by non-isize type {b}"));
}
}
Eq | Lt | Le | Ne | Ge | Gt => {
@@ -1313,7 +1315,7 @@ macro_rules! check_kinds {
{
self.fail(
location,
- format!("Cannot transmute from non-`Sized` type {op_ty:?}"),
+ format!("Cannot transmute from non-`Sized` type {op_ty}"),
);
}
if !self
@@ -1340,7 +1342,7 @@ macro_rules! check_kinds {
}
Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => {
let fail_out_of_bounds = |this: &mut Self, location, field, ty| {
- this.fail(location, format!("Out of bounds field {field:?} for {ty:?}"));
+ this.fail(location, format!("Out of bounds field {field:?} for {ty}"));
};
let mut current_ty = *container;
@@ -1374,7 +1376,7 @@ macro_rules! check_kinds {
_ => {
self.fail(
location,
- format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"),
+ format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty}"),
);
return;
}
@@ -1403,7 +1405,7 @@ macro_rules! check_kinds {
if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) {
self.fail(
location,
- format!("Cannot wrap {unwrapped_ty:?} into unsafe binder {binder_ty:?}"),
+ format!("Cannot wrap {unwrapped_ty} into unsafe binder {binder_ty:?}"),
);
}
}
@@ -1489,24 +1491,27 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
// since CopyNonOverlapping is parametrized by 1 type,
// we only need to check that they are equal and not keep an extra parameter.
if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
- self.fail(location, format!("bad arg ({op_src_ty:?} != {op_dst_ty:?})"));
+ self.fail(location, format!("bad arg ({op_src_ty} != {op_dst_ty})"));
}
let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx);
if op_cnt_ty != self.tcx.types.usize {
- self.fail(location, format!("bad arg ({op_cnt_ty:?} != usize)"))
+ self.fail(location, format!("bad arg ({op_cnt_ty} != usize)"))
}
}
StatementKind::SetDiscriminant { place, .. } => {
if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
}
- let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
- if !matches!(pty, ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)) {
+ let pty = place.ty(&self.body.local_decls, self.tcx).ty;
+ if !matches!(
+ pty.kind(),
+ ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)
+ ) {
self.fail(
location,
format!(
- "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty:?}"
+ "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty}"
),
);
}
@@ -1555,7 +1560,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
if ScalarInt::try_from_uint(value, size).is_none() {
self.fail(
location,
- format!("the value {value:#x} is not a proper {switch_ty:?}"),
+ format!("the value {value:#x} is not a proper {switch_ty}"),
)
}
}
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 67fca1d..2a1b20b 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -225,13 +225,13 @@
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths};
use rustc_middle::ty::{
- self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Interner, Ty, TyCtxt,
- TypeFoldable, TypeVisitableExt, VtblEntry,
+ self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
+ TypeVisitableExt, VtblEntry,
};
use rustc_middle::util::Providers;
use rustc_middle::{bug, span_bug};
use rustc_session::Limit;
-use rustc_session::config::EntryFnType;
+use rustc_session::config::{DebugInfo, EntryFnType};
use rustc_span::source_map::{Spanned, dummy_spanned, respan};
use rustc_span::{DUMMY_SP, Span};
use tracing::{debug, instrument, trace};
@@ -967,7 +967,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
{
// `#[rustc_force_inline]` items should never be codegened. This should be caught by
// the MIR validator.
- tcx.delay_bug("attempt to codegen `#[rustc_force_inline]` item");
+ tcx.dcx().delayed_bug("attempt to codegen `#[rustc_force_inline]` item");
}
if def_id.is_local() {
@@ -1235,6 +1235,11 @@ fn collect_items_of_instance<'tcx>(
};
if mode == CollectionMode::UsedItems {
+ if tcx.sess.opts.debuginfo == DebugInfo::Full {
+ for var_debug_info in &body.var_debug_info {
+ collector.visit_var_debug_info(var_debug_info);
+ }
+ }
for (bb, data) in traversal::mono_reachable(body, tcx, instance) {
collector.visit_basic_block_data(bb, data)
}
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index 259b39e..c4b6b18 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -62,14 +62,12 @@ fn instantiate_canonical_var_with_infer(
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> <Self::Interner as Interner>::GenericArg;
- // FIXME: Can we implement this in terms of `add` and `inject`?
- fn insert_hidden_type(
+ fn register_hidden_type_in_storage(
&self,
opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
- param_env: <Self::Interner as Interner>::ParamEnv,
hidden_ty: <Self::Interner as Interner>::Ty,
- goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
- ) -> Result<(), NoSolution>;
+ span: <Self::Interner as Interner>::Span,
+ ) -> Option<<Self::Interner as Interner>::Ty>;
fn add_item_bounds_for_hidden_type(
&self,
@@ -79,14 +77,6 @@ fn add_item_bounds_for_hidden_type(
hidden_ty: <Self::Interner as Interner>::Ty,
goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
);
-
- fn inject_new_hidden_type_unchecked(
- &self,
- key: ty::OpaqueTypeKey<Self::Interner>,
- hidden_ty: <Self::Interner as Interner>::Ty,
- span: <Self::Interner as Interner>::Span,
- );
-
fn reset_opaque_types(&self);
fn fetch_eligible_assoc_item(
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index f6963a7..f575fe0 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -6,6 +6,7 @@
// tidy-alphabetical-start
#![allow(rustc::usage_of_type_ir_inherent)]
+#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
// tidy-alphabetical-end
pub mod canonicalizer;
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index ac6b521..4edc293 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -425,7 +425,8 @@ fn register_region_constraints(
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
for &(key, ty) in opaque_types {
- self.delegate.inject_new_hidden_type_unchecked(key, ty, self.origin_span);
+ let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span);
+ assert_eq!(prev, None);
}
}
}
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 7ef36d0..148ba02 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -387,7 +387,8 @@ fn enter_canonical<R>(
};
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
- ecx.delegate.inject_new_hidden_type_unchecked(key, ty, ecx.origin_span);
+ let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span);
+ assert_eq!(prev, None);
}
if !ecx.nested_goals.is_empty() {
@@ -1070,16 +1071,12 @@ pub(super) fn fetch_eligible_assoc_item(
self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
}
- pub(super) fn insert_hidden_type(
+ pub(super) fn register_hidden_type_in_storage(
&mut self,
opaque_type_key: ty::OpaqueTypeKey<I>,
- param_env: I::ParamEnv,
hidden_ty: I::Ty,
- ) -> Result<(), NoSolution> {
- let mut goals = Vec::new();
- self.delegate.insert_hidden_type(opaque_type_key, param_env, hidden_ty, &mut goals)?;
- self.add_goals(GoalSource::Misc, goals);
- Ok(())
+ ) -> Option<I::Ty> {
+ self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span)
}
pub(super) fn add_item_bounds_for_hidden_type(
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index 817dffa..82dae51 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -86,8 +86,8 @@ pub(super) fn normalize_opaque_type(
}
// Otherwise, define a new opaque type
- // FIXME: should we use `inject_hidden_type_unchecked` here?
- self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
+ let prev = self.register_hidden_type_in_storage(opaque_type_key, expected);
+ assert_eq!(prev, None);
self.add_item_bounds_for_hidden_type(
def_id.into(),
opaque_ty.args,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 3253222..2467969 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -838,8 +838,6 @@
parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard
-parse_unexpected_expr_in_pat_inline_const_sugg = consider wrapping the expression in an inline `const` (requires `{"#"}![feature(inline_const_pat)]`)
-
parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard
parse_unexpected_if_with_if = unexpected `if` in the condition expression
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index f813c33..55cb768 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -810,16 +810,16 @@ pub(crate) enum WrapInParentheses {
#[derive(Diagnostic)]
#[diag(parse_array_brackets_instead_of_braces)]
-pub(crate) struct ArrayBracketsInsteadOfSpaces {
+pub(crate) struct ArrayBracketsInsteadOfBraces {
#[primary_span]
pub span: Span,
#[subdiagnostic]
- pub sub: ArrayBracketsInsteadOfSpacesSugg,
+ pub sub: ArrayBracketsInsteadOfBracesSugg,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
-pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
+pub(crate) struct ArrayBracketsInsteadOfBracesSugg {
#[suggestion_part(code = "[")]
pub left: Span,
#[suggestion_part(code = "]")]
@@ -2769,17 +2769,6 @@ pub(crate) enum UnexpectedExpressionInPatternSugg {
/// The statement's block's indentation.
indentation: String,
},
-
- #[multipart_suggestion(
- parse_unexpected_expr_in_pat_inline_const_sugg,
- applicability = "maybe-incorrect"
- )]
- InlineConst {
- #[suggestion_part(code = "const {{ ")]
- start_span: Span,
- #[suggestion_part(code = " }}")]
- end_span: Span,
- },
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 92e8357..00e75cc 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2200,7 +2200,9 @@ pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
}
fn is_array_like_block(&mut self) -> bool {
- self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
+ matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
+ && self
+ .look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
&& self.look_ahead(2, |t| t == &token::Comma)
&& self.look_ahead(3, |t| t.can_begin_expr())
}
@@ -2212,9 +2214,9 @@ fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Exp
let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
Ok(arr) => {
- let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfSpaces {
+ let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfBraces {
span: arr.span,
- sub: errors::ArrayBracketsInsteadOfSpacesSugg {
+ sub: errors::ArrayBracketsInsteadOfBracesSugg {
left: lo,
right: snapshot.prev_token.span,
},
@@ -2337,7 +2339,8 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
let capture_clause = self.parse_capture_clause()?;
let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
let decl_hi = self.prev_token.span;
- let mut body = match fn_decl.output {
+ let mut body = match &fn_decl.output {
+ // No return type.
FnRetTy::Default(_) => {
let restrictions =
self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
@@ -2349,11 +2352,8 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?,
}
}
- _ => {
- // If an explicit return type is given, require a block to appear (RFC 968).
- let body_lo = self.token.span;
- self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
- }
+ // Explicit return type (`->`) needs block `-> T { }`.
+ FnRetTy::Ty(ty) => self.parse_closure_block_body(ty.span)?,
};
match coroutine_kind {
@@ -2405,6 +2405,49 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
Ok(closure)
}
+ /// If an explicit return type is given, require a block to appear (RFC 968).
+ fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P<Expr>> {
+ if self.may_recover()
+ && self.token.can_begin_expr()
+ && !matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
+ && !self.token.is_whole_block()
+ {
+ let snapshot = self.create_snapshot_for_diagnostic();
+ let restrictions =
+ self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
+ let tok = self.token.clone();
+ match self.parse_expr_res(restrictions, AttrWrapper::empty()) {
+ Ok((expr, _)) => {
+ let descr = super::token_descr(&tok);
+ let mut diag = self
+ .dcx()
+ .struct_span_err(tok.span, format!("expected `{{`, found {descr}"));
+ diag.span_label(
+ ret_span,
+ "explicit return type requires closure body to be enclosed in braces",
+ );
+ diag.multipart_suggestion_verbose(
+ "wrap the expression in curly braces",
+ vec![
+ (expr.span.shrink_to_lo(), "{ ".to_string()),
+ (expr.span.shrink_to_hi(), " }".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ );
+ diag.emit();
+ return Ok(expr);
+ }
+ Err(diag) => {
+ diag.cancel();
+ self.restore_snapshot(snapshot);
+ }
+ }
+ }
+
+ let body_lo = self.token.span;
+ self.parse_expr_block(None, body_lo, BlockCheckMode::Default)
+ }
+
/// Parses an optional `move` or `use` prefix to a closure-like construct.
fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
if self.eat_keyword(exp!(Move)) {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index aad1857..e93fb24 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -34,10 +34,10 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
}
/// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
- fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> {
+ fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
let safety = self.parse_safety(Case::Sensitive);
self.expect_keyword(exp!(Mod))?;
- let id = self.parse_ident()?;
+ let ident = self.parse_ident()?;
let mod_kind = if self.eat(exp!(Semi)) {
ModKind::Unloaded
} else {
@@ -46,7 +46,7 @@ fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> {
attrs.extend(inner_attrs);
ModKind::Loaded(items, Inline::Yes, inner_span, Ok(()))
};
- Ok((id, ItemKind::Mod(safety, mod_kind)))
+ Ok(ItemKind::Mod(safety, ident, mod_kind))
}
/// Parses the contents of a module (inner attributes followed by module items).
@@ -115,8 +115,6 @@ pub fn parse_mod(
}
}
-pub(super) type ItemInfo = (Ident, ItemKind);
-
impl<'a> Parser<'a> {
pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<P<Item>>> {
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
@@ -163,11 +161,11 @@ pub(super) fn parse_item_common(
fn_parse_mode,
Case::Sensitive,
)?;
- if let Some((ident, kind)) = kind {
+ if let Some(kind) = kind {
this.error_on_unconsumed_default(def, &kind);
let span = lo.to(this.prev_token.span);
let id = DUMMY_NODE_ID;
- let item = Item { ident, attrs, id, kind, vis, span, tokens: None };
+ let item = Item { attrs, id, kind, vis, span, tokens: None };
return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
}
@@ -208,7 +206,7 @@ fn parse_item_kind(
def: &mut Defaultness,
fn_parse_mode: FnParseMode,
case: Case,
- ) -> PResult<'a, Option<ItemInfo>> {
+ ) -> PResult<'a, Option<ItemKind>> {
let check_pub = def == &Defaultness::Final;
let mut def_ = || mem::replace(def, Defaultness::Final);
@@ -218,17 +216,15 @@ fn parse_item_kind(
// FUNCTION ITEM
let (ident, sig, generics, contract, body) =
self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
- (
+ ItemKind::Fn(Box::new(Fn {
+ defaultness: def_(),
ident,
- ItemKind::Fn(Box::new(Fn {
- defaultness: def_(),
- sig,
- generics,
- contract,
- body,
- define_opaque: None,
- })),
- )
+ sig,
+ generics,
+ contract,
+ body,
+ define_opaque: None,
+ }))
} else if self.eat_keyword(exp!(Extern)) {
if self.eat_keyword(exp!(Crate)) {
// EXTERN CRATE
@@ -247,8 +243,7 @@ fn parse_item_kind(
// STATIC ITEM
self.bump(); // `static`
let mutability = self.parse_mutability();
- let (ident, item) = self.parse_static_item(safety, mutability)?;
- (ident, ItemKind::Static(Box::new(item)))
+ self.parse_static_item(safety, mutability)?
} else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
// CONST ITEM
if self.token.is_keyword(kw::Impl) {
@@ -258,16 +253,14 @@ fn parse_item_kind(
self.recover_const_mut(const_span);
self.recover_missing_kw_before_item()?;
let (ident, generics, ty, expr) = self.parse_const_item()?;
- (
+ ItemKind::Const(Box::new(ConstItem {
+ defaultness: def_(),
ident,
- ItemKind::Const(Box::new(ConstItem {
- defaultness: def_(),
- generics,
- ty,
- expr,
- define_opaque: None,
- })),
- )
+ generics,
+ ty,
+ expr,
+ define_opaque: None,
+ }))
}
} else if self.check_keyword(exp!(Trait)) || self.check_auto_or_unsafe_trait_item() {
// TRAIT ITEM
@@ -334,14 +327,14 @@ fn parse_item_kind(
self.recover_missing_kw_before_item()?;
}
// MACRO INVOCATION ITEM
- (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?)))
+ ItemKind::MacCall(P(self.parse_item_macro(vis)?))
} else {
return Ok(None);
};
Ok(Some(info))
}
- fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemInfo>> {
+ fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
let span = self.token.span;
let token_name = super::token_descr(&self.token);
let snapshot = self.create_snapshot_for_diagnostic();
@@ -359,7 +352,7 @@ fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemInfo>> {
}
}
- fn parse_use_item(&mut self) -> PResult<'a, ItemInfo> {
+ fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
let tree = self.parse_use_tree()?;
if let Err(mut e) = self.expect_semi() {
match tree.kind {
@@ -373,7 +366,7 @@ fn parse_use_item(&mut self) -> PResult<'a, ItemInfo> {
}
return Err(e);
}
- Ok((Ident::empty(), ItemKind::Use(tree)))
+ Ok(ItemKind::Use(tree))
}
/// When parsing a statement, would the start of a path be an item?
@@ -483,7 +476,7 @@ fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
}
- fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> {
+ fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
// To be expanded
Ok(None)
}
@@ -577,7 +570,7 @@ fn parse_item_impl(
&mut self,
attrs: &mut AttrVec,
defaultness: Defaultness,
- ) -> PResult<'a, ItemInfo> {
+ ) -> PResult<'a, ItemKind> {
let safety = self.parse_safety(Case::Sensitive);
self.expect_keyword(exp!(Impl))?;
@@ -687,7 +680,7 @@ fn parse_item_impl(
}
None => (None, ty_first), // impl Type
};
- let item_kind = ItemKind::Impl(Box::new(Impl {
+ Ok(ItemKind::Impl(Box::new(Impl {
safety,
polarity,
defaultness,
@@ -696,12 +689,10 @@ fn parse_item_impl(
of_trait,
self_ty,
items: impl_items,
- }));
-
- Ok((Ident::empty(), item_kind))
+ })))
}
- fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
+ fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> {
let span = self.token.span;
self.expect_keyword(exp!(Reuse))?;
@@ -724,7 +715,7 @@ fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
})
};
- let (ident, item_kind) = if self.eat_path_sep() {
+ let item_kind = if self.eat_path_sep() {
let suffixes = if self.eat(exp!(Star)) {
None
} else {
@@ -732,7 +723,7 @@ fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0)
};
let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? };
- (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg)))
+ ItemKind::DelegationMac(Box::new(deleg))
} else {
let rename = rename(self)?;
let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
@@ -740,17 +731,18 @@ fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
id: DUMMY_NODE_ID,
qself,
path,
+ ident,
rename,
body: body(self)?,
from_glob: false,
};
- (ident, ItemKind::Delegation(Box::new(deleg)))
+ ItemKind::Delegation(Box::new(deleg))
};
let span = span.to(self.prev_token.span);
self.psess.gated_spans.gate(sym::fn_delegation, span);
- Ok((ident, item_kind))
+ Ok(item_kind)
}
fn parse_item_list<T>(
@@ -900,7 +892,7 @@ fn check_auto_or_unsafe_trait_item(&mut self) -> bool {
}
/// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
- fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> {
+ fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
let safety = self.parse_safety(Case::Sensitive);
// Parse optional `auto` prefix.
let is_auto = if self.eat_keyword(exp!(Auto)) {
@@ -941,15 +933,12 @@ fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, Ite
self.psess.gated_spans.gate(sym::trait_alias, whole_span);
- Ok((ident, ItemKind::TraitAlias(generics, bounds)))
+ Ok(ItemKind::TraitAlias(ident, generics, bounds))
} else {
// It's a normal trait.
generics.where_clause = self.parse_where_clause()?;
let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
- Ok((
- ident,
- ItemKind::Trait(Box::new(Trait { is_auto, safety, generics, bounds, items })),
- ))
+ Ok(ItemKind::Trait(Box::new(Trait { is_auto, safety, ident, generics, bounds, items })))
}
}
@@ -977,11 +966,12 @@ fn parse_assoc_item(
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<P<AssocItem>>>> {
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
- |Item { attrs, id, span, vis, ident, kind, tokens }| {
+ |Item { attrs, id, span, vis, kind, tokens }| {
let kind = match AssocItemKind::try_from(kind) {
Ok(kind) => kind,
Err(kind) => match kind {
ItemKind::Static(box StaticItem {
+ ident,
ty,
safety: _,
mutability: _,
@@ -991,6 +981,7 @@ fn parse_assoc_item(
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
AssocItemKind::Const(Box::new(ConstItem {
defaultness: Defaultness::Final,
+ ident,
generics: Generics::default(),
ty,
expr,
@@ -1000,7 +991,7 @@ fn parse_assoc_item(
_ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
},
};
- Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
+ Some(P(Item { attrs, id, span, vis, kind, tokens }))
},
))
}
@@ -1010,7 +1001,7 @@ fn parse_assoc_item(
/// TypeAlias = "type" Ident Generics (":" GenericBounds)? WhereClause ("=" Ty)? WhereClause ";" ;
/// ```
/// The `"type"` has already been eaten.
- fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> {
+ fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
@@ -1045,16 +1036,14 @@ fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo
self.expect_semi()?;
- Ok((
+ Ok(ItemKind::TyAlias(Box::new(TyAlias {
+ defaultness,
ident,
- ItemKind::TyAlias(Box::new(TyAlias {
- defaultness,
- generics,
- where_clauses,
- bounds,
- ty,
- })),
- ))
+ generics,
+ where_clauses,
+ bounds,
+ ty,
+ })))
}
/// Parses a `UseTree`.
@@ -1158,16 +1147,16 @@ fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
/// extern crate foo;
/// extern crate bar as foo;
/// ```
- fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> {
+ fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
// Accept `extern crate name-like-this` for better diagnostics
- let orig_name = self.parse_crate_name_with_dashes()?;
- let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
- (rename, Some(orig_name.name))
+ let orig_ident = self.parse_crate_name_with_dashes()?;
+ let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
+ (Some(orig_ident.name), rename)
} else {
- (orig_name, None)
+ (None, orig_ident)
};
self.expect_semi()?;
- Ok((item_name, ItemKind::ExternCrate(orig_name)))
+ Ok(ItemKind::ExternCrate(orig_name, item_ident))
}
fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
@@ -1218,7 +1207,7 @@ fn parse_item_foreign_mod(
&mut self,
attrs: &mut AttrVec,
mut safety: Safety,
- ) -> PResult<'a, ItemInfo> {
+ ) -> PResult<'a, ItemKind> {
let extern_span = self.prev_token.uninterpolated_span();
let abi = self.parse_abi(); // ABI?
// FIXME: This recovery should be tested better.
@@ -1230,13 +1219,12 @@ fn parse_item_foreign_mod(
safety = Safety::Unsafe(self.token.span);
let _ = self.eat_keyword(exp!(Unsafe));
}
- let module = ast::ForeignMod {
+ Ok(ItemKind::ForeignMod(ast::ForeignMod {
extern_span,
safety,
abi,
items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
- };
- Ok((Ident::empty(), ItemKind::ForeignMod(module)))
+ }))
}
/// Parses a foreign item (one in an `extern { ... }` block).
@@ -1246,11 +1234,11 @@ pub fn parse_foreign_item(
) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false };
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
- |Item { attrs, id, span, vis, ident, kind, tokens }| {
+ |Item { attrs, id, span, vis, kind, tokens }| {
let kind = match ForeignItemKind::try_from(kind) {
Ok(kind) => kind,
Err(kind) => match kind {
- ItemKind::Const(box ConstItem { ty, expr, .. }) => {
+ ItemKind::Const(box ConstItem { ident, ty, expr, .. }) => {
let const_span = Some(span.with_hi(ident.span.lo()))
.filter(|span| span.can_be_used_for_suggestions());
self.dcx().emit_err(errors::ExternItemCannotBeConst {
@@ -1258,6 +1246,7 @@ pub fn parse_foreign_item(
const_span,
});
ForeignItemKind::Static(Box::new(StaticItem {
+ ident,
ty,
mutability: Mutability::Not,
expr,
@@ -1268,7 +1257,7 @@ pub fn parse_foreign_item(
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
},
};
- Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
+ Some(P(Item { attrs, id, span, vis, kind, tokens }))
},
))
}
@@ -1343,13 +1332,13 @@ fn recover_const_impl(
const_span: Span,
attrs: &mut AttrVec,
defaultness: Defaultness,
- ) -> PResult<'a, ItemInfo> {
+ ) -> PResult<'a, ItemKind> {
let impl_span = self.token.span;
let err = self.expected_ident_found_err();
// Only try to recover if this is implementing a trait for a type
- let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
- Ok(impl_info) => impl_info,
+ let mut item_kind = match self.parse_item_impl(attrs, defaultness) {
+ Ok(item_kind) => item_kind,
Err(recovery_error) => {
// Recovery failed, raise the "expected identifier" error
recovery_error.cancel();
@@ -1357,7 +1346,7 @@ fn recover_const_impl(
}
};
- match &mut impl_info.1 {
+ match &mut item_kind {
ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => {
*constness = Const::Yes(const_span);
@@ -1374,10 +1363,11 @@ fn recover_const_impl(
_ => unreachable!(),
}
- Ok(impl_info)
+ Ok(item_kind)
}
- /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in `mutability`.
+ /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in
+ /// `mutability`.
///
/// ```ebnf
/// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
@@ -1386,7 +1376,7 @@ fn parse_static_item(
&mut self,
safety: Safety,
mutability: Mutability,
- ) -> PResult<'a, (Ident, StaticItem)> {
+ ) -> PResult<'a, ItemKind> {
let ident = self.parse_ident()?;
if self.token == TokenKind::Lt && self.may_recover() {
@@ -1398,7 +1388,8 @@ fn parse_static_item(
// FIXME: This could maybe benefit from `.may_recover()`?
let ty = match (self.eat(exp!(Colon)), self.check(exp!(Eq)) | self.check(exp!(Semi))) {
(true, false) => self.parse_ty()?,
- // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing type.
+ // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing
+ // type.
(colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
};
@@ -1406,7 +1397,8 @@ fn parse_static_item(
self.expect_semi()?;
- Ok((ident, StaticItem { ty, safety, mutability, expr, define_opaque: None }))
+ let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None };
+ Ok(ItemKind::Static(Box::new(item)))
}
/// Parse a constant item with the prefix `"const"` already parsed.
@@ -1531,7 +1523,7 @@ fn recover_missing_global_item_type(
}
/// Parses an enum declaration.
- fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
+ fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
if self.token.is_keyword(kw::Struct) {
let span = self.prev_token.span.to(self.token.span);
let err = errors::EnumStructMutuallyExclusive { span };
@@ -1544,7 +1536,7 @@ fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
}
let prev_span = self.prev_token.span;
- let id = self.parse_ident()?;
+ let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
generics.where_clause = self.parse_where_clause()?;
@@ -1555,10 +1547,10 @@ fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
(thin_vec![], Trailing::No)
} else {
self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| {
- p.parse_enum_variant(id.span)
+ p.parse_enum_variant(ident.span)
})
.map_err(|mut err| {
- err.span_label(id.span, "while parsing this enum");
+ err.span_label(ident.span, "while parsing this enum");
if self.token == token::Colon {
let snapshot = self.create_snapshot_for_diagnostic();
self.bump();
@@ -1584,7 +1576,7 @@ fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
};
let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
- Ok((id, ItemKind::Enum(enum_definition, generics)))
+ Ok(ItemKind::Enum(ident, enum_definition, generics))
}
fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
@@ -1676,8 +1668,8 @@ fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
}
/// Parses `struct Foo { ... }`.
- fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
- let class_name = self.parse_ident()?;
+ fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
+ let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
@@ -1698,7 +1690,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
let vdata = if self.token.is_keyword(kw::Where) {
let tuple_struct_body;
(generics.where_clause, tuple_struct_body) =
- self.parse_struct_where_clause(class_name, generics.span)?;
+ self.parse_struct_where_clause(ident, generics.span)?;
if let Some(body) = tuple_struct_body {
// If we see a misplaced tuple struct body: `struct Foo<T> where T: Copy, (T);`
@@ -1712,7 +1704,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
// If we see: `struct Foo<T> where T: Copy { ... }`
let (fields, recovered) = self.parse_record_struct_body(
"struct",
- class_name.span,
+ ident.span,
generics.where_clause.has_where_token,
)?;
VariantData::Struct { fields, recovered }
@@ -1724,7 +1716,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
} else if self.token == token::OpenDelim(Delimiter::Brace) {
let (fields, recovered) = self.parse_record_struct_body(
"struct",
- class_name.span,
+ ident.span,
generics.where_clause.has_where_token,
)?;
VariantData::Struct { fields, recovered }
@@ -1740,12 +1732,12 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
return Err(self.dcx().create_err(err));
};
- Ok((class_name, ItemKind::Struct(vdata, generics)))
+ Ok(ItemKind::Struct(ident, vdata, generics))
}
/// Parses `union Foo { ... }`.
- fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
- let class_name = self.parse_ident()?;
+ fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
+ let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
@@ -1753,14 +1745,14 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
generics.where_clause = self.parse_where_clause()?;
let (fields, recovered) = self.parse_record_struct_body(
"union",
- class_name.span,
+ ident.span,
generics.where_clause.has_where_token,
)?;
VariantData::Struct { fields, recovered }
} else if self.token == token::OpenDelim(Delimiter::Brace) {
let (fields, recovered) = self.parse_record_struct_body(
"union",
- class_name.span,
+ ident.span,
generics.where_clause.has_where_token,
)?;
VariantData::Struct { fields, recovered }
@@ -1772,7 +1764,7 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
return Err(err);
};
- Ok((class_name, ItemKind::Union(vdata, generics)))
+ Ok(ItemKind::Union(ident, vdata, generics))
}
/// This function parses the fields of record structs:
@@ -2124,15 +2116,17 @@ fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
}
} else if self.eat_keyword(exp!(Struct)) {
match self.parse_item_struct() {
- Ok((ident, _)) => self
- .dcx()
- .struct_span_err(
- lo.with_hi(ident.span.hi()),
- format!("structs are not allowed in {adt_ty} definitions"),
- )
- .with_help(
- "consider creating a new `struct` definition instead of nesting",
- ),
+ Ok(item) => {
+ let ItemKind::Struct(ident, ..) = item else { unreachable!() };
+ self.dcx()
+ .struct_span_err(
+ lo.with_hi(ident.span.hi()),
+ format!("structs are not allowed in {adt_ty} definitions"),
+ )
+ .with_help(
+ "consider creating a new `struct` definition instead of nesting",
+ )
+ }
Err(err) => {
err.cancel();
self.restore_snapshot(snapshot);
@@ -2177,7 +2171,7 @@ fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
/// MacParams = "(" TOKEN_STREAM ")" ;
/// DeclMac = "macro" Ident MacParams? MacBody ;
/// ```
- fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> {
+ fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
let ident = self.parse_ident()?;
let body = if self.check(exp!(OpenBrace)) {
self.parse_delim_args()? // `MacBody`
@@ -2199,7 +2193,7 @@ fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> {
};
self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
- Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false })))
+ Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: false }))
}
/// Is this a possibly malformed start of a `macro_rules! foo` item definition?
@@ -2228,7 +2222,7 @@ fn parse_item_macro_rules(
&mut self,
vis: &Visibility,
has_bang: bool,
- ) -> PResult<'a, ItemInfo> {
+ ) -> PResult<'a, ItemKind> {
self.expect_keyword(exp!(MacroRules))?; // `macro_rules`
if has_bang {
@@ -2246,7 +2240,7 @@ fn parse_item_macro_rules(
self.eat_semi_for_macro_if_needed(&body);
self.complain_if_pub_macro(vis, true);
- Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true })))
+ Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: true }))
}
/// Item macro invocations or `macro_rules!` definitions need inherited visibility.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index a79b404..d865fd4 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1370,9 +1370,6 @@ fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
/// Parses inline const expressions.
fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
- if pat {
- self.psess.gated_spans.gate(sym::inline_const_pat, span);
- }
self.expect_keyword(exp!(Const))?;
let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
let anon_const = AnonConst {
@@ -1380,7 +1377,17 @@ fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
};
let blk_span = anon_const.value.span;
- Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs))
+ let kind = if pat {
+ let guar = self
+ .dcx()
+ .struct_span_err(blk_span, "`inline_const_pat` has been removed")
+ .with_help("use a named `const`-item or an `if`-guard instead")
+ .emit();
+ ExprKind::Err(guar)
+ } else {
+ ExprKind::ConstBlock(anon_const)
+ };
+ Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs))
}
/// Parses mutability (`mut` or nothing).
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index ec14c57..174cc92 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -631,15 +631,6 @@ fn maybe_add_suggestions_then_emit(
ident,
indentation,
});
-
- // help: wrap the expr in a `const { expr }`
- // FIXME(inline_const_pat): once stabilized, remove this check and remove the `(requires #[feature(inline_const_pat)])` note from the message
- if self.parser.psess.unstable_features.is_nightly_build() {
- err.subdiagnostic(UnexpectedExpressionInPatternSugg::InlineConst {
- start_span: expr_span.shrink_to_lo(),
- end_span: expr_span.shrink_to_hi(),
- });
- }
},
);
}
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 471966d..49ae6cb 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -2922,7 +2922,7 @@ fn out_of_line_mod() {
.unwrap()
.unwrap();
- let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() };
+ let ast::ItemKind::Mod(_, _, mod_kind) = &item.kind else { panic!() };
assert_matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2);
});
}
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 9ecde2a..6bbd650 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -16,7 +16,8 @@
use crate::{errors, parse_in};
pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
- if attr.is_doc_comment() || attr.has_name(sym::cfg_attr_trace) {
+ if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace)
+ {
return;
}
@@ -215,11 +216,7 @@ pub fn check_builtin_meta_item(
template: AttributeTemplate,
deny_unsafety: bool,
) {
- // Some special attributes like `cfg` must be checked
- // before the generic check, so we skip them here.
- let should_skip = |name| name == sym::cfg;
-
- if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
+ if !is_attr_template_compatible(&template, &meta.kind) {
emit_malformed_attribute(psess, style, meta.span, name, template);
}
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 06398dd..bea8680 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -383,6 +383,10 @@
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "65833")}
+passes_inline_ignored_for_exported =
+ `#[inline]` is ignored on externally exported functions
+ .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
passes_inline_ignored_function_prototype =
`#[inline]` is ignored on function prototypes
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 9238c73..cfc0369 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -35,7 +35,7 @@
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
};
use rustc_session::parse::feature_err;
-use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, kw, sym};
+use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::ObligationCtxt;
@@ -272,6 +272,7 @@ fn check_attributes(
| sym::forbid
| sym::cfg
| sym::cfg_attr
+ | sym::cfg_trace
| sym::cfg_attr_trace
// need to be fixed
| sym::cfi_encoding // FIXME(cfi_encoding)
@@ -450,6 +451,23 @@ fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Targ
});
}
}
+
+ // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
+ if let Some(did) = hir_id.as_owner()
+ && self.tcx.def_kind(did).has_codegen_attrs()
+ && !matches!(attr.meta_item_list().as_deref(), Some([item]) if item.has_name(sym::never))
+ {
+ let attrs = self.tcx.codegen_fn_attrs(did);
+ // Not checking naked as `#[inline]` is forbidden for naked functions anyways.
+ if attrs.contains_extern_indicator() {
+ self.tcx.emit_node_span_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span(),
+ errors::InlineIgnoredForExported {},
+ );
+ }
+ }
}
/// Checks that `#[coverage(..)]` is applied to a function/closure/method,
@@ -574,8 +592,7 @@ fn check_naked(
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
const ALLOW_LIST: &[rustc_span::Symbol] = &[
// conditional compilation
- sym::cfg,
- sym::cfg_attr,
+ sym::cfg_trace,
sym::cfg_attr_trace,
// testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`)
sym::test,
@@ -1021,14 +1038,14 @@ fn is_doc_keyword(s: Symbol) -> bool {
// FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we
// can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the
// `#[doc(keyword = "SelfTy")` attribute in `library/std/src/keyword_docs.rs`.
- s <= kw::Union || s == sym::SelfTy
+ s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy
}
- let doc_keyword = meta.value_str().unwrap_or(kw::Empty);
- if doc_keyword == kw::Empty {
- self.doc_attr_str_error(meta, "keyword");
- return;
- }
+ let doc_keyword = match meta.value_str() {
+ Some(value) if value != kw::Empty => value,
+ _ => return self.doc_attr_str_error(meta, "keyword"),
+ };
+
let item_kind = match self.tcx.hir_node(hir_id) {
hir::Node::Item(item) => Some(&item.kind),
_ => None,
@@ -2656,7 +2673,7 @@ fn visit_where_predicate(&mut self, where_predicate: &'tcx hir::WherePredicate<'
// only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
// if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
// in where clauses. After that, only `self.check_attributes` should be enough.
- const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr, sym::cfg_attr_trace];
+ const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg_trace, sym::cfg_attr_trace];
let spans = self
.tcx
.hir_attrs(where_predicate.hir_id)
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index d272987..2a435c4 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -24,7 +24,7 @@ struct EntryContext<'tcx> {
}
fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
- let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable);
+ let any_exe = tcx.crate_types().contains(&CrateType::Executable);
if !any_exe {
// No need to find a main function.
return None;
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 0ee1743..4e3e032 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1441,6 +1441,11 @@ pub(crate) struct OnlyHasEffectOn {
pub target_name: String,
}
+#[derive(LintDiagnostic)]
+#[diag(passes_inline_ignored_for_exported)]
+#[help]
+pub(crate) struct InlineIgnoredForExported {}
+
#[derive(Diagnostic)]
#[diag(passes_object_lifetime_err)]
pub(crate) struct ObjectLifetimeErr {
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 9d4b46c..664bd4a 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -268,22 +268,22 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
fn visit_item(&mut self, i: &'ast ast::Item) {
let target = match &i.kind {
- ast::ItemKind::ExternCrate(_) => Target::ExternCrate,
+ ast::ItemKind::ExternCrate(..) => Target::ExternCrate,
ast::ItemKind::Use(_) => Target::Use,
ast::ItemKind::Static(_) => Target::Static,
ast::ItemKind::Const(_) => Target::Const,
ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn,
- ast::ItemKind::Mod(_, _) => Target::Mod,
+ ast::ItemKind::Mod(..) => Target::Mod,
ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm,
ast::ItemKind::TyAlias(_) => Target::TyAlias,
- ast::ItemKind::Enum(_, _) => Target::Enum,
- ast::ItemKind::Struct(_, _) => Target::Struct,
- ast::ItemKind::Union(_, _) => Target::Union,
+ ast::ItemKind::Enum(..) => Target::Enum,
+ ast::ItemKind::Struct(..) => Target::Struct,
+ ast::ItemKind::Union(..) => Target::Union,
ast::ItemKind::Trait(_) => Target::Trait,
- ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
+ ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
ast::ItemKind::Impl(_) => Target::Impl,
- ast::ItemKind::MacroDef(_) => Target::MacroDef,
+ ast::ItemKind::MacroDef(..) => Target::MacroDef,
ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
unreachable!("macros should have been expanded")
}
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index a83c388..30a9e71 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -26,8 +26,8 @@
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
- CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryState,
- get_query_incr, get_query_non_incr,
+ CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryStackDeferred,
+ QueryState, get_query_incr, get_query_non_incr,
};
use rustc_query_system::{HandleCycleError, Value};
use rustc_span::{ErrorGuaranteed, Span};
@@ -84,7 +84,10 @@ fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
}
#[inline(always)]
- fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key>
+ fn query_state<'a>(
+ self,
+ qcx: QueryCtxt<'tcx>,
+ ) -> &'a QueryState<Self::Key, QueryStackDeferred<'tcx>>
where
QueryCtxt<'tcx>: 'a,
{
@@ -93,7 +96,7 @@ fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key>
unsafe {
&*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>)
.byte_add(self.dynamic.query_state)
- .cast::<QueryState<Self::Key>>()
+ .cast::<QueryState<Self::Key, QueryStackDeferred<'tcx>>>()
}
}
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 55281cd..3238c7a 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -5,6 +5,7 @@
use std::num::NonZero;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_data_structures::unord::UnordMap;
use rustc_hashes::Hash64;
use rustc_index::Idx;
@@ -24,8 +25,8 @@
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
- QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame,
- force_query,
+ QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect,
+ QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query,
};
use rustc_query_system::{QueryOverflow, QueryOverflowNote};
use rustc_serialize::{Decodable, Encodable};
@@ -65,7 +66,9 @@ fn dep_context(&self) -> &Self::DepContext {
}
}
-impl QueryContext for QueryCtxt<'_> {
+impl<'tcx> QueryContext for QueryCtxt<'tcx> {
+ type QueryInfo = QueryStackDeferred<'tcx>;
+
#[inline]
fn next_job_id(self) -> QueryJobId {
QueryJobId(
@@ -82,7 +85,9 @@ fn current_query_job(self) -> Option<QueryJobId> {
/// Returns a query map representing active query jobs.
/// It returns an incomplete map as an error if it fails
/// to take locks.
- fn collect_active_jobs(self) -> Result<QueryMap, QueryMap> {
+ fn collect_active_jobs(
+ self,
+ ) -> Result<QueryMap<QueryStackDeferred<'tcx>>, QueryMap<QueryStackDeferred<'tcx>>> {
let mut jobs = QueryMap::default();
let mut complete = true;
@@ -95,6 +100,13 @@ fn collect_active_jobs(self) -> Result<QueryMap, QueryMap> {
if complete { Ok(jobs) } else { Err(jobs) }
}
+ fn lift_query_info(
+ self,
+ info: &QueryStackDeferred<'tcx>,
+ ) -> rustc_query_system::query::QueryStackFrameExtra {
+ info.extract()
+ }
+
// Interactions with on_disk_cache
fn load_side_effect(
self,
@@ -159,7 +171,10 @@ fn depth_limit_error(self, job: QueryJobId) {
self.sess.dcx().emit_fatal(QueryOverflow {
span: info.job.span,
- note: QueryOverflowNote { desc: info.query.description, depth },
+ note: QueryOverflowNote {
+ desc: self.lift_query_info(&info.query.info).description,
+ depth,
+ },
suggested_limit,
crate_name: self.crate_name(LOCAL_CRATE),
});
@@ -296,16 +311,17 @@ macro_rules! should_ever_cache_on_disk {
};
}
-pub(crate) fn create_query_frame<
- 'tcx,
- K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>,
->(
- tcx: TyCtxt<'tcx>,
- do_describe: fn(TyCtxt<'tcx>, K) -> String,
- key: K,
- kind: DepKind,
- name: &'static str,
-) -> QueryStackFrame {
+fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>(
+ (tcx, key, kind, name, do_describe): (
+ TyCtxt<'tcx>,
+ K,
+ DepKind,
+ &'static str,
+ fn(TyCtxt<'tcx>, K) -> String,
+ ),
+) -> QueryStackFrameExtra {
+ let def_id = key.key_as_def_id();
+
// If reduced queries are requested, we may be printing a query stack due
// to a panic. Avoid using `default_span` and `def_kind` in that case.
let reduce_queries = with_reduced_queries();
@@ -324,13 +340,28 @@ pub(crate) fn create_query_frame<
} else {
Some(key.default_span(tcx))
};
- let def_id = key.key_as_def_id();
+
let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries {
// Try to avoid infinite recursion.
None
} else {
def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
};
+ QueryStackFrameExtra::new(description, span, def_kind)
+}
+
+pub(crate) fn create_query_frame<
+ 'tcx,
+ K: Copy + DynSend + DynSync + Key + for<'a> HashStable<StableHashingContext<'a>> + 'tcx,
+>(
+ tcx: TyCtxt<'tcx>,
+ do_describe: fn(TyCtxt<'tcx>, K) -> String,
+ key: K,
+ kind: DepKind,
+ name: &'static str,
+) -> QueryStackFrame<QueryStackDeferred<'tcx>> {
+ let def_id = key.key_as_def_id();
+
let hash = || {
tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
@@ -341,7 +372,10 @@ pub(crate) fn create_query_frame<
};
let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();
- QueryStackFrame::new(description, span, def_id, def_kind, kind, def_id_for_ty_in_cycle, hash)
+ let info =
+ QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra);
+
+ QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle)
}
pub(crate) fn encode_query_results<'a, 'tcx, Q>(
@@ -688,7 +722,10 @@ fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self
}
}
- pub(crate) fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) -> Option<()> {
+ pub(crate) fn try_collect_active_jobs<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ qmap: &mut QueryMap<QueryStackDeferred<'tcx>>,
+ ) -> Option<()> {
let make_query = |tcx, key| {
let kind = rustc_middle::dep_graph::dep_kinds::$name;
let name = stringify!($name);
@@ -768,7 +805,9 @@ pub fn dynamic_queries<'tcx>() -> DynamicQueries<'tcx> {
// These arrays are used for iteration and can't be indexed by `DepKind`.
- const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap) -> Option<()>] =
+ const TRY_COLLECT_ACTIVE_JOBS: &[
+ for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<QueryStackDeferred<'tcx>>) -> Option<()>
+ ] =
&[$(query_impl::$name::try_collect_active_jobs),*];
const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 495f347..127dcd8 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -66,6 +66,7 @@ pub struct MarkFrame<'a> {
parent: Option<&'a MarkFrame<'a>>,
}
+#[derive(Debug)]
pub(super) enum DepNodeColor {
Red,
Green(DepNodeIndex),
@@ -909,7 +910,7 @@ fn try_mark_parent_green<Qcx: QueryContext<Deps = D>>(
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
if node_index.is_some() {
- debug!("managed to MARK dependency {dep_dep_node:?} as green",);
+ debug!("managed to MARK dependency {dep_dep_node:?} as green");
return Some(());
}
}
@@ -930,7 +931,7 @@ fn try_mark_parent_green<Qcx: QueryContext<Deps = D>>(
return Some(());
}
Some(DepNodeColor::Red) => {
- debug!("dependency {dep_dep_node:?} was red after forcing",);
+ debug!("dependency {dep_dep_node:?} was red after forcing");
return None;
}
None => {}
@@ -950,7 +951,7 @@ fn try_mark_parent_green<Qcx: QueryContext<Deps = D>>(
// invalid state will not be persisted to the
// incremental compilation cache because of
// compilation errors being present.
- debug!("dependency {dep_dep_node:?} resulted in compilation error",);
+ debug!("dependency {dep_dep_node:?} resulted in compilation error");
return None;
}
diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs
index 852d93b..25778ad 100644
--- a/compiler/rustc_query_system/src/ich/mod.rs
+++ b/compiler/rustc_query_system/src/ich/mod.rs
@@ -8,7 +8,7 @@
mod impls_syntax;
pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
- sym::cfg,
+ sym::cfg_trace, // FIXME should this really be ignored?
sym::rustc_if_this_changed,
sym::rustc_then_this_would_need,
sym::rustc_dirty,
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index 371b896..e508ead 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -6,6 +6,7 @@
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_span::ErrorGuaranteed;
+use super::QueryStackFrameExtra;
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
use crate::error::HandleCycleError;
use crate::ich::StableHashingContext;
@@ -27,7 +28,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
fn format_value(self) -> fn(&Self::Value) -> String;
// Don't use this method to access query results, instead use the methods on TyCtxt
- fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key>
+ fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::QueryInfo>
where
Qcx: 'a;
@@ -57,7 +58,7 @@ fn try_load_from_disk(
fn value_from_cycle_error(
self,
tcx: Qcx::DepContext,
- cycle_error: &CycleError,
+ cycle_error: &CycleError<QueryStackFrameExtra>,
guar: ErrorGuaranteed,
) -> Self::Value;
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 402c783..de35cd7 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -1,3 +1,4 @@
+use std::fmt::Debug;
use std::hash::Hash;
use std::io::Write;
use std::iter;
@@ -12,6 +13,7 @@
use rustc_session::Session;
use rustc_span::{DUMMY_SP, Span};
+use super::QueryStackFrameExtra;
use crate::dep_graph::DepContext;
use crate::error::CycleStack;
use crate::query::plumbing::CycleError;
@@ -19,45 +21,54 @@
/// Represents a span and a query key.
#[derive(Clone, Debug)]
-pub struct QueryInfo {
+pub struct QueryInfo<I> {
/// The span corresponding to the reason for which this query was required.
pub span: Span,
- pub query: QueryStackFrame,
+ pub query: QueryStackFrame<I>,
}
-pub type QueryMap = FxHashMap<QueryJobId, QueryJobInfo>;
+impl<I> QueryInfo<I> {
+ pub(crate) fn lift<Qcx: QueryContext<QueryInfo = I>>(
+ &self,
+ qcx: Qcx,
+ ) -> QueryInfo<QueryStackFrameExtra> {
+ QueryInfo { span: self.span, query: self.query.lift(qcx) }
+ }
+}
+
+pub type QueryMap<I> = FxHashMap<QueryJobId, QueryJobInfo<I>>;
/// A value uniquely identifying an active query job.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct QueryJobId(pub NonZero<u64>);
impl QueryJobId {
- fn query(self, map: &QueryMap) -> QueryStackFrame {
+ fn query<I: Clone>(self, map: &QueryMap<I>) -> QueryStackFrame<I> {
map.get(&self).unwrap().query.clone()
}
- fn span(self, map: &QueryMap) -> Span {
+ fn span<I>(self, map: &QueryMap<I>) -> Span {
map.get(&self).unwrap().job.span
}
- fn parent(self, map: &QueryMap) -> Option<QueryJobId> {
+ fn parent<I>(self, map: &QueryMap<I>) -> Option<QueryJobId> {
map.get(&self).unwrap().job.parent
}
- fn latch(self, map: &QueryMap) -> Option<&QueryLatch> {
+ fn latch<I>(self, map: &QueryMap<I>) -> Option<&QueryLatch<I>> {
map.get(&self).unwrap().job.latch.as_ref()
}
}
#[derive(Clone, Debug)]
-pub struct QueryJobInfo {
- pub query: QueryStackFrame,
- pub job: QueryJob,
+pub struct QueryJobInfo<I> {
+ pub query: QueryStackFrame<I>,
+ pub job: QueryJob<I>,
}
/// Represents an active query job.
-#[derive(Clone, Debug)]
-pub struct QueryJob {
+#[derive(Debug)]
+pub struct QueryJob<I> {
pub id: QueryJobId,
/// The span corresponding to the reason for which this query was required.
@@ -67,17 +78,23 @@ pub struct QueryJob {
pub parent: Option<QueryJobId>,
/// The latch that is used to wait on this job.
- latch: Option<QueryLatch>,
+ latch: Option<QueryLatch<I>>,
}
-impl QueryJob {
+impl<I> Clone for QueryJob<I> {
+ fn clone(&self) -> Self {
+ Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() }
+ }
+}
+
+impl<I> QueryJob<I> {
/// Creates a new query job.
#[inline]
pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
QueryJob { id, span, parent, latch: None }
}
- pub(super) fn latch(&mut self) -> QueryLatch {
+ pub(super) fn latch(&mut self) -> QueryLatch<I> {
if self.latch.is_none() {
self.latch = Some(QueryLatch::new());
}
@@ -97,12 +114,12 @@ pub fn signal_complete(self) {
}
impl QueryJobId {
- pub(super) fn find_cycle_in_stack(
+ pub(super) fn find_cycle_in_stack<I: Clone>(
&self,
- query_map: QueryMap,
+ query_map: QueryMap<I>,
current_job: &Option<QueryJobId>,
span: Span,
- ) -> CycleError {
+ ) -> CycleError<I> {
// Find the waitee amongst `current_job` parents
let mut cycle = Vec::new();
let mut current_job = Option::clone(current_job);
@@ -136,7 +153,7 @@ pub(super) fn find_cycle_in_stack(
#[cold]
#[inline(never)]
- pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) {
+ pub fn find_dep_kind_root<I: Clone>(&self, query_map: QueryMap<I>) -> (QueryJobInfo<I>, usize) {
let mut depth = 1;
let info = query_map.get(&self).unwrap();
let dep_kind = info.query.dep_kind;
@@ -156,25 +173,31 @@ pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) {
}
#[derive(Debug)]
-struct QueryWaiter {
+struct QueryWaiter<I> {
query: Option<QueryJobId>,
condvar: Condvar,
span: Span,
- cycle: Mutex<Option<CycleError>>,
+ cycle: Mutex<Option<CycleError<I>>>,
}
#[derive(Debug)]
-struct QueryLatchInfo {
+struct QueryLatchInfo<I> {
complete: bool,
- waiters: Vec<Arc<QueryWaiter>>,
+ waiters: Vec<Arc<QueryWaiter<I>>>,
}
-#[derive(Clone, Debug)]
-pub(super) struct QueryLatch {
- info: Arc<Mutex<QueryLatchInfo>>,
+#[derive(Debug)]
+pub(super) struct QueryLatch<I> {
+ info: Arc<Mutex<QueryLatchInfo<I>>>,
}
-impl QueryLatch {
+impl<I> Clone for QueryLatch<I> {
+ fn clone(&self) -> Self {
+ Self { info: Arc::clone(&self.info) }
+ }
+}
+
+impl<I> QueryLatch<I> {
fn new() -> Self {
QueryLatch {
info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })),
@@ -182,7 +205,11 @@ fn new() -> Self {
}
/// Awaits for the query job to complete.
- pub(super) fn wait_on(&self, query: Option<QueryJobId>, span: Span) -> Result<(), CycleError> {
+ pub(super) fn wait_on(
+ &self,
+ query: Option<QueryJobId>,
+ span: Span,
+ ) -> Result<(), CycleError<I>> {
let waiter =
Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() });
self.wait_on_inner(&waiter);
@@ -197,7 +224,7 @@ pub(super) fn wait_on(&self, query: Option<QueryJobId>, span: Span) -> Result<()
}
/// Awaits the caller on this latch by blocking the current thread.
- fn wait_on_inner(&self, waiter: &Arc<QueryWaiter>) {
+ fn wait_on_inner(&self, waiter: &Arc<QueryWaiter<I>>) {
let mut info = self.info.lock();
if !info.complete {
// We push the waiter on to the `waiters` list. It can be accessed inside
@@ -232,7 +259,7 @@ fn set(&self) {
/// Removes a single waiter from the list of waiters.
/// This is used to break query cycles.
- fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter> {
+ fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter<I>> {
let mut info = self.info.lock();
debug_assert!(!info.complete);
// Remove the waiter from the list of waiters
@@ -252,7 +279,11 @@ fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter> {
/// For visits of resumable waiters it returns Some(Some(Waiter)) which has the
/// required information to resume the waiter.
/// If all `visit` calls returns None, this function also returns None.
-fn visit_waiters<F>(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option<Option<Waiter>>
+fn visit_waiters<I, F>(
+ query_map: &QueryMap<I>,
+ query: QueryJobId,
+ mut visit: F,
+) -> Option<Option<Waiter>>
where
F: FnMut(Span, QueryJobId) -> Option<Option<Waiter>>,
{
@@ -282,8 +313,8 @@ fn visit_waiters<F>(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Op
/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP.
/// If a cycle is detected, this initial value is replaced with the span causing
/// the cycle.
-fn cycle_check(
- query_map: &QueryMap,
+fn cycle_check<I>(
+ query_map: &QueryMap<I>,
query: QueryJobId,
span: Span,
stack: &mut Vec<(Span, QueryJobId)>,
@@ -322,8 +353,8 @@ fn cycle_check(
/// Finds out if there's a path to the compiler root (aka. code which isn't in a query)
/// from `query` without going through any of the queries in `visited`.
/// This is achieved with a depth first search.
-fn connected_to_root(
- query_map: &QueryMap,
+fn connected_to_root<I>(
+ query_map: &QueryMap<I>,
query: QueryJobId,
visited: &mut FxHashSet<QueryJobId>,
) -> bool {
@@ -344,7 +375,7 @@ fn connected_to_root(
}
// Deterministically pick an query from a list
-fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T
+fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap<I>, queries: &'a [T], f: F) -> &'a T
where
F: Fn(&T) -> (Span, QueryJobId),
{
@@ -369,10 +400,10 @@ fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T
/// the function return true.
/// If a cycle was not found, the starting query is removed from `jobs` and
/// the function returns false.
-fn remove_cycle(
- query_map: &QueryMap,
+fn remove_cycle<I: Clone>(
+ query_map: &QueryMap<I>,
jobs: &mut Vec<QueryJobId>,
- wakelist: &mut Vec<Arc<QueryWaiter>>,
+ wakelist: &mut Vec<Arc<QueryWaiter<I>>>,
) -> bool {
let mut visited = FxHashSet::default();
let mut stack = Vec::new();
@@ -473,7 +504,10 @@ fn remove_cycle(
/// uses a query latch and then resuming that waiter.
/// There may be multiple cycles involved in a deadlock, so this searches
/// all active queries for cycles before finally resuming all the waiters at once.
-pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) {
+pub fn break_query_cycles<I: Clone + Debug>(
+ query_map: QueryMap<I>,
+ registry: &rayon_core::Registry,
+) {
let mut wakelist = Vec::new();
let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();
@@ -520,7 +554,7 @@ pub fn report_cycle<'a>(
) -> Diag<'a> {
assert!(!stack.is_empty());
- let span = stack[0].query.default_span(stack[1 % stack.len()].span);
+ let span = stack[0].query.info.default_span(stack[1 % stack.len()].span);
let mut cycle_stack = Vec::new();
@@ -529,31 +563,31 @@ pub fn report_cycle<'a>(
for i in 1..stack.len() {
let query = &stack[i].query;
- let span = query.default_span(stack[(i + 1) % stack.len()].span);
- cycle_stack.push(CycleStack { span, desc: query.description.to_owned() });
+ let span = query.info.default_span(stack[(i + 1) % stack.len()].span);
+ cycle_stack.push(CycleStack { span, desc: query.info.description.to_owned() });
}
let mut cycle_usage = None;
if let Some((span, ref query)) = *usage {
cycle_usage = Some(crate::error::CycleUsage {
- span: query.default_span(span),
- usage: query.description.to_string(),
+ span: query.info.default_span(span),
+ usage: query.info.description.to_string(),
});
}
- let alias = if stack.iter().all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias)))
- {
- Some(crate::error::Alias::Ty)
- } else if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TraitAlias)) {
- Some(crate::error::Alias::Trait)
- } else {
- None
- };
+ let alias =
+ if stack.iter().all(|entry| matches!(entry.query.info.def_kind, Some(DefKind::TyAlias))) {
+ Some(crate::error::Alias::Ty)
+ } else if stack.iter().all(|entry| entry.query.info.def_kind == Some(DefKind::TraitAlias)) {
+ Some(crate::error::Alias::Trait)
+ } else {
+ None
+ };
let cycle_diag = crate::error::Cycle {
span,
cycle_stack,
- stack_bottom: stack[0].query.description.to_owned(),
+ stack_bottom: stack[0].query.info.description.to_owned(),
alias,
cycle_usage,
stack_count,
@@ -589,6 +623,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
let Some(query_info) = query_map.get(&query) else {
break;
};
+ let query_extra = qcx.lift_query_info(&query_info.query.info);
if Some(count_printed) < limit_frames || limit_frames.is_none() {
// Only print to stderr as many stack frames as `num_frames` when present.
// FIXME: needs translation
@@ -596,7 +631,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
#[allow(rustc::untranslatable_diagnostic)]
dcx.struct_failure_note(format!(
"#{} [{:?}] {}",
- count_printed, query_info.query.dep_kind, query_info.query.description
+ count_printed, query_info.query.dep_kind, query_extra.description
))
.with_span(query_info.job.span)
.emit();
@@ -609,7 +644,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
"#{} [{}] {}",
count_total,
qcx.dep_context().dep_kind_info(query_info.query.dep_kind).name,
- query_info.query.description
+ query_extra.description
);
}
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 0d0c66a..ef21af7 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -1,4 +1,9 @@
mod plumbing;
+use std::fmt::Debug;
+use std::marker::PhantomData;
+use std::mem::transmute;
+use std::sync::Arc;
+
pub use self::plumbing::*;
mod job;
@@ -11,6 +16,7 @@
pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
mod config;
+use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::DiagInner;
use rustc_hashes::Hash64;
use rustc_hir::def::DefKind;
@@ -25,31 +31,59 @@
///
/// This is mostly used in case of cycles for error reporting.
#[derive(Clone, Debug)]
-pub struct QueryStackFrame {
- pub description: String,
- span: Option<Span>,
- pub def_id: Option<DefId>,
- pub def_kind: Option<DefKind>,
- /// A def-id that is extracted from a `Ty` in a query key
- pub def_id_for_ty_in_cycle: Option<DefId>,
+pub struct QueryStackFrame<I> {
+ /// This field initially stores a `QueryStackDeferred` during collection,
+ /// but can later be changed to `QueryStackFrameExtra` containing concrete information
+ /// by calling `lift`. This is done so that collecting query does not need to invoke
+ /// queries, instead `lift` will call queries in a more appropriate location.
+ pub info: I,
+
pub dep_kind: DepKind,
/// This hash is used to deterministically pick
/// a query to remove cycles in the parallel compiler.
hash: Hash64,
+ pub def_id: Option<DefId>,
+ /// A def-id that is extracted from a `Ty` in a query key
+ pub def_id_for_ty_in_cycle: Option<DefId>,
}
-impl QueryStackFrame {
+impl<I> QueryStackFrame<I> {
#[inline]
pub fn new(
- description: String,
- span: Option<Span>,
- def_id: Option<DefId>,
- def_kind: Option<DefKind>,
+ info: I,
dep_kind: DepKind,
- def_id_for_ty_in_cycle: Option<DefId>,
hash: impl FnOnce() -> Hash64,
+ def_id: Option<DefId>,
+ def_id_for_ty_in_cycle: Option<DefId>,
) -> Self {
- Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash: hash() }
+ Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle }
+ }
+
+ fn lift<Qcx: QueryContext<QueryInfo = I>>(
+ &self,
+ qcx: Qcx,
+ ) -> QueryStackFrame<QueryStackFrameExtra> {
+ QueryStackFrame {
+ info: qcx.lift_query_info(&self.info),
+ dep_kind: self.dep_kind,
+ hash: self.hash,
+ def_id: self.def_id,
+ def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct QueryStackFrameExtra {
+ pub description: String,
+ span: Option<Span>,
+ pub def_kind: Option<DefKind>,
+}
+
+impl QueryStackFrameExtra {
+ #[inline]
+ pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
+ Self { description, span, def_kind }
}
// FIXME(eddyb) Get more valid `Span`s on queries.
@@ -62,7 +96,41 @@ pub fn default_span(&self, span: Span) -> Span {
}
}
-/// Track a 'side effects' for a particular query.
+/// Track a 'side effect' for a particular query.
+/// This is used to hold a closure which can create `QueryStackFrameExtra`.
+#[derive(Clone)]
+pub struct QueryStackDeferred<'tcx> {
+ _dummy: PhantomData<&'tcx ()>,
+
+ // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't
+ // access it in the destructor.
+ extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
+}
+
+impl<'tcx> QueryStackDeferred<'tcx> {
+ pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
+ context: C,
+ extract: fn(C) -> QueryStackFrameExtra,
+ ) -> Self {
+ let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
+ Arc::new(move || extract(context));
+ // SAFETY: The `extract` closure does not access 'tcx in its destructor as the only
+ // captured variable is `context` which is Copy and cannot have a destructor.
+ Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
+ }
+
+ pub fn extract(&self) -> QueryStackFrameExtra {
+ (self.extract)()
+ }
+}
+
+impl<'tcx> Debug for QueryStackDeferred<'tcx> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str("QueryStackDeferred")
+ }
+}
+
+/// Tracks 'side effects' for a particular query.
/// This struct is saved to disk along with the query result,
/// and loaded from disk if we mark the query as green.
/// This allows us to 'replay' changes to global state
@@ -81,12 +149,16 @@ pub enum QuerySideEffect {
}
pub trait QueryContext: HasDepContext {
+ type QueryInfo: Clone;
+
fn next_job_id(self) -> QueryJobId;
/// Get the query information from the TLS context.
fn current_query_job(self) -> Option<QueryJobId>;
- fn collect_active_jobs(self) -> Result<QueryMap, QueryMap>;
+ fn collect_active_jobs(self) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>;
+
+ fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra;
/// Load a side effect associated to the node in the previous session.
fn load_side_effect(
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 3a9d802..6ea8e3b 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -16,7 +16,7 @@
use rustc_span::{DUMMY_SP, Span};
use tracing::instrument;
-use super::QueryConfig;
+use super::{QueryConfig, QueryStackFrameExtra};
use crate::HandleCycleError;
use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
use crate::ich::StableHashingContext;
@@ -29,23 +29,23 @@ fn equivalent_key<K: Eq, V>(k: &K) -> impl Fn(&(K, V)) -> bool + '_ {
move |x| x.0 == *k
}
-pub struct QueryState<K> {
- active: Sharded<hashbrown::HashTable<(K, QueryResult)>>,
+pub struct QueryState<K, I> {
+ active: Sharded<hashbrown::HashTable<(K, QueryResult<I>)>>,
}
/// Indicates the state of a query for a given key in a query map.
-enum QueryResult {
+enum QueryResult<I> {
/// An already executing query. The query job can be used to await for its completion.
- Started(QueryJob),
+ Started(QueryJob<I>),
/// The query panicked. Queries trying to wait on this will raise a fatal error which will
/// silently panic.
Poisoned,
}
-impl QueryResult {
+impl<I> QueryResult<I> {
/// Unwraps the query job expecting that it has started.
- fn expect_job(self) -> QueryJob {
+ fn expect_job(self) -> QueryJob<I> {
match self {
Self::Started(job) => job,
Self::Poisoned => {
@@ -55,7 +55,7 @@ fn expect_job(self) -> QueryJob {
}
}
-impl<K> QueryState<K>
+impl<K, I> QueryState<K, I>
where
K: Eq + Hash + Copy + Debug,
{
@@ -66,8 +66,8 @@ pub fn all_inactive(&self) -> bool {
pub fn try_collect_active_jobs<Qcx: Copy>(
&self,
qcx: Qcx,
- make_query: fn(Qcx, K) -> QueryStackFrame,
- jobs: &mut QueryMap,
+ make_query: fn(Qcx, K) -> QueryStackFrame<I>,
+ jobs: &mut QueryMap<I>,
) -> Option<()> {
let mut active = Vec::new();
@@ -76,7 +76,7 @@ pub fn try_collect_active_jobs<Qcx: Copy>(
for shard in self.active.try_lock_shards() {
for (k, v) in shard?.iter() {
if let QueryResult::Started(ref job) = *v {
- active.push((*k, job.clone()));
+ active.push((*k, (*job).clone()));
}
}
}
@@ -92,19 +92,19 @@ pub fn try_collect_active_jobs<Qcx: Copy>(
}
}
-impl<K> Default for QueryState<K> {
- fn default() -> QueryState<K> {
+impl<K, I> Default for QueryState<K, I> {
+ fn default() -> QueryState<K, I> {
QueryState { active: Default::default() }
}
}
/// A type representing the responsibility to execute the job in the `job` field.
/// This will poison the relevant query if dropped.
-struct JobOwner<'tcx, K>
+struct JobOwner<'tcx, K, I>
where
K: Eq + Hash + Copy,
{
- state: &'tcx QueryState<K>,
+ state: &'tcx QueryState<K, I>,
key: K,
}
@@ -146,7 +146,7 @@ fn handle_cycle_error<Q, Qcx>(
}
Stash => {
let guar = if let Some(root) = cycle_error.cycle.first()
- && let Some(span) = root.query.span
+ && let Some(span) = root.query.info.span
{
error.stash(span, StashKey::Cycle).unwrap()
} else {
@@ -157,7 +157,7 @@ fn handle_cycle_error<Q, Qcx>(
}
}
-impl<'tcx, K> JobOwner<'tcx, K>
+impl<'tcx, K, I> JobOwner<'tcx, K, I>
where
K: Eq + Hash + Copy,
{
@@ -194,7 +194,7 @@ fn complete<C>(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index:
}
}
-impl<'tcx, K> Drop for JobOwner<'tcx, K>
+impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I>
where
K: Eq + Hash + Copy,
{
@@ -222,10 +222,19 @@ fn drop(&mut self) {
}
#[derive(Clone, Debug)]
-pub struct CycleError {
+pub struct CycleError<I = QueryStackFrameExtra> {
/// The query and related span that uses the cycle.
- pub usage: Option<(Span, QueryStackFrame)>,
- pub cycle: Vec<QueryInfo>,
+ pub usage: Option<(Span, QueryStackFrame<I>)>,
+ pub cycle: Vec<QueryInfo<I>>,
+}
+
+impl<I> CycleError<I> {
+ fn lift<Qcx: QueryContext<QueryInfo = I>>(&self, qcx: Qcx) -> CycleError<QueryStackFrameExtra> {
+ CycleError {
+ usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))),
+ cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(),
+ }
+ }
}
/// Checks whether there is already a value for this key in the in-memory
@@ -262,10 +271,10 @@ fn cycle_error<Q, Qcx>(
{
// Ensure there was no errors collecting all active jobs.
// We need the complete map to ensure we find a cycle to break.
- let query_map = qcx.collect_active_jobs().expect("failed to collect active queries");
+ let query_map = qcx.collect_active_jobs().ok().expect("failed to collect active queries");
let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span);
- (mk_cycle(query, qcx, error), None)
+ (mk_cycle(query, qcx, error.lift(qcx)), None)
}
#[inline(always)]
@@ -274,7 +283,7 @@ fn wait_for_query<Q, Qcx>(
qcx: Qcx,
span: Span,
key: Q::Key,
- latch: QueryLatch,
+ latch: QueryLatch<Qcx::QueryInfo>,
current: Option<QueryJobId>,
) -> (Q::Value, Option<DepNodeIndex>)
where
@@ -314,7 +323,7 @@ fn wait_for_query<Q, Qcx>(
(v, Some(index))
}
- Err(cycle) => (mk_cycle(query, qcx, cycle), None),
+ Err(cycle) => (mk_cycle(query, qcx, cycle.lift(qcx)), None),
}
}
@@ -392,7 +401,7 @@ fn try_execute_query<Q, Qcx, const INCR: bool>(
fn execute_job<Q, Qcx, const INCR: bool>(
query: Q,
qcx: Qcx,
- state: &QueryState<Q::Key>,
+ state: &QueryState<Q::Key, Qcx::QueryInfo>,
key: Q::Key,
key_hash: u64,
id: QueryJobId,
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index f4771f1..9ea9c58 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -6,6 +6,7 @@
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
+itertools = "0.12"
pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 97fbf7e..4368f78 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -10,8 +10,8 @@
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
use rustc_ast::{
- self as ast, AssocItem, AssocItemKind, Block, ForeignItem, ForeignItemKind, Impl, Item,
- ItemKind, MetaItemKind, NodeId, StmtKind,
+ self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
+ ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, TyAlias,
};
use rustc_attr_parsing as attr;
use rustc_expand::base::ResolverExpand;
@@ -735,7 +735,6 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
let parent_scope = &self.parent_scope;
let parent = parent_scope.module;
let expansion = parent_scope.expansion;
- let ident = item.ident;
let sp = item.span;
let vis = self.resolve_visibility(&item.vis);
let feed = self.r.feed(item.id);
@@ -762,17 +761,18 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
);
}
- ItemKind::ExternCrate(orig_name) => {
+ ItemKind::ExternCrate(orig_name, ident) => {
self.build_reduced_graph_for_extern_crate(
orig_name,
item,
+ ident,
local_def_id,
vis,
parent,
);
}
- ItemKind::Mod(.., ref mod_kind) => {
+ ItemKind::Mod(_, ident, ref mod_kind) => {
let module = self.r.new_module(
Some(parent),
ModuleKind::Def(def_kind, def_id, Some(ident.name)),
@@ -792,10 +792,12 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
}
// These items live in the value namespace.
- ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => {
+ ItemKind::Const(box ConstItem { ident, .. })
+ | ItemKind::Delegation(box Delegation { ident, .. })
+ | ItemKind::Static(box StaticItem { ident, .. }) => {
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
}
- ItemKind::Fn(..) => {
+ ItemKind::Fn(box Fn { ident, .. }) => {
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
// Functions introducing procedural macros reserve a slot
@@ -804,11 +806,11 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
}
// These items live in the type namespace.
- ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => {
+ ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => {
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
}
- ItemKind::Enum(_, _) | ItemKind::Trait(..) => {
+ ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => {
let module = self.r.new_module(
Some(parent),
ModuleKind::Def(def_kind, def_id, Some(ident.name)),
@@ -821,7 +823,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
}
// These items live in both the type and value namespaces.
- ItemKind::Struct(ref vdata, _) => {
+ ItemKind::Struct(ident, ref vdata, _) => {
self.build_reduced_graph_for_struct_variant(
vdata.fields(),
ident,
@@ -872,7 +874,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
}
}
- ItemKind::Union(ref vdata, _) => {
+ ItemKind::Union(ident, ref vdata, _) => {
self.build_reduced_graph_for_struct_variant(
vdata.fields(),
ident,
@@ -899,11 +901,11 @@ fn build_reduced_graph_for_extern_crate(
&mut self,
orig_name: Option<Symbol>,
item: &Item,
+ ident: Ident,
local_def_id: LocalDefId,
vis: ty::Visibility,
parent: Module<'ra>,
) {
- let ident = item.ident;
let sp = item.span;
let parent_scope = self.parent_scope;
let expansion = parent_scope.expansion;
@@ -987,7 +989,7 @@ fn build_reduced_graph_for_extern_crate(
}
/// Constructs the reduced graph for one foreign item.
- fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
+ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Ident) {
let feed = self.r.feed(item.id);
let local_def_id = feed.key();
let def_id = local_def_id.to_def_id();
@@ -1000,7 +1002,7 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
let parent = self.parent_scope.module;
let expansion = self.parent_scope.expansion;
let vis = self.resolve_visibility(&item.vis);
- self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
+ self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
self.r.feed_visibility(feed, vis);
}
@@ -1043,7 +1045,7 @@ fn process_macro_use_imports(&mut self, item: &Item, module: Module<'ra>) -> boo
span: item.span,
});
}
- if let ItemKind::ExternCrate(Some(orig_name)) = item.kind
+ if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind
&& orig_name == kw::SelfLower
{
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
@@ -1177,11 +1179,15 @@ fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'ra> {
self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
}
- fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
+ fn proc_macro_stub(
+ &self,
+ item: &ast::Item,
+ fn_ident: Ident,
+ ) -> Option<(MacroKind, Ident, Span)> {
if ast::attr::contains_name(&item.attrs, sym::proc_macro) {
- return Some((MacroKind::Bang, item.ident, item.span));
+ return Some((MacroKind::Bang, fn_ident, item.span));
} else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
- return Some((MacroKind::Attr, item.ident, item.span));
+ return Some((MacroKind::Attr, fn_ident, item.span));
} else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive)
&& let Some(meta_item_inner) =
attr.meta_item_list().and_then(|list| list.get(0).cloned())
@@ -1214,17 +1220,21 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'ra> {
let feed = self.r.feed(item.id);
let def_id = feed.key();
let (res, ident, span, macro_rules) = match &item.kind {
- ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules),
- ItemKind::Fn(..) => match self.proc_macro_stub(item) {
- Some((macro_kind, ident, span)) => {
- let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
- let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
- self.r.macro_map.insert(def_id.to_def_id(), macro_data);
- self.r.proc_macro_stubs.insert(def_id);
- (res, ident, span, false)
+ ItemKind::MacroDef(ident, def) => {
+ (self.res(def_id), *ident, item.span, def.macro_rules)
+ }
+ ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => {
+ match self.proc_macro_stub(item, *fn_ident) {
+ Some((macro_kind, ident, span)) => {
+ let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
+ let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
+ self.r.macro_map.insert(def_id.to_def_id(), macro_data);
+ self.r.proc_macro_stubs.insert(def_id);
+ (res, ident, span, false)
+ }
+ None => return parent_scope.macro_rules,
}
- None => return parent_scope.macro_rules,
- },
+ }
_ => unreachable!(),
};
@@ -1327,8 +1337,7 @@ fn visit_item(&mut self, item: &'a Item) {
// Visit attributes after items for backward compatibility.
// This way they can use `macro_rules` defined later.
self.visit_vis(&item.vis);
- self.visit_ident(&item.ident);
- item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self);
+ item.kind.walk(item.span, item.id, &item.vis, (), self);
visit::walk_list!(self, visit_attribute, &item.attrs);
}
_ => visit::walk_item(self, item),
@@ -1353,12 +1362,17 @@ fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
}
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
- if let ForeignItemKind::MacCall(_) = foreign_item.kind {
- self.visit_invoc_in_module(foreign_item.id);
- return;
- }
+ let ident = match foreign_item.kind {
+ ForeignItemKind::Static(box StaticItem { ident, .. })
+ | ForeignItemKind::Fn(box Fn { ident, .. })
+ | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => ident,
+ ForeignItemKind::MacCall(_) => {
+ self.visit_invoc_in_module(foreign_item.id);
+ return;
+ }
+ };
- self.build_reduced_graph_for_foreign_item(foreign_item);
+ self.build_reduced_graph_for_foreign_item(foreign_item, ident);
visit::walk_item(self, foreign_item);
}
@@ -1372,26 +1386,35 @@ fn visit_block(&mut self, block: &'a Block) {
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
- if let AssocItemKind::MacCall(_) = item.kind {
- match ctxt {
- AssocCtxt::Trait => {
- self.visit_invoc_in_module(item.id);
- }
- AssocCtxt::Impl { .. } => {
- let invoc_id = item.id.placeholder_to_expn_id();
- if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) {
- self.r
- .impl_unexpanded_invocations
- .entry(self.r.invocation_parent(invoc_id))
- .or_default()
- .insert(invoc_id);
- }
- self.visit_invoc(item.id);
- }
- }
- return;
- }
+ let (ident, ns) = match item.kind {
+ AssocItemKind::Const(box ConstItem { ident, .. })
+ | AssocItemKind::Fn(box Fn { ident, .. })
+ | AssocItemKind::Delegation(box Delegation { ident, .. }) => (ident, ValueNS),
+ AssocItemKind::Type(box TyAlias { ident, .. }) => (ident, TypeNS),
+
+ AssocItemKind::MacCall(_) => {
+ match ctxt {
+ AssocCtxt::Trait => {
+ self.visit_invoc_in_module(item.id);
+ }
+ AssocCtxt::Impl { .. } => {
+ let invoc_id = item.id.placeholder_to_expn_id();
+ if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) {
+ self.r
+ .impl_unexpanded_invocations
+ .entry(self.r.invocation_parent(invoc_id))
+ .or_default()
+ .insert(invoc_id);
+ }
+ self.visit_invoc(item.id);
+ }
+ }
+ return;
+ }
+
+ AssocItemKind::DelegationMac(..) => bug!(),
+ };
let vis = self.resolve_visibility(&item.vis);
let feed = self.r.feed(item.id);
let local_def_id = feed.key();
@@ -1406,20 +1429,13 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
self.r.feed_visibility(feed, vis);
}
- let ns = match item.kind {
- AssocItemKind::Const(..) | AssocItemKind::Delegation(..) | AssocItemKind::Fn(..) => {
- ValueNS
- }
- AssocItemKind::Type(..) => TypeNS,
- AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above
- };
if ctxt == AssocCtxt::Trait {
let parent = self.parent_scope.module;
let expansion = self.parent_scope.expansion;
- self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
+ self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
let impl_def_id = self.r.tcx.local_parent(local_def_id);
- let key = BindingKey::new(item.ident.normalize_to_macros_2_0(), ns);
+ let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
}
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 51ff4aa..e97233e 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -219,14 +219,14 @@ fn visit_item(&mut self, item: &'a ast::Item) {
// because this means that they were generated in some fashion by the
// compiler and we don't need to consider them.
ast::ItemKind::Use(..) if item.span.is_dummy() => return,
- ast::ItemKind::ExternCrate(orig_name) => {
+ ast::ItemKind::ExternCrate(orig_name, ident) => {
self.extern_crate_items.push(ExternCrateToLint {
id: item.id,
span: item.span,
vis_span: item.vis.span,
span_with_attributes: item.span_with_attributes(),
has_attrs: !item.attrs.is_empty(),
- ident: item.ident,
+ ident,
renames: orig_name.is_some(),
});
}
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index fcb638a..13dfb59 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -19,18 +19,15 @@ pub(crate) fn collect_definitions(
fragment: &AstFragment,
expansion: LocalExpnId,
) {
- let InvocationParent { parent_def, impl_trait_context, in_attr } =
- resolver.invocation_parents[&expansion];
- let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr };
+ let invocation_parent = resolver.invocation_parents[&expansion];
+ let mut visitor = DefCollector { resolver, expansion, invocation_parent };
fragment.visit_with(&mut visitor);
}
/// Creates `DefId`s for nodes in the AST.
struct DefCollector<'a, 'ra, 'tcx> {
resolver: &'a mut Resolver<'ra, 'tcx>,
- parent_def: LocalDefId,
- impl_trait_context: ImplTraitContext,
- in_attr: bool,
+ invocation_parent: InvocationParent,
expansion: LocalExpnId,
}
@@ -42,7 +39,7 @@ fn create_def(
def_kind: DefKind,
span: Span,
) -> LocalDefId {
- let parent_def = self.parent_def;
+ let parent_def = self.invocation_parent.parent_def;
debug!(
"create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
node_id, def_kind, parent_def
@@ -60,9 +57,9 @@ fn create_def(
}
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
- let orig_parent_def = mem::replace(&mut self.parent_def, parent_def);
+ let orig_parent_def = mem::replace(&mut self.invocation_parent.parent_def, parent_def);
f(self);
- self.parent_def = orig_parent_def;
+ self.invocation_parent.parent_def = orig_parent_def;
}
fn with_impl_trait<F: FnOnce(&mut Self)>(
@@ -70,9 +67,10 @@ fn with_impl_trait<F: FnOnce(&mut Self)>(
impl_trait_context: ImplTraitContext,
f: F,
) {
- let orig_itc = mem::replace(&mut self.impl_trait_context, impl_trait_context);
+ let orig_itc =
+ mem::replace(&mut self.invocation_parent.impl_trait_context, impl_trait_context);
f(self);
- self.impl_trait_context = orig_itc;
+ self.invocation_parent.impl_trait_context = orig_itc;
}
fn collect_field(&mut self, field: &'a FieldDef, index: Option<usize>) {
@@ -96,14 +94,7 @@ fn collect_field(&mut self, field: &'a FieldDef, index: Option<usize>) {
fn visit_macro_invoc(&mut self, id: NodeId) {
let id = id.placeholder_to_expn_id();
- let old_parent = self.resolver.invocation_parents.insert(
- id,
- InvocationParent {
- parent_def: self.parent_def,
- impl_trait_context: self.impl_trait_context,
- in_attr: self.in_attr,
- },
- );
+ let old_parent = self.resolver.invocation_parents.insert(id, self.invocation_parent);
assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
}
}
@@ -131,7 +122,7 @@ fn visit_item(&mut self, i: &'a Item) {
},
ItemKind::Const(..) => DefKind::Const,
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
- ItemKind::MacroDef(def) => {
+ ItemKind::MacroDef(ident, def) => {
let edition = i.span.edition();
// FIXME(jdonszelmann) make one of these in the resolver?
@@ -150,7 +141,7 @@ fn visit_item(&mut self, i: &'a Item) {
);
let macro_data =
- self.resolver.compile_macro(def, i.ident, &attrs, i.span, i.id, edition);
+ self.resolver.compile_macro(def, *ident, &attrs, i.span, i.id, edition);
let macro_kind = macro_data.ext.macro_kind();
opt_macro_data = Some(macro_data);
DefKind::Macro(macro_kind)
@@ -161,7 +152,8 @@ fn visit_item(&mut self, i: &'a Item) {
return self.visit_macro_invoc(i.id);
}
};
- let def_id = self.create_def(i.id, Some(i.ident.name), def_kind, i.span);
+ let def_id =
+ self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span);
if let Some(macro_data) = opt_macro_data {
self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
@@ -170,7 +162,8 @@ fn visit_item(&mut self, i: &'a Item) {
self.with_parent(def_id, |this| {
this.with_impl_trait(ImplTraitContext::Existential, |this| {
match i.kind {
- ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
+ ItemKind::Struct(_, ref struct_def, _)
+ | ItemKind::Union(_, ref struct_def, _) => {
// If this is a unit or tuple-like struct, register the constructor.
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
this.create_def(
@@ -192,10 +185,12 @@ fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
match fn_kind {
FnKind::Fn(
_ctxt,
- _ident,
_vis,
- Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. },
+ Fn {
+ sig: FnSig { header, decl, span: _ }, ident, generics, contract, body, ..
+ },
) if let Some(coroutine_kind) = header.coroutine_kind => {
+ self.visit_ident(ident);
self.visit_fn_header(header);
self.visit_generics(generics);
if let Some(contract) = contract {
@@ -243,8 +238,9 @@ fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
}
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
- let def_kind = match fi.kind {
+ let (ident, def_kind) = match fi.kind {
ForeignItemKind::Static(box StaticItem {
+ ident,
ty: _,
mutability,
expr: _,
@@ -256,14 +252,14 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
ast::Safety::Safe(_) => hir::Safety::Safe,
};
- DefKind::Static { safety, mutability, nested: false }
+ (ident, DefKind::Static { safety, mutability, nested: false })
}
- ForeignItemKind::Fn(_) => DefKind::Fn,
- ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
+ ForeignItemKind::Fn(box Fn { ident, .. }) => (ident, DefKind::Fn),
+ ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => (ident, DefKind::ForeignTy),
ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
};
- let def = self.create_def(fi.id, Some(fi.ident.name), def_kind, fi.span);
+ let def = self.create_def(fi.id, Some(ident.name), def_kind, fi.span);
self.with_parent(def, |this| visit::walk_item(this, fi));
}
@@ -327,16 +323,17 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) {
}
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
- let def_kind = match &i.kind {
- AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
- AssocItemKind::Const(..) => DefKind::AssocConst,
- AssocItemKind::Type(..) => DefKind::AssocTy,
+ let (ident, def_kind) = match &i.kind {
+ AssocItemKind::Fn(box Fn { ident, .. })
+ | AssocItemKind::Delegation(box Delegation { ident, .. }) => (*ident, DefKind::AssocFn),
+ AssocItemKind::Const(box ConstItem { ident, .. }) => (*ident, DefKind::AssocConst),
+ AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, DefKind::AssocTy),
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
return self.visit_macro_invoc(i.id);
}
};
- let def = self.create_def(i.id, Some(i.ident.name), def_kind, i.span);
+ let def = self.create_def(i.id, Some(ident.name), def_kind, i.span);
self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
}
@@ -367,7 +364,7 @@ fn visit_expr(&mut self, expr: &'a Expr) {
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
return;
}
- _ => self.parent_def,
+ _ => self.invocation_parent.parent_def,
};
self.with_parent(parent_def, |this| visit::walk_expr(this, expr))
@@ -382,13 +379,13 @@ fn visit_ty(&mut self, ty: &'a Ty) {
// output or built artifacts, so replace them here...
// Perhaps we should instead format APITs more robustly.
let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " "));
- let kind = match self.impl_trait_context {
+ let kind = match self.invocation_parent.impl_trait_context {
ImplTraitContext::Universal => DefKind::TyParam,
ImplTraitContext::Existential => DefKind::OpaqueTy,
ImplTraitContext::InBinding => return visit::walk_ty(self, ty),
};
let id = self.create_def(*id, Some(name), kind, ty.span);
- match self.impl_trait_context {
+ match self.invocation_parent.impl_trait_context {
// Do not nest APIT, as we desugar them as `impl_trait: bounds`,
// so the `impl_trait` node is not a parent to `bounds`.
ImplTraitContext::Universal => visit::walk_ty(self, ty),
@@ -459,9 +456,9 @@ fn visit_crate(&mut self, krate: &'a Crate) {
}
fn visit_attribute(&mut self, attr: &'a Attribute) -> Self::Result {
- let orig_in_attr = mem::replace(&mut self.in_attr, true);
+ let orig_in_attr = mem::replace(&mut self.invocation_parent.in_attr, true);
visit::walk_attribute(self, attr);
- self.in_attr = orig_in_attr;
+ self.invocation_parent.in_attr = orig_in_attr;
}
fn visit_inline_asm(&mut self, asm: &'a InlineAsm) {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 63ea8c4..6dc8547 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1091,7 +1091,7 @@ fn early_lookup_typo_candidate(
));
}
Scope::BuiltinAttrs => {
- let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty));
+ let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
if filter_fn(res) {
suggestions.extend(
BUILTIN_ATTRIBUTES
@@ -1325,11 +1325,6 @@ fn lookup_import_candidates_from_module<FilterFn>(
})
}
- // If only some candidates are accessible, take just them
- if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) {
- candidates.retain(|x| x.accessible)
- }
-
candidates
}
@@ -1793,7 +1788,7 @@ fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
&import_suggestions,
Instead::Yes,
FoundUse::Yes,
- DiagMode::Import { append: single_nested },
+ DiagMode::Import { append: single_nested, unresolved_import: false },
vec![],
"",
);
@@ -2750,6 +2745,8 @@ pub(crate) enum DiagMode {
Pattern,
/// The binding is part of a use statement
Import {
+ /// `true` means diagnostics is for unresolved import
+ unresolved_import: bool,
/// `true` mean add the tips afterward for case `use a::{b,c}`,
/// rather than replacing within.
append: bool,
@@ -2800,6 +2797,7 @@ fn show_candidates(
return false;
}
+ let mut showed = false;
let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
@@ -2958,8 +2956,11 @@ fn show_candidates(
append_candidates(&mut msg, accessible_path_strings);
err.help(msg);
}
- true
- } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagMode::Import { .. })) {
+ showed = true;
+ }
+ if !inaccessible_path_strings.is_empty()
+ && (!matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
+ {
let prefix =
if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
@@ -3022,10 +3023,9 @@ fn show_candidates(
err.span_note(multi_span, msg);
}
- true
- } else {
- false
+ showed = true;
}
+ showed
}
#[derive(Debug)]
@@ -3063,7 +3063,7 @@ fn visit_crate(&mut self, c: &Crate) {
fn visit_item(&mut self, item: &'tcx ast::Item) {
if self.target_module == item.id {
- if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
+ if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
let inject = mod_spans.inject_use_span;
if is_span_suitable_for_use_injection(inject) {
self.first_legal_span = Some(inject);
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 6ef4aa4..a5ca456 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -252,7 +252,7 @@ fn visit_item(&mut self, item: &'a ast::Item) {
self.current_private_vis = prev_private_vis;
}
- ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
+ ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => {
self.set_bindings_effective_visibilities(def_id);
for variant in variants {
let variant_def_id = self.r.local_def_id(variant.id);
@@ -262,7 +262,7 @@ fn visit_item(&mut self, item: &'a ast::Item) {
}
}
- ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
+ ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => {
for field in def.fields() {
self.update_field(self.r.local_def_id(field.id), def_id);
}
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 454460e..0b3633a 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -734,7 +734,7 @@ fn throw_unresolved_import_error(
&mut diag,
Some(err.span),
candidates,
- DiagMode::Import { append: false },
+ DiagMode::Import { append: false, unresolved_import: true },
(source != target)
.then(|| format!(" as {target}"))
.as_deref()
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 6bc644e..20e19ca 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1025,9 +1025,10 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
match fn_kind {
// Bail if the function is foreign, and thus cannot validly have
// a body, or if there's no body for some other reason.
- FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. })
- | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => {
+ FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, ident, generics, .. })
+ | FnKind::Fn(_, _, Fn { sig, ident, generics, body: None, .. }) => {
self.visit_fn_header(&sig.header);
+ self.visit_ident(ident);
self.visit_generics(generics);
self.with_lifetime_rib(
LifetimeRibKind::AnonymousCreateParameter {
@@ -1058,7 +1059,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
// Create a label rib for the function.
this.with_label_rib(RibKind::FnOrCoroutine, |this| {
match fn_kind {
- FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => {
+ FnKind::Fn(_, _, Fn { sig, generics, contract, body, .. }) => {
this.visit_generics(generics);
let declaration = &sig.decl;
@@ -1833,7 +1834,7 @@ fn resolve_anonymous_lifetime(
}
LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
let mut lifetimes_in_scope = vec![];
- for rib in &self.lifetime_ribs[..i] {
+ for rib in self.lifetime_ribs[..i].iter().rev() {
lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
// Consider any anonymous lifetimes, too
if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
@@ -1841,6 +1842,9 @@ fn resolve_anonymous_lifetime(
{
lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
}
+ if let LifetimeRibKind::Item = rib.kind {
+ break;
+ }
}
if lifetimes_in_scope.is_empty() {
self.record_lifetime_res(
@@ -2629,8 +2633,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
}
- let name = item.ident.name;
- debug!("(resolving item) resolving {} ({:?})", name, item.kind);
+ debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind);
let def_kind = self.r.local_def_kind(item.id);
match item.kind {
@@ -2661,9 +2664,9 @@ fn resolve_item(&mut self, item: &'ast Item) {
self.resolve_define_opaques(define_opaque);
}
- ItemKind::Enum(_, ref generics)
- | ItemKind::Struct(_, ref generics)
- | ItemKind::Union(_, ref generics) => {
+ ItemKind::Enum(_, _, ref generics)
+ | ItemKind::Struct(_, _, ref generics)
+ | ItemKind::Union(_, _, ref generics) => {
self.resolve_adt(item, generics);
}
@@ -2707,7 +2710,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
);
}
- ItemKind::TraitAlias(ref generics, ref bounds) => {
+ ItemKind::TraitAlias(_, ref generics, ref bounds) => {
// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(
&generics.params,
@@ -2745,7 +2748,11 @@ fn resolve_item(&mut self, item: &'ast Item) {
}
ItemKind::Static(box ast::StaticItem {
- ref ty, ref expr, ref define_opaque, ..
+ ident,
+ ref ty,
+ ref expr,
+ ref define_opaque,
+ ..
}) => {
self.with_static_rib(def_kind, |this| {
this.with_lifetime_rib(
@@ -2759,13 +2766,14 @@ fn resolve_item(&mut self, item: &'ast Item) {
if let Some(expr) = expr {
// We already forbid generic params because of the above item rib,
// so it doesn't matter whether this is a trivial constant.
- this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
+ this.resolve_const_body(expr, Some((ident, ConstantItemKind::Static)));
}
});
self.resolve_define_opaques(define_opaque);
}
ItemKind::Const(box ast::ConstItem {
+ ident,
ref generics,
ref ty,
ref expr,
@@ -2798,10 +2806,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
);
if let Some(expr) = expr {
- this.resolve_const_body(
- expr,
- Some((item.ident, ConstantItemKind::Const)),
- );
+ this.resolve_const_body(expr, Some((ident, ConstantItemKind::Const)));
}
},
);
@@ -2818,7 +2823,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
self.future_proof_import(use_tree);
}
- ItemKind::MacroDef(ref macro_def) => {
+ ItemKind::MacroDef(_, ref macro_def) => {
// Maintain macro_rules scopes in the same way as during early resolution
// for diagnostics and doc links.
if macro_def.macro_rules {
@@ -3316,7 +3321,12 @@ fn resolve_impl_item(
self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
match &item.kind {
AssocItemKind::Const(box ast::ConstItem {
- generics, ty, expr, define_opaque, ..
+ ident,
+ generics,
+ ty,
+ expr,
+ define_opaque,
+ ..
}) => {
debug!("resolve_implementation AssocItemKind::Const");
self.with_generic_param_rib(
@@ -3329,41 +3339,51 @@ fn resolve_impl_item(
},
|this| {
this.with_lifetime_rib(
- LifetimeRibKind::StaticIfNoLifetimeInScope {
- lint_id: item.id,
- // In impls, it's not a hard error yet due to backcompat.
- emit_lint: true,
+ // Until these are a hard error, we need to create them within the correct binder,
+ // Otherwise the lifetimes of this assoc const think they are lifetimes of the trait.
+ LifetimeRibKind::AnonymousCreateParameter {
+ binder: item.id,
+ report_in_path: true,
},
|this| {
- // If this is a trait impl, ensure the const
- // exists in trait
- this.check_trait_item(
- item.id,
- item.ident,
- &item.kind,
- ValueNS,
- item.span,
- seen_trait_items,
- |i, s, c| ConstNotMemberOfTrait(i, s, c),
- );
+ this.with_lifetime_rib(
+ LifetimeRibKind::StaticIfNoLifetimeInScope {
+ lint_id: item.id,
+ // In impls, it's not a hard error yet due to backcompat.
+ emit_lint: true,
+ },
+ |this| {
+ // If this is a trait impl, ensure the const
+ // exists in trait
+ this.check_trait_item(
+ item.id,
+ *ident,
+ &item.kind,
+ ValueNS,
+ item.span,
+ seen_trait_items,
+ |i, s, c| ConstNotMemberOfTrait(i, s, c),
+ );
- this.visit_generics(generics);
- this.visit_ty(ty);
- if let Some(expr) = expr {
- // We allow arbitrary const expressions inside of associated consts,
- // even if they are potentially not const evaluatable.
- //
- // Type parameters can already be used and as associated consts are
- // not used as part of the type system, this is far less surprising.
- this.resolve_const_body(expr, None);
- }
+ this.visit_generics(generics);
+ this.visit_ty(ty);
+ if let Some(expr) = expr {
+ // We allow arbitrary const expressions inside of associated consts,
+ // even if they are potentially not const evaluatable.
+ //
+ // Type parameters can already be used and as associated consts are
+ // not used as part of the type system, this is far less surprising.
+ this.resolve_const_body(expr, None);
+ }
+ },
+ )
},
);
},
);
self.resolve_define_opaques(define_opaque);
}
- AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
+ AssocItemKind::Fn(box Fn { ident, generics, define_opaque, .. }) => {
debug!("resolve_implementation AssocItemKind::Fn");
// We also need a new scope for the impl item type parameters.
self.with_generic_param_rib(
@@ -3379,7 +3399,7 @@ fn resolve_impl_item(
// exists in trait
this.check_trait_item(
item.id,
- item.ident,
+ *ident,
&item.kind,
ValueNS,
item.span,
@@ -3393,7 +3413,7 @@ fn resolve_impl_item(
self.resolve_define_opaques(define_opaque);
}
- AssocItemKind::Type(box TyAlias { generics, .. }) => {
+ AssocItemKind::Type(box TyAlias { ident, generics, .. }) => {
self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
debug!("resolve_implementation AssocItemKind::Type");
// We also need a new scope for the impl item type parameters.
@@ -3411,7 +3431,7 @@ fn resolve_impl_item(
// exists in trait
this.check_trait_item(
item.id,
- item.ident,
+ *ident,
&item.kind,
TypeNS,
item.span,
@@ -3438,7 +3458,7 @@ fn resolve_impl_item(
|this| {
this.check_trait_item(
item.id,
- item.ident,
+ delegation.ident,
&item.kind,
ValueNS,
item.span,
@@ -4324,7 +4344,13 @@ fn smart_resolve_path_fragment(
if let Some(items) = self.diag_metadata.current_trait_assoc_items
&& let [Segment { ident, .. }] = path
&& items.iter().any(|item| {
- item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
+ if let AssocItemKind::Type(alias) = &item.kind
+ && alias.ident == *ident
+ {
+ true
+ } else {
+ false
+ }
})
{
let mut diag = self.r.tcx.dcx().struct_allow("");
@@ -5146,12 +5172,12 @@ fn visit_item(&mut self, item: &'ast Item) {
ItemKind::TyAlias(box TyAlias { generics, .. })
| ItemKind::Const(box ConstItem { generics, .. })
| ItemKind::Fn(box Fn { generics, .. })
- | ItemKind::Enum(_, generics)
- | ItemKind::Struct(_, generics)
- | ItemKind::Union(_, generics)
+ | ItemKind::Enum(_, _, generics)
+ | ItemKind::Struct(_, _, generics)
+ | ItemKind::Union(_, _, generics)
| ItemKind::Impl(box Impl { generics, .. })
| ItemKind::Trait(box Trait { generics, .. })
- | ItemKind::TraitAlias(generics, _) => {
+ | ItemKind::TraitAlias(_, generics, _) => {
if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind {
self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
}
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index cf8db22..b62bc6c 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -224,12 +224,13 @@ fn make_base_error(
let suggestion = if self.current_trait_ref.is_none()
&& let Some((fn_kind, _)) = self.diag_metadata.current_function
&& let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
- && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = fn_kind
+ && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind
&& let Some(items) = self.diag_metadata.current_impl_items
&& let Some(item) = items.iter().find(|i| {
- i.ident.name == item_str.name
+ i.kind.ident().is_some_and(|ident| {
// Don't suggest if the item is in Fn signature arguments (#112590).
- && !sig.span.contains(item_span)
+ ident.name == item_str.name && !sig.span.contains(item_span)
+ })
}) {
let sp = item_span.shrink_to_lo();
@@ -268,14 +269,14 @@ fn make_base_error(
// you can't call `fn foo(&self)` from `fn bar()` (#115992).
// We also want to mention that the method exists.
span_label = Some((
- item.ident.span,
+ fn_.ident.span,
"a method by that name is available on `Self` here",
));
None
}
AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => {
span_label = Some((
- item.ident.span,
+ fn_.ident.span,
"an associated function by that name is available on `Self` here",
));
None
@@ -604,7 +605,7 @@ fn suggest_self_or_self_ref(&mut self, err: &mut Diag<'_>, path: &[Segment], spa
Applicability::MaybeIncorrect,
);
if !self.self_value_is_available(path[0].ident.span) {
- if let Some((FnKind::Fn(_, _, _, ast::Fn { sig, .. }), fn_span)) =
+ if let Some((FnKind::Fn(_, _, ast::Fn { sig, .. }), fn_span)) =
&self.diag_metadata.current_function
{
let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
@@ -1064,15 +1065,11 @@ fn suggest_self_ty(
}
err.code(E0411);
err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
- if let Some(item_kind) = self.diag_metadata.current_item {
- if !item_kind.ident.span.is_dummy() {
+ if let Some(item) = self.diag_metadata.current_item {
+ if let Some(ident) = item.kind.ident() {
err.span_label(
- item_kind.ident.span,
- format!(
- "`Self` not allowed in {} {}",
- item_kind.kind.article(),
- item_kind.kind.descr()
- ),
+ ident.span,
+ format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
);
}
}
@@ -1150,17 +1147,14 @@ fn suggest_self_value(
);
}
}
- } else if let Some(item_kind) = self.diag_metadata.current_item {
- if matches!(item_kind.kind, ItemKind::Delegation(..)) {
- err.span_label(item_kind.span, format!("delegation supports {self_from_macro}"));
+ } else if let Some(item) = self.diag_metadata.current_item {
+ if matches!(item.kind, ItemKind::Delegation(..)) {
+ err.span_label(item.span, format!("delegation supports {self_from_macro}"));
} else {
+ let span = if let Some(ident) = item.kind.ident() { ident.span } else { item.span };
err.span_label(
- item_kind.ident.span,
- format!(
- "`self` not allowed in {} {}",
- item_kind.kind.article(),
- item_kind.kind.descr()
- ),
+ span,
+ format!("`self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
);
}
}
@@ -1665,41 +1659,81 @@ fn smart_resolve_context_dependent_help(
// the struct literal syntax at all, as that will cause a subsequent error.
let fields = this.r.field_idents(def_id);
let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty());
- let (fields, applicability) = match fields {
- Some(fields) => {
- let fields = if let Some(old_fields) = old_fields {
- fields
- .iter()
- .enumerate()
- .map(|(idx, new)| (new, old_fields.get(idx)))
- .map(|(new, old)| {
- if let Some(Some(old)) = old
- && new.as_str() != old
- {
- format!("{new}: {old}")
- } else {
- new.to_string()
- }
- })
- .collect::<Vec<String>>()
- } else {
- fields
- .iter()
- .map(|f| format!("{f}{tail}"))
- .collect::<Vec<String>>()
- };
- (fields.join(", "), applicability)
- }
- None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
- };
- let pad = if has_fields { " " } else { "" };
- err.span_suggestion(
+ if let PathSource::Expr(Some(Expr {
+ kind: ExprKind::Call(path, args),
span,
- format!("use struct {descr} syntax instead"),
- format!("{path_str} {{{pad}{fields}{pad}}}"),
- applicability,
- );
+ ..
+ })) = source
+ && !args.is_empty()
+ && let Some(fields) = &fields
+ && args.len() == fields.len()
+ // Make sure we have same number of args as fields
+ {
+ let path_span = path.span;
+ let mut parts = Vec::new();
+
+ // Start with the opening brace
+ parts.push((
+ path_span.shrink_to_hi().until(args[0].span),
+ "{".to_owned(),
+ ));
+
+ for (field, arg) in fields.iter().zip(args.iter()) {
+ // Add the field name before the argument
+ parts.push((arg.span.shrink_to_lo(), format!("{}: ", field)));
+ }
+
+ // Add the closing brace
+ parts.push((
+ args.last().unwrap().span.shrink_to_hi().until(span.shrink_to_hi()),
+ "}".to_owned(),
+ ));
+
+ err.multipart_suggestion_verbose(
+ format!("use struct {descr} syntax instead of calling"),
+ parts,
+ applicability,
+ );
+ } else {
+ let (fields, applicability) = match fields {
+ Some(fields) => {
+ let fields = if let Some(old_fields) = old_fields {
+ fields
+ .iter()
+ .enumerate()
+ .map(|(idx, new)| (new, old_fields.get(idx)))
+ .map(|(new, old)| {
+ if let Some(Some(old)) = old
+ && new.as_str() != old
+ {
+ format!("{new}: {old}")
+ } else {
+ new.to_string()
+ }
+ })
+ .collect::<Vec<String>>()
+ } else {
+ fields
+ .iter()
+ .map(|f| format!("{f}{tail}"))
+ .collect::<Vec<String>>()
+ };
+
+ (fields.join(", "), applicability)
+ }
+ None => {
+ ("/* fields */".to_string(), Applicability::HasPlaceholders)
+ }
+ };
+ let pad = if has_fields { " " } else { "" };
+ err.span_suggestion(
+ span,
+ format!("use struct {descr} syntax instead"),
+ format!("{path_str} {{{pad}{fields}{pad}}}"),
+ applicability,
+ );
+ }
}
if let PathSource::Expr(Some(Expr {
kind: ExprKind::Call(path, args),
@@ -2156,7 +2190,9 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
if let Some(items) = self.diag_metadata.current_trait_assoc_items {
for assoc_item in items {
- if assoc_item.ident == ident {
+ if let Some(assoc_ident) = assoc_item.kind.ident()
+ && assoc_ident == ident
+ {
return Some(match &assoc_item.kind {
ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
@@ -2695,7 +2731,7 @@ pub(crate) fn suggest_adding_generic_parameter(
return None;
}
match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) {
- (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => {
+ (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => {
// Ignore `fn main()` as we don't want to suggest `fn main<T>()`
}
(
@@ -3360,7 +3396,7 @@ fn add_missing_lifetime_specifiers_label(
{
let pre = if lt.kind == MissingLifetimeKind::Ampersand
&& let Some((kind, _span)) = self.diag_metadata.current_function
- && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+ && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
&& !sig.decl.inputs.is_empty()
&& let sugg = sig
.decl
@@ -3401,7 +3437,7 @@ fn add_missing_lifetime_specifiers_label(
} else if (lt.kind == MissingLifetimeKind::Ampersand
|| lt.kind == MissingLifetimeKind::Underscore)
&& let Some((kind, _span)) = self.diag_metadata.current_function
- && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+ && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
&& let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output
&& !sig.decl.inputs.is_empty()
&& let arg_refs = sig
@@ -3461,7 +3497,7 @@ fn add_missing_lifetime_specifiers_label(
let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
let mut sugg = vec![(lt.span, String::new())];
if let Some((kind, _span)) = self.diag_metadata.current_function
- && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+ && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
&& let ast::FnRetTy::Ty(ty) = &sig.decl.output
{
let mut lt_finder =
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 52aaab7..a32fe69 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -1,13 +1,15 @@
use std::mem;
use std::ops::Range;
+use itertools::Itertools;
use pulldown_cmark::{
BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, Options, Parser, Tag,
};
use rustc_ast as ast;
use rustc_ast::attr::AttributeExt;
use rustc_ast::util::comments::beautify_doc_string;
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::unord::UnordSet;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId;
use rustc_span::{DUMMY_SP, InnerSpan, Span, Symbol, kw, sym};
@@ -422,7 +424,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
);
let mut links = Vec::new();
- let mut refids = FxHashSet::default();
+ let mut refids = UnordSet::default();
while let Some(event) = event_iter.next() {
match event {
@@ -454,7 +456,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
}
}
- for (label, refdef) in event_iter.reference_definitions().iter() {
+ for (label, refdef) in event_iter.reference_definitions().iter().sorted_by_key(|x| x.0) {
if !refids.contains(label) {
links.push(preprocess_link(&refdef.dest));
}
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index e088417..d56ca9c 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
hir::definitions::DefPathData::Ctor => "c",
hir::definitions::DefPathData::AnonConst => "k",
hir::definitions::DefPathData::OpaqueTy => "i",
+ hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
hir::definitions::DefPathData::CrateRoot
| hir::definitions::DefPathData::Use
| hir::definitions::DefPathData::GlobalAsm
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 4cc666b..cd5e2c4 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2175,6 +2175,8 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
them only if an error has not been emitted"),
ehcont_guard: bool = (false, parse_bool, [TRACKED],
"generate Windows EHCont Guard tables"),
+ embed_metadata: bool = (true, parse_bool, [TRACKED],
+ "embed metadata in rlibs and dylibs (default: yes)"),
embed_source: bool = (false, parse_bool, [TRACKED],
"embed source text in DWARF debug sections (default: no)"),
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index fcede37..2243e83 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -149,14 +149,15 @@ pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
arg[a.len()..].to_string()
};
let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
- if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
+ if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&option) {
excluded_cargo_defaults = true;
} else {
result.push(a.to_string());
- match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
- Some(s) => result.push(format!("{s}=[REDACTED]")),
- None => result.push(content),
- }
+ result.push(if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&option) {
+ format!("{option}=[REDACTED]")
+ } else {
+ content
+ });
}
}
}
diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs
index 8a2baaa..4f3202b 100644
--- a/compiler/rustc_span/src/edit_distance.rs
+++ b/compiler/rustc_span/src/edit_distance.rs
@@ -118,7 +118,7 @@ pub fn edit_distance_with_substrings(a: &str, b: &str, limit: usize) -> Option<u
// Check one isn't less than half the length of the other. If this is true then there is a
// big difference in length.
let big_len_diff = (n * 2) < m || (m * 2) < n;
- let len_diff = if n < m { m - n } else { n - m };
+ let len_diff = m.abs_diff(n);
let distance = edit_distance(a, b, limit + len_diff)?;
// This is the crux, subtracting length difference means exact substring matches will now be 0
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 4390085..9959e98 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -75,6 +75,21 @@ pub struct SyntaxContextData {
}
impl SyntaxContextData {
+ fn new(
+ (parent, outer_expn, outer_transparency): SyntaxContextKey,
+ opaque: SyntaxContext,
+ opaque_and_semitransparent: SyntaxContext,
+ ) -> SyntaxContextData {
+ SyntaxContextData {
+ outer_expn,
+ outer_transparency,
+ parent,
+ opaque,
+ opaque_and_semitransparent,
+ dollar_crate_name: kw::DollarCrate,
+ }
+ }
+
fn root() -> SyntaxContextData {
SyntaxContextData {
outer_expn: ExpnId::root(),
@@ -543,7 +558,7 @@ fn apply_mark(
) -> SyntaxContext {
assert_ne!(expn_id, ExpnId::root());
if transparency == Transparency::Opaque {
- return self.apply_mark_internal(ctxt, expn_id, transparency);
+ return self.alloc_ctxt(ctxt, expn_id, transparency);
}
let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
@@ -554,7 +569,7 @@ fn apply_mark(
};
if call_site_ctxt.is_root() {
- return self.apply_mark_internal(ctxt, expn_id, transparency);
+ return self.alloc_ctxt(ctxt, expn_id, transparency);
}
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
@@ -567,74 +582,60 @@ fn apply_mark(
//
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
for (expn_id, transparency) in self.marks(ctxt) {
- call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency);
+ call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency);
}
- self.apply_mark_internal(call_site_ctxt, expn_id, transparency)
+ self.alloc_ctxt(call_site_ctxt, expn_id, transparency)
}
- fn apply_mark_internal(
+ /// Allocate a new context with the given key, or retrieve it from cache if the given key
+ /// already exists. The auxiliary fields are calculated from the key.
+ fn alloc_ctxt(
&mut self,
- ctxt: SyntaxContext,
+ parent: SyntaxContext,
expn_id: ExpnId,
transparency: Transparency,
) -> SyntaxContext {
- let syntax_context_data = &mut self.syntax_context_data;
- debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
- let mut opaque = syntax_context_data[ctxt.0 as usize].opaque;
- let mut opaque_and_semitransparent =
- syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent;
+ debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder());
- if transparency >= Transparency::Opaque {
- let parent = opaque;
- opaque = *self
- .syntax_context_map
- .entry((parent, expn_id, transparency))
- .or_insert_with(|| {
- let new_opaque = SyntaxContext::from_usize(syntax_context_data.len());
- syntax_context_data.push(SyntaxContextData {
- outer_expn: expn_id,
- outer_transparency: transparency,
- parent,
- opaque: new_opaque,
- opaque_and_semitransparent: new_opaque,
- dollar_crate_name: kw::DollarCrate,
- });
- new_opaque
- });
+ // Look into the cache first.
+ let key = (parent, expn_id, transparency);
+ if let Some(ctxt) = self.syntax_context_map.get(&key) {
+ return *ctxt;
}
- if transparency >= Transparency::SemiTransparent {
- let parent = opaque_and_semitransparent;
- opaque_and_semitransparent = *self
- .syntax_context_map
- .entry((parent, expn_id, transparency))
- .or_insert_with(|| {
- let new_opaque_and_semitransparent =
- SyntaxContext::from_usize(syntax_context_data.len());
- syntax_context_data.push(SyntaxContextData {
- outer_expn: expn_id,
- outer_transparency: transparency,
- parent,
- opaque,
- opaque_and_semitransparent: new_opaque_and_semitransparent,
- dollar_crate_name: kw::DollarCrate,
- });
- new_opaque_and_semitransparent
- });
- }
+ // Reserve a new syntax context.
+ let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len());
+ self.syntax_context_data.push(SyntaxContextData::decode_placeholder());
+ self.syntax_context_map.insert(key, ctxt);
- let parent = ctxt;
- *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| {
- syntax_context_data.push(SyntaxContextData {
- outer_expn: expn_id,
- outer_transparency: transparency,
- parent,
- opaque,
- opaque_and_semitransparent,
- dollar_crate_name: kw::DollarCrate,
- });
- SyntaxContext::from_usize(syntax_context_data.len() - 1)
- })
+ // Opaque and semi-transparent versions of the parent. Note that they may be equal to the
+ // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
+ // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques
+ // and semi-transparents.
+ let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque;
+ let parent_opaque_and_semitransparent =
+ self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent;
+
+ // Evaluate opaque and semi-transparent versions of the new syntax context.
+ let (opaque, opaque_and_semitransparent) = match transparency {
+ Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent),
+ Transparency::SemiTransparent => (
+ parent_opaque,
+ // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
+ self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+ ),
+ Transparency::Opaque => (
+ // Will be the same as `ctxt` if the expn chain contains only opaques.
+ self.alloc_ctxt(parent_opaque, expn_id, transparency),
+ // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
+ self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+ ),
+ };
+
+ // Fill the full data, now that we have it.
+ self.syntax_context_data[ctxt.as_u32() as usize] =
+ SyntaxContextData::new(key, opaque, opaque_and_semitransparent);
+ ctxt
}
}
@@ -1439,7 +1440,8 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
}
}
Entry::Vacant(entry) => {
- // We are the first thread to start decoding. Mark the current thread as being progress.
+ // We are the first thread to start decoding. Mark the current thread as being
+ // progress.
context.local_in_progress.borrow_mut().insert(raw_id);
// Allocate and store SyntaxContext id *before* calling the decoder function,
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index f19d4d9..9e6ba2e 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -876,7 +876,7 @@ pub fn allows_unstable(self, feature: Symbol) -> bool {
self.ctxt()
.outer_expn_data()
.allow_internal_unstable
- .is_some_and(|features| features.iter().any(|&f| f == feature))
+ .is_some_and(|features| features.contains(&feature))
}
/// Checks if this span arises from a compiler desugaring of kind `kind`.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 3e47424..bc853fe 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -131,7 +131,7 @@
// tidy-alphabetical-end
// Weak keywords, have special meaning only in specific contexts.
- // Matching predicates: none
+ // Matching predicates: `is_weak`
// tidy-alphabetical-start
Auto: "auto",
Builtin: "builtin",
@@ -623,6 +623,7 @@
cfg_target_has_atomic_equal_alignment,
cfg_target_thread_local,
cfg_target_vendor,
+ cfg_trace: "<cfg>", // must not be a valid identifier
cfg_ub_checks,
cfg_version,
cfi,
@@ -985,6 +986,7 @@
field_init_shorthand,
file,
file_options,
+ flags,
float,
float_to_int_unchecked,
floorf128,
@@ -1376,6 +1378,7 @@
movbe_target_feature,
move_ref_pattern,
move_size_limit,
+ movrs_target_feature,
mul,
mul_assign,
mul_with_overflow,
@@ -1569,6 +1572,7 @@
pointer_like,
poll,
poll_next,
+ position,
post_dash_lto: "post-lto",
postfix_match,
powerpc_target_feature,
@@ -1584,6 +1588,7 @@
precise_capturing,
precise_capturing_in_traits,
precise_pointer_size_matching,
+ precision,
pref_align_of,
prefetch_read_data,
prefetch_read_instruction,
@@ -1770,6 +1775,7 @@
rustc_deallocator,
rustc_def_path,
rustc_default_body_unstable,
+ rustc_delayed_bug_from_inside_query,
rustc_deny_explicit_impl,
rustc_deprecated_safe_2024,
rustc_diagnostic_item,
@@ -1786,7 +1792,6 @@
rustc_dump_user_args,
rustc_dump_vtable,
rustc_effective_visibility,
- rustc_error,
rustc_evaluate_where_clauses,
rustc_expected_cgu_reuse,
rustc_force_inline,
@@ -2118,7 +2123,9 @@
type_changing_struct_update,
type_const,
type_id,
+ type_ir_infer_ctxt_like,
type_ir_inherent,
+ type_ir_interner,
type_length_limit,
type_macros,
type_name,
@@ -2271,6 +2278,7 @@
wasm_target_feature,
where_clause_attrs,
while_let,
+ width,
windows,
windows_subsystem,
with_negative_coherence,
@@ -2718,6 +2726,10 @@ pub fn is_reserved(self, edition: impl Copy + FnOnce() -> Edition) -> bool {
|| self.is_unused_keyword_conditional(edition)
}
+ pub fn is_weak(self) -> bool {
+ self >= kw::Auto && self <= kw::Yeet
+ }
+
/// A keyword or reserved identifier that can be used as a path segment.
pub fn is_path_segment_keyword(self) -> bool {
self == kw::Super
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 88754f1..2802e89 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>(
loop {
let key = tcx.def_key(ty_def_id);
match key.disambiguated_data.data {
- DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => {
+ DefPathData::TypeNs(_)
+ | DefPathData::ValueNs(_)
+ | DefPathData::Closure
+ | DefPathData::SyntheticCoroutineBody => {
instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
debug!(?instance_ty);
break;
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index d824a23..99d44bc 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -850,6 +850,7 @@ fn path_append(
DefPathData::Ctor => 'c',
DefPathData::AnonConst => 'k',
DefPathData::OpaqueTy => 'i',
+ DefPathData::SyntheticCoroutineBody => 's',
// These should never show up as `path_append` arguments.
DefPathData::CrateRoot
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
index dbe1540..860629b 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
@@ -2,7 +2,7 @@
pub(crate) fn target() -> Target {
Target {
- llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
+ llvm_target: "armv5te-unknown-linux-gnueabi".into(),
metadata: TargetMetadata {
description: Some("Armv5TE Linux with uClibc".into()),
tier: Some(3),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
index 5d292bb..6a83835 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
);
Target {
- llvm_target: "thumbv7a-vita-eabihf".into(),
+ llvm_target: "thumbv7a-sony-vita-eabihf".into(),
metadata: TargetMetadata {
description: Some(
"Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
index 1300280..71b3fbe 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
@@ -23,6 +23,7 @@ pub(crate) fn target() -> Target {
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "mips64".into(),
options: TargetOptions {
+ vendor: "openwrt".into(),
abi: "abi64".into(),
endian: Endian::Big,
mcount: "_mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
index 0955b3d..c14bfbf 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
@@ -4,7 +4,7 @@
pub(crate) fn target() -> Target {
Target {
- llvm_target: "mips-unknown-linux-uclibc".into(),
+ llvm_target: "mips-unknown-linux-gnu".into(),
metadata: TargetMetadata {
description: Some("MIPS Linux with uClibc".into()),
tier: Some(3),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
index 08c4347..f005679 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
@@ -2,7 +2,7 @@
pub(crate) fn target() -> Target {
Target {
- llvm_target: "mipsel-unknown-linux-uclibc".into(),
+ llvm_target: "mipsel-unknown-linux-gnu".into(),
metadata: TargetMetadata {
description: Some("MIPS (LE) Linux with uClibc".into()),
tier: Some(3),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
index 8a4bc58..efc17d8 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv32".into(),
llvm_abiname: "ilp32d".into(),
max_atomic_width: Some(32),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
stack_probes: StackProbeType::Inline,
..base::vxworks::opts()
},
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
index 6dda346..5b7feef 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv32".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "ilp32d".into(),
max_atomic_width: Some(32),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
index ba10e3c..938b39b 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv32".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "ilp32d".into(),
max_atomic_width: Some(32),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
index c8ef737..9f02ed4 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c,+zba,+zbb,+zbs,+v".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei,+zba,+zbb,+zbs,+v".into(),
llvm_abiname: "lp64d".into(),
supported_sanitizers: SanitizerSet::ADDRESS,
max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
index 39aa700..8d8c219 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
cpu: "generic-rv64".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
stack_probes: StackProbeType::Inline,
..base::vxworks::opts()
},
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
index ecf6567..e628095 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
..base::freebsd::opts()
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
index e260237..c4466e1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
@@ -4,7 +4,7 @@ pub(crate) fn target() -> Target {
let mut base = base::fuchsia::opts();
base.code_model = Some(CodeModel::Medium);
base.cpu = "generic-rv64".into();
- base.features = "+m,+a,+f,+d,+c".into();
+ base.features = "+m,+a,+f,+d,+c,+zicsr,+zifencei".into();
base.llvm_abiname = "lp64d".into();
base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
index 88b5dca..5c15bdd 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
@@ -14,7 +14,7 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
options: TargetOptions {
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
relocation_model: RelocModel::Pic,
code_model: Some(CodeModel::Medium),
tls_model: TlsModel::LocalExec,
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
index 8ffb622..af2f42f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
index 33b08fd..70c1995 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
index 2b647e3..1f359d1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
mcount: "__mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
index d6f0a54..5a5aad9 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
@@ -22,7 +22,7 @@ pub(crate) fn target() -> Target {
llvm_abiname: "lp64d".into(),
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
index bc68298..e8abc92 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
llvm_abiname: "lp64d".into(),
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
index 75f508d..85d7dfe 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c".into(),
+ features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
..base::openbsd::opts()
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
index a034a9f..4107249 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
base.panic_strategy = PanicStrategy::Abort;
Target {
- llvm_target: "x86_64-unknown-l4re-uclibc".into(),
+ llvm_target: "x86_64-unknown-l4re-gnu".into(),
metadata: TargetMetadata {
description: None,
tier: Some(3),
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index a96caf2..b4ec187 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -380,11 +380,16 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
// tidy-alphabetical-start
("adx", Stable, &[]),
("aes", Stable, &["sse2"]),
+ ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+ ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+ ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+ ("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
+ ("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("avx", Stable, &["sse4.2"]),
("avx2", Stable, &["avx"]),
("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
@@ -418,6 +423,7 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
("lzcnt", Stable, &[]),
("movbe", Stable, &[]),
+ ("movrs", Unstable(sym::movrs_target_feature), &[]),
("pclmulqdq", Stable, &["sse2"]),
("popcnt", Stable, &[]),
("prfchw", Unstable(sym::prfchw_target_feature), &[]),
@@ -488,7 +494,7 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
("c", Stable, &[]),
("d", Unstable(sym::riscv_target_feature), &["f"]),
("e", Unstable(sym::riscv_target_feature), &[]),
- ("f", Unstable(sym::riscv_target_feature), &[]),
+ ("f", Unstable(sym::riscv_target_feature), &["zicsr"]),
(
"forced-atomics",
Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
@@ -497,7 +503,8 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
("m", Stable, &[]),
("relax", Unstable(sym::riscv_target_feature), &[]),
("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
- ("v", Unstable(sym::riscv_target_feature), &[]),
+ ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]),
+ ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]),
("za128rs", Unstable(sym::riscv_target_feature), &[]),
("za64rs", Unstable(sym::riscv_target_feature), &[]),
("zaamo", Unstable(sym::riscv_target_feature), &[]),
@@ -516,19 +523,59 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
- ("zfinx", Unstable(sym::riscv_target_feature), &[]),
+ ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]),
("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
+ ("zicntr", Unstable(sym::riscv_target_feature), &["zicsr"]),
+ ("zicsr", Unstable(sym::riscv_target_feature), &[]),
+ ("zifencei", Unstable(sym::riscv_target_feature), &[]),
+ ("zihintpause", Unstable(sym::riscv_target_feature), &[]),
+ ("zihpm", Unstable(sym::riscv_target_feature), &["zicsr"]),
("zk", Stable, &["zkn", "zkr", "zkt"]),
("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
("zknd", Stable, &[]),
("zkne", Stable, &[]),
("zknh", Stable, &[]),
- ("zkr", Stable, &[]),
+ ("zkr", Stable, &["zicsr"]),
("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
("zksed", Stable, &[]),
("zksh", Stable, &[]),
("zkt", Stable, &[]),
+ ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]),
+ ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
+ ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
+ ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
+ ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
+ ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
+ ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),
+ ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zfhmin"]),
+ ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
+ ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]),
+ ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]),
+ ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]),
+ ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]),
+ ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]),
+ ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]),
+ ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]),
+ ("zvknhb", Unstable(sym::riscv_target_feature), &["zve64x"]),
+ ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]),
+ ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]),
+ ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]),
+ ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]),
+ ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]),
+ ("zvkt", Unstable(sym::riscv_target_feature), &[]),
+ ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]),
+ ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]),
+ ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]),
+ ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]),
+ ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]),
+ ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]),
+ ("zvl32b", Unstable(sym::riscv_target_feature), &[]),
+ ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]),
+ ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]),
+ ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]),
+ ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]),
+ ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]),
// tidy-alphabetical-end
];
@@ -704,8 +751,20 @@ pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> {
const POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "altivec")];
const WASM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "simd128")];
const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vector")];
-const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
- &[/*(64, "zvl64b"), */ (128, "v")];
+const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[
+ (32, "zvl32b"),
+ (64, "zvl64b"),
+ (128, "zvl128b"),
+ (256, "zvl256b"),
+ (512, "zvl512b"),
+ (1024, "zvl1024b"),
+ (2048, "zvl2048b"),
+ (4096, "zvl4096b"),
+ (8192, "zvl8192b"),
+ (16384, "zvl16384b"),
+ (32768, "zvl32768b"),
+ (65536, "zvl65536b"),
+];
// Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "vis")*/];
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 7159397..b30390a 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -9,7 +9,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
-use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
+use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt};
@@ -567,10 +567,14 @@ struct ImplicitLifetimeFinder {
impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
- let make_suggestion = |ident: Ident| {
- if ident.name == kw::Empty && ident.span.is_empty() {
+ let make_suggestion = |lifetime: &hir::Lifetime| {
+ if lifetime.is_anon_in_path == IsAnonInPath::Yes
+ && lifetime.ident.span.is_empty()
+ {
format!("{}, ", self.suggestion_param_name)
- } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
+ } else if lifetime.ident.name == kw::UnderscoreLifetime
+ && lifetime.ident.span.is_empty()
+ {
format!("{} ", self.suggestion_param_name)
} else {
self.suggestion_param_name.clone()
@@ -584,7 +588,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
matches!(
arg,
hir::GenericArg::Lifetime(lifetime)
- if lifetime.ident.name == kw::Empty
+ if lifetime.is_anon_in_path == IsAnonInPath::Yes
)
}) {
self.suggestions.push((
@@ -605,7 +609,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
{
self.suggestions.push((
lifetime.ident.span,
- make_suggestion(lifetime.ident),
+ make_suggestion(lifetime),
));
}
}
@@ -614,8 +618,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
}
}
hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
- self.suggestions
- .push((lifetime.ident.span, make_suggestion(lifetime.ident)));
+ self.suggestions.push((lifetime.ident.span, make_suggestion(lifetime)));
}
_ => {}
}
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index 3d9a90e..f272541 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -149,16 +149,16 @@ fn instantiate_canonical_var_with_infer(
self.0.instantiate_canonical_var(span, cv_info, universe_map)
}
- fn insert_hidden_type(
+ fn register_hidden_type_in_storage(
&self,
- opaque_type_key: ty::OpaqueTypeKey<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- hidden_ty: Ty<'tcx>,
- goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
- ) -> Result<(), NoSolution> {
- self.0
- .insert_hidden_type(opaque_type_key, DUMMY_SP, param_env, hidden_ty, goals)
- .map_err(|_| NoSolution)
+ opaque_type_key: rustc_type_ir::OpaqueTypeKey<Self::Interner>,
+ hidden_ty: <Self::Interner as ty::Interner>::Ty,
+ span: <Self::Interner as ty::Interner>::Span,
+ ) -> Option<<Self::Interner as ty::Interner>::Ty> {
+ self.0.register_hidden_type_in_storage(
+ opaque_type_key,
+ ty::OpaqueHiddenType { span, ty: hidden_ty },
+ )
}
fn add_item_bounds_for_hidden_type(
@@ -172,15 +172,6 @@ fn add_item_bounds_for_hidden_type(
self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals);
}
- fn inject_new_hidden_type_unchecked(
- &self,
- key: ty::OpaqueTypeKey<'tcx>,
- hidden_ty: Ty<'tcx>,
- span: Span,
- ) {
- self.0.inject_new_hidden_type_unchecked(key, ty::OpaqueHiddenType { ty: hidden_ty, span })
- }
-
fn reset_opaque_types(&self) {
let _ = self.take_opaque_types();
}
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index 78a4524..fa6bbf1 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>(
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
let param_env = {
- let param_env = tcx.param_env(method.def_id);
+ // N.B. We generally want to emulate the construction of the `unnormalized_param_env`
+ // in the param-env query here. The fact that we don't just start with the clauses
+ // in the param-env of the method is because those are already normalized, and mixing
+ // normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
+ // will cause ambiguity that the user can't really avoid.
+ //
+ // We leave out certain complexities of the param-env query here. Specifically, we:
+ // 1. Do not add `~const` bounds since there are no `dyn const Trait`s.
+ // 2. Do not add RPITIT self projection bounds for defaulted methods, since we
+ // are not constructing a param-env for "inside" of the body of the defaulted
+ // method, so we don't really care about projecting to a specific RPIT type,
+ // and because RPITITs are not dyn compatible (yet).
+ let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
// Self: Unsize<U>
let unsize_predicate =
- ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx);
+ ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
+ predicates.push(unsize_predicate.upcast(tcx));
// U: Trait<Arg1, ..., ArgN>
- let trait_predicate = {
- let trait_def_id = method.trait_container(tcx).unwrap();
- let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
- if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
- });
-
- ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
- };
+ let trait_def_id = method.trait_container(tcx).unwrap();
+ let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
+ if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
+ });
+ let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
+ predicates.push(trait_predicate.upcast(tcx));
normalize_param_env_or_error(
tcx,
- ty::ParamEnv::new(tcx.mk_clauses_from_iter(
- param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
- )),
+ ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
)
};
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 3c12741..b8e1508 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -106,10 +106,6 @@ fn match_candidate<'tcx>(
more_nested(selcx, &mut nested);
- for nested in &mut nested {
- nested.set_depth_from_parent(obligation.recursion_depth);
- }
-
Ok(nested)
}
@@ -378,10 +374,6 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
}),
);
- for nested in &mut nested {
- nested.set_depth_from_parent(obligation.recursion_depth);
- }
-
Ok(nested)
}
_ => Err(EvaluationFailure::NoSolution),
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e39f8e6..e98a240 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -225,9 +225,15 @@ struct FulfillProcessor<'a, 'tcx> {
selcx: SelectionContext<'a, 'tcx>,
}
-fn mk_pending<'tcx>(os: PredicateObligations<'tcx>) -> PendingPredicateObligations<'tcx> {
+fn mk_pending<'tcx>(
+ parent: &PredicateObligation<'tcx>,
+ os: PredicateObligations<'tcx>,
+) -> PendingPredicateObligations<'tcx> {
os.into_iter()
- .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] })
+ .map(|mut o| {
+ o.set_depth_from_parent(parent.recursion_depth);
+ PendingPredicateObligation { obligation: o, stalled_on: vec![] }
+ })
.collect()
}
@@ -341,7 +347,7 @@ fn process_obligation(
);
if predicate != obligation.predicate {
obligations.push(obligation.with(infcx.tcx, predicate));
- return ProcessResult::Changed(mk_pending(obligations));
+ return ProcessResult::Changed(mk_pending(obligation, obligations));
}
}
let binder = obligation.predicate.kind();
@@ -385,7 +391,7 @@ fn process_obligation(
let mut obligations = PredicateObligations::with_capacity(1);
obligations.push(obligation.with(infcx.tcx, pred));
- ProcessResult::Changed(mk_pending(obligations))
+ ProcessResult::Changed(mk_pending(obligation, obligations))
}
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
ty::PredicateKind::NormalizesTo(..) => {
@@ -410,6 +416,7 @@ fn process_obligation(
let host_obligation = obligation.with(infcx.tcx, data);
self.process_host_obligation(
+ obligation,
host_obligation,
&mut pending_obligation.stalled_on,
)
@@ -486,7 +493,10 @@ fn process_obligation(
// `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
// `lhs + rhs`.
ty::ConstKind::Expr(_) => {
- return ProcessResult::Changed(mk_pending(PredicateObligations::new()));
+ return ProcessResult::Changed(mk_pending(
+ obligation,
+ PredicateObligations::new(),
+ ));
}
ty::ConstKind::Placeholder(_) => {
bug!("placeholder const {:?} in old solver", ct)
@@ -503,7 +513,10 @@ fn process_obligation(
ct_ty,
ty,
) {
- Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
+ Ok(inf_ok) => ProcessResult::Changed(mk_pending(
+ obligation,
+ inf_ok.into_obligations(),
+ )),
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
)),
@@ -537,7 +550,7 @@ fn process_obligation(
vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()];
ProcessResult::Unchanged
}
- Some(os) => ProcessResult::Changed(mk_pending(os)),
+ Some(os) => ProcessResult::Changed(mk_pending(obligation, os)),
}
}
@@ -553,11 +566,8 @@ fn process_obligation(
vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
ProcessResult::Unchanged
}
- Ok(Ok(mut ok)) => {
- for subobligation in &mut ok.obligations {
- subobligation.set_depth_from_parent(obligation.recursion_depth);
- }
- ProcessResult::Changed(mk_pending(ok.obligations))
+ Ok(Ok(ok)) => {
+ ProcessResult::Changed(mk_pending(obligation, ok.obligations))
}
Ok(Err(err)) => {
let expected_found = if subtype.a_is_expected {
@@ -582,7 +592,9 @@ fn process_obligation(
vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
ProcessResult::Unchanged
}
- Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
+ Ok(Ok(ok)) => {
+ ProcessResult::Changed(mk_pending(obligation, ok.obligations))
+ }
Ok(Err(err)) => {
let expected_found = ExpectedFound::new(coerce.b, coerce.a);
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
@@ -645,6 +657,7 @@ fn process_obligation(
)
{
return ProcessResult::Changed(mk_pending(
+ obligation,
new_obligations.into_obligations(),
));
}
@@ -659,6 +672,7 @@ fn process_obligation(
.eq(DefineOpaqueTypes::Yes, c1, c2)
{
return ProcessResult::Changed(mk_pending(
+ obligation,
new_obligations.into_obligations(),
));
}
@@ -704,9 +718,10 @@ fn process_obligation(
c1,
c2,
) {
- Ok(inf_ok) => {
- ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
- }
+ Ok(inf_ok) => ProcessResult::Changed(mk_pending(
+ obligation,
+ inf_ok.into_obligations(),
+ )),
Err(err) => {
ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
ExpectedFound::new(c1, c2),
@@ -790,7 +805,7 @@ fn process_trait_obligation(
match self.selcx.poly_select(&trait_obligation) {
Ok(Some(impl_source)) => {
debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth);
- ProcessResult::Changed(mk_pending(impl_source.nested_obligations()))
+ ProcessResult::Changed(mk_pending(obligation, impl_source.nested_obligations()))
}
Ok(None) => {
debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth);
@@ -854,7 +869,7 @@ fn process_projection_obligation(
}
match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) {
- ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
+ ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(obligation, os)),
ProjectAndUnifyResult::FailedNormalization => {
stalled_on.clear();
stalled_on.extend(args_infer_vars(
@@ -868,7 +883,7 @@ fn process_projection_obligation(
let mut obligations = PredicateObligations::with_capacity(1);
obligations.push(project_obligation.with(tcx, project_obligation.predicate));
- ProcessResult::Changed(mk_pending(obligations))
+ ProcessResult::Changed(mk_pending(obligation, obligations))
}
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
ProcessResult::Error(FulfillmentErrorCode::Project(e))
@@ -878,11 +893,12 @@ fn process_projection_obligation(
fn process_host_obligation(
&mut self,
+ obligation: &PredicateObligation<'tcx>,
host_obligation: HostEffectObligation<'tcx>,
stalled_on: &mut Vec<TyOrConstInferVar>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) {
- Ok(nested) => ProcessResult::Changed(mk_pending(nested)),
+ Ok(nested) => ProcessResult::Changed(mk_pending(obligation, nested)),
Err(effects::EvaluationFailure::Ambiguous) => {
stalled_on.clear();
stalled_on.extend(args_infer_vars(
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index fc35249..d15c9af 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -16,7 +16,7 @@
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug};
-use rustc_type_ir::{Interner, elaborate};
+use rustc_type_ir::elaborate;
use tracing::{debug, instrument, trace};
use super::SelectionCandidate::*;
@@ -86,10 +86,7 @@ pub(super) fn assemble_candidates<'o>(
// `Pointee` is automatically implemented for every type.
candidates.vec.push(BuiltinCandidate { has_nested: false });
} else if tcx.is_lang_item(def_id, LangItem::Sized) {
- // Sized is never implementable by end-users, it is
- // always automatically computed.
- let sized_conditions = self.sized_conditions(obligation);
- self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
+ self.assemble_builtin_sized_candidate(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::Unsize) {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
} else if tcx.is_lang_item(def_id, LangItem::Destruct) {
@@ -802,7 +799,9 @@ fn assemble_candidates_from_auto_impls(
| ty::UnsafeBinder(_) => {
// Only consider auto impls of unsafe traits when there are
// no unsafe fields.
- if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
+ if self.tcx().trait_def(def_id).safety.is_unsafe()
+ && self_ty.has_unsafe_fields()
+ {
return;
}
@@ -1059,6 +1058,27 @@ fn assemble_candidates_for_trait_alias(
/// Assembles the trait which are built-in to the language itself:
/// `Copy`, `Clone` and `Sized`.
#[instrument(level = "debug", skip(self, candidates))]
+ fn assemble_builtin_sized_candidate(
+ &mut self,
+ obligation: &PolyTraitObligation<'tcx>,
+ candidates: &mut SelectionCandidateSet<'tcx>,
+ ) {
+ match self.sized_conditions(obligation) {
+ BuiltinImplConditions::Where(nested) => {
+ candidates
+ .vec
+ .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
+ }
+ BuiltinImplConditions::None => {}
+ BuiltinImplConditions::Ambiguous => {
+ candidates.ambiguous = true;
+ }
+ }
+ }
+
+ /// Assembles the trait which are built-in to the language itself:
+ /// e.g. `Copy` and `Clone`.
+ #[instrument(level = "debug", skip(self, candidates))]
fn assemble_builtin_bound_candidates(
&mut self,
conditions: BuiltinImplConditions<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 4404324..2cb7d2d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -39,7 +39,12 @@ pub(super) fn confirm_candidate(
obligation: &PolyTraitObligation<'tcx>,
candidate: SelectionCandidate<'tcx>,
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
- let mut impl_src = match candidate {
+ Ok(match candidate {
+ SizedCandidate { has_nested } => {
+ let data = self.confirm_builtin_candidate(obligation, has_nested);
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
+ }
+
BuiltinCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested);
ImplSource::Builtin(BuiltinImplSource::Misc, data)
@@ -134,15 +139,7 @@ pub(super) fn confirm_candidate(
BikeshedGuaranteedNoDropCandidate => {
self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation)
}
- };
-
- // The obligations returned by confirmation are recursively evaluated
- // so we need to make sure they have the correct depth.
- for subobligation in impl_src.borrow_nested_obligations_mut() {
- subobligation.set_depth_from_parent(obligation.recursion_depth);
- }
-
- Ok(impl_src)
+ })
}
fn confirm_projection_candidate(
@@ -266,9 +263,10 @@ fn confirm_builtin_candidate(
} else {
bug!("unexpected builtin trait {:?}", trait_def)
};
- let BuiltinImplConditions::Where(nested) = conditions else {
+ let BuiltinImplConditions::Where(types) = conditions else {
bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);
};
+ let types = self.infcx.enter_forall_and_leak_universe(types);
let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
self.collect_predicates_for_types(
@@ -276,7 +274,7 @@ fn confirm_builtin_candidate(
cause,
obligation.recursion_depth + 1,
trait_def,
- nested,
+ types,
)
} else {
PredicateObligations::new()
@@ -444,37 +442,25 @@ fn confirm_auto_impl_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
- debug!(?obligation, "confirm_auto_impl_candidate");
-
- let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
- let types = self.constituent_types_for_ty(self_ty)?;
- Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
- }
-
- /// See `confirm_auto_impl_candidate`.
- fn vtable_auto_impl(
- &mut self,
- obligation: &PolyTraitObligation<'tcx>,
- trait_def_id: DefId,
- nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
- ) -> PredicateObligations<'tcx> {
- debug!(?nested, "vtable_auto_impl");
ensure_sufficient_stack(|| {
- let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
-
assert_eq!(obligation.predicate.polarity(), ty::PredicatePolarity::Positive);
+ let self_ty =
+ obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
+
+ let types = self.constituent_types_for_ty(self_ty)?;
+ let types = self.infcx.enter_forall_and_leak_universe(types);
+
+ let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
let obligations = self.collect_predicates_for_types(
obligation.param_env,
cause,
obligation.recursion_depth + 1,
- trait_def_id,
- nested,
+ obligation.predicate.def_id(),
+ types,
);
- debug!(?obligations, "vtable_auto_impl");
-
- obligations
+ Ok(obligations)
})
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e1adabb..0679dbf 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1801,17 +1801,21 @@ fn winnow_candidates(
return Some(candidates.pop().unwrap().candidate);
}
- // We prefer trivial builtin candidates, i.e. builtin impls without any nested
- // requirements, over all others. This is a fix for #53123 and prevents winnowing
- // from accidentally extending the lifetime of a variable.
- let mut trivial_builtin = candidates
- .iter()
- .filter(|c| matches!(c.candidate, BuiltinCandidate { has_nested: false }));
- if let Some(_trivial) = trivial_builtin.next() {
- // There should only ever be a single trivial builtin candidate
+ // We prefer `Sized` candidates over everything.
+ let mut sized_candidates =
+ candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate { has_nested: _ }));
+ if let Some(sized_candidate) = sized_candidates.next() {
+ // There should only ever be a single sized candidate
// as they would otherwise overlap.
- debug_assert_eq!(trivial_builtin.next(), None);
- return Some(BuiltinCandidate { has_nested: false });
+ debug_assert_eq!(sized_candidates.next(), None);
+ // Only prefer the built-in `Sized` candidate if its nested goals are certain.
+ // Otherwise, we may encounter failure later on if inference causes this candidate
+ // to not hold, but a where clause would've applied instead.
+ if sized_candidate.evaluation.must_apply_modulo_regions() {
+ return Some(sized_candidate.candidate.clone());
+ } else {
+ return None;
+ }
}
// Before we consider where-bounds, we have to deduplicate them here and also
@@ -1940,7 +1944,8 @@ fn winnow_candidates(
// Don't use impl candidates which overlap with other candidates.
// This should pretty much only ever happen with malformed impls.
if candidates.iter().all(|c| match c.candidate {
- BuiltinCandidate { has_nested: _ }
+ SizedCandidate { has_nested: _ }
+ | BuiltinCandidate { has_nested: _ }
| TransmutabilityCandidate
| AutoImplCandidate
| ClosureCandidate { .. }
@@ -2370,7 +2375,7 @@ fn collect_predicates_for_types(
cause: ObligationCause<'tcx>,
recursion_depth: usize,
trait_def_id: DefId,
- types: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
+ types: Vec<Ty<'tcx>>,
) -> PredicateObligations<'tcx> {
// Because the types were potentially derived from
// higher-ranked obligations they may reference late-bound
@@ -2387,13 +2392,8 @@ fn collect_predicates_for_types(
// 3. Re-bind the regions back to `for<'a> &'a i32 : Copy`
types
- .as_ref()
- .skip_binder() // binder moved -\
- .iter()
- .flat_map(|ty| {
- let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/
-
- let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty);
+ .into_iter()
+ .flat_map(|placeholder_ty| {
let Normalized { value: normalized_ty, mut obligations } =
ensure_sufficient_stack(|| {
normalize_with_depth(
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index 26c4951..e512e8f 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -102,6 +102,7 @@ pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I
}
}
+#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
pub trait InferCtxtLike: Sized {
type Interner: Interner;
fn cx(&self) -> Self::Interner;
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index e765cb6..8f86270 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -15,6 +15,7 @@
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{self as ty, search_graph};
+#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")]
pub trait Interner:
Sized
+ Copy
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 6291218..4e2baca 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -6,6 +6,7 @@
feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
)]
#![cfg_attr(feature = "nightly", allow(internal_features))]
+#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
// tidy-alphabetical-end
extern crate self as rustc_type_ir;
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index b1bf7bc..2a1c163 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -1057,8 +1057,7 @@ impl Place {
/// In order to retrieve the correct type, the `locals` argument must match the list of all
/// locals from the function body where this place originates from.
pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
- let start_ty = locals[self.local].ty;
- self.projection.iter().fold(Ok(start_ty), |place_ty, elem| elem.ty(place_ty?))
+ self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty))
}
}
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index 09447e7..9d2368b 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -563,7 +563,7 @@ pub struct PlaceRef<'a> {
impl PlaceRef<'_> {
/// Get the type of this place.
pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
- self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?))
+ self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty))
}
}
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index c62f8e5..be58166 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -20,7 +20,7 @@
use core::marker::{PhantomData, Unsize};
use core::mem::{self, ManuallyDrop, align_of_val_raw};
use core::num::NonZeroUsize;
-use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver};
+use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
use core::panic::{RefUnwindSafe, UnwindSafe};
use core::pin::{Pin, PinCoerceUnsized};
use core::ptr::{self, NonNull};
@@ -4066,3 +4066,413 @@ fn provide<'a>(&'a self, req: &mut core::error::Request<'a>) {
core::error::Error::provide(&**self, req);
}
}
+
+/// A uniquely owned [`Arc`].
+///
+/// This represents an `Arc` that is known to be uniquely owned -- that is, have exactly one strong
+/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
+/// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`.
+///
+/// Because it is uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common
+/// use case is to have an object be mutable during its initialization phase but then have it become
+/// immutable and converted to a normal `Arc`.
+///
+/// This can be used as a flexible way to create cyclic data structures, as in the example below.
+///
+/// ```
+/// #![feature(unique_rc_arc)]
+/// use std::sync::{Arc, Weak, UniqueArc};
+///
+/// struct Gadget {
+/// me: Weak<Gadget>,
+/// }
+///
+/// fn create_gadget() -> Option<Arc<Gadget>> {
+/// let mut rc = UniqueArc::new(Gadget {
+/// me: Weak::new(),
+/// });
+/// rc.me = UniqueArc::downgrade(&rc);
+/// Some(UniqueArc::into_arc(rc))
+/// }
+///
+/// create_gadget().unwrap();
+/// ```
+///
+/// An advantage of using `UniqueArc` over [`Arc::new_cyclic`] to build cyclic data structures is that
+/// [`Arc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the
+/// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data,
+/// including fallible or async constructors.
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+pub struct UniqueArc<
+ T: ?Sized,
+ #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+> {
+ ptr: NonNull<ArcInner<T>>,
+ // Define the ownership of `ArcInner<T>` for drop-check
+ _marker: PhantomData<ArcInner<T>>,
+ // Invariance is necessary for soundness: once other `Weak`
+ // references exist, we already have a form of shared mutability!
+ _marker2: PhantomData<*mut T>,
+ alloc: A,
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<T: ?Sized + Sync + Send, A: Allocator + Send> Send for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<T: ?Sized + Sync + Send, A: Allocator + Sync> Sync for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+// #[unstable(feature = "coerce_unsized", issue = "18598")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueArc<U, A>>
+ for UniqueArc<T, A>
+{
+}
+
+//#[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<UniqueArc<U>> for UniqueArc<T> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + fmt::Display, A: Allocator> fmt::Display for UniqueArc<T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(&**self, f)
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + fmt::Debug, A: Allocator> fmt::Debug for UniqueArc<T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&**self, f)
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> fmt::Pointer for UniqueArc<T, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Pointer::fmt(&(&raw const **self), f)
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> borrow::Borrow<T> for UniqueArc<T, A> {
+ fn borrow(&self) -> &T {
+ &**self
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> borrow::BorrowMut<T> for UniqueArc<T, A> {
+ fn borrow_mut(&mut self) -> &mut T {
+ &mut **self
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> AsRef<T> for UniqueArc<T, A> {
+ fn as_ref(&self) -> &T {
+ &**self
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> AsMut<T> for UniqueArc<T, A> {
+ fn as_mut(&mut self) -> &mut T {
+ &mut **self
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> Unpin for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for UniqueArc<T, A> {
+ /// Equality for two `UniqueArc`s.
+ ///
+ /// Two `UniqueArc`s are equal if their inner values are equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unique_rc_arc)]
+ /// use std::sync::UniqueArc;
+ ///
+ /// let five = UniqueArc::new(5);
+ ///
+ /// assert!(five == UniqueArc::new(5));
+ /// ```
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ PartialEq::eq(&**self, &**other)
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for UniqueArc<T, A> {
+ /// Partial comparison for two `UniqueArc`s.
+ ///
+ /// The two are compared by calling `partial_cmp()` on their inner values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unique_rc_arc)]
+ /// use std::sync::UniqueArc;
+ /// use std::cmp::Ordering;
+ ///
+ /// let five = UniqueArc::new(5);
+ ///
+ /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&UniqueArc::new(6)));
+ /// ```
+ #[inline(always)]
+ fn partial_cmp(&self, other: &UniqueArc<T, A>) -> Option<Ordering> {
+ (**self).partial_cmp(&**other)
+ }
+
+ /// Less-than comparison for two `UniqueArc`s.
+ ///
+ /// The two are compared by calling `<` on their inner values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unique_rc_arc)]
+ /// use std::sync::UniqueArc;
+ ///
+ /// let five = UniqueArc::new(5);
+ ///
+ /// assert!(five < UniqueArc::new(6));
+ /// ```
+ #[inline(always)]
+ fn lt(&self, other: &UniqueArc<T, A>) -> bool {
+ **self < **other
+ }
+
+ /// 'Less than or equal to' comparison for two `UniqueArc`s.
+ ///
+ /// The two are compared by calling `<=` on their inner values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unique_rc_arc)]
+ /// use std::sync::UniqueArc;
+ ///
+ /// let five = UniqueArc::new(5);
+ ///
+ /// assert!(five <= UniqueArc::new(5));
+ /// ```
+ #[inline(always)]
+ fn le(&self, other: &UniqueArc<T, A>) -> bool {
+ **self <= **other
+ }
+
+ /// Greater-than comparison for two `UniqueArc`s.
+ ///
+ /// The two are compared by calling `>` on their inner values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unique_rc_arc)]
+ /// use std::sync::UniqueArc;
+ ///
+ /// let five = UniqueArc::new(5);
+ ///
+ /// assert!(five > UniqueArc::new(4));
+ /// ```
+ #[inline(always)]
+ fn gt(&self, other: &UniqueArc<T, A>) -> bool {
+ **self > **other
+ }
+
+ /// 'Greater than or equal to' comparison for two `UniqueArc`s.
+ ///
+ /// The two are compared by calling `>=` on their inner values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unique_rc_arc)]
+ /// use std::sync::UniqueArc;
+ ///
+ /// let five = UniqueArc::new(5);
+ ///
+ /// assert!(five >= UniqueArc::new(5));
+ /// ```
+ #[inline(always)]
+ fn ge(&self, other: &UniqueArc<T, A>) -> bool {
+ **self >= **other
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Ord, A: Allocator> Ord for UniqueArc<T, A> {
+ /// Comparison for two `UniqueArc`s.
+ ///
+ /// The two are compared by calling `cmp()` on their inner values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unique_rc_arc)]
+ /// use std::sync::UniqueArc;
+ /// use std::cmp::Ordering;
+ ///
+ /// let five = UniqueArc::new(5);
+ ///
+ /// assert_eq!(Ordering::Less, five.cmp(&UniqueArc::new(6)));
+ /// ```
+ #[inline]
+ fn cmp(&self, other: &UniqueArc<T, A>) -> Ordering {
+ (**self).cmp(&**other)
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Eq, A: Allocator> Eq for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Hash, A: Allocator> Hash for UniqueArc<T, A> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (**self).hash(state);
+ }
+}
+
+impl<T> UniqueArc<T, Global> {
+ /// Creates a new `UniqueArc`.
+ ///
+ /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading
+ /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`].
+ /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will
+ /// point to the new [`Arc`].
+ #[cfg(not(no_global_oom_handling))]
+ #[unstable(feature = "unique_rc_arc", issue = "112566")]
+ #[must_use]
+ pub fn new(value: T) -> Self {
+ Self::new_in(value, Global)
+ }
+}
+
+impl<T, A: Allocator> UniqueArc<T, A> {
+ /// Creates a new `UniqueArc` in the provided allocator.
+ ///
+ /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading
+ /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`].
+ /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will
+ /// point to the new [`Arc`].
+ #[cfg(not(no_global_oom_handling))]
+ #[unstable(feature = "unique_rc_arc", issue = "112566")]
+ #[must_use]
+ // #[unstable(feature = "allocator_api", issue = "32838")]
+ pub fn new_in(data: T, alloc: A) -> Self {
+ let (ptr, alloc) = Box::into_unique(Box::new_in(
+ ArcInner {
+ strong: atomic::AtomicUsize::new(0),
+ // keep one weak reference so if all the weak pointers that are created are dropped
+ // the UniqueArc still stays valid.
+ weak: atomic::AtomicUsize::new(1),
+ data,
+ },
+ alloc,
+ ));
+ Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc }
+ }
+}
+
+impl<T: ?Sized, A: Allocator> UniqueArc<T, A> {
+ /// Converts the `UniqueArc` into a regular [`Arc`].
+ ///
+ /// This consumes the `UniqueArc` and returns a regular [`Arc`] that contains the `value` that
+ /// is passed to `into_arc`.
+ ///
+ /// Any weak references created before this method is called can now be upgraded to strong
+ /// references.
+ #[unstable(feature = "unique_rc_arc", issue = "112566")]
+ #[must_use]
+ pub fn into_arc(this: Self) -> Arc<T, A> {
+ let this = ManuallyDrop::new(this);
+
+ // Move the allocator out.
+ // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in
+ // a `ManuallyDrop`.
+ let alloc: A = unsafe { ptr::read(&this.alloc) };
+
+ // SAFETY: This pointer was allocated at creation time so we know it is valid.
+ unsafe {
+ // Convert our weak reference into a strong reference
+ (*this.ptr.as_ptr()).strong.store(1, Release);
+ Arc::from_inner_in(this.ptr, alloc)
+ }
+ }
+}
+
+impl<T: ?Sized, A: Allocator + Clone> UniqueArc<T, A> {
+ /// Creates a new weak reference to the `UniqueArc`.
+ ///
+ /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted
+ /// to a [`Arc`] using [`UniqueArc::into_arc`].
+ #[unstable(feature = "unique_rc_arc", issue = "112566")]
+ #[must_use]
+ pub fn downgrade(this: &Self) -> Weak<T, A> {
+ // Using a relaxed ordering is alright here, as knowledge of the
+ // original reference prevents other threads from erroneously deleting
+ // the object or converting the object to a normal `Arc<T, A>`.
+ //
+ // Note that we don't need to test if the weak counter is locked because there
+ // are no such operations like `Arc::get_mut` or `Arc::make_mut` that will lock
+ // the weak counter.
+ //
+ // SAFETY: This pointer was allocated at creation time so we know it is valid.
+ let old_size = unsafe { (*this.ptr.as_ptr()).weak.fetch_add(1, Relaxed) };
+
+ // See comments in Arc::clone() for why we do this (for mem::forget).
+ if old_size > MAX_REFCOUNT {
+ abort();
+ }
+
+ Weak { ptr: this.ptr, alloc: this.alloc.clone() }
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> Deref for UniqueArc<T, A> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ // SAFETY: This pointer was allocated at creation time so we know it is valid.
+ unsafe { &self.ptr.as_ref().data }
+ }
+}
+
+// #[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueArc<T> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> DerefMut for UniqueArc<T, A> {
+ fn deref_mut(&mut self) -> &mut T {
+ // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
+ // have unique ownership and therefore it's safe to make a mutable reference because
+ // `UniqueArc` owns the only strong reference to itself.
+ // We also need to be careful to only create a mutable reference to the `data` field,
+ // as a mutable reference to the entire `ArcInner` would assert uniqueness over the
+ // ref count fields too, invalidating any attempt by `Weak`s to access the ref count.
+ unsafe { &mut (*self.ptr.as_ptr()).data }
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+// #[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized, A: Allocator> DerefPure for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc<T, A> {
+ fn drop(&mut self) {
+ // See `Arc::drop_slow` which drops an `Arc` with a strong count of 0.
+ // SAFETY: This pointer was allocated at creation time so we know it is valid.
+ let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
+
+ unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) };
+ }
+}
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 3782f9e..633ef71 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -3360,10 +3360,6 @@ fn hash<H: Hasher>(&self, state: &mut H) {
}
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(
- message = "vector indices are of type `usize` or ranges of `usize`",
- label = "vector indices are of type `usize` or ranges of `usize`"
-)]
impl<T, I: SliceIndex<[T]>, A: Allocator> Index<I> for Vec<T, A> {
type Output = I::Output;
@@ -3374,10 +3370,6 @@ fn index(&self, index: I) -> &Self::Output {
}
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(
- message = "vector indices are of type `usize` or ranges of `usize`",
- label = "vector indices are of type `usize` or ranges of `usize`"
-)]
impl<T, I: SliceIndex<[T]>, A: Allocator> IndexMut<I> for Vec<T, A> {
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs
index 0baa50f..00bdf52 100644
--- a/library/alloctests/tests/arc.rs
+++ b/library/alloctests/tests/arc.rs
@@ -1,7 +1,7 @@
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::iter::TrustedLen;
-use std::sync::{Arc, Weak};
+use std::sync::{Arc, UniqueArc, Weak};
#[test]
fn uninhabited() {
@@ -263,9 +263,30 @@ fn make_mut_unsized() {
assert_eq!(*other_data, [110, 20, 30]);
}
+#[test]
+fn test_unique_arc_weak() {
+ let data = UniqueArc::new(32);
+
+ // Test that `Weak` downgraded from `UniqueArc` cannot be upgraded.
+ let weak = UniqueArc::downgrade(&data);
+ assert_eq!(weak.strong_count(), 0);
+ assert_eq!(weak.weak_count(), 0);
+ assert!(weak.upgrade().is_none());
+
+ // Test that `Weak` can now be upgraded after the `UniqueArc` being converted to `Arc`.
+ let strong = UniqueArc::into_arc(data);
+ assert_eq!(*strong, 32);
+ assert_eq!(weak.strong_count(), 1);
+ assert_eq!(weak.weak_count(), 1);
+ let upgraded = weak.upgrade().unwrap();
+ assert_eq!(*upgraded, 32);
+ assert_eq!(weak.strong_count(), 2);
+ assert_eq!(weak.weak_count(), 1);
+}
+
#[allow(unused)]
mod pin_coerce_unsized {
- use alloc::sync::Arc;
+ use alloc::sync::{Arc, UniqueArc};
use core::pin::Pin;
pub trait MyTrait {}
@@ -275,4 +296,7 @@ impl MyTrait for String {}
pub fn pin_arc(arg: Pin<Arc<String>>) -> Pin<Arc<dyn MyTrait>> {
arg
}
+ pub fn pin_unique_arc(arg: Pin<UniqueArc<String>>) -> Pin<UniqueArc<dyn MyTrait>> {
+ arg
+ }
}
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 1a320b3..e789601 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -495,7 +495,7 @@ fn is_nonoverlapping<T>(src: *const T, dst: *const T) -> bool {
/// ```
#[inline]
#[stable(feature = "move_cell", since = "1.17.0")]
- #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+ #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
#[rustc_confusables("swap")]
pub const fn replace(&self, val: T) -> T {
// SAFETY: This can cause data races if called from a separate thread,
@@ -537,7 +537,7 @@ impl<T: Copy> Cell<T> {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+ #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
pub const fn get(&self) -> T {
// SAFETY: This can cause data races if called from a separate thread,
// but `Cell` is `!Sync` so this won't happen.
@@ -617,7 +617,7 @@ pub const fn as_ptr(&self) -> *mut T {
/// ```
#[inline]
#[stable(feature = "cell_get_mut", since = "1.11.0")]
- #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+ #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
pub const fn get_mut(&mut self) -> &mut T {
self.value.get_mut()
}
@@ -637,7 +637,7 @@ pub const fn get_mut(&mut self) -> &mut T {
/// ```
#[inline]
#[stable(feature = "as_cell", since = "1.37.0")]
- #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+ #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
pub const fn from_mut(t: &mut T) -> &Cell<T> {
// SAFETY: `&mut` ensures unique access.
unsafe { &*(t as *mut T as *const Cell<T>) }
@@ -695,7 +695,7 @@ impl<T> Cell<[T]> {
/// assert_eq!(slice_cell.len(), 3);
/// ```
#[stable(feature = "as_cell", since = "1.37.0")]
- #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+ #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
pub const fn as_slice_of_cells(&self) -> &[Cell<T>] {
// SAFETY: `Cell<T>` has the same memory layout as `T`.
unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index d27f7e6..0b04ebc 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -20,8 +20,8 @@ pub struct Placeholder {
pub width: Count,
}
+#[cfg(bootstrap)]
impl Placeholder {
- #[cfg(bootstrap)]
#[inline]
pub const fn new(
position: usize,
@@ -33,12 +33,6 @@ pub const fn new(
) -> Self {
Self { position, fill, align, flags, precision, width }
}
-
- #[cfg(not(bootstrap))]
- #[inline]
- pub const fn new(position: usize, flags: u32, precision: Count, width: Count) -> Self {
- Self { position, flags, precision, width }
- }
}
#[cfg(bootstrap)]
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
index 5b7d95c..12e2b8b 100644
--- a/library/core/src/iter/traits/accum.rs
+++ b/library/core/src/iter/traits/accum.rs
@@ -10,7 +10,7 @@
/// [`sum()`]: Iterator::sum
/// [`FromIterator`]: iter::FromIterator
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
-#[rustc_on_unimplemented(
+#[diagnostic::on_unimplemented(
message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
)]
@@ -31,7 +31,7 @@ pub trait Sum<A = Self>: Sized {
/// [`product()`]: Iterator::product
/// [`FromIterator`]: iter::FromIterator
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
-#[rustc_on_unimplemented(
+#[diagnostic::on_unimplemented(
message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
)]
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 89c856f..ba4c849 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -127,15 +127,13 @@ mod prim_bool {}
/// [`Result<String, !>`] which we can unpack like this:
///
/// ```
-/// #![feature(exhaustive_patterns)]
/// use std::str::FromStr;
/// let Ok(s) = String::from_str("hello");
/// ```
///
-/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
-/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
-/// [`Ok`] variant. This illustrates another behavior of `!` - it can be used to "delete" certain
-/// enum variants from generic types like `Result`.
+/// Since the [`Err`] variant contains a `!`, it can never occur. This means we can exhaustively
+/// match on [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behavior
+/// of `!` - it can be used to "delete" certain enum variants from generic types like `Result`.
///
/// ## Infinite loops
///
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 7d0839a..71a84af 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -386,7 +386,8 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
/// [allocated object], and the entire memory range between `self` and the result must be in
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
- /// of the address space.
+ /// of the address space. Note that "range" here refers to a half-open range as usual in Rust,
+ /// i.e., `self..result` for non-negative offsets and `result..self` for negative offsets.
///
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 79022fe..7ad1547 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -39,7 +39,6 @@
#![feature(generic_assert_internals)]
#![feature(hasher_prefixfree_extras)]
#![feature(hashmap_internals)]
-#![feature(inline_const_pat)]
#![feature(int_roundings)]
#![feature(ip)]
#![feature(ip_from)]
@@ -95,16 +94,17 @@
/// Version of `assert_matches` that ignores fancy runtime printing in const context and uses structural equality.
macro_rules! assert_eq_const_safe {
- ($left:expr, $right:expr) => {
- assert_eq_const_safe!($left, $right, concat!(stringify!($left), " == ", stringify!($right)));
+ ($t:ty: $left:expr, $right:expr) => {
+ assert_eq_const_safe!($t: $left, $right, concat!(stringify!($left), " == ", stringify!($right)));
};
- ($left:expr, $right:expr$(, $($arg:tt)+)?) => {
+ ($t:ty: $left:expr, $right:expr$(, $($arg:tt)+)?) => {
{
fn runtime() {
assert_eq!($left, $right, $($($arg)*),*);
}
const fn compiletime() {
- assert!(matches!($left, const { $right }));
+ const PAT: $t = $right;
+ assert!(matches!($left, PAT), $($($arg)*),*);
}
core::intrinsics::const_eval_select((), compiletime, runtime)
}
diff --git a/library/coretests/tests/num/int_macros.rs b/library/coretests/tests/num/int_macros.rs
index bbf19d2..0d9fb9e 100644
--- a/library/coretests/tests/num/int_macros.rs
+++ b/library/coretests/tests/num/int_macros.rs
@@ -1,5 +1,6 @@
macro_rules! int_module {
($T:ident, $U:ident) => {
+ use core::num::ParseIntError;
use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
use core::$T::*;
@@ -32,20 +33,20 @@ fn test_bitwise_operators() {
test_runtime_and_compiletime! {
fn test_rem_euclid() {
- assert_eq_const_safe!((-1 as $T).rem_euclid(MIN), MAX);
+ assert_eq_const_safe!($T: (-1 as $T).rem_euclid(MIN), MAX);
}
fn test_abs() {
- assert_eq_const_safe!((1 as $T).abs(), 1 as $T);
- assert_eq_const_safe!((0 as $T).abs(), 0 as $T);
- assert_eq_const_safe!((-1 as $T).abs(), 1 as $T);
+ assert_eq_const_safe!($T: (1 as $T).abs(), 1 as $T);
+ assert_eq_const_safe!($T: (0 as $T).abs(), 0 as $T);
+ assert_eq_const_safe!($T: (-1 as $T).abs(), 1 as $T);
}
fn test_signum() {
- assert_eq_const_safe!((1 as $T).signum(), 1 as $T);
- assert_eq_const_safe!((0 as $T).signum(), 0 as $T);
- assert_eq_const_safe!((-0 as $T).signum(), 0 as $T);
- assert_eq_const_safe!((-1 as $T).signum(), -1 as $T);
+ assert_eq_const_safe!($T: (1 as $T).signum(), 1 as $T);
+ assert_eq_const_safe!($T: (0 as $T).signum(), 0 as $T);
+ assert_eq_const_safe!($T: (-0 as $T).signum(), 0 as $T);
+ assert_eq_const_safe!($T: (-1 as $T).signum(), -1 as $T);
}
fn test_is_positive() {
@@ -72,123 +73,123 @@ fn test_is_negative() {
test_runtime_and_compiletime! {
fn test_count_ones() {
- assert_eq_const_safe!(A.count_ones(), 3);
- assert_eq_const_safe!(B.count_ones(), 2);
- assert_eq_const_safe!(C.count_ones(), 5);
+ assert_eq_const_safe!(u32: A.count_ones(), 3);
+ assert_eq_const_safe!(u32: B.count_ones(), 2);
+ assert_eq_const_safe!(u32: C.count_ones(), 5);
}
fn test_count_zeros() {
- assert_eq_const_safe!(A.count_zeros(), $T::BITS - 3);
- assert_eq_const_safe!(B.count_zeros(), $T::BITS - 2);
- assert_eq_const_safe!(C.count_zeros(), $T::BITS - 5);
+ assert_eq_const_safe!(u32: A.count_zeros(), $T::BITS - 3);
+ assert_eq_const_safe!(u32: B.count_zeros(), $T::BITS - 2);
+ assert_eq_const_safe!(u32: C.count_zeros(), $T::BITS - 5);
}
fn test_leading_trailing_ones() {
const A: $T = 0b0101_1111;
- assert_eq_const_safe!(A.trailing_ones(), 5);
- assert_eq_const_safe!((!A).leading_ones(), $T::BITS - 7);
+ assert_eq_const_safe!(u32: A.trailing_ones(), 5);
+ assert_eq_const_safe!(u32: (!A).leading_ones(), $T::BITS - 7);
- assert_eq_const_safe!(A.reverse_bits().leading_ones(), 5);
+ assert_eq_const_safe!(u32: A.reverse_bits().leading_ones(), 5);
- assert_eq_const_safe!(_1.leading_ones(), $T::BITS);
- assert_eq_const_safe!(_1.trailing_ones(), $T::BITS);
+ assert_eq_const_safe!(u32: _1.leading_ones(), $T::BITS);
+ assert_eq_const_safe!(u32: _1.trailing_ones(), $T::BITS);
- assert_eq_const_safe!((_1 << 1).trailing_ones(), 0);
- assert_eq_const_safe!(MAX.leading_ones(), 0);
+ assert_eq_const_safe!(u32: (_1 << 1).trailing_ones(), 0);
+ assert_eq_const_safe!(u32: MAX.leading_ones(), 0);
- assert_eq_const_safe!((_1 << 1).leading_ones(), $T::BITS - 1);
- assert_eq_const_safe!(MAX.trailing_ones(), $T::BITS - 1);
+ assert_eq_const_safe!(u32: (_1 << 1).leading_ones(), $T::BITS - 1);
+ assert_eq_const_safe!(u32: MAX.trailing_ones(), $T::BITS - 1);
- assert_eq_const_safe!(_0.leading_ones(), 0);
- assert_eq_const_safe!(_0.trailing_ones(), 0);
+ assert_eq_const_safe!(u32: _0.leading_ones(), 0);
+ assert_eq_const_safe!(u32: _0.trailing_ones(), 0);
const X: $T = 0b0010_1100;
- assert_eq_const_safe!(X.leading_ones(), 0);
- assert_eq_const_safe!(X.trailing_ones(), 0);
+ assert_eq_const_safe!(u32: X.leading_ones(), 0);
+ assert_eq_const_safe!(u32: X.trailing_ones(), 0);
}
fn test_rotate() {
- assert_eq_const_safe!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
- assert_eq_const_safe!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
- assert_eq_const_safe!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+ assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+ assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+ assert_eq_const_safe!($T: C.rotate_left(6).rotate_right(2).rotate_right(4), C);
// Rotating these should make no difference
//
// We test using 124 bits because to ensure that overlong bit shifts do
// not cause undefined behavior. See #10183.
- assert_eq_const_safe!(_0.rotate_left(124), _0);
- assert_eq_const_safe!(_1.rotate_left(124), _1);
- assert_eq_const_safe!(_0.rotate_right(124), _0);
- assert_eq_const_safe!(_1.rotate_right(124), _1);
+ assert_eq_const_safe!($T: _0.rotate_left(124), _0);
+ assert_eq_const_safe!($T: _1.rotate_left(124), _1);
+ assert_eq_const_safe!($T: _0.rotate_right(124), _0);
+ assert_eq_const_safe!($T: _1.rotate_right(124), _1);
// Rotating by 0 should have no effect
- assert_eq_const_safe!(A.rotate_left(0), A);
- assert_eq_const_safe!(B.rotate_left(0), B);
- assert_eq_const_safe!(C.rotate_left(0), C);
+ assert_eq_const_safe!($T: A.rotate_left(0), A);
+ assert_eq_const_safe!($T: B.rotate_left(0), B);
+ assert_eq_const_safe!($T: C.rotate_left(0), C);
// Rotating by a multiple of word size should also have no effect
- assert_eq_const_safe!(A.rotate_left(128), A);
- assert_eq_const_safe!(B.rotate_left(128), B);
- assert_eq_const_safe!(C.rotate_left(128), C);
+ assert_eq_const_safe!($T: A.rotate_left(128), A);
+ assert_eq_const_safe!($T: B.rotate_left(128), B);
+ assert_eq_const_safe!($T: C.rotate_left(128), C);
}
fn test_swap_bytes() {
- assert_eq_const_safe!(A.swap_bytes().swap_bytes(), A);
- assert_eq_const_safe!(B.swap_bytes().swap_bytes(), B);
- assert_eq_const_safe!(C.swap_bytes().swap_bytes(), C);
+ assert_eq_const_safe!($T: A.swap_bytes().swap_bytes(), A);
+ assert_eq_const_safe!($T: B.swap_bytes().swap_bytes(), B);
+ assert_eq_const_safe!($T: C.swap_bytes().swap_bytes(), C);
// Swapping these should make no difference
- assert_eq_const_safe!(_0.swap_bytes(), _0);
- assert_eq_const_safe!(_1.swap_bytes(), _1);
+ assert_eq_const_safe!($T: _0.swap_bytes(), _0);
+ assert_eq_const_safe!($T: _1.swap_bytes(), _1);
}
fn test_le() {
- assert_eq_const_safe!($T::from_le(A.to_le()), A);
- assert_eq_const_safe!($T::from_le(B.to_le()), B);
- assert_eq_const_safe!($T::from_le(C.to_le()), C);
- assert_eq_const_safe!($T::from_le(_0), _0);
- assert_eq_const_safe!($T::from_le(_1), _1);
- assert_eq_const_safe!(_0.to_le(), _0);
- assert_eq_const_safe!(_1.to_le(), _1);
+ assert_eq_const_safe!($T: $T::from_le(A.to_le()), A);
+ assert_eq_const_safe!($T: $T::from_le(B.to_le()), B);
+ assert_eq_const_safe!($T: $T::from_le(C.to_le()), C);
+ assert_eq_const_safe!($T: $T::from_le(_0), _0);
+ assert_eq_const_safe!($T: $T::from_le(_1), _1);
+ assert_eq_const_safe!($T: _0.to_le(), _0);
+ assert_eq_const_safe!($T: _1.to_le(), _1);
}
fn test_be() {
- assert_eq_const_safe!($T::from_be(A.to_be()), A);
- assert_eq_const_safe!($T::from_be(B.to_be()), B);
- assert_eq_const_safe!($T::from_be(C.to_be()), C);
- assert_eq_const_safe!($T::from_be(_0), _0);
- assert_eq_const_safe!($T::from_be(_1), _1);
- assert_eq_const_safe!(_0.to_be(), _0);
- assert_eq_const_safe!(_1.to_be(), _1);
+ assert_eq_const_safe!($T: $T::from_be(A.to_be()), A);
+ assert_eq_const_safe!($T: $T::from_be(B.to_be()), B);
+ assert_eq_const_safe!($T: $T::from_be(C.to_be()), C);
+ assert_eq_const_safe!($T: $T::from_be(_0), _0);
+ assert_eq_const_safe!($T: $T::from_be(_1), _1);
+ assert_eq_const_safe!($T: _0.to_be(), _0);
+ assert_eq_const_safe!($T: _1.to_be(), _1);
}
fn test_signed_checked_div() {
- assert_eq_const_safe!((10 as $T).checked_div(2), Some(5));
- assert_eq_const_safe!((5 as $T).checked_div(0), None);
- assert_eq_const_safe!(isize::MIN.checked_div(-1), None);
+ assert_eq_const_safe!(Option<$T>: (10 as $T).checked_div(2), Some(5));
+ assert_eq_const_safe!(Option<$T>: (5 as $T).checked_div(0), None);
+ assert_eq_const_safe!(Option<$T>: $T::MIN.checked_div(-1), None);
}
fn test_saturating_abs() {
- assert_eq_const_safe!((0 as $T).saturating_abs(), 0);
- assert_eq_const_safe!((123 as $T).saturating_abs(), 123);
- assert_eq_const_safe!((-123 as $T).saturating_abs(), 123);
- assert_eq_const_safe!((MAX - 2).saturating_abs(), MAX - 2);
- assert_eq_const_safe!((MAX - 1).saturating_abs(), MAX - 1);
- assert_eq_const_safe!(MAX.saturating_abs(), MAX);
- assert_eq_const_safe!((MIN + 2).saturating_abs(), MAX - 1);
- assert_eq_const_safe!((MIN + 1).saturating_abs(), MAX);
- assert_eq_const_safe!(MIN.saturating_abs(), MAX);
+ assert_eq_const_safe!($T: (0 as $T).saturating_abs(), 0);
+ assert_eq_const_safe!($T: (123 as $T).saturating_abs(), 123);
+ assert_eq_const_safe!($T: (-123 as $T).saturating_abs(), 123);
+ assert_eq_const_safe!($T: (MAX - 2).saturating_abs(), MAX - 2);
+ assert_eq_const_safe!($T: (MAX - 1).saturating_abs(), MAX - 1);
+ assert_eq_const_safe!($T: MAX.saturating_abs(), MAX);
+ assert_eq_const_safe!($T: (MIN + 2).saturating_abs(), MAX - 1);
+ assert_eq_const_safe!($T: (MIN + 1).saturating_abs(), MAX);
+ assert_eq_const_safe!($T: MIN.saturating_abs(), MAX);
}
fn test_saturating_neg() {
- assert_eq_const_safe!((0 as $T).saturating_neg(), 0);
- assert_eq_const_safe!((123 as $T).saturating_neg(), -123);
- assert_eq_const_safe!((-123 as $T).saturating_neg(), 123);
- assert_eq_const_safe!((MAX - 2).saturating_neg(), MIN + 3);
- assert_eq_const_safe!((MAX - 1).saturating_neg(), MIN + 2);
- assert_eq_const_safe!(MAX.saturating_neg(), MIN + 1);
- assert_eq_const_safe!((MIN + 2).saturating_neg(), MAX - 1);
- assert_eq_const_safe!((MIN + 1).saturating_neg(), MAX);
- assert_eq_const_safe!(MIN.saturating_neg(), MAX);
+ assert_eq_const_safe!($T: (0 as $T).saturating_neg(), 0);
+ assert_eq_const_safe!($T: (123 as $T).saturating_neg(), -123);
+ assert_eq_const_safe!($T: (-123 as $T).saturating_neg(), 123);
+ assert_eq_const_safe!($T: (MAX - 2).saturating_neg(), MIN + 3);
+ assert_eq_const_safe!($T: (MAX - 1).saturating_neg(), MIN + 2);
+ assert_eq_const_safe!($T: MAX.saturating_neg(), MIN + 1);
+ assert_eq_const_safe!($T: (MIN + 2).saturating_neg(), MAX - 1);
+ assert_eq_const_safe!($T: (MIN + 1).saturating_neg(), MAX);
+ assert_eq_const_safe!($T: MIN.saturating_neg(), MAX);
}
}
@@ -250,23 +251,23 @@ fn from_str<T: std::str::FromStr>(t: &str) -> Option<T> {
test_runtime_and_compiletime! {
fn test_from_str_radix() {
- assert_eq_const_safe!($T::from_str_radix("123", 10), Ok(123 as $T));
- assert_eq_const_safe!($T::from_str_radix("1001", 2), Ok(9 as $T));
- assert_eq_const_safe!($T::from_str_radix("123", 8), Ok(83 as $T));
- assert_eq_const_safe!(i32::from_str_radix("123", 16), Ok(291 as i32));
- assert_eq_const_safe!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
- assert_eq_const_safe!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
- assert_eq_const_safe!($T::from_str_radix("z", 36), Ok(35 as $T));
- assert_eq_const_safe!($T::from_str_radix("Z", 36), Ok(35 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 10), Ok(123 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("1001", 2), Ok(9 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 8), Ok(83 as $T));
+ assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("123", 16), Ok(291 as i32));
+ assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("ffff", 16), Ok(65535 as i32));
+ assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("z", 36), Ok(35 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("Z", 36), Ok(35 as $T));
- assert_eq_const_safe!($T::from_str_radix("-123", 10), Ok(-123 as $T));
- assert_eq_const_safe!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
- assert_eq_const_safe!($T::from_str_radix("-123", 8), Ok(-83 as $T));
- assert_eq_const_safe!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
- assert_eq_const_safe!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
- assert_eq_const_safe!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
- assert_eq_const_safe!($T::from_str_radix("-z", 36), Ok(-35 as $T));
- assert_eq_const_safe!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-123", 10), Ok(-123 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-1001", 2), Ok(-9 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-123", 8), Ok(-83 as $T));
+ assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("-123", 16), Ok(-291 as i32));
+ assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
+ assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-z", 36), Ok(-35 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-Z", 36), Ok(-35 as $T));
assert!($T::from_str_radix("Z", 35).is_err());
assert!($T::from_str_radix("-9", 2).is_err());
@@ -277,16 +278,16 @@ fn test_from_str_radix() {
fn test_pow() {
{
const R: $T = 2;
- assert_eq_const_safe!(R.pow(2), 4 as $T);
- assert_eq_const_safe!(R.pow(0), 1 as $T);
- assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T);
- assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T);
- assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T));
- assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T));
- assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false));
- assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false));
- assert_eq_const_safe!(R.saturating_pow(2), 4 as $T);
- assert_eq_const_safe!(R.saturating_pow(0), 1 as $T);
+ assert_eq_const_safe!($T: R.pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.pow(0), 1 as $T);
+ assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T);
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T));
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T));
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false));
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false));
+ assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T);
}
{
@@ -295,221 +296,227 @@ fn test_pow() {
// if itest::MAX == 2^j-1, then itest is a `j` bit int,
// so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`,
// thussaturating_pow the overflowing result is exactly 1.
- assert_eq_const_safe!(R.wrapping_pow(2), 1 as $T);
- assert_eq_const_safe!(R.checked_pow(2), None);
- assert_eq_const_safe!(R.overflowing_pow(2), (1 as $T, true));
- assert_eq_const_safe!(R.saturating_pow(2), MAX);
+ assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T);
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None);
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true));
+ assert_eq_const_safe!($T: R.saturating_pow(2), MAX);
}
{
// test for negative exponent.
const R: $T = -2;
- assert_eq_const_safe!(R.pow(2), 4 as $T);
- assert_eq_const_safe!(R.pow(3), -8 as $T);
- assert_eq_const_safe!(R.pow(0), 1 as $T);
- assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T);
- assert_eq_const_safe!(R.wrapping_pow(3), -8 as $T);
- assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T);
- assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T));
- assert_eq_const_safe!(R.checked_pow(3), Some(-8 as $T));
- assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T));
- assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false));
- assert_eq_const_safe!(R.overflowing_pow(3), (-8 as $T, false));
- assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false));
- assert_eq_const_safe!(R.saturating_pow(2), 4 as $T);
- assert_eq_const_safe!(R.saturating_pow(3), -8 as $T);
- assert_eq_const_safe!(R.saturating_pow(0), 1 as $T);
+ assert_eq_const_safe!($T: R.pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.pow(3), -8 as $T);
+ assert_eq_const_safe!($T: R.pow(0), 1 as $T);
+ assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.wrapping_pow(3), -8 as $T);
+ assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T);
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T));
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(3), Some(-8 as $T));
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T));
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false));
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(3), (-8 as $T, false));
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false));
+ assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.saturating_pow(3), -8 as $T);
+ assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T);
}
}
fn test_div_floor() {
const A: $T = 8;
const B: $T = 3;
- assert_eq_const_safe!(A.div_floor(B), 2);
- assert_eq_const_safe!(A.div_floor(-B), -3);
- assert_eq_const_safe!((-A).div_floor(B), -3);
- assert_eq_const_safe!((-A).div_floor(-B), 2);
+ assert_eq_const_safe!($T: A.div_floor(B), 2);
+ assert_eq_const_safe!($T: A.div_floor(-B), -3);
+ assert_eq_const_safe!($T: (-A).div_floor(B), -3);
+ assert_eq_const_safe!($T: (-A).div_floor(-B), 2);
}
fn test_div_ceil() {
const A: $T = 8;
const B: $T = 3;
- assert_eq_const_safe!(A.div_ceil(B), 3);
- assert_eq_const_safe!(A.div_ceil(-B), -2);
- assert_eq_const_safe!((-A).div_ceil(B), -2);
- assert_eq_const_safe!((-A).div_ceil(-B), 3);
+ assert_eq_const_safe!($T: A.div_ceil(B), 3);
+ assert_eq_const_safe!($T: A.div_ceil(-B), -2);
+ assert_eq_const_safe!($T: (-A).div_ceil(B), -2);
+ assert_eq_const_safe!($T: (-A).div_ceil(-B), 3);
}
fn test_next_multiple_of() {
- assert_eq_const_safe!((16 as $T).next_multiple_of(8), 16);
- assert_eq_const_safe!((23 as $T).next_multiple_of(8), 24);
- assert_eq_const_safe!((16 as $T).next_multiple_of(-8), 16);
- assert_eq_const_safe!((23 as $T).next_multiple_of(-8), 16);
- assert_eq_const_safe!((-16 as $T).next_multiple_of(8), -16);
- assert_eq_const_safe!((-23 as $T).next_multiple_of(8), -16);
- assert_eq_const_safe!((-16 as $T).next_multiple_of(-8), -16);
- assert_eq_const_safe!((-23 as $T).next_multiple_of(-8), -24);
- assert_eq_const_safe!(MIN.next_multiple_of(-1), MIN);
+ assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16);
+ assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24);
+ assert_eq_const_safe!($T: (16 as $T).next_multiple_of(-8), 16);
+ assert_eq_const_safe!($T: (23 as $T).next_multiple_of(-8), 16);
+ assert_eq_const_safe!($T: (-16 as $T).next_multiple_of(8), -16);
+ assert_eq_const_safe!($T: (-23 as $T).next_multiple_of(8), -16);
+ assert_eq_const_safe!($T: (-16 as $T).next_multiple_of(-8), -16);
+ assert_eq_const_safe!($T: (-23 as $T).next_multiple_of(-8), -24);
+ assert_eq_const_safe!($T: MIN.next_multiple_of(-1), MIN);
}
fn test_checked_next_multiple_of() {
- assert_eq_const_safe!((16 as $T).checked_next_multiple_of(8), Some(16));
- assert_eq_const_safe!((23 as $T).checked_next_multiple_of(8), Some(24));
- assert_eq_const_safe!((16 as $T).checked_next_multiple_of(-8), Some(16));
- assert_eq_const_safe!((23 as $T).checked_next_multiple_of(-8), Some(16));
- assert_eq_const_safe!((-16 as $T).checked_next_multiple_of(8), Some(-16));
- assert_eq_const_safe!((-23 as $T).checked_next_multiple_of(8), Some(-16));
- assert_eq_const_safe!((-16 as $T).checked_next_multiple_of(-8), Some(-16));
- assert_eq_const_safe!((-23 as $T).checked_next_multiple_of(-8), Some(-24));
- assert_eq_const_safe!((1 as $T).checked_next_multiple_of(0), None);
- assert_eq_const_safe!(MAX.checked_next_multiple_of(2), None);
- assert_eq_const_safe!(MIN.checked_next_multiple_of(-3), None);
- assert_eq_const_safe!(MIN.checked_next_multiple_of(-1), Some(MIN));
+ assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16));
+ assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24));
+ assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(-8), Some(16));
+ assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(-8), Some(16));
+ assert_eq_const_safe!(Option<$T>: (-16 as $T).checked_next_multiple_of(8), Some(-16));
+ assert_eq_const_safe!(Option<$T>: (-23 as $T).checked_next_multiple_of(8), Some(-16));
+ assert_eq_const_safe!(Option<$T>: (-16 as $T).checked_next_multiple_of(-8), Some(-16));
+ assert_eq_const_safe!(Option<$T>: (-23 as $T).checked_next_multiple_of(-8), Some(-24));
+ assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None);
+ assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None);
+ assert_eq_const_safe!(Option<$T>: MIN.checked_next_multiple_of(-3), None);
+ assert_eq_const_safe!(Option<$T>: MIN.checked_next_multiple_of(-1), Some(MIN));
}
fn test_carrying_add() {
- assert_eq_const_safe!(MAX.carrying_add(1, false), (MIN, true));
- assert_eq_const_safe!(MAX.carrying_add(0, true), (MIN, true));
- assert_eq_const_safe!(MAX.carrying_add(1, true), (MIN + 1, true));
- assert_eq_const_safe!(MAX.carrying_add(-1, false), (MAX - 1, false));
- assert_eq_const_safe!(MAX.carrying_add(-1, true), (MAX, false)); // no intermediate overflow
- assert_eq_const_safe!(MIN.carrying_add(-1, false), (MAX, true));
- assert_eq_const_safe!(MIN.carrying_add(-1, true), (MIN, false)); // no intermediate overflow
- assert_eq_const_safe!((0 as $T).carrying_add(MAX, true), (MIN, true));
- assert_eq_const_safe!((0 as $T).carrying_add(MIN, true), (MIN + 1, false));
+ assert_eq_const_safe!(($T, bool): MAX.carrying_add(1, false), (MIN, true));
+ assert_eq_const_safe!(($T, bool): MAX.carrying_add(0, true), (MIN, true));
+ assert_eq_const_safe!(($T, bool): MAX.carrying_add(1, true), (MIN + 1, true));
+ assert_eq_const_safe!(($T, bool): MAX.carrying_add(-1, false), (MAX - 1, false));
+ assert_eq_const_safe!(($T, bool): MAX.carrying_add(-1, true), (MAX, false)); // no intermediate overflow
+ assert_eq_const_safe!(($T, bool): MIN.carrying_add(-1, false), (MAX, true));
+ assert_eq_const_safe!(($T, bool): MIN.carrying_add(-1, true), (MIN, false)); // no intermediate overflow
+ assert_eq_const_safe!(($T, bool): (0 as $T).carrying_add(MAX, true), (MIN, true));
+ assert_eq_const_safe!(($T, bool): (0 as $T).carrying_add(MIN, true), (MIN + 1, false));
}
fn test_borrowing_sub() {
- assert_eq_const_safe!(MIN.borrowing_sub(1, false), (MAX, true));
- assert_eq_const_safe!(MIN.borrowing_sub(0, true), (MAX, true));
- assert_eq_const_safe!(MIN.borrowing_sub(1, true), (MAX - 1, true));
- assert_eq_const_safe!(MIN.borrowing_sub(-1, false), (MIN + 1, false));
- assert_eq_const_safe!(MIN.borrowing_sub(-1, true), (MIN, false)); // no intermediate overflow
- assert_eq_const_safe!(MAX.borrowing_sub(-1, false), (MIN, true));
- assert_eq_const_safe!(MAX.borrowing_sub(-1, true), (MAX, false)); // no intermediate overflow
- assert_eq_const_safe!((0 as $T).borrowing_sub(MIN, false), (MIN, true));
- assert_eq_const_safe!((0 as $T).borrowing_sub(MIN, true), (MAX, false));
+ assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(1, false), (MAX, true));
+ assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(0, true), (MAX, true));
+ assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(1, true), (MAX - 1, true));
+ assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(-1, false), (MIN + 1, false));
+ assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(-1, true), (MIN, false)); // no intermediate overflow
+ assert_eq_const_safe!(($T, bool): MAX.borrowing_sub(-1, false), (MIN, true));
+ assert_eq_const_safe!(($T, bool): MAX.borrowing_sub(-1, true), (MAX, false)); // no intermediate overflow
+ assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, false), (MIN, true));
+ assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, true), (MAX, false));
}
fn test_widening_mul() {
- assert_eq_const_safe!(MAX.widening_mul(MAX), (1, MAX / 2));
- assert_eq_const_safe!(MIN.widening_mul(MAX), (MIN as $U, MIN / 2));
- assert_eq_const_safe!(MIN.widening_mul(MIN), (0, MAX / 2 + 1));
+ assert_eq_const_safe!(($U, $T): MAX.widening_mul(MAX), (1, MAX / 2));
+ assert_eq_const_safe!(($U, $T): MIN.widening_mul(MAX), (MIN as $U, MIN / 2));
+ assert_eq_const_safe!(($U, $T): MIN.widening_mul(MIN), (0, MAX / 2 + 1));
}
fn test_carrying_mul() {
- assert_eq_const_safe!(MAX.carrying_mul(MAX, 0), (1, MAX / 2));
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T): MAX.carrying_mul(MAX, 0), (1, MAX / 2));
+ assert_eq_const_safe!(($U, $T):
MAX.carrying_mul(MAX, MAX),
(UMAX / 2 + 1, MAX / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MAX.carrying_mul(MAX, MIN),
(UMAX / 2 + 2, MAX / 2 - 1)
);
- assert_eq_const_safe!(MIN.carrying_mul(MAX, 0), (MIN as $U, MIN / 2));
- assert_eq_const_safe!(MIN.carrying_mul(MAX, MAX), (UMAX, MIN / 2));
- assert_eq_const_safe!(MIN.carrying_mul(MAX, MIN), (0, MIN / 2));
- assert_eq_const_safe!(MIN.carrying_mul(MIN, 0), (0, MAX / 2 + 1));
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, 0), (MIN as $U, MIN / 2));
+ assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, MAX), (UMAX, MIN / 2));
+ assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, MIN), (0, MIN / 2));
+ assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MIN, 0), (0, MAX / 2 + 1));
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul(MIN, MAX),
(UMAX / 2, MAX / 2 + 1)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul(MIN, MIN),
(UMAX / 2 + 1, MAX / 2)
);
}
fn test_carrying_mul_add() {
- assert_eq_const_safe!(MAX.carrying_mul_add(MAX, 0, 0), (1, MAX / 2));
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, 0, 0), (1, MAX / 2));
+ assert_eq_const_safe!(($U, $T):
MAX.carrying_mul_add(MAX, MAX, 0),
(UMAX / 2 + 1, MAX / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MAX.carrying_mul_add(MAX, MIN, 0),
(UMAX / 2 + 2, MAX / 2 - 1)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MAX.carrying_mul_add(MAX, MAX, MAX),
(UMAX, MAX / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MAX.carrying_mul_add(MAX, MAX, MIN),
(0, MAX / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MAX.carrying_mul_add(MAX, MIN, MIN),
(1, MAX / 2 - 1)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MAX, 0, 0),
(MIN as $U, MIN / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MAX, MAX, 0),
(UMAX, MIN / 2)
);
- assert_eq_const_safe!(MIN.carrying_mul_add(MAX, MIN, 0), (0, MIN / 2));
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
+ MIN.carrying_mul_add(MAX, MIN, 0),
+ (0, MIN / 2)
+ );
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MAX, MAX, MAX),
(UMAX / 2 - 1, MIN / 2 + 1)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MAX, MAX, MIN),
(UMAX / 2, MIN / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MAX, MIN, MIN),
(UMAX / 2 + 1, MIN / 2 - 1)
);
- assert_eq_const_safe!(MIN.carrying_mul_add(MIN, 0, 0), (0, MAX / 2 + 1));
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
+ MIN.carrying_mul_add(MIN, 0, 0),
+ (0, MAX / 2 + 1)
+ );
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MIN, MAX, 0),
(UMAX / 2, MAX / 2 + 1)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MIN, MIN, 0),
(UMAX / 2 + 1, MAX / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MIN, MAX, MAX),
(UMAX - 1, MAX / 2 + 1)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MIN, MAX, MIN),
(UMAX, MAX / 2)
);
- assert_eq_const_safe!(
+ assert_eq_const_safe!(($U, $T):
MIN.carrying_mul_add(MIN, MIN, MIN),
(0, MAX / 2)
);
}
fn test_midpoint() {
- assert_eq_const_safe!(<$T>::midpoint(1, 3), 2);
- assert_eq_const_safe!(<$T>::midpoint(3, 1), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(1, 3), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(3, 1), 2);
- assert_eq_const_safe!(<$T>::midpoint(0, 0), 0);
- assert_eq_const_safe!(<$T>::midpoint(0, 2), 1);
- assert_eq_const_safe!(<$T>::midpoint(2, 0), 1);
- assert_eq_const_safe!(<$T>::midpoint(2, 2), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(0, 0), 0);
+ assert_eq_const_safe!($T: <$T>::midpoint(0, 2), 1);
+ assert_eq_const_safe!($T: <$T>::midpoint(2, 0), 1);
+ assert_eq_const_safe!($T: <$T>::midpoint(2, 2), 2);
- assert_eq_const_safe!(<$T>::midpoint(1, 4), 2);
- assert_eq_const_safe!(<$T>::midpoint(4, 1), 2);
- assert_eq_const_safe!(<$T>::midpoint(3, 4), 3);
- assert_eq_const_safe!(<$T>::midpoint(4, 3), 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(1, 4), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(4, 1), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(3, 4), 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(4, 3), 3);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), 0);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), 0);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MAX), 0);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MIN), 0);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
- assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3);
- assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3);
}
}
@@ -526,154 +533,154 @@ fn test_midpoint() {
test_runtime_and_compiletime! {
fn test_unbounded_shl() {
// <$T>::MIN
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
// <$T>::MAX
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
// 1
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, 1), (1 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, 3), (1 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, 5), (1 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 1), (1 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 3), (1 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 5), (1 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
// -1
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_ONE), (-1 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_TWO), (-1 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_THREE), (-1 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, 1), (-1 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, 3), (-1 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, 5), (-1 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_ONE), (-1 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_TWO), (-1 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_THREE), (-1 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 1), (-1 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 3), (-1 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 5), (-1 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW3), 0);
// 8
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, 1), (8 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, 3), (8 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, 5), (8 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 1), (8 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 3), (8 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 5), (8 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
// 17
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, 1), (17 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, 3), (17 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, 5), (17 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 1), (17 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 3), (17 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 5), (17 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
}
fn test_unbounded_shr() {
// <$T>::MIN
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), -1);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), -1);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), -1);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), -1);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), -1);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), -1);
// <$T>::MAX
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
// 1
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, 1), (1 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, 3), (1 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, 5), (1 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 1), (1 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 3), (1 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 5), (1 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
// -1
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_ONE), (-1 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_TWO), (-1 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_THREE), (-1 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, 1), (-1 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, 3), (-1 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, 5), (-1 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW2), -1);
- assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW3), -1);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_ONE), (-1 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_TWO), (-1 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_THREE), (-1 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 1), (-1 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 3), (-1 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 5), (-1 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW2), -1);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW3), -1);
// 8
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, 1), (8 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, 3), (8 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, 5), (8 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 1), (8 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 3), (8 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 5), (8 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
// 17
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, 1), (17 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, 3), (17 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, 5), (17 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 1), (17 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 3), (17 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 5), (17 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
}
}
};
diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs
index d09eb97..2e35e8b 100644
--- a/library/coretests/tests/num/uint_macros.rs
+++ b/library/coretests/tests/num/uint_macros.rs
@@ -1,5 +1,6 @@
macro_rules! uint_module {
($T:ident) => {
+ use core::num::ParseIntError;
use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
use core::$T::*;
@@ -49,95 +50,95 @@ fn test_count_zeros() {
fn test_leading_trailing_ones() {
const A: $T = 0b0101_1111;
- assert_eq_const_safe!(A.trailing_ones(), 5);
- assert_eq_const_safe!((!A).leading_ones(), $T::BITS - 7);
+ assert_eq_const_safe!(u32: A.trailing_ones(), 5);
+ assert_eq_const_safe!(u32: (!A).leading_ones(), $T::BITS - 7);
- assert_eq_const_safe!(A.reverse_bits().leading_ones(), 5);
+ assert_eq_const_safe!(u32: A.reverse_bits().leading_ones(), 5);
- assert_eq_const_safe!(_1.leading_ones(), $T::BITS);
- assert_eq_const_safe!(_1.trailing_ones(), $T::BITS);
+ assert_eq_const_safe!(u32: _1.leading_ones(), $T::BITS);
+ assert_eq_const_safe!(u32: _1.trailing_ones(), $T::BITS);
- assert_eq_const_safe!((_1 << 1).trailing_ones(), 0);
- assert_eq_const_safe!((_1 >> 1).leading_ones(), 0);
+ assert_eq_const_safe!(u32: (_1 << 1).trailing_ones(), 0);
+ assert_eq_const_safe!(u32: (_1 >> 1).leading_ones(), 0);
- assert_eq_const_safe!((_1 << 1).leading_ones(), $T::BITS - 1);
- assert_eq_const_safe!((_1 >> 1).trailing_ones(), $T::BITS - 1);
+ assert_eq_const_safe!(u32: (_1 << 1).leading_ones(), $T::BITS - 1);
+ assert_eq_const_safe!(u32: (_1 >> 1).trailing_ones(), $T::BITS - 1);
- assert_eq_const_safe!(_0.leading_ones(), 0);
- assert_eq_const_safe!(_0.trailing_ones(), 0);
+ assert_eq_const_safe!(u32: _0.leading_ones(), 0);
+ assert_eq_const_safe!(u32: _0.trailing_ones(), 0);
const X: $T = 0b0010_1100;
- assert_eq_const_safe!(X.leading_ones(), 0);
- assert_eq_const_safe!(X.trailing_ones(), 0);
+ assert_eq_const_safe!(u32: X.leading_ones(), 0);
+ assert_eq_const_safe!(u32: X.trailing_ones(), 0);
}
fn test_rotate() {
- assert_eq_const_safe!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
- assert_eq_const_safe!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
- assert_eq_const_safe!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+ assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+ assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+ assert_eq_const_safe!($T: C.rotate_left(6).rotate_right(2).rotate_right(4), C);
// Rotating these should make no difference
//
// We test using 124 bits because to ensure that overlong bit shifts do
// not cause undefined behavior. See #10183.
- assert_eq_const_safe!(_0.rotate_left(124), _0);
- assert_eq_const_safe!(_1.rotate_left(124), _1);
- assert_eq_const_safe!(_0.rotate_right(124), _0);
- assert_eq_const_safe!(_1.rotate_right(124), _1);
+ assert_eq_const_safe!($T: _0.rotate_left(124), _0);
+ assert_eq_const_safe!($T: _1.rotate_left(124), _1);
+ assert_eq_const_safe!($T: _0.rotate_right(124), _0);
+ assert_eq_const_safe!($T: _1.rotate_right(124), _1);
// Rotating by 0 should have no effect
- assert_eq_const_safe!(A.rotate_left(0), A);
- assert_eq_const_safe!(B.rotate_left(0), B);
- assert_eq_const_safe!(C.rotate_left(0), C);
+ assert_eq_const_safe!($T: A.rotate_left(0), A);
+ assert_eq_const_safe!($T: B.rotate_left(0), B);
+ assert_eq_const_safe!($T: C.rotate_left(0), C);
// Rotating by a multiple of word size should also have no effect
- assert_eq_const_safe!(A.rotate_left(128), A);
- assert_eq_const_safe!(B.rotate_left(128), B);
- assert_eq_const_safe!(C.rotate_left(128), C);
+ assert_eq_const_safe!($T: A.rotate_left(128), A);
+ assert_eq_const_safe!($T: B.rotate_left(128), B);
+ assert_eq_const_safe!($T: C.rotate_left(128), C);
}
fn test_swap_bytes() {
- assert_eq_const_safe!(A.swap_bytes().swap_bytes(), A);
- assert_eq_const_safe!(B.swap_bytes().swap_bytes(), B);
- assert_eq_const_safe!(C.swap_bytes().swap_bytes(), C);
+ assert_eq_const_safe!($T: A.swap_bytes().swap_bytes(), A);
+ assert_eq_const_safe!($T: B.swap_bytes().swap_bytes(), B);
+ assert_eq_const_safe!($T: C.swap_bytes().swap_bytes(), C);
// Swapping these should make no difference
- assert_eq_const_safe!(_0.swap_bytes(), _0);
- assert_eq_const_safe!(_1.swap_bytes(), _1);
+ assert_eq_const_safe!($T: _0.swap_bytes(), _0);
+ assert_eq_const_safe!($T: _1.swap_bytes(), _1);
}
fn test_reverse_bits() {
- assert_eq_const_safe!(A.reverse_bits().reverse_bits(), A);
- assert_eq_const_safe!(B.reverse_bits().reverse_bits(), B);
- assert_eq_const_safe!(C.reverse_bits().reverse_bits(), C);
+ assert_eq_const_safe!($T: A.reverse_bits().reverse_bits(), A);
+ assert_eq_const_safe!($T: B.reverse_bits().reverse_bits(), B);
+ assert_eq_const_safe!($T: C.reverse_bits().reverse_bits(), C);
// Swapping these should make no difference
- assert_eq_const_safe!(_0.reverse_bits(), _0);
- assert_eq_const_safe!(_1.reverse_bits(), _1);
+ assert_eq_const_safe!($T: _0.reverse_bits(), _0);
+ assert_eq_const_safe!($T: _1.reverse_bits(), _1);
}
fn test_le() {
- assert_eq_const_safe!($T::from_le(A.to_le()), A);
- assert_eq_const_safe!($T::from_le(B.to_le()), B);
- assert_eq_const_safe!($T::from_le(C.to_le()), C);
- assert_eq_const_safe!($T::from_le(_0), _0);
- assert_eq_const_safe!($T::from_le(_1), _1);
- assert_eq_const_safe!(_0.to_le(), _0);
- assert_eq_const_safe!(_1.to_le(), _1);
+ assert_eq_const_safe!($T: $T::from_le(A.to_le()), A);
+ assert_eq_const_safe!($T: $T::from_le(B.to_le()), B);
+ assert_eq_const_safe!($T: $T::from_le(C.to_le()), C);
+ assert_eq_const_safe!($T: $T::from_le(_0), _0);
+ assert_eq_const_safe!($T: $T::from_le(_1), _1);
+ assert_eq_const_safe!($T: _0.to_le(), _0);
+ assert_eq_const_safe!($T: _1.to_le(), _1);
}
fn test_be() {
- assert_eq_const_safe!($T::from_be(A.to_be()), A);
- assert_eq_const_safe!($T::from_be(B.to_be()), B);
- assert_eq_const_safe!($T::from_be(C.to_be()), C);
- assert_eq_const_safe!($T::from_be(_0), _0);
- assert_eq_const_safe!($T::from_be(_1), _1);
- assert_eq_const_safe!(_0.to_be(), _0);
- assert_eq_const_safe!(_1.to_be(), _1);
+ assert_eq_const_safe!($T: $T::from_be(A.to_be()), A);
+ assert_eq_const_safe!($T: $T::from_be(B.to_be()), B);
+ assert_eq_const_safe!($T: $T::from_be(C.to_be()), C);
+ assert_eq_const_safe!($T: $T::from_be(_0), _0);
+ assert_eq_const_safe!($T: $T::from_be(_1), _1);
+ assert_eq_const_safe!($T: _0.to_be(), _0);
+ assert_eq_const_safe!($T: _1.to_be(), _1);
}
fn test_unsigned_checked_div() {
- assert_eq_const_safe!((10 as $T).checked_div(2), Some(5));
- assert_eq_const_safe!((5 as $T).checked_div(0), None);
+ assert_eq_const_safe!(Option<$T>: (10 as $T).checked_div(2), Some(5));
+ assert_eq_const_safe!(Option<$T>: (5 as $T).checked_div(0), None);
}
}
@@ -194,12 +195,12 @@ pub fn test_from_str() {
test_runtime_and_compiletime! {
fn test_parse_bytes() {
- assert_eq_const_safe!($T::from_str_radix("123", 10), Ok(123 as $T));
- assert_eq_const_safe!($T::from_str_radix("1001", 2), Ok(9 as $T));
- assert_eq_const_safe!($T::from_str_radix("123", 8), Ok(83 as $T));
- assert_eq_const_safe!(u16::from_str_radix("123", 16), Ok(291 as u16));
- assert_eq_const_safe!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
- assert_eq_const_safe!($T::from_str_radix("z", 36), Ok(35 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 10), Ok(123 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("1001", 2), Ok(9 as $T));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 8), Ok(83 as $T));
+ assert_eq_const_safe!(Result<u16, ParseIntError>: u16::from_str_radix("123", 16), Ok(291 as u16));
+ assert_eq_const_safe!(Result<u16, ParseIntError>: u16::from_str_radix("ffff", 16), Ok(65535 as u16));
+ assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("z", 36), Ok(35 as $T));
assert!($T::from_str_radix("Z", 10).is_err());
assert!($T::from_str_radix("_", 2).is_err());
@@ -208,16 +209,16 @@ fn test_parse_bytes() {
fn test_pow() {
{
const R: $T = 2;
- assert_eq_const_safe!(R.pow(2), 4 as $T);
- assert_eq_const_safe!(R.pow(0), 1 as $T);
- assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T);
- assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T);
- assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T));
- assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T));
- assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false));
- assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false));
- assert_eq_const_safe!(R.saturating_pow(2), 4 as $T);
- assert_eq_const_safe!(R.saturating_pow(0), 1 as $T);
+ assert_eq_const_safe!($T: R.pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.pow(0), 1 as $T);
+ assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T);
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T));
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T));
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false));
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false));
+ assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T);
+ assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T);
}
{
@@ -226,20 +227,20 @@ fn test_pow() {
// if itest::MAX == 2^j-1, then itest is a `j` bit int,
// so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`,
// thussaturating_pow the overflowing result is exactly 1.
- assert_eq_const_safe!(R.wrapping_pow(2), 1 as $T);
- assert_eq_const_safe!(R.checked_pow(2), None);
- assert_eq_const_safe!(R.overflowing_pow(2), (1 as $T, true));
- assert_eq_const_safe!(R.saturating_pow(2), MAX);
+ assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T);
+ assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None);
+ assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true));
+ assert_eq_const_safe!($T: R.saturating_pow(2), MAX);
}
}
fn test_isqrt() {
- assert_eq_const_safe!((0 as $T).isqrt(), 0 as $T);
- assert_eq_const_safe!((1 as $T).isqrt(), 1 as $T);
- assert_eq_const_safe!((2 as $T).isqrt(), 1 as $T);
- assert_eq_const_safe!((99 as $T).isqrt(), 9 as $T);
- assert_eq_const_safe!((100 as $T).isqrt(), 10 as $T);
- assert_eq_const_safe!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1);
+ assert_eq_const_safe!($T: (0 as $T).isqrt(), 0 as $T);
+ assert_eq_const_safe!($T: (1 as $T).isqrt(), 1 as $T);
+ assert_eq_const_safe!($T: (2 as $T).isqrt(), 1 as $T);
+ assert_eq_const_safe!($T: (99 as $T).isqrt(), 9 as $T);
+ assert_eq_const_safe!($T: (100 as $T).isqrt(), 10 as $T);
+ assert_eq_const_safe!($T: $T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1);
}
}
@@ -264,24 +265,24 @@ fn test_lots_of_isqrt() {
test_runtime_and_compiletime! {
fn test_div_floor() {
- assert_eq_const_safe!((8 as $T).div_floor(3), 2);
+ assert_eq_const_safe!($T: (8 as $T).div_floor(3), 2);
}
fn test_div_ceil() {
- assert_eq_const_safe!((8 as $T).div_ceil(3), 3);
+ assert_eq_const_safe!($T: (8 as $T).div_ceil(3), 3);
}
fn test_next_multiple_of() {
- assert_eq_const_safe!((16 as $T).next_multiple_of(8), 16);
- assert_eq_const_safe!((23 as $T).next_multiple_of(8), 24);
- assert_eq_const_safe!(MAX.next_multiple_of(1), MAX);
+ assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16);
+ assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24);
+ assert_eq_const_safe!($T: MAX.next_multiple_of(1), MAX);
}
fn test_checked_next_multiple_of() {
- assert_eq_const_safe!((16 as $T).checked_next_multiple_of(8), Some(16));
- assert_eq_const_safe!((23 as $T).checked_next_multiple_of(8), Some(24));
- assert_eq_const_safe!((1 as $T).checked_next_multiple_of(0), None);
- assert_eq_const_safe!(MAX.checked_next_multiple_of(2), None);
+ assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16));
+ assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24));
+ assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None);
+ assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None);
}
fn test_is_next_multiple_of() {
@@ -292,63 +293,63 @@ fn test_is_next_multiple_of() {
}
fn test_carrying_add() {
- assert_eq_const_safe!($T::MAX.carrying_add(1, false), (0, true));
- assert_eq_const_safe!($T::MAX.carrying_add(0, true), (0, true));
- assert_eq_const_safe!($T::MAX.carrying_add(1, true), (1, true));
+ assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(1, false), (0, true));
+ assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(0, true), (0, true));
+ assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(1, true), (1, true));
- assert_eq_const_safe!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false));
- assert_eq_const_safe!($T::MIN.carrying_add(0, true), (1, false));
- assert_eq_const_safe!($T::MIN.carrying_add($T::MAX, true), (0, true));
+ assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add($T::MAX, false), ($T::MAX, false));
+ assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add(0, true), (1, false));
+ assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add($T::MAX, true), (0, true));
}
fn test_borrowing_sub() {
- assert_eq_const_safe!($T::MIN.borrowing_sub(1, false), ($T::MAX, true));
- assert_eq_const_safe!($T::MIN.borrowing_sub(0, true), ($T::MAX, true));
- assert_eq_const_safe!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true));
+ assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(1, false), ($T::MAX, true));
+ assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(0, true), ($T::MAX, true));
+ assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true));
- assert_eq_const_safe!($T::MAX.borrowing_sub($T::MAX, false), (0, false));
- assert_eq_const_safe!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false));
- assert_eq_const_safe!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
+ assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, false), (0, false));
+ assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false));
+ assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
}
fn test_widening_mul() {
- assert_eq_const_safe!($T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1));
+ assert_eq_const_safe!(($T, $T): $T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1));
}
fn test_carrying_mul() {
- assert_eq_const_safe!($T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1));
- assert_eq_const_safe!($T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX));
+ assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1));
+ assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX));
}
fn test_carrying_mul_add() {
- assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, 0, 0), (1, $T::MAX - 1));
- assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, $T::MAX, 0), (0, $T::MAX));
- assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, $T::MAX, $T::MAX), ($T::MAX, $T::MAX));
+ assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, 0, 0), (1, $T::MAX - 1));
+ assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, $T::MAX, 0), (0, $T::MAX));
+ assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, $T::MAX, $T::MAX), ($T::MAX, $T::MAX));
}
fn test_midpoint() {
- assert_eq_const_safe!(<$T>::midpoint(1, 3), 2);
- assert_eq_const_safe!(<$T>::midpoint(3, 1), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(1, 3), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(3, 1), 2);
- assert_eq_const_safe!(<$T>::midpoint(0, 0), 0);
- assert_eq_const_safe!(<$T>::midpoint(0, 2), 1);
- assert_eq_const_safe!(<$T>::midpoint(2, 0), 1);
- assert_eq_const_safe!(<$T>::midpoint(2, 2), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(0, 0), 0);
+ assert_eq_const_safe!($T: <$T>::midpoint(0, 2), 1);
+ assert_eq_const_safe!($T: <$T>::midpoint(2, 0), 1);
+ assert_eq_const_safe!($T: <$T>::midpoint(2, 2), 2);
- assert_eq_const_safe!(<$T>::midpoint(1, 4), 2);
- assert_eq_const_safe!(<$T>::midpoint(4, 1), 2);
- assert_eq_const_safe!(<$T>::midpoint(3, 4), 3);
- assert_eq_const_safe!(<$T>::midpoint(4, 3), 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(1, 4), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(4, 1), 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(3, 4), 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(4, 3), 3);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
- assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
- assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3);
- assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+ assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3);
}
}
@@ -365,154 +366,154 @@ fn test_midpoint() {
test_runtime_and_compiletime! {
fn test_unbounded_shl() {
// <$T>::MIN
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
// <$T>::MAX
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
// 1
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, 1), (1 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, 3), (1 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, 5), (1 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 1), (1 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 3), (1 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 5), (1 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
// !0
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_ONE), (!0 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_TWO), (!0 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_THREE), (!0 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, 1), (!0 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, 3), (!0 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, 5), (!0 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_ONE), (!0 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_TWO), (!0 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_THREE), (!0 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 1), (!0 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 3), (!0 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 5), (!0 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
// 8
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, 1), (8 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, 3), (8 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, 5), (8 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 1), (8 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 3), (8 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 5), (8 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
// 17
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, 1), (17 << 1));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, 3), (17 << 3));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, 5), (17 << 5));
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 1), (17 << 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 3), (17 << 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 5), (17 << 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
}
fn test_unbounded_shr() {
// <$T>::MIN
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
// <$T>::MAX
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
// 1
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, 1), (1 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, 3), (1 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, 5), (1 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 1), (1 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 3), (1 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 5), (1 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
// !0
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_ONE), (!0 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_TWO), (!0 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_THREE), (!0 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, 1), (!0 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, 3), (!0 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, 5), (!0 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_ONE), (!0 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_TWO), (!0 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_THREE), (!0 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 1), (!0 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 3), (!0 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 5), (!0 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
// 8
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, 1), (8 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, 3), (8 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, 5), (8 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 1), (8 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 3), (8 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 5), (8 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
// 17
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, 1), (17 >> 1));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, 3), (17 >> 3));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, 5), (17 >> 5));
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
- assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 1), (17 >> 1));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 3), (17 >> 3));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 5), (17 >> 5));
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+ assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
}
}
};
diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs
index a866cf1..b3fb06e 100644
--- a/library/coretests/tests/pin.rs
+++ b/library/coretests/tests/pin.rs
@@ -34,9 +34,6 @@ const fn pin_mut_const() {
}
pin_mut_const();
-
- // Check that we accept a Rust 2024 $expr.
- std::pin::pin!(const { 1 });
}
#[allow(unused)]
@@ -84,14 +81,3 @@ pub fn nesting_pins(arg: Pin<Pin<&String>>) -> Pin<Pin<&dyn MyTrait>> {
arg
}
}
-
-#[test]
-#[cfg(not(bootstrap))]
-fn temp_lifetime() {
- // Check that temporary lifetimes work as in Rust 2021.
- // Regression test for https://github.com/rust-lang/rust/issues/138596
- match std::pin::pin!(foo(&mut 0)) {
- _ => {}
- }
- async fn foo(_: &mut usize) {}
-}
diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs
index 4354239..3174c91 100644
--- a/library/coretests/tests/pin_macro.rs
+++ b/library/coretests/tests/pin_macro.rs
@@ -30,3 +30,31 @@ fn unsize_coercion() {
let dyn_obj: Pin<&mut dyn Send> = pin!([PhantomPinned; 2]);
stuff(dyn_obj);
}
+
+#[test]
+fn rust_2024_expr() {
+ // Check that we accept a Rust 2024 $expr.
+ std::pin::pin!(const { 1 });
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn temp_lifetime() {
+ // Check that temporary lifetimes work as in Rust 2021.
+ // Regression test for https://github.com/rust-lang/rust/issues/138596
+ match std::pin::pin!(foo(&mut 0)) {
+ _ => {}
+ }
+ async fn foo(_: &mut usize) {}
+}
+
+#[test]
+fn transitive_extension() {
+ async fn temporary() {}
+
+ // `pin!` witnessed in the wild being used like this, even if it yields
+ // a `Pin<&mut &mut impl Unpin>`; it does work because `pin!`
+ // happens to transitively extend the lifespan of `temporary()`.
+ let p = pin!(&mut temporary());
+ let _use = p;
+}
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index fa98db6..801baf3 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2370,7 +2370,7 @@ fn as_inner(&self) -> &fs_imp::DirEntry {
#[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
- fs_imp::unlink(path.as_ref())
+ fs_imp::remove_file(path.as_ref())
}
/// Given a path, queries the file system to get information about a file,
@@ -2409,7 +2409,7 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
#[doc(alias = "stat")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
- fs_imp::stat(path.as_ref()).map(Metadata)
+ fs_imp::metadata(path.as_ref()).map(Metadata)
}
/// Queries the metadata about a file without following symlinks.
@@ -2444,7 +2444,7 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
#[doc(alias = "lstat")]
#[stable(feature = "symlink_metadata", since = "1.1.0")]
pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
- fs_imp::lstat(path.as_ref()).map(Metadata)
+ fs_imp::symlink_metadata(path.as_ref()).map(Metadata)
}
/// Renames a file or directory to a new name, replacing the original file if
@@ -2598,7 +2598,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
#[doc(alias = "CreateHardLink", alias = "linkat")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
- fs_imp::link(original.as_ref(), link.as_ref())
+ fs_imp::hard_link(original.as_ref(), link.as_ref())
}
/// Creates a new symbolic link on the filesystem.
@@ -2664,7 +2664,7 @@ pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Re
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
- fs_imp::readlink(path.as_ref())
+ fs_imp::read_link(path.as_ref())
}
/// Returns the canonical, absolute form of a path with all intermediate
@@ -2840,7 +2840,7 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
#[doc(alias = "rmdir", alias = "RemoveDirectory")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
- fs_imp::rmdir(path.as_ref())
+ fs_imp::remove_dir(path.as_ref())
}
/// Removes a directory at this path, after removing all its contents. Use
@@ -2967,7 +2967,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
#[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
- fs_imp::readdir(path.as_ref()).map(ReadDir)
+ fs_imp::read_dir(path.as_ref()).map(ReadDir)
}
/// Changes the permissions found on a file or a directory.
@@ -3003,7 +3003,7 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
#[doc(alias = "chmod", alias = "SetFileAttributes")]
#[stable(feature = "set_permissions", since = "1.1.0")]
pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
- fs_imp::set_perm(path.as_ref(), perm.0)
+ fs_imp::set_permissions(path.as_ref(), perm.0)
}
impl DirBuilder {
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 6579b68..314cbb4 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2989,11 +2989,11 @@ fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> Result<()> {
return Ok(());
}
- if self.limit <= buf.capacity() as u64 {
- // if we just use an as cast to convert, limit may wrap around on a 32 bit target
- let limit = cmp::min(self.limit, usize::MAX as u64) as usize;
+ if self.limit < buf.capacity() as u64 {
+ // The condition above guarantees that `self.limit` fits in `usize`.
+ let limit = self.limit as usize;
- let extra_init = cmp::min(limit as usize, buf.init_ref().len());
+ let extra_init = cmp::min(limit, buf.init_ref().len());
// SAFETY: no uninit data is written to ibuf
let ibuf = unsafe { &mut buf.as_mut()[..limit] };
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ad00583..9dcedaa 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -297,6 +297,7 @@
#![feature(extended_varargs_abi_support)]
#![feature(f128)]
#![feature(f16)]
+#![feature(ffi_const)]
#![feature(formatting_options)]
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index f81ce8e..3b765a9 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1836,7 +1836,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
/// # if cfg!(unix) {
/// use std::process::{Command, ExitStatusError};
///
-/// fn run(cmd: &str) -> Result<(),ExitStatusError> {
+/// fn run(cmd: &str) -> Result<(), ExitStatusError> {
/// Command::new(cmd).status().unwrap().exit_ok()?;
/// Ok(())
/// }
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 5b50a3c..e67b4f6 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -176,6 +176,8 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::sync::atomic;
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+pub use alloc_crate::sync::UniqueArc;
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::sync::{Arc, Weak};
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index c2e19eb..3b176d0 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -1,28 +1,115 @@
#![deny(unsafe_op_in_unsafe_fn)]
+use crate::io;
+use crate::path::{Path, PathBuf};
+
pub mod common;
cfg_if::cfg_if! {
if #[cfg(target_family = "unix")] {
mod unix;
- pub use unix::*;
+ use unix as imp;
+ pub use unix::{chown, fchown, lchown};
+ #[cfg(not(target_os = "fuchsia"))]
+ pub use unix::chroot;
+ pub(crate) use unix::debug_assert_fd_is_open;
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ pub(crate) use unix::CachedFileMetadata;
+ use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path;
} else if #[cfg(target_os = "windows")] {
mod windows;
- pub use windows::*;
+ use windows as imp;
+ pub use windows::{symlink_inner, junction_point};
} else if #[cfg(target_os = "hermit")] {
mod hermit;
- pub use hermit::*;
+ use hermit as imp;
} else if #[cfg(target_os = "solid_asp3")] {
mod solid;
- pub use solid::*;
+ use solid as imp;
} else if #[cfg(target_os = "uefi")] {
mod uefi;
- pub use uefi::*;
+ use uefi as imp;
} else if #[cfg(target_os = "wasi")] {
mod wasi;
- pub use wasi::*;
+ use wasi as imp;
} else {
mod unsupported;
- pub use unsupported::*;
+ use unsupported as imp;
}
}
+
+// FIXME: Replace this with platform-specific path conversion functions.
+#[cfg(not(target_family = "unix"))]
+#[inline]
+pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
+ f(path)
+}
+
+pub use imp::{
+ DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
+ ReadDir,
+};
+
+pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
+ // FIXME: use with_native_path
+ imp::readdir(path)
+}
+
+pub fn remove_file(path: &Path) -> io::Result<()> {
+ with_native_path(path, &imp::unlink)
+}
+
+pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
+ with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new)))
+}
+
+pub fn remove_dir(path: &Path) -> io::Result<()> {
+ with_native_path(path, &imp::rmdir)
+}
+
+pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+ // FIXME: use with_native_path
+ imp::remove_dir_all(path)
+}
+
+pub fn read_link(path: &Path) -> io::Result<PathBuf> {
+ with_native_path(path, &imp::readlink)
+}
+
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+ with_native_path(original, &|original| {
+ with_native_path(link, &|link| imp::symlink(original, link))
+ })
+}
+
+pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> {
+ with_native_path(original, &|original| {
+ with_native_path(link, &|link| imp::link(original, link))
+ })
+}
+
+pub fn metadata(path: &Path) -> io::Result<FileAttr> {
+ with_native_path(path, &imp::stat)
+}
+
+pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
+ with_native_path(path, &imp::lstat)
+}
+
+pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
+ with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
+}
+
+pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
+ with_native_path(path, &imp::canonicalize)
+}
+
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+ // FIXME: use with_native_path
+ imp::copy(from, to)
+}
+
+pub fn exists(path: &Path) -> io::Result<bool> {
+ // FIXME: use with_native_path
+ imp::exists(path)
+}
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index 7c3ed80..87865be 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -155,15 +155,15 @@ unsafe fn try_statx(
enum STATX_STATE{ Unknown = 0, Present, Unavailable }
static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8);
- syscall! {
+ syscall!(
fn statx(
fd: c_int,
pathname: *const c_char,
flags: c_int,
mask: libc::c_uint,
- statxbuf: *mut libc::statx
- ) -> c_int
- }
+ statxbuf: *mut libc::statx,
+ ) -> c_int;
+ );
let statx_availability = STATX_SAVED_STATE.load(Ordering::Relaxed);
if statx_availability == STATX_STATE::Unavailable as u8 {
@@ -926,7 +926,7 @@ pub fn metadata(&self) -> io::Result<FileAttr> {
miri
))]
pub fn metadata(&self) -> io::Result<FileAttr> {
- lstat(&self.path())
+ run_path_with_cstr(&self.path(), &lstat)
}
#[cfg(any(
@@ -1540,7 +1540,9 @@ pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
// futimens requires Android API level 19
cvt(unsafe {
- weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
+ weak!(
+ fn futimens(fd: c_int, times: *const libc::timespec) -> c_int;
+ );
match futimens.get() {
Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
None => return Err(io::const_error!(
@@ -1556,7 +1558,9 @@ pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
use crate::sys::{time::__timespec64, weak::weak};
// Added in glibc 2.34
- weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int);
+ weak!(
+ fn __futimens64(fd: c_int, times: *const __timespec64) -> c_int;
+ );
if let Some(futimens64) = __futimens64.get() {
let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64())
@@ -1653,7 +1657,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn get_path(fd: c_int) -> Option<PathBuf> {
let mut p = PathBuf::from("/proc/self/fd");
p.push(&fd.to_string());
- readlink(&p).ok()
+ run_path_with_cstr(&p, &readlink).ok()
}
#[cfg(any(target_vendor = "apple", target_os = "netbsd"))]
@@ -1671,7 +1675,7 @@ fn get_path(fd: c_int) -> Option<PathBuf> {
// fallback to procfs as last resort
let mut p = PathBuf::from("/proc/self/fd");
p.push(&fd.to_string());
- return readlink(&p).ok();
+ return run_path_with_cstr(&p, &readlink).ok()
} else {
return None;
}
@@ -1826,127 +1830,106 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
}
}
-pub fn unlink(p: &Path) -> io::Result<()> {
- run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()))
+pub fn unlink(p: &CStr) -> io::Result<()> {
+ cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())
}
-pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
- run_path_with_cstr(old, &|old| {
- run_path_with_cstr(new, &|new| {
- cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
- })
- })
+pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> {
+ cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
}
-pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
- run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()))
+pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> {
+ cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())
}
-pub fn rmdir(p: &Path) -> io::Result<()> {
- run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()))
+pub fn rmdir(p: &CStr) -> io::Result<()> {
+ cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())
}
-pub fn readlink(p: &Path) -> io::Result<PathBuf> {
- run_path_with_cstr(p, &|c_path| {
- let p = c_path.as_ptr();
+pub fn readlink(c_path: &CStr) -> io::Result<PathBuf> {
+ let p = c_path.as_ptr();
- let mut buf = Vec::with_capacity(256);
+ let mut buf = Vec::with_capacity(256);
- loop {
- let buf_read =
- cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })?
- as usize;
+ loop {
+ let buf_read =
+ cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize;
- unsafe {
- buf.set_len(buf_read);
- }
-
- if buf_read != buf.capacity() {
- buf.shrink_to_fit();
-
- return Ok(PathBuf::from(OsString::from_vec(buf)));
- }
-
- // Trigger the internal buffer resizing logic of `Vec` by requiring
- // more space than the current capacity. The length is guaranteed to be
- // the same as the capacity due to the if statement above.
- buf.reserve(1);
- }
- })
-}
-
-pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
- run_path_with_cstr(original, &|original| {
- run_path_with_cstr(link, &|link| {
- cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
- })
- })
-}
-
-pub fn link(original: &Path, link: &Path) -> io::Result<()> {
- run_path_with_cstr(original, &|original| {
- run_path_with_cstr(link, &|link| {
- cfg_if::cfg_if! {
- if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] {
- // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
- // it implementation-defined whether `link` follows symlinks, so rely on the
- // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
- // Android has `linkat` on newer versions, but we happen to know `link`
- // always has the correct behavior, so it's here as well.
- cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
- } else {
- // Where we can, use `linkat` instead of `link`; see the comment above
- // this one for details on why.
- cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
- }
- }
- Ok(())
- })
- })
-}
-
-pub fn stat(p: &Path) -> io::Result<FileAttr> {
- run_path_with_cstr(p, &|p| {
- cfg_has_statx! {
- if let Some(ret) = unsafe { try_statx(
- libc::AT_FDCWD,
- p.as_ptr(),
- libc::AT_STATX_SYNC_AS_STAT,
- libc::STATX_BASIC_STATS | libc::STATX_BTIME,
- ) } {
- return ret;
- }
+ unsafe {
+ buf.set_len(buf_read);
}
- let mut stat: stat64 = unsafe { mem::zeroed() };
- cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
- Ok(FileAttr::from_stat64(stat))
- })
-}
+ if buf_read != buf.capacity() {
+ buf.shrink_to_fit();
-pub fn lstat(p: &Path) -> io::Result<FileAttr> {
- run_path_with_cstr(p, &|p| {
- cfg_has_statx! {
- if let Some(ret) = unsafe { try_statx(
- libc::AT_FDCWD,
- p.as_ptr(),
- libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
- libc::STATX_BASIC_STATS | libc::STATX_BTIME,
- ) } {
- return ret;
- }
+ return Ok(PathBuf::from(OsString::from_vec(buf)));
}
- let mut stat: stat64 = unsafe { mem::zeroed() };
- cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
- Ok(FileAttr::from_stat64(stat))
- })
+ // Trigger the internal buffer resizing logic of `Vec` by requiring
+ // more space than the current capacity. The length is guaranteed to be
+ // the same as the capacity due to the if statement above.
+ buf.reserve(1);
+ }
}
-pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
- let r = run_path_with_cstr(p, &|path| unsafe {
- Ok(libc::realpath(path.as_ptr(), ptr::null_mut()))
- })?;
+pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> {
+ cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
+}
+
+pub fn link(original: &CStr, link: &CStr) -> io::Result<()> {
+ cfg_if::cfg_if! {
+ if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] {
+ // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
+ // it implementation-defined whether `link` follows symlinks, so rely on the
+ // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
+ // Android has `linkat` on newer versions, but we happen to know `link`
+ // always has the correct behavior, so it's here as well.
+ cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+ } else {
+ // Where we can, use `linkat` instead of `link`; see the comment above
+ // this one for details on why.
+ cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
+ }
+ }
+ Ok(())
+}
+
+pub fn stat(p: &CStr) -> io::Result<FileAttr> {
+ cfg_has_statx! {
+ if let Some(ret) = unsafe { try_statx(
+ libc::AT_FDCWD,
+ p.as_ptr(),
+ libc::AT_STATX_SYNC_AS_STAT,
+ libc::STATX_BASIC_STATS | libc::STATX_BTIME,
+ ) } {
+ return ret;
+ }
+ }
+
+ let mut stat: stat64 = unsafe { mem::zeroed() };
+ cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
+ Ok(FileAttr::from_stat64(stat))
+}
+
+pub fn lstat(p: &CStr) -> io::Result<FileAttr> {
+ cfg_has_statx! {
+ if let Some(ret) = unsafe { try_statx(
+ libc::AT_FDCWD,
+ p.as_ptr(),
+ libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
+ libc::STATX_BASIC_STATS | libc::STATX_BTIME,
+ ) } {
+ return ret;
+ }
+ }
+
+ let mut stat: stat64 = unsafe { mem::zeroed() };
+ cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
+ Ok(FileAttr::from_stat64(stat))
+}
+
+pub fn canonicalize(path: &CStr) -> io::Result<PathBuf> {
+ let r = unsafe { libc::realpath(path.as_ptr(), ptr::null_mut()) };
if r.is_null() {
return Err(io::Error::last_os_error());
}
@@ -2324,19 +2307,19 @@ fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result
Ok(())
}
- fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
+ fn remove_dir_all_modern(p: &CStr) -> io::Result<()> {
// We cannot just call remove_dir_all_recursive() here because that would not delete a passed
// symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
// into symlinks.
let attr = lstat(p)?;
if attr.file_type().is_symlink() {
- crate::fs::remove_file(p)
+ super::unlink(p)
} else {
- run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p))
+ remove_dir_all_recursive(None, &p)
}
}
pub fn remove_dir_all(p: &Path) -> io::Result<()> {
- remove_dir_all_modern(p)
+ run_path_with_cstr(p, &remove_dir_all_modern)
}
}
diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs
index 06bba01..15727c9 100644
--- a/library/std/src/sys/fs/windows.rs
+++ b/library/std/src/sys/fs/windows.rs
@@ -547,7 +547,7 @@ pub fn file_attr(&self) -> io::Result<FileAttr> {
))?;
attr.file_size = info.AllocationSize as u64;
attr.number_of_links = Some(info.NumberOfLinks);
- if attr.file_type().is_reparse_point() {
+ if attr.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
cvt(c::GetFileInformationByHandleEx(
self.handle.as_raw_handle(),
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index f03c440..2ec8d01 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -232,14 +232,14 @@ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::
// implementation if `preadv` is not available.
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
- super::weak::syscall! {
+ super::weak::syscall!(
fn preadv(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
- offset: off64_t
- ) -> isize
- }
+ offset: off64_t,
+ ) -> isize;
+ );
let ret = cvt(unsafe {
preadv(
@@ -257,7 +257,14 @@ fn preadv(
// and its metadata from LLVM IR.
#[no_sanitize(cfi)]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
- super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+ super::weak::weak!(
+ fn preadv64(
+ fd: libc::c_int,
+ iovec: *const libc::iovec,
+ n_iovec: libc::c_int,
+ offset: off64_t,
+ ) -> isize;
+ );
match preadv64.get() {
Some(preadv) => {
@@ -286,7 +293,14 @@ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::
// use "weak" linking.
#[cfg(target_vendor = "apple")]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
- super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+ super::weak::weak!(
+ fn preadv(
+ fd: libc::c_int,
+ iovec: *const libc::iovec,
+ n_iovec: libc::c_int,
+ offset: off64_t,
+ ) -> isize;
+ );
match preadv.get() {
Some(preadv) => {
@@ -428,14 +442,14 @@ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result
// implementation if `pwritev` is not available.
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
- super::weak::syscall! {
+ super::weak::syscall!(
fn pwritev(
fd: libc::c_int,
iovec: *const libc::iovec,
n_iovec: libc::c_int,
- offset: off64_t
- ) -> isize
- }
+ offset: off64_t,
+ ) -> isize;
+ );
let ret = cvt(unsafe {
pwritev(
@@ -450,7 +464,14 @@ fn pwritev(
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
- super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+ super::weak::weak!(
+ fn pwritev64(
+ fd: libc::c_int,
+ iovec: *const libc::iovec,
+ n_iovec: libc::c_int,
+ offset: off64_t,
+ ) -> isize;
+ );
match pwritev64.get() {
Some(pwritev) => {
@@ -479,7 +500,14 @@ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result
// use "weak" linking.
#[cfg(target_vendor = "apple")]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
- super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+ super::weak::weak!(
+ fn pwritev(
+ fd: libc::c_int,
+ iovec: *const libc::iovec,
+ n_iovec: libc::c_int,
+ offset: off64_t,
+ ) -> isize;
+ );
match pwritev.get() {
Some(pwritev) => {
diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs
index bbf29f3..d42a7e2a 100644
--- a/library/std/src/sys/pal/unix/kernel_copy.rs
+++ b/library/std/src/sys/pal/unix/kernel_copy.rs
@@ -604,16 +604,16 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
_ => true,
};
- syscall! {
+ syscall!(
fn copy_file_range(
fd_in: libc::c_int,
off_in: *mut libc::loff_t,
fd_out: libc::c_int,
off_out: *mut libc::loff_t,
len: libc::size_t,
- flags: libc::c_uint
- ) -> libc::ssize_t
- }
+ flags: libc::c_uint,
+ ) -> libc::ssize_t;
+ );
fn probe_copy_file_range_support() -> u8 {
// In some cases, we cannot determine availability from the first
@@ -727,16 +727,16 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
// Android builds use feature level 14, but the libc wrapper for splice is
// gated on feature level 21+, so we have to invoke the syscall directly.
#[cfg(target_os = "android")]
- syscall! {
+ syscall!(
fn splice(
srcfd: libc::c_int,
src_offset: *const i64,
dstfd: libc::c_int,
dst_offset: *const i64,
len: libc::size_t,
- flags: libc::c_int
- ) -> libc::ssize_t
- }
+ flags: libc::c_int,
+ ) -> libc::ssize_t;
+ );
#[cfg(target_os = "linux")]
use libc::splice;
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 30282fb..f47421c 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -59,11 +59,14 @@
#[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
#[cfg_attr(target_os = "aix", link_name = "_Errno")]
+ // SAFETY: this will always return the same pointer on a given thread.
+ #[unsafe(ffi_const)]
fn errno_location() -> *mut c_int;
}
/// Returns the platform-specific value of errno
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
+#[inline]
pub fn errno() -> i32 {
unsafe { (*errno_location()) as i32 }
}
@@ -72,16 +75,19 @@ pub fn errno() -> i32 {
// needed for readdir and syscall!
#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))]
#[allow(dead_code)] // but not all target cfgs actually end up using it
+#[inline]
pub fn set_errno(e: i32) {
unsafe { *errno_location() = e as c_int }
}
#[cfg(target_os = "vxworks")]
+#[inline]
pub fn errno() -> i32 {
unsafe { libc::errnoGet() }
}
#[cfg(target_os = "rtems")]
+#[inline]
pub fn errno() -> i32 {
unsafe extern "C" {
#[thread_local]
@@ -92,6 +98,7 @@ pub fn errno() -> i32 {
}
#[cfg(target_os = "dragonfly")]
+#[inline]
pub fn errno() -> i32 {
unsafe extern "C" {
#[thread_local]
@@ -103,6 +110,7 @@ pub fn errno() -> i32 {
#[cfg(target_os = "dragonfly")]
#[allow(dead_code)]
+#[inline]
pub fn set_errno(e: i32) {
unsafe extern "C" {
#[thread_local]
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 4bd0ced..34b3948 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -424,18 +424,32 @@ unsafe fn install_main_guard_freebsd(page_size: usize) -> Option<Range<usize>> {
let pages = PAGES.get_or_init(|| {
use crate::sys::weak::dlsym;
- dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int);
+ dlsym!(
+ fn sysctlbyname(
+ name: *const libc::c_char,
+ oldp: *mut libc::c_void,
+ oldlenp: *mut libc::size_t,
+ newp: *const libc::c_void,
+ newlen: libc::size_t,
+ ) -> libc::c_int;
+ );
let mut guard: usize = 0;
let mut size = size_of_val(&guard);
let oid = c"security.bsd.stack_guard_page";
match sysctlbyname.get() {
- Some(fcn) if unsafe {
- fcn(oid.as_ptr(),
- (&raw mut guard).cast(),
- &raw mut size,
- ptr::null_mut(),
- 0) == 0
- } => guard,
+ Some(fcn)
+ if unsafe {
+ fcn(
+ oid.as_ptr(),
+ (&raw mut guard).cast(),
+ &raw mut size,
+ ptr::null_mut(),
+ 0,
+ ) == 0
+ } =>
+ {
+ guard
+ }
_ => 1,
}
});
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index bb34c2f..9078dd1 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -193,11 +193,12 @@ pub fn set_name(name: &CStr) {
// and its metadata from LLVM IR.
#[no_sanitize(cfi)]
pub fn set_name(name: &CStr) {
- weak! {
+ weak!(
fn pthread_setname_np(
- libc::pthread_t, *const libc::c_char
- ) -> libc::c_int
- }
+ thread: libc::pthread_t,
+ name: *const libc::c_char,
+ ) -> libc::c_int;
+ );
if let Some(f) = pthread_setname_np.get() {
#[cfg(target_os = "nto")]
@@ -762,7 +763,9 @@ unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
// We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628)
// We shouldn't really be using such an internal symbol, but there's currently
// no other way to account for the TLS size.
- dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
+ dlsym!(
+ fn __pthread_get_minstack(attr: *const libc::pthread_attr_t) -> libc::size_t;
+ );
match __pthread_get_minstack.get() {
None => libc::PTHREAD_STACK_MIN,
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index c0a3044..b8469b1 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -123,7 +123,12 @@ pub fn now(clock: libc::clockid_t) -> Timespec {
// __clock_gettime64 was added to 32-bit arches in glibc 2.34,
// and it handles both vDSO calls and ENOSYS fallbacks itself.
- weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int);
+ weak!(
+ fn __clock_gettime64(
+ clockid: libc::clockid_t,
+ tp: *mut __timespec64,
+ ) -> libc::c_int;
+ );
if let Some(clock_gettime64) = __clock_gettime64.get() {
let mut t = MaybeUninit::uninit();
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index ce3f66a..e7f4e00 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -29,7 +29,7 @@
// We can use true weak linkage on ELF targets.
#[cfg(all(unix, not(target_vendor = "apple")))]
pub(crate) macro weak {
- (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+ (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
unsafe extern "C" {
#[linkage = "extern_weak"]
@@ -62,10 +62,16 @@ pub(crate) fn get(&self) -> Option<F> {
}
pub(crate) macro dlsym {
- (fn $name:ident($($t:ty),*) -> $ret:ty) => (
- dlsym!(fn $name($($t),*) -> $ret, stringify!($name));
+ (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
+ dlsym!(
+ #[link_name = stringify!($name)]
+ fn $name($($param : $t),*) -> $ret;
+ );
),
- (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => (
+ (
+ #[link_name = $sym:expr]
+ fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
+ ) => (
static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> =
DlsymWeak::new(concat!($sym, '\0'));
let $name = &DLSYM;
@@ -143,15 +149,15 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void {
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub(crate) macro syscall {
- (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
// FIXME(#115199): Rust currently omits weak function definitions
// and its metadata from LLVM IR.
#[no_sanitize(cfi)]
- unsafe fn $name($($arg_name: $t),*) -> $ret {
- weak! { fn $name($($t),*) -> $ret }
+ unsafe fn $name($($param: $t),*) -> $ret {
+ weak!(fn $name($($param: $t),*) -> $ret;);
if let Some(fun) = $name.get() {
- fun($($arg_name),*)
+ fun($($param),*)
} else {
super::os::set_errno(libc::ENOSYS);
-1
@@ -162,16 +168,18 @@ unsafe fn $name($($arg_name: $t),*) -> $ret {
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) macro syscall {
- (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
- unsafe fn $name($($arg_name:$t),*) -> $ret {
- weak! { fn $name($($t),*) -> $ret }
+ (
+ fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
+ ) => (
+ unsafe fn $name($($param: $t),*) -> $ret {
+ weak!(fn $name($($param: $t),*) -> $ret;);
// Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
// interposition, but if it's not found just use a raw syscall.
if let Some(fun) = $name.get() {
- fun($($arg_name),*)
+ fun($($param),*)
} else {
- libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
+ libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret
}
}
)
@@ -179,9 +187,9 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) macro raw_syscall {
- (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
- unsafe fn $name($($arg_name:$t),*) -> $ret {
- libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
+ (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
+ unsafe fn $name($($param: $t),*) -> $ret {
+ libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret
}
)
}
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index c85b03d..cc569bb 100644
--- a/library/std/src/sys/pal/wasi/thread.rs
+++ b/library/std/src/sys/pal/wasi/thread.rs
@@ -67,7 +67,7 @@ fn drop(&mut self) {
}
}
-pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024;
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs
index afdb159..dd5aff3 100644
--- a/library/std/src/sys/pal/wasm/atomics/thread.rs
+++ b/library/std/src/sys/pal/wasm/atomics/thread.rs
@@ -6,7 +6,7 @@
pub struct Thread(!);
-pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024;
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index 8521cf4..c785246 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -74,7 +74,6 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
let ours;
let mut name;
let mut tries = 0;
- let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS;
loop {
tries += 1;
name = format!(
@@ -96,7 +95,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
c::PIPE_TYPE_BYTE
| c::PIPE_READMODE_BYTE
| c::PIPE_WAIT
- | reject_remote_clients_flag,
+ | c::PIPE_REJECT_REMOTE_CLIENTS,
1,
PIPE_BUFFER_CAPACITY,
PIPE_BUFFER_CAPACITY,
@@ -112,30 +111,15 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
//
// Don't try again too much though as this could also perhaps be a
// legit error.
- // If `ERROR_INVALID_PARAMETER` is returned, this probably means we're
- // running on pre-Vista version where `PIPE_REJECT_REMOTE_CLIENTS` is
- // not supported, so we continue retrying without it. This implies
- // reduced security on Windows versions older than Vista by allowing
- // connections to this pipe from remote machines.
- // Proper fix would increase the number of FFI imports and introduce
- // significant amount of Windows XP specific code with no clean
- // testing strategy
- // For more info, see https://github.com/rust-lang/rust/pull/37677.
if handle == c::INVALID_HANDLE_VALUE {
let error = api::get_last_error();
- if tries < 10 {
- if error == WinError::ACCESS_DENIED {
- continue;
- } else if reject_remote_clients_flag != 0
- && error == WinError::INVALID_PARAMETER
- {
- reject_remote_clients_flag = 0;
- tries -= 1;
- continue;
- }
+ if tries < 10 && error == WinError::ACCESS_DENIED {
+ continue;
+ } else {
+ return Err(io::Error::from_raw_os_error(error.code as i32));
}
- return Err(io::Error::from_raw_os_error(error.code as i32));
}
+
ours = Handle::from_raw_handle(handle);
break;
}
diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs
index 42542f8..191a09c 100644
--- a/library/std/src/sys/process/unix/unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -461,18 +461,20 @@ fn posix_spawn(
if #[cfg(target_os = "linux")] {
use crate::sys::weak::weak;
- weak! {
+ weak!(
fn pidfd_spawnp(
- *mut libc::c_int,
- *const libc::c_char,
- *const libc::posix_spawn_file_actions_t,
- *const libc::posix_spawnattr_t,
- *const *mut libc::c_char,
- *const *mut libc::c_char
- ) -> libc::c_int
- }
+ pidfd: *mut libc::c_int,
+ path: *const libc::c_char,
+ file_actions: *const libc::posix_spawn_file_actions_t,
+ attrp: *const libc::posix_spawnattr_t,
+ argv: *const *mut libc::c_char,
+ envp: *const *mut libc::c_char,
+ ) -> libc::c_int;
+ );
- weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int }
+ weak!(
+ fn pidfd_getpid(pidfd: libc::c_int) -> libc::c_int;
+ );
static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0);
const UNKNOWN: u8 = 0;
@@ -593,19 +595,19 @@ fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
// https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addchdir.html.
// The _np version is more widely available, though, so try that first.
- weak! {
+ weak!(
fn posix_spawn_file_actions_addchdir_np(
- *mut libc::posix_spawn_file_actions_t,
- *const libc::c_char
- ) -> libc::c_int
- }
+ file_actions: *mut libc::posix_spawn_file_actions_t,
+ path: *const libc::c_char,
+ ) -> libc::c_int;
+ );
- weak! {
+ weak!(
fn posix_spawn_file_actions_addchdir(
- *mut libc::posix_spawn_file_actions_t,
- *const libc::c_char
- ) -> libc::c_int
- }
+ file_actions: *mut libc::posix_spawn_file_actions_t,
+ path: *const libc::c_char,
+ ) -> libc::c_int;
+ );
posix_spawn_file_actions_addchdir_np
.get()
diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs
index e3cb792..c0591ec 100644
--- a/library/std/src/sys/random/linux.rs
+++ b/library/std/src/sys/random/linux.rs
@@ -73,13 +73,13 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) {
// A weak symbol allows interposition, e.g. for perf measurements that want to
// disable randomness for consistency. Otherwise, we'll try a raw syscall.
// (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28)
- syscall! {
+ syscall!(
fn getrandom(
buffer: *mut libc::c_void,
length: libc::size_t,
- flags: libc::c_uint
- ) -> libc::ssize_t
- }
+ flags: libc::c_uint,
+ ) -> libc::ssize_t;
+ );
static GETRANDOM_AVAILABLE: AtomicBool = AtomicBool::new(true);
static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true);
diff --git a/library/std/src/thread/spawnhook.rs b/library/std/src/thread/spawnhook.rs
index 99b5ad9..98f471a 100644
--- a/library/std/src/thread/spawnhook.rs
+++ b/library/std/src/thread/spawnhook.rs
@@ -113,18 +113,23 @@ pub fn add_spawn_hook<F, G>(hook: F)
pub(super) fn run_spawn_hooks(thread: &Thread) -> ChildSpawnHooks {
// Get a snapshot of the spawn hooks.
// (Increments the refcount to the first node.)
- let hooks = SPAWN_HOOKS.with(|hooks| {
+ if let Ok(hooks) = SPAWN_HOOKS.try_with(|hooks| {
let snapshot = hooks.take();
hooks.set(snapshot.clone());
snapshot
- });
- // Iterate over the hooks, run them, and collect the results in a vector.
- let to_run: Vec<_> = iter::successors(hooks.first.as_deref(), |hook| hook.next.as_deref())
- .map(|hook| (hook.hook)(thread))
- .collect();
- // Pass on the snapshot of the hooks and the results to the new thread,
- // which will then run SpawnHookResults::run().
- ChildSpawnHooks { hooks, to_run }
+ }) {
+ // Iterate over the hooks, run them, and collect the results in a vector.
+ let to_run: Vec<_> = iter::successors(hooks.first.as_deref(), |hook| hook.next.as_deref())
+ .map(|hook| (hook.hook)(thread))
+ .collect();
+ // Pass on the snapshot of the hooks and the results to the new thread,
+ // which will then run SpawnHookResults::run().
+ ChildSpawnHooks { hooks, to_run }
+ } else {
+ // TLS has been destroyed. Skip running the hooks.
+ // See https://github.com/rust-lang/rust/issues/138696
+ ChildSpawnHooks::default()
+ }
}
/// The results of running the spawn hooks.
diff --git a/rustfmt.toml b/rustfmt.toml
index 8feeb60..c884a33 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -49,7 +49,6 @@
# These are ignored by a standard cargo fmt run.
"compiler/rustc_codegen_cranelift/scripts",
- "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", # uses edition 2024
"compiler/rustc_codegen_gcc/tests",
# Code automatically generated and included.
"compiler/rustc_codegen_gcc/src/intrinsic/archs.rs",
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 890e64e..17ee4d6 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -88,9 +88,9 @@
[[package]]
name = "cc"
-version = "1.1.22"
+version = "1.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
+checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
dependencies = [
"shlex",
]
@@ -150,9 +150,9 @@
[[package]]
name = "cmake"
-version = "0.1.48"
+version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a"
+checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
dependencies = [
"cc",
]
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index d3e2b9e..23aa87a 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -32,10 +32,8 @@
# Most of the time updating these dependencies requires modifications to the
# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
# otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
-#
-# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed.
-cc = "=1.1.22"
-cmake = "=0.1.48"
+cc = "=1.2.17"
+cmake = "=0.1.54"
build_helper = { path = "../build_helper" }
clap = { version = "4.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 68400ba..140f601 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1162,6 +1162,30 @@
config = self.get_toml("build")
return config or default_build_triple(self.verbose)
+ def is_git_repository(self, repo_path):
+ return os.path.isdir(os.path.join(repo_path, ".git"))
+
+ def get_latest_commit(self):
+ repo_path = self.rust_root
+ author_email = self.stage0_data.get("git_merge_commit_email")
+ if not self.is_git_repository(repo_path):
+ return "<commit>"
+ cmd = [
+ "git",
+ "-C",
+ repo_path,
+ "rev-list",
+ "--author",
+ author_email,
+ "-n1",
+ "HEAD",
+ ]
+ try:
+ commit = subprocess.check_output(cmd, universal_newlines=True).strip()
+ return commit or "<commit>"
+ except subprocess.CalledProcessError:
+ return "<commit>"
+
def check_vendored_status(self):
"""Check that vendoring is configured properly"""
# keep this consistent with the equivalent check in bootstrap:
@@ -1174,7 +1198,8 @@
eprint(" use vendored sources by default.")
cargo_dir = os.path.join(self.rust_root, ".cargo")
- url = "https://ci-artifacts.rust-lang.org/rustc-builds/<commit>/rustc-nightly-src.tar.xz"
+ commit = self.get_latest_commit()
+ url = f"https://ci-artifacts.rust-lang.org/rustc-builds/{commit}/rustc-nightly-src.tar.xz"
if self.use_vendored_sources:
vendor_dir = os.path.join(self.rust_root, "vendor")
if not os.path.exists(vendor_dir):
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index d2c0d38..e157ff2 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
-Last change is for: https://github.com/rust-lang/rust/pull/134740
+Last change is for: https://github.com/rust-lang/rust/pull/138784
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 443131d..cbfe00a 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -11,8 +11,8 @@
use std::{env, process};
use bootstrap::{
- Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, debug, find_recent_config_change_ids,
- human_readable_changes, t,
+ Build, CONFIG_CHANGE_HISTORY, ChangeId, Config, Flags, Subcommand, debug,
+ find_recent_config_change_ids, human_readable_changes, t,
};
#[cfg(feature = "tracing")]
use tracing::instrument;
@@ -155,51 +155,53 @@ fn check_version(config: &Config) -> Option<String> {
let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id");
- if let Some(mut id) = config.change_id {
- if id == latest_change_id {
- return None;
+ let mut id = match config.change_id {
+ Some(ChangeId::Id(id)) if id == latest_change_id => return None,
+ Some(ChangeId::Ignore) => return None,
+ Some(ChangeId::Id(id)) => id,
+ None => {
+ msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
+ msg.push_str("NOTE: to silence this warning, ");
+ msg.push_str(&format!(
+ "add `change-id = {latest_change_id}` or change-id = \"ignore\" at the top of `bootstrap.toml`"
+ ));
+ return Some(msg);
}
-
- // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
- // then use the one from the bootstrap.toml. This way we never show the same warnings
- // more than once.
- if let Ok(t) = fs::read_to_string(&warned_id_path) {
- let last_warned_id = usize::from_str(&t)
- .unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display()));
-
- // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
- // Otherwise, we may retrieve all the changes if it's not the highest value.
- // For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
- if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
- id = last_warned_id;
- }
- };
-
- let changes = find_recent_config_change_ids(id);
-
- if changes.is_empty() {
- return None;
- }
-
- msg.push_str("There have been changes to x.py since you last updated:\n");
- msg.push_str(&human_readable_changes(&changes));
-
- msg.push_str("NOTE: to silence this warning, ");
- msg.push_str(&format!(
- "update `bootstrap.toml` to use `change-id = {latest_change_id}` instead"
- ));
-
- if io::stdout().is_terminal() {
- t!(fs::write(warned_id_path, latest_change_id.to_string()));
- }
- } else {
- msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
- msg.push_str("NOTE: to silence this warning, ");
- msg.push_str(&format!(
- "add `change-id = {latest_change_id}` at the top of `bootstrap.toml`"
- ));
};
+ // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
+ // then use the one from the bootstrap.toml. This way we never show the same warnings
+ // more than once.
+ if let Ok(t) = fs::read_to_string(&warned_id_path) {
+ let last_warned_id = usize::from_str(&t)
+ .unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display()));
+
+ // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
+ // Otherwise, we may retrieve all the changes if it's not the highest value.
+ // For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
+ if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
+ id = last_warned_id;
+ }
+ };
+
+ let changes = find_recent_config_change_ids(id);
+
+ if changes.is_empty() {
+ return None;
+ }
+
+ msg.push_str("There have been changes to x.py since you last updated:\n");
+ msg.push_str(&human_readable_changes(changes));
+
+ msg.push_str("NOTE: to silence this warning, ");
+ msg.push_str(&format!(
+ "update `bootstrap.toml` to use `change-id = {latest_change_id}` or change-id = \"ignore\" instead"
+ ));
+
+ if io::stdout().is_terminal() {
+ t!(fs::write(warned_id_path, latest_change_id.to_string()));
+ }
+
Some(msg)
}
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 7aa5cb2..b1a97bd 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -31,7 +31,7 @@ fn rustfmt(
// Avoid the submodule config paths from coming into play. We only allow a single global config
// for the workspace for now.
cmd.arg("--config-path").arg(src.canonicalize().unwrap());
- cmd.arg("--edition").arg("2021");
+ cmd.arg("--edition").arg("2024");
cmd.arg("--unstable-features");
cmd.arg("--skip-children");
if check {
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 9ae1825..e21804f 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -385,9 +385,6 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
|| target.contains("apple-watchos")
|| target.contains("apple-visionos")
{
- // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error.
- cfg.define("CMAKE_OSX_SYSROOT", "/");
- cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", "");
// Prevent cmake from adding -bundle to CFLAGS automatically, which leads to a compiler error because "-bitcode_bundle" also gets added.
cfg.define("LLVM_ENABLE_PLUGINS", "OFF");
// Zlib fails to link properly, leading to a compiler error.
@@ -645,10 +642,17 @@ fn configure_cmake(
if !builder.is_builder_target(target) {
cfg.define("CMAKE_CROSSCOMPILING", "True");
+ // NOTE: Ideally, we wouldn't have to do this, and `cmake-rs` would just handle it for us.
+ // But it currently determines this based on the `CARGO_CFG_TARGET_OS` environment variable,
+ // which isn't set when compiling outside `build.rs` (like bootstrap is).
+ //
+ // So for now, we define `CMAKE_SYSTEM_NAME` ourselves, to panicking in `cmake-rs`.
if target.contains("netbsd") {
cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
} else if target.contains("dragonfly") {
cfg.define("CMAKE_SYSTEM_NAME", "DragonFly");
+ } else if target.contains("openbsd") {
+ cfg.define("CMAKE_SYSTEM_NAME", "OpenBSD");
} else if target.contains("freebsd") {
cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
} else if target.is_windows() {
@@ -659,10 +663,27 @@ fn configure_cmake(
cfg.define("CMAKE_SYSTEM_NAME", "SunOS");
} else if target.contains("linux") {
cfg.define("CMAKE_SYSTEM_NAME", "Linux");
+ } else if target.contains("darwin") {
+ // macOS
+ cfg.define("CMAKE_SYSTEM_NAME", "Darwin");
+ } else if target.contains("ios") {
+ cfg.define("CMAKE_SYSTEM_NAME", "iOS");
+ } else if target.contains("tvos") {
+ cfg.define("CMAKE_SYSTEM_NAME", "tvOS");
+ } else if target.contains("visionos") {
+ cfg.define("CMAKE_SYSTEM_NAME", "visionOS");
+ } else if target.contains("watchos") {
+ cfg.define("CMAKE_SYSTEM_NAME", "watchOS");
+ } else if target.contains("none") {
+ // "none" should be the last branch
+ cfg.define("CMAKE_SYSTEM_NAME", "Generic");
} else {
builder.info(&format!(
"could not determine CMAKE_SYSTEM_NAME from the target `{target}`, build may fail",
));
+ // Fallback, set `CMAKE_SYSTEM_NAME` anyhow to avoid the logic `cmake-rs` tries, and
+ // to avoid CMAKE_SYSTEM_NAME being inferred from the host.
+ cfg.define("CMAKE_SYSTEM_NAME", "Generic");
}
// When cross-compiling we should also set CMAKE_SYSTEM_VERSION, but in
@@ -672,7 +693,19 @@ fn configure_cmake(
// CMakeFiles (and then only in tests), and so far no issues have been
// reported, the system version is currently left unset.
- if target.contains("darwin") {
+ if target.contains("apple") {
+ if !target.contains("darwin") {
+ // FIXME(madsmtm): compiler-rt's CMake setup is kinda weird, it seems like they do
+ // version testing etc. for macOS (i.e. Darwin), even while building for iOS?
+ //
+ // So for now we set it to "Darwin" on all Apple platforms.
+ cfg.define("CMAKE_SYSTEM_NAME", "Darwin");
+
+ // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error.
+ cfg.define("CMAKE_OSX_SYSROOT", "/");
+ cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", "");
+ }
+
// Make sure that CMake does not build universal binaries on macOS.
// Explicitly specify the one single target architecture.
if target.starts_with("aarch64") {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index cf4ef4e..1712be7 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -193,7 +193,7 @@ pub enum GccCiMode {
/// `bootstrap.example.toml`.
#[derive(Default, Clone)]
pub struct Config {
- pub change_id: Option<usize>,
+ pub change_id: Option<ChangeId>,
pub bypass_bootstrap_lock: bool,
pub ccache: Option<String>,
/// Call Build::ninja() instead of this.
@@ -700,14 +700,36 @@ pub(crate) struct TomlConfig {
profile: Option<String>,
}
+/// This enum is used for deserializing change IDs from TOML, allowing both numeric values and the string `"ignore"`.
+#[derive(Clone, Debug, PartialEq)]
+pub enum ChangeId {
+ Ignore,
+ Id(usize),
+}
+
/// Since we use `#[serde(deny_unknown_fields)]` on `TomlConfig`, we need a wrapper type
/// for the "change-id" field to parse it even if other fields are invalid. This ensures
/// that if deserialization fails due to other fields, we can still provide the changelogs
/// to allow developers to potentially find the reason for the failure in the logs..
#[derive(Deserialize, Default)]
pub(crate) struct ChangeIdWrapper {
- #[serde(alias = "change-id")]
- pub(crate) inner: Option<usize>,
+ #[serde(alias = "change-id", default, deserialize_with = "deserialize_change_id")]
+ pub(crate) inner: Option<ChangeId>,
+}
+
+fn deserialize_change_id<'de, D: Deserializer<'de>>(
+ deserializer: D,
+) -> Result<Option<ChangeId>, D::Error> {
+ let value = toml::Value::deserialize(deserializer)?;
+ Ok(match value {
+ toml::Value::String(s) if s == "ignore" => Some(ChangeId::Ignore),
+ toml::Value::Integer(i) => Some(ChangeId::Id(i as usize)),
+ _ => {
+ return Err(serde::de::Error::custom(
+ "expected \"ignore\" or an integer for change-id",
+ ));
+ }
+ })
}
/// Describes how to handle conflicts in merging two [`TomlConfig`]
@@ -1351,14 +1373,15 @@ pub(crate) fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
toml::from_str(&contents)
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
.inspect_err(|_| {
- if let Ok(Some(changes)) = toml::from_str(&contents)
- .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
- .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
+ if let Ok(ChangeIdWrapper { inner: Some(ChangeId::Id(id)) }) =
+ toml::from_str::<toml::Value>(&contents)
+ .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
{
+ let changes = crate::find_recent_config_change_ids(id);
if !changes.is_empty() {
println!(
"WARNING: There have been changes to x.py since you last updated:\n{}",
- crate::human_readable_changes(&changes)
+ crate::human_readable_changes(changes)
);
}
}
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 068e237..d8002ba 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -10,6 +10,7 @@
use super::flags::Flags;
use super::{ChangeIdWrapper, Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS};
+use crate::ChangeId;
use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
use crate::core::build_steps::llvm;
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
@@ -24,31 +25,11 @@ pub(crate) fn parse(config: &str) -> Config {
#[test]
fn download_ci_llvm() {
- let config = parse("");
- let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions);
- if is_available {
- assert!(config.llvm_from_ci);
- }
-
- let config = Config::parse_inner(
- Flags::parse(&[
- "check".to_string(),
- "--config=/does/not/exist".to_string(),
- "--ci".to_string(),
- "false".to_string(),
- ]),
- |&_| toml::from_str("llvm.download-ci-llvm = true"),
- );
- let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions);
- if is_available {
- assert!(config.llvm_from_ci);
- }
-
let config = parse("llvm.download-ci-llvm = false");
assert!(!config.llvm_from_ci);
let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\"");
- if if_unchanged_config.llvm_from_ci {
+ if if_unchanged_config.llvm_from_ci && if_unchanged_config.is_running_on_ci {
let has_changes = if_unchanged_config
.last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true)
.is_none();
@@ -171,7 +152,7 @@ fn override_toml() {
)
},
);
- assert_eq!(config.change_id, Some(1), "setting top-level value");
+ assert_eq!(config.change_id, Some(ChangeId::Id(1)), "setting top-level value");
assert_eq!(
config.rust_lto,
crate::core::config::RustcLto::Fat,
@@ -311,7 +292,7 @@ fn parse_change_id_with_unknown_field() {
"#;
let change_id_wrapper: ChangeIdWrapper = toml::from_str(config).unwrap();
- assert_eq!(change_id_wrapper.inner, Some(3461));
+ assert_eq!(change_id_wrapper.inner, Some(ChangeId::Id(3461)));
}
#[test]
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index c47cd8b..843d474 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -45,8 +45,8 @@
mod utils;
pub use core::builder::PathSet;
-pub use core::config::Config;
pub use core::config::flags::{Flags, Subcommand};
+pub use core::config::{ChangeId, Config};
#[cfg(feature = "tracing")]
use tracing::{instrument, span};
diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs
index c97529c..b4a1b52 100644
--- a/src/bootstrap/src/utils/cc_detect/tests.rs
+++ b/src/bootstrap/src/utils/cc_detect/tests.rs
@@ -264,7 +264,7 @@ fn test_find_target_without_config() {
fn test_find() {
let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
let target1 = TargetSelection::from_user("x86_64-unknown-linux-gnu");
- let target2 = TargetSelection::from_user("arm-linux-androideabi");
+ let target2 = TargetSelection::from_user("x86_64-unknown-openbsd");
build.targets.push(target1.clone());
build.hosts.push(target2.clone());
find(&build);
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 1a101b0..2443917 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -35,29 +35,25 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
}
}
-pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
- if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) {
+pub fn find_recent_config_change_ids(current_id: usize) -> &'static [ChangeInfo] {
+ if let Some(index) =
+ CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id)
+ {
+ // Skip the current_id and IDs before it
+ &CONFIG_CHANGE_HISTORY[index + 1..]
+ } else {
// If the current change-id is greater than the most recent one, return
// an empty list (it may be due to switching from a recent branch to an
// older one); otherwise, return the full list (assuming the user provided
// the incorrect change-id by accident).
if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) {
if current_id > config.change_id {
- return Vec::new();
+ return &[];
}
}
- return CONFIG_CHANGE_HISTORY.to_vec();
+ CONFIG_CHANGE_HISTORY
}
-
- let index =
- CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap();
-
- CONFIG_CHANGE_HISTORY
- .iter()
- .skip(index + 1) // Skip the current_id and IDs before it
- .cloned()
- .collect()
}
pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
@@ -390,4 +386,9 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
severity: ChangeSeverity::Warning,
summary: "The default configuration filename has changed from `config.toml` to `bootstrap.toml`. `config.toml` is deprecated but remains supported for backward compatibility.",
},
+ ChangeInfo {
+ change_id: 138986,
+ severity: ChangeSeverity::Info,
+ summary: "You can now use `change-id = \"ignore\"` to suppress `change-id ` warnings in the console.",
+ },
];
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index 885fff9..862c444 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -9,9 +9,10 @@
use std::io::BufWriter;
use std::time::{Duration, Instant, SystemTime};
+use build_helper::ci::CiEnv;
use build_helper::metrics::{
- JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test,
- TestOutcome, TestSuite, TestSuiteMetadata,
+ CiMetadata, JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats,
+ Test, TestOutcome, TestSuite, TestSuiteMetadata,
};
use sysinfo::{CpuRefreshKind, RefreshKind, System};
@@ -217,7 +218,12 @@ pub(crate) fn persist(&self, build: &Build) {
children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(),
});
- let json = JsonRoot { format_version: CURRENT_FORMAT_VERSION, system_stats, invocations };
+ let json = JsonRoot {
+ format_version: CURRENT_FORMAT_VERSION,
+ system_stats,
+ invocations,
+ ci_metadata: get_ci_metadata(CiEnv::current()),
+ };
t!(std::fs::create_dir_all(dest.parent().unwrap()));
let mut file = BufWriter::new(t!(File::create(&dest)));
@@ -245,6 +251,16 @@ fn prepare_json_step(&self, step: StepMetrics) -> JsonNode {
}
}
+fn get_ci_metadata(ci_env: CiEnv) -> Option<CiMetadata> {
+ if ci_env != CiEnv::GitHubActions {
+ return None;
+ }
+ let workflow_run_id =
+ std::env::var("GITHUB_WORKFLOW_RUN_ID").ok().and_then(|id| id.parse::<u64>().ok())?;
+ let repository = std::env::var("GITHUB_REPOSITORY").ok()?;
+ Some(CiMetadata { workflow_run_id, repository })
+}
+
struct MetricsState {
finished_steps: Vec<StepMetrics>,
running_steps: Vec<StepMetrics>,
diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs
index fdff9cd..8b82e62 100644
--- a/src/build_helper/src/metrics.rs
+++ b/src/build_helper/src/metrics.rs
@@ -9,6 +9,19 @@ pub struct JsonRoot {
pub format_version: usize,
pub system_stats: JsonInvocationSystemStats,
pub invocations: Vec<JsonInvocation>,
+ #[serde(default)]
+ pub ci_metadata: Option<CiMetadata>,
+}
+
+/// Represents metadata about bootstrap's execution in CI.
+#[derive(Serialize, Deserialize)]
+pub struct CiMetadata {
+ /// GitHub run ID of the workflow where bootstrap was executed.
+ /// Note that the run ID will be shared amongst all jobs executed in that workflow.
+ pub workflow_run_id: u64,
+ /// Full name of a GitHub repository where bootstrap was executed in CI.
+ /// e.g. `rust-lang-ci/rust`.
+ pub repository: String,
}
#[derive(Serialize, Deserialize)]
diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs
index 2b001f2..7fbfad4 100644
--- a/src/ci/citool/src/analysis.rs
+++ b/src/ci/citool/src/analysis.rs
@@ -1,5 +1,6 @@
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt::Debug;
+use std::time::Duration;
use build_helper::metrics::{
BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name,
@@ -184,11 +185,70 @@ fn write_row(
}
/// Outputs a report of test differences between the `parent` and `current` commits.
-pub fn output_test_diffs(job_metrics: HashMap<JobName, JobMetrics>) {
+pub fn output_test_diffs(job_metrics: &HashMap<JobName, JobMetrics>) {
let aggregated_test_diffs = aggregate_test_diffs(&job_metrics);
report_test_diffs(aggregated_test_diffs);
}
+/// Prints the ten largest differences in bootstrap durations.
+pub fn output_largest_duration_changes(job_metrics: &HashMap<JobName, JobMetrics>) {
+ struct Entry<'a> {
+ job: &'a JobName,
+ before: Duration,
+ after: Duration,
+ change: f64,
+ }
+
+ let mut changes: Vec<Entry> = vec![];
+ for (job, metrics) in job_metrics {
+ if let Some(parent) = &metrics.parent {
+ let duration_before = parent
+ .invocations
+ .iter()
+ .map(|i| BuildStep::from_invocation(i).duration)
+ .sum::<Duration>();
+ let duration_after = metrics
+ .current
+ .invocations
+ .iter()
+ .map(|i| BuildStep::from_invocation(i).duration)
+ .sum::<Duration>();
+ let pct_change = duration_after.as_secs_f64() / duration_before.as_secs_f64();
+ let pct_change = pct_change * 100.0;
+ // Normalize around 100, to get + for regression and - for improvements
+ let pct_change = pct_change - 100.0;
+ changes.push(Entry {
+ job,
+ before: duration_before,
+ after: duration_after,
+ change: pct_change,
+ });
+ }
+ }
+ changes.sort_by(|e1, e2| e1.change.partial_cmp(&e2.change).unwrap().reverse());
+
+ println!("# Job duration changes");
+ for (index, entry) in changes.into_iter().take(10).enumerate() {
+ println!(
+ "{}. `{}`: {:.1}s -> {:.1}s ({:.1}%)",
+ index + 1,
+ entry.job,
+ entry.before.as_secs_f64(),
+ entry.after.as_secs_f64(),
+ entry.change
+ );
+ }
+
+ println!();
+ output_details("How to interpret the job duration changes?", || {
+ println!(
+ r#"Job durations can vary a lot, based on the actual runner instance
+that executed the job, system noise, invalidated caches, etc. The table above is provided
+mostly for t-infra members, for simpler debugging of potential CI slow-downs."#
+ );
+ });
+}
+
#[derive(Default)]
struct TestSuiteRecord {
passed: u64,
diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs
index 5f5c50d..6db5eab 100644
--- a/src/ci/citool/src/main.rs
+++ b/src/ci/citool/src/main.rs
@@ -15,7 +15,7 @@
use jobs::JobDatabase;
use serde_yaml::Value;
-use crate::analysis::output_test_diffs;
+use crate::analysis::{output_largest_duration_changes, output_test_diffs};
use crate::cpu_usage::load_cpu_usage;
use crate::datadog::upload_datadog_metric;
use crate::jobs::RunType;
@@ -160,7 +160,7 @@ fn postprocess_metrics(
job_name,
JobMetrics { parent: Some(parent_metrics), current: metrics },
)]);
- output_test_diffs(job_metrics);
+ output_test_diffs(&job_metrics);
return Ok(());
}
Err(error) => {
@@ -180,7 +180,8 @@ fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow
let metrics = download_auto_job_metrics(&db, &parent, ¤t)?;
println!("\nComparing {parent} (parent) -> {current} (this PR)\n");
- output_test_diffs(metrics);
+ output_test_diffs(&metrics);
+ output_largest_duration_changes(&metrics);
Ok(())
}
diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs
index 086aa50..a816fb3 100644
--- a/src/ci/citool/src/metrics.rs
+++ b/src/ci/citool/src/metrics.rs
@@ -1,5 +1,5 @@
use std::collections::HashMap;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use anyhow::Context;
use build_helper::metrics::{JsonNode, JsonRoot, TestSuite};
@@ -74,6 +74,17 @@ pub fn download_auto_job_metrics(
}
pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoot> {
+ // Best effort cache to speed-up local re-executions of citool
+ let cache_path = PathBuf::from(".citool-cache").join(sha).join(format!("{job_name}.json"));
+ if cache_path.is_file() {
+ if let Ok(metrics) = std::fs::read_to_string(&cache_path)
+ .map_err(|err| err.into())
+ .and_then(|data| anyhow::Ok::<JsonRoot>(serde_json::from_str::<JsonRoot>(&data)?))
+ {
+ return Ok(metrics);
+ }
+ }
+
let url = get_metrics_url(job_name, sha);
let mut response = ureq::get(&url).call()?;
if !response.status().is_success() {
@@ -87,6 +98,13 @@ pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoo
.body_mut()
.read_json()
.with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?;
+
+ if let Ok(_) = std::fs::create_dir_all(cache_path.parent().unwrap()) {
+ if let Ok(data) = serde_json::to_string(&data) {
+ let _ = std::fs::write(cache_path, data);
+ }
+ }
+
Ok(data)
}
diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs
index b9b1bf4..a4c6ff8 100644
--- a/src/ci/citool/src/utils.rs
+++ b/src/ci/citool/src/utils.rs
@@ -23,7 +23,6 @@ pub fn output_details<F>(summary: &str, func: F)
println!(
r"<details>
<summary>{summary}</summary>
-
"
);
func();
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 2805bb1..00d791e 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -355,6 +355,8 @@
--env GITHUB_ACTIONS \
--env GITHUB_REF \
--env GITHUB_STEP_SUMMARY="/checkout/obj/${SUMMARY_FILE}" \
+ --env GITHUB_WORKFLOW_RUN_ID \
+ --env GITHUB_REPOSITORY \
--env RUST_BACKTRACE \
--env TOOLSTATE_REPO_ACCESS_TOKEN \
--env TOOLSTATE_REPO \
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index 98bb9de..1190c26 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -202,6 +202,9 @@
* `~|`: Associates the error level and message with the *same* line as the
*previous comment*. This is more convenient than using multiple carets when
there are multiple messages associated with the same line.
+* `~v`: Associates the error level and message with the *next* error
+ annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv`
+ is three lines below the error annotation line.
* `~?`: Used to match error levels and messages with errors not having line
information. These can be placed on any line in the test file, but are
conventionally placed at the end.
@@ -273,6 +276,18 @@
//~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023]
```
+#### Positioned above error line
+
+Use the `//~v` idiom with number of v's in the string to indicate the number
+of lines below. This is typically used in lexer or parser tests matching on errors like unclosed
+delimiter or unclosed literal happening at the end of file.
+
+```rust,ignore
+// ignore-tidy-trailing-newlines
+//~v ERROR this file contains an unclosed delimiter
+fn main((ؼ
+```
+
#### Error without line information
Use `//~?` to match an error without line information.
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index b3bd449..e1ba27c 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -14,6 +14,22 @@
- [Deny-by-default Lints](lints/listing/deny-by-default.md)
- [JSON Output](json.md)
- [Tests](tests/index.md)
+- [Targets](targets/index.md)
+ - [Built-in Targets](targets/built-in.md)
+ - [Custom Targets](targets/custom.md)
+ - [Known Issues](targets/known-issues.md)
+- [Profile-guided Optimization](profile-guided-optimization.md)
+- [Instrumentation-based Code Coverage](instrument-coverage.md)
+- [Linker-plugin-based LTO](linker-plugin-lto.md)
+- [Checking Conditional Configurations](check-cfg.md)
+ - [Cargo Specifics](check-cfg/cargo-specifics.md)
+- [Exploit Mitigations](exploit-mitigations.md)
+- [Symbol Mangling](symbol-mangling/index.md)
+ - [v0 Symbol Format](symbol-mangling/v0.md)
+- [Contributing to `rustc`](contributing.md)
+
+--------
+
- [Platform Support](platform-support.md)
- [Target Tier Policy](target-tier-policy.md)
- [Template for Target-specific Documentation](platform-support/TEMPLATE.md)
@@ -66,6 +82,7 @@
- [m68k-unknown-none-elf](platform-support/m68k-unknown-none-elf.md)
- [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
- [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)
+ - [mipsel-unknown-linux-gnu](platform-support/mipsel-unknown-linux-gnu.md)
- [mips\*-mti-none-elf](platform-support/mips-mti-none-elf.md)
- [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
- [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
@@ -85,7 +102,7 @@
- [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
- [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
- - [sparcv9-sun-solaris](platform-support/solaris.md)
+ - [solaris](platform-support/solaris.md)
- [\*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
- [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
@@ -109,21 +126,7 @@
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
- [x86_64-pc-cygwin](platform-support/x86_64-pc-cygwin.md)
- - [x86_64-pc-solaris](platform-support/solaris.md)
- [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
- [xtensa-\*-none-elf](platform-support/xtensa.md)
- [\*-nuttx-\*](platform-support/nuttx.md)
-- [Targets](targets/index.md)
- - [Built-in Targets](targets/built-in.md)
- - [Custom Targets](targets/custom.md)
- - [Known Issues](targets/known-issues.md)
-- [Profile-guided Optimization](profile-guided-optimization.md)
-- [Instrumentation-based Code Coverage](instrument-coverage.md)
-- [Linker-plugin-based LTO](linker-plugin-lto.md)
-- [Checking Conditional Configurations](check-cfg.md)
- - [Cargo Specifics](check-cfg/cargo-specifics.md)
-- [Exploit Mitigations](exploit-mitigations.md)
-- [Symbol Mangling](symbol-mangling/index.md)
- - [v0 Symbol Format](symbol-mangling/v0.md)
-- [Contributing to `rustc`](contributing.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 3a8f840..bc97568 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -334,7 +334,7 @@
`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.3
`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` | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23)
+[`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.3
`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc
[`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support
diff --git a/src/doc/rustc/src/platform-support/apple-darwin.md b/src/doc/rustc/src/platform-support/apple-darwin.md
index dba2c4b..22c54d0 100644
--- a/src/doc/rustc/src/platform-support/apple-darwin.md
+++ b/src/doc/rustc/src/platform-support/apple-darwin.md
@@ -70,4 +70,5 @@
to disambiguate.
The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk macosx --show-sdk-path`.
diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
index a546561..79966d9 100644
--- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md
+++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
@@ -20,7 +20,8 @@
iOS-specific headers, as provided by Xcode 11 or higher.
The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk macosx --show-sdk-path`.
### OS version
diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md
index cfb458f..7f5dc36 100644
--- a/src/doc/rustc/src/platform-support/apple-ios.md
+++ b/src/doc/rustc/src/platform-support/apple-ios.md
@@ -26,7 +26,8 @@
ARM64 targets, Xcode 12 or higher is required.
The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk iphoneos --show-sdk-path`.
### OS version
diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md
index 166bb1b6..fc46db2 100644
--- a/src/doc/rustc/src/platform-support/apple-tvos.md
+++ b/src/doc/rustc/src/platform-support/apple-tvos.md
@@ -20,7 +20,8 @@
ARM64 targets, Xcode 12 or higher is required.
The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk appletvos --show-sdk-path`.
### OS version
diff --git a/src/doc/rustc/src/platform-support/apple-visionos.md b/src/doc/rustc/src/platform-support/apple-visionos.md
index a7bbae1..7cf9549 100644
--- a/src/doc/rustc/src/platform-support/apple-visionos.md
+++ b/src/doc/rustc/src/platform-support/apple-visionos.md
@@ -18,7 +18,8 @@
(`XROS.sdk` or `XRSimulator.sdk`), as provided by Xcode 15 or newer.
The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk xros --show-sdk-path`.
### OS version
diff --git a/src/doc/rustc/src/platform-support/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md
index 0bf8cdf..7b12d9e 100644
--- a/src/doc/rustc/src/platform-support/apple-watchos.md
+++ b/src/doc/rustc/src/platform-support/apple-watchos.md
@@ -24,7 +24,8 @@
ARM64 targets, Xcode 12 or higher is required.
The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk watchos --show-sdk-path`.
### OS version
diff --git a/src/doc/rustc/src/platform-support/mipsel-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/mipsel-unknown-linux-gnu.md
new file mode 100644
index 0000000..b1ee872
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/mipsel-unknown-linux-gnu.md
@@ -0,0 +1,28 @@
+# `mipsel-unknown-linux-gnu`
+
+**Tier: 3**
+
+Little-endian 32 bit MIPS for Linux with `glibc.
+
+## Target maintainers
+
+- [@LukasWoodtli](https://github.com/LukasWoodtli)
+
+## Requirements
+
+The target supports std on Linux. Host tools are supported but not tested.
+
+
+## Building the target
+
+For cross compilation the GNU C compiler for the mipsel architecture needs to
+be installed. On Ubuntu install the packets: `gcc-mipsel-linux-gnu` and
+`g++-mipsel-linux-gnu`.
+
+Add `mipsel-unknown-linux-gnu` as `target` list in `config.toml`.
+
+## Building Rust programs
+
+Rust does not ship pre-compiled artifacts for this target. To compile for
+this target, you will need to build Rust with the target enabled (see
+"Building the target" above).
diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md
index ef9337b..5c2ce0e 100644
--- a/src/doc/rustc/src/platform-support/netbsd.md
+++ b/src/doc/rustc/src/platform-support/netbsd.md
@@ -34,7 +34,7 @@
## Designated Developers
- [@he32](https://github.com/he32), `he@NetBSD.org`
-- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust
+- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust185/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust
- [NetBSD's pkgsrc lang/rust](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust) for the "proper" package in pkgsrc.
- [NetBSD's pkgsrc lang/rust-bin](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust-bin) which re-uses the bootstrap kit as a binary distribution and therefore avoids the rather protracted native build time of rust itself
diff --git a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
index f4ed620..746b844 100644
--- a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
@@ -26,8 +26,7 @@
## Target maintainers
-* [Rust Embedded Devices Working Group Cortex-M
- Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
## Target CPU and Target Feature options
diff --git a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
index 11c9486..12e2826 100644
--- a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
@@ -21,8 +21,7 @@
## Target maintainers
-* [Rust Embedded Devices Working Group Cortex-M
- Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
## Target CPU and Target Feature options
diff --git a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
index b258033..03324b3 100644
--- a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
@@ -22,8 +22,7 @@
## Target maintainers
-* [Rust Embedded Devices Working Group Cortex-M
- Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
## Target CPU and Target Feature options
diff --git a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
index 0ae4e3e..4a92e85 100644
--- a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
@@ -22,8 +22,7 @@
## Target maintainers
-* [Rust Embedded Devices Working Group Cortex-M
- Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
## Target CPU and Target Feature options
diff --git a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
index 82fdc5b..9f85d08 100644
--- a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
@@ -25,8 +25,7 @@
## Target maintainers
-* [Rust Embedded Devices Working Group Cortex-M
- Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
## Target CPU and Target Feature options
diff --git a/src/doc/unstable-book/src/compiler-flags/embed-metadata.md b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md
new file mode 100644
index 0000000..a2a790e
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md
@@ -0,0 +1,3 @@
+## `embed-metadata`
+
+This option instructs `rustc` to include the full metadata in `rlib` and `dylib` crate types. The default value is `yes` (enabled). If disabled (`no`), only stub metadata will be stored in these files, to reduce their size on disk. When using `-Zembed-metadata=no`, you will probably want to use `--emit=metadata` to produce the full metadata into a separate `.rmeta` file.
diff --git a/src/doc/unstable-book/src/language-features/inline-const-pat.md b/src/doc/unstable-book/src/language-features/inline-const-pat.md
deleted file mode 100644
index c6f54d7..0000000
--- a/src/doc/unstable-book/src/language-features/inline-const-pat.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# `inline_const_pat`
-
-The tracking issue for this feature is: [#76001]
-
-------
-
-This feature allows you to use inline constant expressions in pattern position:
-
-```rust
-#![feature(inline_const_pat)]
-
-const fn one() -> i32 { 1 }
-
-let some_int = 3;
-match some_int {
- const { 1 + 2 } => println!("Matched 1 + 2"),
- const { one() } => println!("Matched const fn returning 1"),
- _ => println!("Didn't match anything :("),
-}
-```
-
-[#76001]: https://github.com/rust-lang/rust/issues/76001
diff --git a/src/doc/unstable-book/src/library-features/c-variadic.md b/src/doc/unstable-book/src/library-features/c-variadic.md
deleted file mode 100644
index 7776211..0000000
--- a/src/doc/unstable-book/src/library-features/c-variadic.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# `c_variadic`
-
-The tracking issue for this feature is: [#44930]
-
-[#44930]: https://github.com/rust-lang/rust/issues/44930
-
-------------------------
-
-The `c_variadic` library feature exposes the `VaList` structure,
-Rust's analogue of C's `va_list` type.
-
-## Examples
-
-```rust
-#![feature(c_variadic)]
-
-use std::ffi::VaList;
-
-pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize {
- let mut sum = 0;
- for _ in 0..n {
- sum += args.arg::<usize>();
- }
- sum
-}
-```
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
index bacb9e0..8a9c532 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/etc/test-float-parse/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "test-float-parse"
version = "0.1.0"
-edition = "2021"
+edition = "2024"
publish = false
[dependencies]
diff --git a/src/etc/test-float-parse/src/gen/exhaustive.rs b/src/etc/test-float-parse/src/gen_/exhaustive.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/exhaustive.rs
rename to src/etc/test-float-parse/src/gen_/exhaustive.rs
diff --git a/src/etc/test-float-parse/src/gen/exponents.rs b/src/etc/test-float-parse/src/gen_/exponents.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/exponents.rs
rename to src/etc/test-float-parse/src/gen_/exponents.rs
diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen_/fuzz.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/fuzz.rs
rename to src/etc/test-float-parse/src/gen_/fuzz.rs
diff --git a/src/etc/test-float-parse/src/gen/integers.rs b/src/etc/test-float-parse/src/gen_/integers.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/integers.rs
rename to src/etc/test-float-parse/src/gen_/integers.rs
diff --git a/src/etc/test-float-parse/src/gen/long_fractions.rs b/src/etc/test-float-parse/src/gen_/long_fractions.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/long_fractions.rs
rename to src/etc/test-float-parse/src/gen_/long_fractions.rs
diff --git a/src/etc/test-float-parse/src/gen/many_digits.rs b/src/etc/test-float-parse/src/gen_/many_digits.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/many_digits.rs
rename to src/etc/test-float-parse/src/gen_/many_digits.rs
diff --git a/src/etc/test-float-parse/src/gen/sparse.rs b/src/etc/test-float-parse/src/gen_/sparse.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/sparse.rs
rename to src/etc/test-float-parse/src/gen_/sparse.rs
diff --git a/src/etc/test-float-parse/src/gen/spot_checks.rs b/src/etc/test-float-parse/src/gen_/spot_checks.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/spot_checks.rs
rename to src/etc/test-float-parse/src/gen_/spot_checks.rs
diff --git a/src/etc/test-float-parse/src/gen/subnorm.rs b/src/etc/test-float-parse/src/gen_/subnorm.rs
similarity index 100%
rename from src/etc/test-float-parse/src/gen/subnorm.rs
rename to src/etc/test-float-parse/src/gen_/subnorm.rs
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
index e2f84b0..3c3ef58 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/etc/test-float-parse/src/lib.rs
@@ -17,7 +17,7 @@
use validate::CheckError;
/// Test generators.
-mod gen {
+mod gen_ {
pub mod exhaustive;
pub mod exponents;
pub mod fuzz;
@@ -136,24 +136,24 @@ fn register_float<F: Float>(tests: &mut Vec<TestInfo>, cfg: &Config)
{
if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE {
// Only run exhaustive tests if there is a chance of completion.
- TestInfo::register::<F, gen::exhaustive::Exhaustive<F>>(tests);
+ TestInfo::register::<F, gen_::exhaustive::Exhaustive<F>>(tests);
}
- gen::fuzz::Fuzz::<F>::set_iterations(cfg.fuzz_count);
+ gen_::fuzz::Fuzz::<F>::set_iterations(cfg.fuzz_count);
- TestInfo::register::<F, gen::exponents::LargeExponents<F>>(tests);
- TestInfo::register::<F, gen::exponents::SmallExponents<F>>(tests);
- TestInfo::register::<F, gen::fuzz::Fuzz<F>>(tests);
- TestInfo::register::<F, gen::integers::LargeInt<F>>(tests);
- TestInfo::register::<F, gen::integers::SmallInt>(tests);
- TestInfo::register::<F, gen::long_fractions::RepeatingDecimal>(tests);
- TestInfo::register::<F, gen::many_digits::RandDigits<F>>(tests);
- TestInfo::register::<F, gen::sparse::FewOnesFloat<F>>(tests);
- TestInfo::register::<F, gen::sparse::FewOnesInt<F>>(tests);
- TestInfo::register::<F, gen::spot_checks::RegressionCheck>(tests);
- TestInfo::register::<F, gen::spot_checks::Special>(tests);
- TestInfo::register::<F, gen::subnorm::SubnormComplete<F>>(tests);
- TestInfo::register::<F, gen::subnorm::SubnormEdgeCases<F>>(tests);
+ TestInfo::register::<F, gen_::exponents::LargeExponents<F>>(tests);
+ TestInfo::register::<F, gen_::exponents::SmallExponents<F>>(tests);
+ TestInfo::register::<F, gen_::fuzz::Fuzz<F>>(tests);
+ TestInfo::register::<F, gen_::integers::LargeInt<F>>(tests);
+ TestInfo::register::<F, gen_::integers::SmallInt>(tests);
+ TestInfo::register::<F, gen_::long_fractions::RepeatingDecimal>(tests);
+ TestInfo::register::<F, gen_::many_digits::RandDigits<F>>(tests);
+ TestInfo::register::<F, gen_::sparse::FewOnesFloat<F>>(tests);
+ TestInfo::register::<F, gen_::sparse::FewOnesInt<F>>(tests);
+ TestInfo::register::<F, gen_::spot_checks::RegressionCheck>(tests);
+ TestInfo::register::<F, gen_::spot_checks::Special>(tests);
+ TestInfo::register::<F, gen_::subnorm::SubnormComplete<F>>(tests);
+ TestInfo::register::<F, gen_::subnorm::SubnormEdgeCases<F>>(tests);
}
/// Configuration for a single test.
@@ -343,7 +343,7 @@ fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration {
///
/// This calls the generator's iterator multiple times (in parallel) and validates each output.
fn test_runner<F: Float, G: Generator<F>>(test: &TestInfo, cfg: &Config) {
- let gen = G::new();
+ let gen_ = G::new();
let executed = AtomicU64::new(0);
let failures = AtomicU64::new(0);
@@ -387,7 +387,7 @@ fn test_runner<F: Float, G: Generator<F>>(test: &TestInfo, cfg: &Config) {
// Run the test iterations in parallel. Each thread gets a string buffer to write
// its check values to.
- let res = gen.par_bridge().try_for_each_init(String::new, check_one);
+ let res = gen_.par_bridge().try_for_each_init(String::new, check_one);
let elapsed = started.elapsed();
let executed = executed.into_inner();
diff --git a/src/etc/test-float-parse/src/ui.rs b/src/etc/test-float-parse/src/ui.rs
index 1ee5772..73473eef 100644
--- a/src/etc/test-float-parse/src/ui.rs
+++ b/src/etc/test-float-parse/src/ui.rs
@@ -157,7 +157,7 @@ pub fn set_panic_hook(drop_bars: &[ProgressBar]) {
}));
}
-/// Allow non-Debug items in a `derive(Debug)` struct`.
+/// Allow non-Debug items in a `derive(Debug)` struct.
#[derive(Clone)]
struct NoDebug<T>(T);
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 6ace626..a48f5c6 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -114,8 +114,8 @@ fn synthesize_auto_trait_impl<'tcx>(
};
Some(clean::Item {
- name: None,
inner: Box::new(clean::ItemInner {
+ name: None,
attrs: Default::default(),
stability: None,
kind: clean::ImplItem(Box::new(clean::Impl {
@@ -127,10 +127,10 @@ fn synthesize_auto_trait_impl<'tcx>(
polarity,
kind: clean::ImplKind::Auto,
})),
+ item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
+ cfg: None,
+ inline_stmt_id: None,
}),
- item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
- cfg: None,
- inline_stmt_id: None,
})
}
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index a6d9676..89245fe 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -83,9 +83,9 @@ pub(crate) fn synthesize_blanket_impls(
cx.generated_synthetics.insert((ty.skip_binder(), trait_def_id));
blanket_impls.push(clean::Item {
- name: None,
- item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
inner: Box::new(clean::ItemInner {
+ name: None,
+ item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
attrs: Default::default(),
stability: None,
kind: clean::ImplItem(Box::new(clean::Impl {
@@ -122,9 +122,9 @@ pub(crate) fn synthesize_blanket_impls(
None,
))),
})),
+ cfg: None,
+ inline_stmt_id: None,
}),
- cfg: None,
- inline_stmt_id: None,
});
}
}
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4fd669a..e0e09b5 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -151,7 +151,7 @@ pub(crate) fn try_inline(
let mut item =
crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None);
// The visibility needs to reflect the one from the reexport and not from the "source" DefId.
- item.inline_stmt_id = import_def_id;
+ item.inner.inline_stmt_id = import_def_id;
ret.push(item);
Some(ret)
}
@@ -655,11 +655,11 @@ fn build_module_items(
// Primitive types can't be inlined so generate an import instead.
let prim_ty = clean::PrimitiveType::from(p);
items.push(clean::Item {
- name: None,
- // We can use the item's `DefId` directly since the only information ever used
- // from it is `DefId.krate`.
- item_id: ItemId::DefId(did),
inner: Box::new(clean::ItemInner {
+ name: None,
+ // We can use the item's `DefId` directly since the only information ever
+ // used from it is `DefId.krate`.
+ item_id: ItemId::DefId(did),
attrs: Default::default(),
stability: None,
kind: clean::ImportItem(clean::Import::new_simple(
@@ -679,9 +679,9 @@ fn build_module_items(
},
true,
)),
+ cfg: None,
+ inline_stmt_id: None,
}),
- cfg: None,
- inline_stmt_id: None,
});
} else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) {
items.extend(i)
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index de6dc08..c08ae16 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -210,7 +210,7 @@ fn generate_item_with_correct_attrs(
let name = renamed.or(Some(name));
let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
- item.inline_stmt_id = import_id;
+ item.inner.inline_stmt_id = import_id;
item
}
@@ -1943,14 +1943,11 @@ fn clean_trait_object_lifetime_bound<'tcx>(
// latter contrary to `clean_middle_region`.
match *region {
ty::ReStatic => Some(Lifetime::statik()),
- ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)),
- ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. })
- if name != kw::Empty =>
- {
+ ty::ReEarlyParam(region) => Some(Lifetime(region.name)),
+ ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => {
Some(Lifetime(name))
}
- ty::ReEarlyParam(_)
- | ty::ReBound(..)
+ ty::ReBound(..)
| ty::ReLateParam(_)
| ty::ReVar(_)
| ty::RePlaceholder(_)
@@ -2773,7 +2770,7 @@ fn add_without_unwanted_attributes<'hir>(
if ident == sym::doc {
filter_doc_attr(&mut normal.args, is_inline);
attrs.push((Cow::Owned(attr), import_parent));
- } else if is_inline || ident != sym::cfg {
+ } else if is_inline || ident != sym::cfg_trace {
// If it's not a `cfg()` attribute, we keep it.
attrs.push((Cow::Owned(attr), import_parent));
}
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 27eb56a..143191a 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -311,26 +311,31 @@ pub(crate) enum ExternalLocation {
/// directly to the AST's concept of an item; it's a strict superset.
#[derive(Clone)]
pub(crate) struct Item {
+ pub(crate) inner: Box<ItemInner>,
+}
+
+// Why does the `Item`/`ItemInner` split exist? `Vec<Item>`s are common, and
+// without the split `Item` would be a large type (100+ bytes) which results in
+// lots of wasted space in the unused parts of a `Vec<Item>`. With the split,
+// `Item` is just 8 bytes, and the wasted space is avoided, at the cost of an
+// extra allocation per item. This is a performance win.
+#[derive(Clone)]
+pub(crate) struct ItemInner {
/// The name of this item.
/// Optional because not every item has a name, e.g. impls.
pub(crate) name: Option<Symbol>,
- pub(crate) inner: Box<ItemInner>,
- pub(crate) item_id: ItemId,
- /// This is the `LocalDefId` of the `use` statement if the item was inlined.
- /// The crate metadata doesn't hold this information, so the `use` statement
- /// always belongs to the current crate.
- pub(crate) inline_stmt_id: Option<LocalDefId>,
- pub(crate) cfg: Option<Arc<Cfg>>,
-}
-
-#[derive(Clone)]
-pub(crate) struct ItemInner {
/// Information about this item that is specific to what kind of item it is.
/// E.g., struct vs enum vs function.
pub(crate) kind: ItemKind,
pub(crate) attrs: Attributes,
/// The effective stability, filled out by the `propagate-stability` pass.
pub(crate) stability: Option<Stability>,
+ pub(crate) item_id: ItemId,
+ /// This is the `LocalDefId` of the `use` statement if the item was inlined.
+ /// The crate metadata doesn't hold this information, so the `use` statement
+ /// always belongs to the current crate.
+ pub(crate) inline_stmt_id: Option<LocalDefId>,
+ pub(crate) cfg: Option<Arc<Cfg>>,
}
impl std::ops::Deref for Item {
@@ -488,11 +493,15 @@ pub(crate) fn from_def_id_and_attrs_and_parts(
trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
Item {
- item_id: def_id.into(),
- inner: Box::new(ItemInner { kind, attrs, stability: None }),
- name,
- cfg,
- inline_stmt_id: None,
+ inner: Box::new(ItemInner {
+ item_id: def_id.into(),
+ kind,
+ attrs,
+ stability: None,
+ name,
+ cfg,
+ inline_stmt_id: None,
+ }),
}
}
@@ -1059,7 +1068,7 @@ fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
// `doc(cfg())` overrides `cfg()`).
attrs
.clone()
- .filter(|attr| attr.has_name(sym::cfg))
+ .filter(|attr| attr.has_name(sym::cfg_trace))
.filter_map(|attr| single(attr.meta_item_list()?))
.filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten())
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
@@ -2622,13 +2631,14 @@ mod size_asserts {
use super::*;
// tidy-alphabetical-start
- static_assert_size!(Crate, 56); // frequently moved by-value
+ static_assert_size!(Crate, 16); // frequently moved by-value
static_assert_size!(DocFragment, 32);
static_assert_size!(GenericArg, 32);
static_assert_size!(GenericArgs, 24);
static_assert_size!(GenericParamDef, 40);
static_assert_size!(Generics, 16);
- static_assert_size!(Item, 48);
+ static_assert_size!(Item, 8);
+ static_assert_size!(ItemInner, 136);
static_assert_size!(ItemKind, 48);
static_assert_size!(PathSegment, 32);
static_assert_size!(Type, 32);
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index 9935074..4edd543 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -5,22 +5,36 @@
use std::io;
use std::sync::Arc;
-use rustc_ast as ast;
+use rustc_ast::token::{Delimiter, TokenKind};
+use rustc_ast::tokenstream::TokenTree;
+use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind};
+use rustc_errors::ColorConfig;
use rustc_errors::emitter::stderr_destination;
-use rustc_errors::{ColorConfig, FatalError};
use rustc_parse::new_parser_from_source_str;
-use rustc_parse::parser::attr::InnerAttrPolicy;
use rustc_session::parse::ParseSess;
-use rustc_span::FileName;
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::sym;
+use rustc_span::{FileName, kw};
use tracing::debug;
use super::GlobalTestOptions;
use crate::display::Joined as _;
use crate::html::markdown::LangString;
+#[derive(Default)]
+struct ParseSourceInfo {
+ has_main_fn: bool,
+ already_has_extern_crate: bool,
+ supports_color: bool,
+ has_global_allocator: bool,
+ has_macro_def: bool,
+ everything_else: String,
+ crates: String,
+ crate_attrs: String,
+ maybe_crate_attrs: String,
+}
+
/// This struct contains information about the doctest itself which is then used to generate
/// doctest source code appropriately.
pub(crate) struct DocTestBuilder {
@@ -34,7 +48,7 @@ pub(crate) struct DocTestBuilder {
pub(crate) crates: String,
pub(crate) everything_else: String,
pub(crate) test_id: Option<String>,
- pub(crate) failed_ast: bool,
+ pub(crate) invalid_ast: bool,
pub(crate) can_be_merged: bool,
}
@@ -53,9 +67,26 @@ pub(crate) fn new(
!lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone_crate
});
- let Some(SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else }) =
- partition_source(source, edition)
+ let result = rustc_driver::catch_fatal_errors(|| {
+ rustc_span::create_session_if_not_set_then(edition, |_| {
+ parse_source(source, &crate_name)
+ })
+ });
+
+ let Ok(Ok(ParseSourceInfo {
+ has_main_fn,
+ already_has_extern_crate,
+ supports_color,
+ has_global_allocator,
+ has_macro_def,
+ everything_else,
+ crates,
+ crate_attrs,
+ maybe_crate_attrs,
+ })) = result
else {
+ // If the AST returned an error, we don't want this doctest to be merged with the
+ // others.
return Self::invalid(
String::new(),
String::new(),
@@ -65,35 +96,12 @@ pub(crate) fn new(
);
};
- // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
- // crate already is included.
- let Ok((
- ParseSourceInfo {
- has_main_fn,
- found_extern_crate,
- supports_color,
- has_global_allocator,
- has_macro_def,
- ..
- },
- failed_ast,
- )) = check_for_main_and_extern_crate(
- crate_name,
- source,
- &everything_else,
- &crates,
- edition,
- can_merge_doctests,
- )
- else {
- // If the parser panicked due to a fatal error, pass the test code through unchanged.
- // The error will be reported during compilation.
- return Self::invalid(crate_attrs, maybe_crate_attrs, crates, everything_else, test_id);
- };
- // If the AST returned an error, we don't want this doctest to be merged with the
- // others. Same if it contains `#[feature]` or `#[no_std]`.
+ debug!("crate_attrs:\n{crate_attrs}{maybe_crate_attrs}");
+ debug!("crates:\n{crates}");
+ debug!("after:\n{everything_else}");
+
+ // If it contains `#[feature]` or `#[no_std]`, we don't want it to be merged either.
let can_be_merged = can_merge_doctests
- && !failed_ast
&& !has_global_allocator
&& crate_attrs.is_empty()
// If this is a merged doctest and a defined macro uses `$crate`, then the path will
@@ -106,9 +114,9 @@ pub(crate) fn new(
maybe_crate_attrs,
crates,
everything_else,
- already_has_extern_crate: found_extern_crate,
+ already_has_extern_crate,
test_id,
- failed_ast: false,
+ invalid_ast: false,
can_be_merged,
}
}
@@ -129,7 +137,7 @@ fn invalid(
everything_else,
already_has_extern_crate: false,
test_id,
- failed_ast: true,
+ invalid_ast: true,
can_be_merged: false,
}
}
@@ -143,9 +151,10 @@ pub(crate) fn generate_unique_doctest(
opts: &GlobalTestOptions,
crate_name: Option<&str>,
) -> (String, usize) {
- if self.failed_ast {
+ if self.invalid_ast {
// If the AST failed to compile, no need to go generate a complete doctest, the error
// will be better this way.
+ debug!("invalid AST:\n{test_code}");
return (test_code.to_string(), 0);
}
let mut line_offset = 0;
@@ -168,9 +177,24 @@ pub(crate) fn generate_unique_doctest(
// Now push any outer attributes from the example, assuming they
// are intended to be crate attributes.
- prog.push_str(&self.crate_attrs);
- prog.push_str(&self.maybe_crate_attrs);
- prog.push_str(&self.crates);
+ if !self.crate_attrs.is_empty() {
+ prog.push_str(&self.crate_attrs);
+ if !self.crate_attrs.ends_with('\n') {
+ prog.push('\n');
+ }
+ }
+ if !self.maybe_crate_attrs.is_empty() {
+ prog.push_str(&self.maybe_crate_attrs);
+ if !self.maybe_crate_attrs.ends_with('\n') {
+ prog.push('\n');
+ }
+ }
+ if !self.crates.is_empty() {
+ prog.push_str(&self.crates);
+ if !self.crates.ends_with('\n') {
+ prog.push('\n');
+ }
+ }
// Don't inject `extern crate std` because it's already injected by the
// compiler.
@@ -255,14 +279,7 @@ pub(crate) fn generate_unique_doctest(
}
}
-#[derive(PartialEq, Eq, Debug)]
-enum ParsingResult {
- Failed,
- AstError,
- Ok,
-}
-
-fn cancel_error_count(psess: &ParseSess) {
+fn reset_error_count(psess: &ParseSess) {
// Reset errors so that they won't be reported as compiler bugs when dropping the
// dcx. Any errors in the tests will be reported when the test file is compiled,
// Note that we still need to cancel the errors above otherwise `Diag` will panic on
@@ -270,17 +287,19 @@ fn cancel_error_count(psess: &ParseSess) {
psess.dcx().reset_err_count();
}
-fn parse_source(
- source: String,
- info: &mut ParseSourceInfo,
- crate_name: &Option<&str>,
-) -> ParsingResult {
+const DOCTEST_CODE_WRAPPER: &str = "fn f(){";
+
+fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceInfo, ()> {
use rustc_errors::DiagCtxt;
use rustc_errors::emitter::{Emitter, HumanEmitter};
- use rustc_parse::parser::ForceCollect;
use rustc_span::source_map::FilePathMapping;
- let filename = FileName::anon_source_code(&source);
+ let mut info =
+ ParseSourceInfo { already_has_extern_crate: crate_name.is_none(), ..Default::default() };
+
+ let wrapped_source = format!("{DOCTEST_CODE_WRAPPER}{source}\n}}");
+
+ let filename = FileName::anon_source_code(&wrapped_source);
// Any errors in parsing should also appear when the doctest is compiled for real, so just
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
@@ -299,25 +318,32 @@ fn parse_source(
let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
let psess = ParseSess::with_dcx(dcx, sm);
- let mut parser = match new_parser_from_source_str(&psess, filename, source) {
+ let mut parser = match new_parser_from_source_str(&psess, filename, wrapped_source) {
Ok(p) => p,
Err(errs) => {
errs.into_iter().for_each(|err| err.cancel());
- cancel_error_count(&psess);
- return ParsingResult::Failed;
+ reset_error_count(&psess);
+ return Err(());
}
};
- let mut parsing_result = ParsingResult::Ok;
+
+ fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) {
+ let extra_len = DOCTEST_CODE_WRAPPER.len();
+ // We need to shift by the length of `DOCTEST_CODE_WRAPPER` because we
+ // added it at the beginning of the source we provided to the parser.
+ let mut hi = span.hi().0 as usize - extra_len;
+ if hi > source.len() {
+ hi = source.len();
+ }
+ s.push_str(&source[*prev_span_hi..hi]);
+ *prev_span_hi = hi;
+ }
// Recurse through functions body. It is necessary because the doctest source code is
// wrapped in a function to limit the number of AST errors. If we don't recurse into
// functions, we would thing all top-level items (so basically nothing).
- fn check_item(
- item: &ast::Item,
- info: &mut ParseSourceInfo,
- crate_name: &Option<&str>,
- is_top_level: bool,
- ) {
+ fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool {
+ let mut is_extern_crate = false;
if !info.has_global_allocator
&& item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator)
{
@@ -325,320 +351,130 @@ fn check_item(
}
match item.kind {
ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => {
- if item.ident.name == sym::main && is_top_level {
+ // We only push if it's the top item because otherwise, we would duplicate
+ // its content since the top-level item was already added.
+ if fn_item.ident.name == sym::main {
info.has_main_fn = true;
}
- if let Some(ref body) = fn_item.body {
- for stmt in &body.stmts {
- match stmt.kind {
- ast::StmtKind::Item(ref item) => {
- check_item(item, info, crate_name, false)
- }
- ast::StmtKind::MacCall(..) => info.found_macro = true,
- _ => {}
- }
- }
- }
}
- ast::ItemKind::ExternCrate(original) => {
- if !info.found_extern_crate
+ ast::ItemKind::ExternCrate(original, ident) => {
+ is_extern_crate = true;
+ if !info.already_has_extern_crate
&& let Some(crate_name) = crate_name
{
- info.found_extern_crate = match original {
+ info.already_has_extern_crate = match original {
Some(name) => name.as_str() == *crate_name,
- None => item.ident.as_str() == *crate_name,
+ None => ident.as_str() == *crate_name,
};
}
}
- ast::ItemKind::MacCall(..) => info.found_macro = true,
- ast::ItemKind::MacroDef(..) => info.has_macro_def = true,
+ ast::ItemKind::MacroDef(..) => {
+ info.has_macro_def = true;
+ }
_ => {}
}
+ is_extern_crate
}
- loop {
- match parser.parse_item(ForceCollect::No) {
- Ok(Some(item)) => {
- check_item(&item, info, crate_name, true);
+ let mut prev_span_hi = 0;
+ let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect];
+ let parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No);
- if info.has_main_fn && info.found_extern_crate {
- break;
+ let result = match parsed {
+ Ok(Some(ref item))
+ if let ast::ItemKind::Fn(ref fn_item) = item.kind
+ && let Some(ref body) = fn_item.body =>
+ {
+ for attr in &item.attrs {
+ let attr_name = attr.name_or_empty();
+
+ if attr.style == AttrStyle::Outer || not_crate_attrs.contains(&attr_name) {
+ // There is one exception to these attributes:
+ // `#![allow(internal_features)]`. If this attribute is used, we need to
+ // consider it only as a crate-level attribute.
+ if attr_name == sym::allow
+ && let Some(list) = attr.meta_item_list()
+ && list.iter().any(|sub_attr| {
+ sub_attr.name_or_empty().as_str() == "internal_features"
+ })
+ {
+ push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
+ } else {
+ push_to_s(
+ &mut info.maybe_crate_attrs,
+ source,
+ attr.span,
+ &mut prev_span_hi,
+ );
+ }
+ } else {
+ push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
}
}
- Ok(None) => break,
- Err(e) => {
- parsing_result = ParsingResult::AstError;
- e.cancel();
- break;
+ for stmt in &body.stmts {
+ let mut is_extern_crate = false;
+ match stmt.kind {
+ StmtKind::Item(ref item) => {
+ is_extern_crate = check_item(&item, &mut info, crate_name);
+ }
+ StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => {
+ reset_error_count(&psess);
+ return Err(());
+ }
+ StmtKind::MacCall(ref mac_call) if !info.has_main_fn => {
+ let mut iter = mac_call.mac.args.tokens.iter();
+
+ while let Some(token) = iter.next() {
+ if let TokenTree::Token(token, _) = token
+ && let TokenKind::Ident(name, _) = token.kind
+ && name == kw::Fn
+ && let Some(TokenTree::Token(fn_token, _)) = iter.peek()
+ && let TokenKind::Ident(fn_name, _) = fn_token.kind
+ && fn_name == sym::main
+ && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = {
+ iter.next();
+ iter.peek()
+ }
+ {
+ info.has_main_fn = true;
+ break;
+ }
+ }
+ }
+ _ => {}
+ }
+
+ // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to
+ // tweak the span to include the attributes as well.
+ let mut span = stmt.span;
+ if let Some(attr) =
+ stmt.kind.attrs().iter().find(|attr| attr.style == AttrStyle::Outer)
+ {
+ span = span.with_lo(attr.span.lo());
+ }
+ if info.everything_else.is_empty()
+ && (!info.maybe_crate_attrs.is_empty() || !info.crate_attrs.is_empty())
+ {
+ // To keep the doctest code "as close as possible" to the original, we insert
+ // all the code located between this new span and the previous span which
+ // might contain code comments and backlines.
+ push_to_s(&mut info.crates, source, span.shrink_to_lo(), &mut prev_span_hi);
+ }
+ if !is_extern_crate {
+ push_to_s(&mut info.everything_else, source, span, &mut prev_span_hi);
+ } else {
+ push_to_s(&mut info.crates, source, span, &mut prev_span_hi);
+ }
}
+ Ok(info)
}
-
- // The supplied item is only used for diagnostics,
- // which are swallowed here anyway.
- parser.maybe_consume_incorrect_semicolon(None);
- }
-
- cancel_error_count(&psess);
- parsing_result
-}
-
-#[derive(Default)]
-struct ParseSourceInfo {
- has_main_fn: bool,
- found_extern_crate: bool,
- found_macro: bool,
- supports_color: bool,
- has_global_allocator: bool,
- has_macro_def: bool,
-}
-
-fn check_for_main_and_extern_crate(
- crate_name: Option<&str>,
- original_source_code: &str,
- everything_else: &str,
- crates: &str,
- edition: Edition,
- can_merge_doctests: bool,
-) -> Result<(ParseSourceInfo, bool), FatalError> {
- let result = rustc_driver::catch_fatal_errors(|| {
- rustc_span::create_session_if_not_set_then(edition, |_| {
- let mut info =
- ParseSourceInfo { found_extern_crate: crate_name.is_none(), ..Default::default() };
-
- let mut parsing_result =
- parse_source(format!("{crates}{everything_else}"), &mut info, &crate_name);
- // No need to double-check this if the "merged doctests" feature isn't enabled (so
- // before the 2024 edition).
- if can_merge_doctests && parsing_result != ParsingResult::Ok {
- // If we found an AST error, we want to ensure it's because of an expression being
- // used outside of a function.
- //
- // To do so, we wrap in a function in order to make sure that the doctest AST is
- // correct. For example, if your doctest is `foo::bar()`, if we don't wrap it in a
- // block, it would emit an AST error, which would be problematic for us since we
- // want to filter out such errors which aren't "real" errors.
- //
- // The end goal is to be able to merge as many doctests as possible as one for much
- // faster doctests run time.
- parsing_result = parse_source(
- format!("{crates}\nfn __doctest_wrap(){{{everything_else}\n}}"),
- &mut info,
- &crate_name,
- );
- }
-
- (info, parsing_result)
- })
- });
- let (mut info, parsing_result) = match result {
- Err(..) | Ok((_, ParsingResult::Failed)) => return Err(FatalError),
- Ok((info, parsing_result)) => (info, parsing_result),
+ Err(e) => {
+ e.cancel();
+ Err(())
+ }
+ _ => Err(()),
};
- // If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't
- // see it. In that case, run the old text-based scan to see if they at least have a main
- // function written inside a macro invocation. See
- // https://github.com/rust-lang/rust/issues/56898
- if info.found_macro
- && !info.has_main_fn
- && original_source_code
- .lines()
- .map(|line| {
- let comment = line.find("//");
- if let Some(comment_begins) = comment { &line[0..comment_begins] } else { line }
- })
- .any(|code| code.contains("fn main"))
- {
- info.has_main_fn = true;
- }
-
- Ok((info, parsing_result != ParsingResult::Ok))
-}
-
-enum AttrKind {
- CrateAttr,
- Attr,
-}
-
-/// Returns `Some` if the attribute is complete and `Some(true)` if it is an attribute that can be
-/// placed at the crate root.
-fn check_if_attr_is_complete(source: &str, edition: Edition) -> Option<AttrKind> {
- if source.is_empty() {
- // Empty content so nothing to check in here...
- return None;
- }
- let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny];
-
- rustc_driver::catch_fatal_errors(|| {
- rustc_span::create_session_if_not_set_then(edition, |_| {
- use rustc_errors::DiagCtxt;
- use rustc_errors::emitter::HumanEmitter;
- use rustc_span::source_map::FilePathMapping;
-
- let filename = FileName::anon_source_code(source);
- // Any errors in parsing should also appear when the doctest is compiled for real, so just
- // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
- let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
- let fallback_bundle = rustc_errors::fallback_fluent_bundle(
- rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
- false,
- );
-
- let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
-
- let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
- let psess = ParseSess::with_dcx(dcx, sm);
- let mut parser = match new_parser_from_source_str(&psess, filename, source.to_owned()) {
- Ok(p) => p,
- Err(errs) => {
- errs.into_iter().for_each(|err| err.cancel());
- // If there is an unclosed delimiter, an error will be returned by the
- // tokentrees.
- return None;
- }
- };
- // If a parsing error happened, it's very likely that the attribute is incomplete.
- let ret = match parser.parse_attribute(InnerAttrPolicy::Permitted) {
- Ok(attr) => {
- let attr_name = attr.name_or_empty();
-
- if not_crate_attrs.contains(&attr_name) {
- // There is one exception to these attributes:
- // `#![allow(internal_features)]`. If this attribute is used, we need to
- // consider it only as a crate-level attribute.
- if attr_name == sym::allow
- && let Some(list) = attr.meta_item_list()
- && list.iter().any(|sub_attr| {
- sub_attr.name_or_empty().as_str() == "internal_features"
- })
- {
- Some(AttrKind::CrateAttr)
- } else {
- Some(AttrKind::Attr)
- }
- } else {
- Some(AttrKind::CrateAttr)
- }
- }
- Err(e) => {
- e.cancel();
- None
- }
- };
- ret
- })
- })
- .unwrap_or(None)
-}
-
-fn handle_attr(mod_attr_pending: &mut String, source_info: &mut SourceInfo, edition: Edition) {
- if let Some(attr_kind) = check_if_attr_is_complete(mod_attr_pending, edition) {
- let push_to = match attr_kind {
- AttrKind::CrateAttr => &mut source_info.crate_attrs,
- AttrKind::Attr => &mut source_info.maybe_crate_attrs,
- };
- push_to.push_str(mod_attr_pending);
- push_to.push('\n');
- // If it's complete, then we can clear the pending content.
- mod_attr_pending.clear();
- } else {
- mod_attr_pending.push('\n');
- }
-}
-
-#[derive(Default)]
-struct SourceInfo {
- crate_attrs: String,
- maybe_crate_attrs: String,
- crates: String,
- everything_else: String,
-}
-
-fn partition_source(s: &str, edition: Edition) -> Option<SourceInfo> {
- #[derive(Copy, Clone, PartialEq)]
- enum PartitionState {
- Attrs,
- Crates,
- Other,
- }
- let mut source_info = SourceInfo::default();
- let mut state = PartitionState::Attrs;
- let mut mod_attr_pending = String::new();
-
- for line in s.lines() {
- let trimline = line.trim();
-
- // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
- // shunted into "everything else"
- match state {
- PartitionState::Attrs => {
- state = if trimline.starts_with("#![") {
- mod_attr_pending = line.to_owned();
- handle_attr(&mut mod_attr_pending, &mut source_info, edition);
- continue;
- } else if trimline.chars().all(|c| c.is_whitespace())
- || (trimline.starts_with("//") && !trimline.starts_with("///"))
- {
- PartitionState::Attrs
- } else if trimline.starts_with("extern crate")
- || trimline.starts_with("#[macro_use] extern crate")
- {
- PartitionState::Crates
- } else {
- // First we check if the previous attribute was "complete"...
- if !mod_attr_pending.is_empty() {
- // If not, then we append the new line into the pending attribute to check
- // if this time it's complete...
- mod_attr_pending.push_str(line);
- if !trimline.is_empty() {
- handle_attr(&mut mod_attr_pending, &mut source_info, edition);
- }
- continue;
- } else {
- PartitionState::Other
- }
- };
- }
- PartitionState::Crates => {
- state = if trimline.starts_with("extern crate")
- || trimline.starts_with("#[macro_use] extern crate")
- || trimline.chars().all(|c| c.is_whitespace())
- || (trimline.starts_with("//") && !trimline.starts_with("///"))
- {
- PartitionState::Crates
- } else {
- PartitionState::Other
- };
- }
- PartitionState::Other => {}
- }
-
- match state {
- PartitionState::Attrs => {
- source_info.crate_attrs.push_str(line);
- source_info.crate_attrs.push('\n');
- }
- PartitionState::Crates => {
- source_info.crates.push_str(line);
- source_info.crates.push('\n');
- }
- PartitionState::Other => {
- source_info.everything_else.push_str(line);
- source_info.everything_else.push('\n');
- }
- }
- }
-
- if !mod_attr_pending.is_empty() {
- debug!("invalid doctest code: {s:?}");
- return None;
- }
-
- source_info.everything_else = source_info.everything_else.trim().to_string();
-
- debug!("crate_attrs:\n{}{}", source_info.crate_attrs, source_info.maybe_crate_attrs);
- debug!("crates:\n{}", source_info.crates);
- debug!("after:\n{}", source_info.everything_else);
-
- Some(source_info)
+ reset_error_count(&psess);
+ result
}
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index e2b964b..49add73 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -197,6 +197,7 @@ fn make_test_crate_attrs() {
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
#![feature(sick_rad)]
+
fn main() {
assert_eq!(2+2, 4);
}"
@@ -228,8 +229,8 @@ fn make_test_fake_main() {
let input = "//Ceci n'est pas une `fn main`
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
-//Ceci n'est pas une `fn main`
fn main() {
+//Ceci n'est pas une `fn main`
assert_eq!(2+2, 4);
}"
.to_string();
@@ -259,8 +260,8 @@ fn make_test_issues_21299() {
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
-// fn main
fn main() {
+// fn main
assert_eq!(2+2, 4);
}"
.to_string();
@@ -401,3 +402,76 @@ fn compare(input: &str, expected: &[&str]) {
compare("a\n\t \rb", &["a", "b"]);
compare("a\n\t1 \rb", &["a", "1", "b"]);
}
+
+#[test]
+fn comment_in_attrs() {
+ // If there is an inline code comment after attributes, we need to ensure that
+ // a backline will be added to prevent generating code "inside" it (and thus generating)
+ // invalid code.
+ let opts = default_global_opts("");
+ let input = "\
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.";
+ let expected = "\
+#![allow(unused)]
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.
+fn main() {
+
+}"
+ .to_string();
+ let (output, len) = make_test(input, None, false, &opts, None);
+ assert_eq!((output, len), (expected, 2));
+
+ // And same, if there is a `main` function provided by the user, we ensure that it's
+ // correctly separated.
+ let input = "\
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.
+fn main() {}";
+ let expected = "\
+#![allow(unused)]
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.
+
+fn main() {}"
+ .to_string();
+ let (output, len) = make_test(input, None, false, &opts, None);
+ assert_eq!((output, len), (expected, 1));
+}
+
+// This test ensures that the only attributes taken into account when we switch between
+// "crate level" content and the rest doesn't include inner attributes span, as it would
+// include part of the item and generate broken code.
+#[test]
+fn inner_attributes() {
+ let opts = default_global_opts("");
+ let input = r#"
+//! A doc comment that applies to the implicit anonymous module of this crate
+
+pub mod outer_module {
+ //!! - Still an inner line doc (but with a bang at the beginning)
+}
+"#;
+ let expected = "#![allow(unused)]
+
+//! A doc comment that applies to the implicit anonymous module of this crate
+
+
+fn main() {
+pub mod outer_module {
+ //!! - Still an inner line doc (but with a bang at the beginning)
+}
+}"
+ .to_string();
+ let (output, len) = make_test(input, None, false, &opts, None);
+ assert_eq!((output, len), (expected, 2));
+}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index e74fd67..1940200 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -385,7 +385,6 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
// implementations elsewhere.
let ret = if let clean::Item {
inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. },
- ..
} = item
{
// Figure out the id of this impl. This may map to a
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 0d547a6..334a7a8 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1724,6 +1724,7 @@ pub(crate) fn markdown_links<'md, R>(
md: &'md str,
preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
) -> Vec<R> {
+ use itertools::Itertools;
if md.is_empty() {
return vec![];
}
@@ -1882,7 +1883,7 @@ pub(crate) fn markdown_links<'md, R>(
let mut links = Vec::new();
let mut refdefs = FxIndexMap::default();
- for (label, refdef) in event_iter.reference_definitions().iter() {
+ for (label, refdef) in event_iter.reference_definitions().iter().sorted_by_key(|x| x.0) {
refdefs.insert(label.to_string(), (false, refdef.dest.to_string(), refdef.span.clone()));
}
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index e94c6be..91a58fa 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -6,8 +6,10 @@
declare global {
/** Map from crate name to directory structure, for source view */
declare var srcIndex: Map<string, rustdoc.Dir>;
- /** Defined and documented in `main.js` */
+ /** Defined and documented in `storage.js` */
declare function nonnull(x: T|null, msg: string|undefined);
+ /** Defined and documented in `storage.js` */
+ declare function nonundef(x: T|undefined, msg: string|undefined);
interface Window {
/** Make the current theme easy to find */
currentTheme: HTMLLinkElement|null;
@@ -255,13 +257,21 @@
ty: number,
type?: FunctionSearchType,
paramNames?: string[],
- displayType: Promise<Array<Array<string>>>|null,
- displayTypeMappedNames: Promise<Array<[string, Array<string>]>>|null,
+ displayTypeSignature: Promise<rustdoc.DisplayTypeSignature> | null,
item: Row,
dontValidate?: boolean,
}
/**
+ * output of `formatDisplayTypeSignature`
+ */
+ interface DisplayTypeSignature {
+ type: Array<string>,
+ mappedNames: Map<string, string>,
+ whereClause: Map<string, Array<string>>,
+ }
+
+ /**
* A pair of [inputs, outputs], or 0 for null. This is stored in the search index.
* The JavaScript deserializes this into FunctionSearchType.
*
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index c275127..dce5fdd 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -33,6 +33,20 @@
}
}
+/**
+ * Convert any `undefined` to `null`.
+ *
+ * @template T
+ * @param {T|undefined} x
+ * @returns {T|null}
+ */
+function undef2null(x) {
+ if (x !== undefined) {
+ return x;
+ }
+ return null;
+}
+
// ==================== Core search logic begin ====================
// This mapping table should match the discriminants of
// `rustdoc::formats::item_type::ItemType` type in Rust.
@@ -338,7 +352,7 @@
// The type filter doesn't count as an element since it's a modifier.
const typeFilterElem = elems.pop();
checkExtraTypeFilterCharacters(start, parserState);
- // typeFilterElem is not null. If it was, the elems.length check would have fired.
+ // typeFilterElem is not undefined. If it was, the elems.length check would have fired.
// @ts-expect-error
parserState.typeFilter = typeFilterElem.normalizedPathLast;
parserState.pos += 1;
@@ -1311,10 +1325,9 @@
let sste;
if (substart >= 2) {
const tail = name.substring(substart - 2, substart + 1);
- if (tailTable.has(tail)) {
- // it's not undefined
- // @ts-expect-error
- sste = tailTable.get(tail);
+ const entry = tailTable.get(tail);
+ if (entry !== undefined) {
+ sste = entry;
} else {
sste = [];
tailTable.set(tail, sste);
@@ -1338,10 +1351,9 @@
new Lev1TParametricDescription(name.length);
this.searchLev(name, 0, levParams, results);
const tail = name.substring(0, 3);
- if (tailTable.has(tail)) {
- // it's not undefined
- // @ts-expect-error
- for (const entry of tailTable.get(tail)) {
+ const list = tailTable.get(tail);
+ if (list !== undefined) {
+ for (const entry of list) {
entry.searchSubstringPrefix(name, 3, results);
}
}
@@ -1600,10 +1612,8 @@
return null;
}
- if (this.typeNameIdMap.has(name)) {
- /** @type {{id: number, assocOnly: boolean}} */
- // @ts-expect-error
- const obj = this.typeNameIdMap.get(name);
+ const obj = this.typeNameIdMap.get(name);
+ if (obj !== undefined) {
obj.assocOnly = !!(isAssocType && obj.assocOnly);
return obj.id;
} else {
@@ -2082,7 +2092,8 @@
descIndex += 1;
}
- // a String of one character item type codes
+ // see `RawSearchIndexCrate` in `rustdoc.d.ts` for a more
+ // up to date description of these fields
const itemTypes = crateCorpus.t;
// an array of (String) item names
const itemNames = crateCorpus.n;
@@ -2099,8 +2110,6 @@
const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop);
// a map Number, string for impl disambiguators
const implDisambiguator = new Map(crateCorpus.b);
- // an array of [(Number) item type,
- // (String) name]
const rawPaths = crateCorpus.p;
const aliases = crateCorpus.a;
// an array of [(Number) item index,
@@ -2139,30 +2148,31 @@
// convert `rawPaths` entries into object form
// generate normalizedPaths for function search mode
let len = rawPaths.length;
- let lastPath = itemPaths.get(0);
+ let lastPath = undef2null(itemPaths.get(0));
for (let i = 0; i < len; ++i) {
const elem = rawPaths[i];
const ty = elem[0];
const name = elem[1];
- let path = null;
- if (elem.length > 2 && elem[2] !== null) {
- // @ts-expect-error
- path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath;
- lastPath = path;
- }
- let exactPath = elem.length > 3 && elem[3] !== null ?
- // @ts-expect-error
- itemPaths.get(elem[3]) :
- path;
+ /**
+ * @param {2|3} idx
+ * @param {string|null} if_null
+ * @param {string|null} if_not_found
+ * @returns {string|null}
+ */
+ const elemPath = (idx, if_null, if_not_found) => {
+ if (elem.length > idx && elem[idx] !== undefined) {
+ const p = itemPaths.get(elem[idx]);
+ if (p !== undefined) {
+ return p;
+ }
+ return if_not_found;
+ }
+ return if_null;
+ };
+ const path = elemPath(2, lastPath, null);
+ const exactPath = elemPath(3, path, path);
const unboxFlag = elem.length > 4 && !!elem[4];
- if (path === undefined) {
- path = null;
- }
- if (exactPath === undefined) {
- exactPath = null;
- }
-
lowercasePaths.push({ ty, name: name.toLowerCase(), path, exactPath, unboxFlag });
paths[i] = { ty, name, path, exactPath, unboxFlag };
}
@@ -2196,12 +2206,11 @@
}
const name = itemNames[i] === "" ? lastName : itemNames[i];
const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase();
- /** @type {string} */
- // @ts-expect-error
- const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath;
- const paramNames = itemParamNames.has(i) ?
- // @ts-expect-error
- itemParamNames.get(i).split(",") :
+ const pathU = itemPaths.get(i);
+ const path = pathU !== undefined ? pathU : lastPath;
+ const paramNameString = itemParamNames.get(i);
+ const paramNames = paramNameString !== undefined ?
+ paramNameString.split(",") :
lastParamNames;
const type = itemFunctionDecoder.next();
if (type !== null) {
@@ -2243,8 +2252,7 @@
word,
normalizedName,
bitIndex,
- implDisambiguator: implDisambiguator.has(i) ?
- implDisambiguator.get(i) : null,
+ implDisambiguator: undef2null(implDisambiguator.get(i)),
};
this.nameTrie.insert(normalizedName, id, this.tailTable);
id += 1;
@@ -2482,9 +2490,13 @@
}
} catch (err) {
query = newParsedQuery(userQuery);
- // is string list
- // @ts-expect-error
- query.error = err;
+ if (Array.isArray(err) && err.every(elem => typeof elem === "string")) {
+ query.error = err;
+ } else {
+ // rethrow the error if it isn't a string array
+ throw err;
+ }
+
return query;
}
if (!query.literalSearch) {
@@ -2572,9 +2584,9 @@
if ((elem.id === null && parsedQuery.totalElems > 1 && elem.typeFilter === -1
&& elem.generics.length === 0 && elem.bindings.size === 0)
|| elem.typeFilter === TY_GENERIC) {
- if (genericSymbols.has(elem.normalizedPathLast)) {
- // @ts-expect-error
- elem.id = genericSymbols.get(elem.normalizedPathLast);
+ const id = genericSymbols.get(elem.normalizedPathLast);
+ if (id !== undefined) {
+ elem.id = id;
} else {
elem.id = -(genericSymbols.size + 1);
genericSymbols.set(elem.normalizedPathLast, elem.id);
@@ -2766,15 +2778,28 @@
for (const result of results) {
if (result.id !== -1) {
const res = buildHrefAndPath(this.searchIndex[result.id]);
+ // many of these properties don't strictly need to be
+ // copied over, but copying them over satisfies tsc,
+ // and hopefully plays nice with the shape optimization
+ // of the browser engine.
+ /** @type {rustdoc.ResultObject} */
const obj = Object.assign({
+ parent: result.parent,
+ type: result.type,
dist: result.dist,
+ path_dist: result.path_dist,
+ index: result.index,
+ desc: result.desc,
+ item: result.item,
displayPath: pathSplitter(res[0]),
+ fullPath: "",
+ href: "",
+ displayTypeSignature: null,
}, this.searchIndex[result.id]);
// To be sure than it some items aren't considered as duplicate.
- // @ts-expect-error
obj.fullPath = res[2] + "|" + obj.ty;
- // @ts-expect-error
+
if (duplicates.has(obj.fullPath)) {
continue;
}
@@ -2787,18 +2812,15 @@
if (duplicates.has(res[2] + "|" + TY_IMPORT)) {
continue;
}
- // @ts-expect-error
duplicates.add(obj.fullPath);
duplicates.add(res[2]);
if (typeInfo !== null) {
- // @ts-expect-error
obj.displayTypeSignature =
// @ts-expect-error
this.formatDisplayTypeSignature(obj, typeInfo);
}
- // @ts-expect-error
obj.href = res[1];
out.push(obj);
if (out.length >= MAX_RESULTS) {
@@ -2806,7 +2828,6 @@
}
}
}
- // @ts-expect-error
return out;
};
@@ -2819,11 +2840,7 @@
*
* @param {rustdoc.ResultObject} obj
* @param {"sig"|"elems"|"returned"|null} typeInfo
- * @returns {Promise<{
- * "type": Array<string>,
- * "mappedNames": Map<string, string>,
- * "whereClause": Map<string, Array<string>>,
- * }>}
+ * @returns {Promise<rustdoc.DisplayTypeSignature>}
*/
this.formatDisplayTypeSignature = async(obj, typeInfo) => {
const objType = obj.type;
@@ -2885,7 +2902,7 @@
const whereClause = new Map();
const fnParamNames = obj.paramNames || [];
- // @ts-expect-error
+ /** @type {string[]} */
const queryParamNames = [];
/**
* Recursively writes a map of IDs to query generic names,
@@ -2918,7 +2935,7 @@
* index 2 is not highlighted, etc.
*
* @param {{name?: string, highlighted?: boolean}} fnType - input
- * @param {[string]} result
+ * @param {string[]} result
*/
const pushText = (fnType, result) => {
// If !!(result.length % 2) == false, then pushing a new slot starts an even
@@ -2930,7 +2947,6 @@
// needs coerced to a boolean.
if (!!(result.length % 2) === !!fnType.highlighted) {
result.push("");
- // @ts-expect-error
} else if (result.length === 0 && !!fnType.highlighted) {
result.push("");
result.push("");
@@ -2944,7 +2960,7 @@
* or a trait bound on Fn, FnMut, or FnOnce.
*
* @param {rustdoc.HighlightedFunctionType} fnType - input
- * @param {[string]} result
+ * @param {string[]} result
*/
const writeHof = (fnType, result) => {
const hofOutput = fnType.bindings.get(this.typeNameIdOfOutput) || [];
@@ -2984,7 +3000,7 @@
* Returns `false` if the supplied type isn't special.
*
* @param {rustdoc.HighlightedFunctionType} fnType
- * @param {[string]} result
+ * @param {string[]} result
*/
const writeSpecialPrimitive = (fnType, result) => {
if (fnType.id === this.typeNameIdOfArray || fnType.id === this.typeNameIdOfSlice ||
@@ -3031,7 +3047,7 @@
* updating the where clause and generic type param map.
*
* @param {rustdoc.HighlightedFunctionType} fnType
- * @param {[string]} result
+ * @param {string[]} result
*/
const writeFn = (fnType, result) => {
if (fnType.id !== null && fnType.id < 0) {
@@ -3049,7 +3065,6 @@
for (const [queryId, fnId] of mgens) {
if (fnId === fnType.id) {
mappedNames.set(
- // @ts-expect-error
queryParamNames[-1 - queryId],
fnParamNames[-1 - fnType.id],
);
@@ -3064,7 +3079,6 @@
const where = [];
onEachBtwn(
fnType.generics,
- // @ts-expect-error
nested => writeFn(nested, where),
// @ts-expect-error
() => pushText({ name: " + ", highlighted: false }, where),
@@ -3099,7 +3113,6 @@
// shown in the where clause and name mapping output, but is
// redundant in this spot
for (const value of values) {
- // @ts-expect-error
writeFn(value, []);
}
return true;
@@ -3141,26 +3154,22 @@
}
}
};
- // @ts-expect-error
+ /** @type {string[]} */
const type = [];
onEachBtwn(
fnInputs,
- // @ts-expect-error
fnType => writeFn(fnType, type),
// @ts-expect-error
() => pushText({ name: ", ", highlighted: false }, type),
);
- // @ts-expect-error
pushText({ name: " -> ", highlighted: false }, type);
onEachBtwn(
fnOutput,
- // @ts-expect-error
fnType => writeFn(fnType, type),
// @ts-expect-error
() => pushText({ name: ", ", highlighted: false }, type),
);
- // @ts-expect-error
return {type, mappedNames, whereClause};
};
@@ -3475,8 +3484,7 @@
}
}
}
- // @ts-expect-error
- return false;
+ return null;
}
// Multiple element recursive case
@@ -3532,7 +3540,7 @@
}
/** @type {rustdoc.HighlightedFunctionType[]|null} */
let unifiedGenerics = [];
- // @ts-expect-error
+ /** @type {null|Map<number, number>} */
let unifiedGenericsMgens = null;
/** @type {rustdoc.HighlightedFunctionType[]|null} */
const passesUnification = unifyFunctionTypes(
@@ -3586,7 +3594,6 @@
// @ts-expect-error
queryElem.bindings.get(k),
whereClause,
- // @ts-expect-error
unifiedGenericsMgens,
solutionCb,
unboxingDepth,
@@ -3984,7 +3991,7 @@
}
const fnTypeBindings = fnType.bindings.get(name);
mgensSolutionSet = mgensSolutionSet.flatMap(mgens => {
- // @ts-expect-error
+ /** @type{Array<Map<number, number> | null>} */
const newSolutions = [];
unifyFunctionTypes(
// @ts-expect-error
@@ -4000,7 +4007,6 @@
},
unboxingDepth,
);
- // @ts-expect-error
return newSolutions;
});
}
@@ -4248,6 +4254,7 @@
return false;
}
+ // this does not yet have a type in `rustdoc.d.ts`.
// @ts-expect-error
function createAliasFromItem(item) {
return {
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 748d2ef..7611372 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -44,6 +44,28 @@
}
/**
+ * Assert that the passed value is not undefined, then return it.
+ *
+ * Takes an optional error message argument.
+ *
+ * Must be defined in this file, as it is loaded before all others.
+ *
+ * @template T
+ * @param {T|undefined} x
+ * @param {string=} msg
+ * @returns T
+ */
+// used in other files, not yet used in this one.
+// eslint-disable-next-line no-unused-vars
+function nonundef(x, msg) {
+ if (x === undefined) {
+ throw (msg || "unexpected null value!");
+ } else {
+ return x;
+ }
+}
+
+/**
* Get a configuration value. If it's not set, get the default.
*
* @param {string} settingName
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index a5351b3..9d8eb70f 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -43,7 +43,7 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
let attrs = item.attributes(self.tcx, self.cache(), true);
let span = item.span(self.tcx);
let visibility = item.visibility(self.tcx);
- let clean::Item { name, item_id, .. } = item;
+ let clean::ItemInner { name, item_id, .. } = *item.inner;
let id = self.id_from_item(&item);
let inner = match item.kind {
clean::KeywordItem => return None,
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 572c9bf..eddafa9 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -61,7 +61,7 @@ fn merge_with_parent_attributes(&mut self, item: &mut Item) {
let (_, cfg) =
merge_attrs(self.cx, item.attrs.other_attrs.as_slice(), Some((&attrs, None)));
- item.cfg = cfg;
+ item.inner.cfg = cfg;
}
}
@@ -71,7 +71,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
self.merge_with_parent_attributes(&mut item);
- let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
+ let new_cfg = match (self.parent_cfg.take(), item.inner.cfg.take()) {
(None, None) => None,
(Some(rc), None) | (None, Some(rc)) => Some(rc),
(Some(mut a), Some(b)) => {
@@ -81,7 +81,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
}
};
self.parent_cfg = new_cfg.clone();
- item.cfg = new_cfg;
+ item.inner.cfg = new_cfg;
let old_parent =
if let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
diff --git a/src/tools/cargo b/src/tools/cargo
index 307cbfd..a6c604d 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 307cbfda3119f06600e43cd38283f4a746fe1f8b
+Subproject commit a6c604d1b8a2f2a8ff1f3ba6092f9fda42f4b7e9
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
index 5c486eb..4c84e61 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -37,7 +37,6 @@ fn check_duplicated_attr(
let Some(ident) = attr.ident() else { return };
let name = ident.name;
if name == sym::doc
- || name == sym::cfg_attr
|| name == sym::cfg_attr_trace
|| name == sym::rustc_on_unimplemented
|| name == sym::reason {
@@ -47,7 +46,7 @@ fn check_duplicated_attr(
return;
}
if let Some(direct_parent) = parent.last()
- && ["cfg", "cfg_attr"].contains(&direct_parent.as_str())
+ && direct_parent == sym::cfg_trace.as_str()
&& [sym::all, sym::not, sym::any].contains(&name)
{
// FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
index 84136a2..7590fe9 100644
--- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
+++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
@@ -32,7 +32,7 @@
impl EarlyLintPass for CfgNotTest {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
- if attr.has_name(rustc_span::sym::cfg) && contains_not_test(attr.meta_item_list().as_deref(), false) {
+ if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) {
span_lint_and_then(
cx,
CFG_NOT_TEST,
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index 7d86bd3..c2aac7c 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -53,7 +53,7 @@
impl EarlyLintPass for CrateInMacroDef {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- if let ItemKind::MacroDef(macro_def) = &item.kind
+ if let ItemKind::MacroDef(_, macro_def) = &item.kind
&& item.attrs.iter().any(is_macro_export)
&& let Some(span) = contains_unhygienic_crate_reference(¯o_def.body.tokens)
{
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 7fa23da..39e4516 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -638,7 +638,6 @@
crate::precedence::PRECEDENCE_INFO,
crate::precedence::PRECEDENCE_BITS_INFO,
crate::ptr::CMP_NULL_INFO,
- crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
crate::ptr::MUT_FROM_REF_INFO,
crate::ptr::PTR_ARG_INFO,
crate::ptr::PTR_EQ_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 0031da4..de66ead 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -131,6 +131,8 @@ macro_rules! declare_with_version {
("clippy::clone_double_ref", "suspicious_double_ref_op"),
#[clippy::version = ""]
("clippy::cmp_nan", "invalid_nan_comparisons"),
+ #[clippy::version = "CURRENT_RUSTC_VERSION"]
+ ("clippy::invalid_null_ptr_usage", "invalid_null_arguments"),
#[clippy::version = "1.86.0"]
("clippy::double_neg", "double_negations"),
#[clippy::version = ""]
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index 3008082..f6c10da 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -13,16 +13,16 @@
use rustc_session::parse::ParseSess;
use rustc_span::edition::Edition;
use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::{FileName, Pos, sym};
+use rustc_span::{FileName, Ident, Pos, sym};
use super::Fragments;
-fn get_test_spans(item: &Item, test_attr_spans: &mut Vec<Range<usize>>) {
+fn get_test_spans(item: &Item, ident: Ident, test_attr_spans: &mut Vec<Range<usize>>) {
test_attr_spans.extend(
item.attrs
.iter()
.find(|attr| attr.has_name(sym::test))
- .map(|attr| attr.span.lo().to_usize()..item.ident.span.hi().to_usize()),
+ .map(|attr| attr.span.lo().to_usize()..ident.span.hi().to_usize()),
);
}
@@ -64,10 +64,10 @@ fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec
match parser.parse_item(ForceCollect::No) {
Ok(Some(item)) => match &item.kind {
ItemKind::Fn(box Fn {
- sig, body: Some(block), ..
- }) if item.ident.name == sym::main => {
+ ident, sig, body: Some(block), ..
+ }) if ident.name == sym::main => {
if !ignore {
- get_test_spans(&item, &mut test_attr_spans);
+ get_test_spans(&item, *ident, &mut test_attr_spans);
}
let is_async = matches!(sig.header.coroutine_kind, Some(CoroutineKind::Async { .. }));
let returns_nothing = match &sig.decl.output {
@@ -85,10 +85,10 @@ fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec
}
},
// Another function was found; this case is ignored for needless_doctest_main
- ItemKind::Fn(box Fn { .. }) => {
+ ItemKind::Fn(fn_) => {
eligible = false;
if !ignore {
- get_test_spans(&item, &mut test_attr_spans);
+ get_test_spans(&item, fn_.ident, &mut test_attr_spans);
}
},
// Tests with one of these items are ignored
diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
index 1dac7b9..243c99a 100644
--- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
+++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
@@ -63,7 +63,7 @@ pub struct DuplicateMod {
impl EarlyLintPass for DuplicateMod {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
+ if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
&& let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
&& let Some(local_path) = real.into_local_path()
&& let Ok(absolute_path) = local_path.canonicalize()
diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
index 80c2b03..c67dcd3 100644
--- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
@@ -8,8 +8,7 @@
use rustc_lexer::TokenKind;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::kw;
-use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol};
+use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw};
declare_clippy_lint! {
/// ### What it does
@@ -375,21 +374,23 @@ fn check_item_kind(
&mut self,
cx: &EarlyContext<'_>,
kind: &ItemKind,
- ident: &Ident,
+ ident: Option<Ident>,
span: Span,
attrs: &[Attribute],
id: NodeId,
) {
self.items.push(ItemInfo {
kind: kind.descr(),
- name: ident.name,
- span: if span.contains(ident.span) {
+ // FIXME: this `sym::empty` can be leaked, see
+ // https://github.com/rust-lang/rust/pull/138740#discussion_r2021979899
+ name: if let Some(ident) = ident { ident.name } else { kw::Empty },
+ span: if let Some(ident) = ident {
span.with_hi(ident.span.hi())
} else {
span.with_hi(span.lo())
},
mod_items: match kind {
- ItemKind::Mod(_, ModKind::Loaded(items, _, _, _)) => items
+ ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items
.iter()
.filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
.map(|i| i.id)
@@ -471,7 +472,7 @@ fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &Item<AssocItemKind>)
self.check_item_kind(
cx,
&item.kind.clone().into(),
- &item.ident,
+ item.kind.ident(),
item.span,
&item.attrs,
item.id,
@@ -482,7 +483,7 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &Item<AssocItemKind>
self.check_item_kind(
cx,
&item.kind.clone().into(),
- &item.ident,
+ item.kind.ident(),
item.span,
&item.attrs,
item.id,
@@ -490,6 +491,6 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &Item<AssocItemKind>
}
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- self.check_item_kind(cx, &item.kind, &item.ident, item.span, &item.attrs, item.id);
+ self.check_item_kind(cx, &item.kind, item.kind.ident(), item.span, &item.attrs, item.id);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
index 743ec5b..7d87f04 100644
--- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
@@ -74,10 +74,9 @@
impl EarlyLintPass for EmptyWithBrackets {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- let span_after_ident = item.span.with_lo(item.ident.span.hi());
-
- if let ItemKind::Struct(var_data, _) = &item.kind
+ if let ItemKind::Struct(ident, var_data, _) = &item.kind
&& has_brackets(var_data)
+ && let span_after_ident = item.span.with_lo(ident.span.hi())
&& has_no_fields(cx, var_data, span_after_ident)
{
span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
index ba2b37f..aae8291 100644
--- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -51,7 +51,7 @@
impl EarlyLintPass for FieldScopedVisibilityModifiers {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- let ItemKind::Struct(ref st, _) = item.kind else {
+ let ItemKind::Struct(_, ref st, _) = item.kind else {
return;
};
for field in st.fields() {
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
index ab53ad9..9bbef8d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
@@ -246,7 +246,6 @@ fn emit_redundant_guards<'tcx>(
fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
for_each_expr_without_closures(expr, |expr| {
if match expr.kind {
- ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat(),
ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => {
// Allow ctors
matches!(cx.qpath_res(&qpath, c.hir_id), Res::Def(DefKind::Ctor(..), ..))
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
index 7c190e1..4c81b22 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
cx.tcx
.hir_parent_id_iter(id)
- .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
+ .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace)))
}
/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
index 0e1980a..4b32ba8 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
@@ -39,7 +39,7 @@
impl EarlyLintPass for MultipleBoundLocations {
fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) {
- if let FnKind::Fn(_, _, _, Fn { generics, .. }) = kind
+ if let FnKind::Fn(_, _, Fn { generics, .. }) = kind
&& !generics.params.is_empty()
&& !generics.where_clause.predicates.is_empty()
{
diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
index 267e206..cda752d 100644
--- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
@@ -41,7 +41,7 @@
impl EarlyLintPass for PartialPubFields {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
- let ItemKind::Struct(ref st, _) = item.kind else {
+ let ItemKind::Struct(_, ref st, _) = item.kind else {
return;
};
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 55f1ece..50ef56d 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -127,29 +127,6 @@
declare_clippy_lint! {
/// ### What it does
- /// This lint checks for invalid usages of `ptr::null`.
- ///
- /// ### Why is this bad?
- /// This causes undefined behavior.
- ///
- /// ### Example
- /// ```ignore
- /// // Undefined behavior
- /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); }
- /// ```
- ///
- /// Use instead:
- /// ```ignore
- /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); }
- /// ```
- #[clippy::version = "1.53.0"]
- pub INVALID_NULL_PTR_USAGE,
- correctness,
- "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead"
-}
-
-declare_clippy_lint! {
- /// ### What it does
/// Use `std::ptr::eq` when applicable
///
/// ### Why is this bad?
@@ -177,7 +154,7 @@
"use `std::ptr::eq` when comparing raw pointers"
}
-declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE, PTR_EQ]);
+declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, PTR_EQ]);
impl<'tcx> LateLintPass<'tcx> for Ptr {
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
@@ -301,54 +278,6 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
format!("{non_null_path_snippet}.is_null()"),
Applicability::MachineApplicable,
);
- } else {
- check_invalid_ptr_usage(cx, expr);
- }
- }
-}
-
-fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if let ExprKind::Call(fun, args) = expr.kind
- && let ExprKind::Path(ref qpath) = fun.kind
- && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
- && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id)
- {
- // TODO: `ptr_slice_from_raw_parts` and its mutable variant should probably still be linted
- // conditionally based on how the return value is used, but not universally like the other
- // functions since there are valid uses for null slice pointers.
- //
- // See: https://github.com/rust-lang/rust-clippy/pull/13452/files#r1773772034
-
- // `arg` positions where null would cause U.B.
- let arg_indices: &[_] = match name {
- sym::ptr_read
- | sym::ptr_read_unaligned
- | sym::ptr_read_volatile
- | sym::ptr_replace
- | sym::ptr_write
- | sym::ptr_write_bytes
- | sym::ptr_write_unaligned
- | sym::ptr_write_volatile
- | sym::slice_from_raw_parts
- | sym::slice_from_raw_parts_mut => &[0],
- sym::ptr_copy | sym::ptr_copy_nonoverlapping | sym::ptr_swap | sym::ptr_swap_nonoverlapping => &[0, 1],
- _ => return,
- };
-
- for &arg_idx in arg_indices {
- if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg))
- && let Some(std_or_core) = std_or_core(cx)
- {
- span_lint_and_sugg(
- cx,
- INVALID_NULL_PTR_USAGE,
- arg.span,
- "pointer must be non-null",
- "change this to",
- format!("{std_or_core}::ptr::NonNull::dangling().as_ptr()"),
- Applicability::MachineApplicable,
- );
- }
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index e9db7c9..76874cc 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -79,10 +79,11 @@ fn check_fn(
if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr {
continue;
}
+ let first_bind_ident = apa.first_bind_ident.unwrap();
span_lint_and_then(
cx,
SIGNIFICANT_DROP_TIGHTENING,
- apa.first_bind_ident.span,
+ first_bind_ident.span,
"temporary with significant `Drop` can be early dropped",
|diag| {
match apa.counter {
@@ -91,13 +92,13 @@ fn check_fn(
let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0));
let init_method = snippet(cx, apa.first_method_span, "..");
let usage_method = snippet(cx, apa.last_method_span, "..");
- let stmt = if apa.last_bind_ident == Ident::empty() {
- format!("\n{indent}{init_method}.{usage_method};")
- } else {
+ let stmt = if let Some(last_bind_ident) = apa.last_bind_ident {
format!(
"\n{indent}let {} = {init_method}.{usage_method};",
- snippet(cx, apa.last_bind_ident.span, ".."),
+ snippet(cx, last_bind_ident.span, ".."),
)
+ } else {
+ format!("\n{indent}{init_method}.{usage_method};")
};
diag.multipart_suggestion_verbose(
@@ -113,7 +114,7 @@ fn check_fn(
format!(
"\n{}drop({});",
" ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)),
- apa.first_bind_ident
+ first_bind_ident
),
Applicability::MaybeIncorrect,
);
@@ -124,7 +125,7 @@ fn check_fn(
apa.first_block_span,
format!(
"temporary `{}` is currently being dropped at the end of its contained scope",
- apa.first_bind_ident
+ first_bind_ident
),
);
},
@@ -283,7 +284,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
let mut apa = AuxParamsAttr {
first_block_hir_id: self.ap.curr_block_hir_id,
first_block_span: self.ap.curr_block_span,
- first_bind_ident: ident,
+ first_bind_ident: Some(ident),
first_method_span: {
let expr_or_init = expr_or_init(self.cx, expr);
if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind {
@@ -307,7 +308,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
match self.ap.curr_stmt.kind {
hir::StmtKind::Let(local) => {
if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
- apa.last_bind_ident = ident;
+ apa.last_bind_ident = Some(ident);
}
if let Some(local_init) = local.init
&& let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind
@@ -373,7 +374,7 @@ struct AuxParamsAttr {
first_block_span: Span,
/// The binding or variable that references the initial construction of the type marked with
/// `#[has_significant_drop]`.
- first_bind_ident: Ident,
+ first_bind_ident: Option<Ident>,
/// Similar to `init_bind_ident` but encompasses the right-hand method call.
first_method_span: Span,
/// Similar to `init_bind_ident` but encompasses the whole contained statement.
@@ -381,7 +382,7 @@ struct AuxParamsAttr {
/// The last visited binding or variable span within a block that had any referenced inner type
/// marked with `#[has_significant_drop]`.
- last_bind_ident: Ident,
+ last_bind_ident: Option<Ident>,
/// Similar to `last_bind_span` but encompasses the right-hand method call.
last_method_span: Span,
/// Similar to `last_bind_span` but encompasses the whole contained statement.
@@ -395,10 +396,10 @@ fn default() -> Self {
has_expensive_expr_after_last_attr: false,
first_block_hir_id: HirId::INVALID,
first_block_span: DUMMY_SP,
- first_bind_ident: Ident::empty(),
+ first_bind_ident: None,
first_method_span: DUMMY_SP,
first_stmt_span: DUMMY_SP,
- last_bind_ident: Ident::empty(),
+ last_bind_ident: None,
last_method_span: DUMMY_SP,
last_stmt_span: DUMMY_SP,
}
@@ -413,7 +414,7 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
}
}
-fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_>) -> bool {
+fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Option<Ident>, lcx: &LateContext<'_>) -> bool {
if let hir::ExprKind::Call(fun, [first_arg]) = expr.kind
&& let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
&& let Res::Def(DefKind::Fn, did) = fun_path.res
@@ -422,6 +423,7 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_
let has_ident = |local_expr: &hir::Expr<'_>| {
if let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &local_expr.kind
&& let [first_arg_ps, ..] = arg_path.segments
+ && let Some(first_bind_ident) = first_bind_ident
&& &first_arg_ps.ident == first_bind_ident
{
true
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index fa08245..35f80b2 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -174,11 +174,11 @@ fn track_uses(
}
match &item.kind {
- ItemKind::Mod(_, ModKind::Loaded(items, ..)) => {
+ ItemKind::Mod(_, _, ModKind::Loaded(items, ..)) => {
self.check_mod(items);
},
- ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
- macros.push(item.ident.name);
+ ItemKind::MacroDef(ident, MacroDef { macro_rules: true, .. }) => {
+ macros.push(ident.name);
},
ItemKind::Use(use_tree) => {
let segments = &use_tree.prefix.segments;
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 6023ae9..eba5763 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -321,17 +321,18 @@ pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool {
}
pub fn eq_item<K>(l: &Item<K>, r: &Item<K>, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool {
- eq_id(l.ident, r.ident) && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind)
+ over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind)
}
#[expect(clippy::similar_names, clippy::too_many_lines)] // Just a big match statement
pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
use ItemKind::*;
match (l, r) {
- (ExternCrate(l), ExternCrate(r)) => l == r,
+ (ExternCrate(ls, li), ExternCrate(rs, ri)) => ls == rs && eq_id(*li, *ri),
(Use(l), Use(r)) => eq_use_tree(l, r),
(
Static(box StaticItem {
+ ident: li,
ty: lt,
mutability: lm,
expr: le,
@@ -339,16 +340,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
define_opaque: _,
}),
Static(box StaticItem {
+ ident: ri,
ty: rt,
mutability: rm,
expr: re,
safety: rs,
define_opaque: _,
}),
- ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+ ) => eq_id(*li, *ri)
+ && lm == rm
+ && ls == rs
+ && eq_ty(lt, rt)
+ && eq_expr_opt(le.as_ref(), re.as_ref()),
(
Const(box ConstItem {
defaultness: ld,
+ ident: li,
generics: lg,
ty: lt,
expr: le,
@@ -356,16 +363,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
}),
Const(box ConstItem {
defaultness: rd,
+ ident: ri,
generics: rg,
ty: rt,
expr: re,
define_opaque: _,
}),
- ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+ ) => eq_defaultness(*ld, *rd)
+ && eq_id(*li, *ri)
+ && eq_generics(lg, rg)
+ && eq_ty(lt, rt)
+ && eq_expr_opt(le.as_ref(), re.as_ref()),
(
Fn(box ast::Fn {
defaultness: ld,
sig: lf,
+ ident: li,
generics: lg,
contract: lc,
body: lb,
@@ -374,6 +387,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
Fn(box ast::Fn {
defaultness: rd,
sig: rf,
+ ident: ri,
generics: rg,
contract: rc,
body: rb,
@@ -382,12 +396,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
) => {
eq_defaultness(*ld, *rd)
&& eq_fn_sig(lf, rf)
+ && eq_id(*li, *ri)
&& eq_generics(lg, rg)
&& eq_opt_fn_contract(lc, rc)
&& both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
},
- (Mod(lu, lmk), Mod(ru, rmk)) => {
- lu == ru
+ (Mod(ls, li, lmk), Mod(rs, ri, rmk)) => {
+ ls == rs
+ && eq_id(*li, *ri)
&& match (lmk, rmk) {
(ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
@@ -421,33 +437,40 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
&& over(lb, rb, eq_generic_bound)
&& both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
},
- (Enum(le, lg), Enum(re, rg)) => over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg),
- (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
- eq_variant_data(lv, rv) && eq_generics(lg, rg)
+ (Enum(li, le, lg), Enum(ri, re, rg)) => {
+ eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg)
+ }
+ (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => {
+ eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg)
},
(
Trait(box ast::Trait {
is_auto: la,
safety: lu,
+ ident: li,
generics: lg,
bounds: lb,
- items: li,
+ items: lis,
}),
Trait(box ast::Trait {
is_auto: ra,
safety: ru,
+ ident: ri,
generics: rg,
bounds: rb,
- items: ri,
+ items: ris,
}),
) => {
la == ra
&& matches!(lu, Safety::Default) == matches!(ru, Safety::Default)
+ && eq_id(*li, *ri)
&& eq_generics(lg, rg)
&& over(lb, rb, eq_generic_bound)
- && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
+ && over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind))
},
- (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound),
+ (TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => {
+ eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound)
+ }
(
Impl(box ast::Impl {
safety: lu,
@@ -480,7 +503,9 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
&& over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
},
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
- (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_delim_args(&l.body, &r.body),
+ (MacroDef(li, ld), MacroDef(ri, rd)) => {
+ eq_id(*li, *ri) && ld.macro_rules == rd.macro_rules && eq_delim_args(&ld.body, &rd.body)
+ }
_ => false,
}
}
@@ -490,6 +515,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
match (l, r) {
(
Static(box StaticItem {
+ ident: li,
ty: lt,
mutability: lm,
expr: le,
@@ -497,17 +523,25 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
define_opaque: _,
}),
Static(box StaticItem {
+ ident: ri,
ty: rt,
mutability: rm,
expr: re,
safety: rs,
define_opaque: _,
}),
- ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
+ ) => {
+ eq_id(*li, *ri)
+ && eq_ty(lt, rt)
+ && lm == rm
+ && eq_expr_opt(le.as_ref(), re.as_ref())
+ && ls == rs
+ }
(
Fn(box ast::Fn {
defaultness: ld,
sig: lf,
+ ident: li,
generics: lg,
contract: lc,
body: lb,
@@ -516,6 +550,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
Fn(box ast::Fn {
defaultness: rd,
sig: rf,
+ ident: ri,
generics: rg,
contract: rc,
body: rb,
@@ -524,6 +559,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
) => {
eq_defaultness(*ld, *rd)
&& eq_fn_sig(lf, rf)
+ && eq_id(*li, *ri)
&& eq_generics(lg, rg)
&& eq_opt_fn_contract(lc, rc)
&& both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
@@ -531,20 +567,23 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
(
TyAlias(box ast::TyAlias {
defaultness: ld,
+ ident: li,
generics: lg,
+ where_clauses: _,
bounds: lb,
ty: lt,
- ..
}),
TyAlias(box ast::TyAlias {
defaultness: rd,
+ ident: ri,
generics: rg,
+ where_clauses: _,
bounds: rb,
ty: rt,
- ..
}),
) => {
eq_defaultness(*ld, *rd)
+ && eq_id(*li, *ri)
&& eq_generics(lg, rg)
&& over(lb, rb, eq_generic_bound)
&& both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
@@ -560,6 +599,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
(
Const(box ConstItem {
defaultness: ld,
+ ident: li,
generics: lg,
ty: lt,
expr: le,
@@ -567,16 +607,24 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
}),
Const(box ConstItem {
defaultness: rd,
+ ident: ri,
generics: rg,
ty: rt,
expr: re,
define_opaque: _,
}),
- ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+ ) => {
+ eq_defaultness(*ld, *rd)
+ && eq_id(*li, *ri)
+ && eq_generics(lg, rg)
+ && eq_ty(lt, rt)
+ && eq_expr_opt(le.as_ref(), re.as_ref())
+ }
(
Fn(box ast::Fn {
defaultness: ld,
sig: lf,
+ ident: li,
generics: lg,
contract: lc,
body: lb,
@@ -585,6 +633,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
Fn(box ast::Fn {
defaultness: rd,
sig: rf,
+ ident: ri,
generics: rg,
contract: rc,
body: rb,
@@ -593,6 +642,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
) => {
eq_defaultness(*ld, *rd)
&& eq_fn_sig(lf, rf)
+ && eq_id(*li, *ri)
&& eq_generics(lg, rg)
&& eq_opt_fn_contract(lc, rc)
&& both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
@@ -600,20 +650,23 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
(
Type(box TyAlias {
defaultness: ld,
+ ident: li,
generics: lg,
+ where_clauses: _,
bounds: lb,
ty: lt,
- ..
}),
Type(box TyAlias {
defaultness: rd,
+ ident: ri,
generics: rg,
+ where_clauses: _,
bounds: rb,
ty: rt,
- ..
}),
) => {
eq_defaultness(*ld, *rd)
+ && eq_id(*li, *ri)
&& eq_generics(lg, rg)
&& over(lb, rb, eq_generic_bound)
&& both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 1307ff7..668b0cb 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2629,7 +2629,7 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>
pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
if let Res::Def(_, def_id) = path.res {
- return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr);
+ return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr);
}
}
false
@@ -2699,7 +2699,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
/// use [`is_in_cfg_test`]
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
tcx.hir_attrs(id).iter().any(|attr| {
- if attr.has_name(sym::cfg)
+ if attr.has_name(sym::cfg_trace)
&& let Some(items) = attr.meta_item_list()
&& let [item] = &*items
&& item.has_name(sym::test)
@@ -2723,11 +2723,11 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- tcx.has_attr(def_id, sym::cfg)
+ tcx.has_attr(def_id, sym::cfg_trace)
|| tcx
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
- .any(|attr| attr.has_name(sym::cfg))
+ .any(|attr| attr.has_name(sym::cfg_trace))
}
/// Walks up the HIR tree from the given expression in an attempt to find where the value is
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1782.rs b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
index fefdc40..4a1886c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1782.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
@@ -1,6 +1,6 @@
//@ check-pass
-#![allow(dead_code, unused_variables)]
+#![allow(dead_code, unused_variables, invalid_null_arguments)]
#![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)]
/// Should not trigger an ICE in `SpanlessEq` / `consts::constant`
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed
deleted file mode 100644
index ce78e89..0000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed
+++ /dev/null
@@ -1,66 +0,0 @@
-fn main() {
- unsafe {
- let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- struct A; // zero sized struct
- assert_eq!(std::mem::size_of::<A>(), 0);
-
- let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
- let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
- let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
- let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- let _a: A = std::ptr::replace(std::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
- let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint
- let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0);
-
- std::ptr::swap::<A>(std::ptr::NonNull::dangling().as_ptr(), &mut A);
- //~^ invalid_null_ptr_usage
- std::ptr::swap::<A>(&mut A, std::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- std::ptr::swap_nonoverlapping::<A>(std::ptr::NonNull::dangling().as_ptr(), &mut A, 0);
- //~^ invalid_null_ptr_usage
- std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write(std::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write_unaligned(std::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write_volatile(std::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write_bytes::<usize>(std::ptr::NonNull::dangling().as_ptr(), 42, 0);
- //~^ invalid_null_ptr_usage
- }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs
deleted file mode 100644
index 361865f..0000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-fn main() {
- unsafe {
- let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0);
- //~^ invalid_null_ptr_usage
- let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- std::ptr::copy::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- std::ptr::copy_nonoverlapping::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- struct A; // zero sized struct
- assert_eq!(std::mem::size_of::<A>(), 0);
-
- let _a: A = std::ptr::read(std::ptr::null());
- //~^ invalid_null_ptr_usage
- let _a: A = std::ptr::read(std::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- let _a: A = std::ptr::read_unaligned(std::ptr::null());
- //~^ invalid_null_ptr_usage
- let _a: A = std::ptr::read_unaligned(std::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- let _a: A = std::ptr::read_volatile(std::ptr::null());
- //~^ invalid_null_ptr_usage
- let _a: A = std::ptr::read_volatile(std::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- let _a: A = std::ptr::replace(std::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
- let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint
- let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0);
-
- std::ptr::swap::<A>(std::ptr::null_mut(), &mut A);
- //~^ invalid_null_ptr_usage
- std::ptr::swap::<A>(&mut A, std::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- std::ptr::swap_nonoverlapping::<A>(std::ptr::null_mut(), &mut A, 0);
- //~^ invalid_null_ptr_usage
- std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write(std::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write_unaligned(std::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write_volatile(std::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
-
- std::ptr::write_bytes::<usize>(std::ptr::null_mut(), 42, 0);
- //~^ invalid_null_ptr_usage
- }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr
deleted file mode 100644
index 3f9d15b..0000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr
+++ /dev/null
@@ -1,136 +0,0 @@
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:3:59
- |
-LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0);
- | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
- |
- = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:5:59
- |
-LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:8:63
- |
-LL | let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:11:33
- |
-LL | std::ptr::copy::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
- | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:13:73
- |
-LL | std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:16:48
- |
-LL | std::ptr::copy_nonoverlapping::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
- | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:18:88
- |
-LL | std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:24:36
- |
-LL | let _a: A = std::ptr::read(std::ptr::null());
- | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:26:36
- |
-LL | let _a: A = std::ptr::read(std::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:29:46
- |
-LL | let _a: A = std::ptr::read_unaligned(std::ptr::null());
- | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:31:46
- |
-LL | let _a: A = std::ptr::read_unaligned(std::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:34:45
- |
-LL | let _a: A = std::ptr::read_volatile(std::ptr::null());
- | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:36:45
- |
-LL | let _a: A = std::ptr::read_volatile(std::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:39:39
- |
-LL | let _a: A = std::ptr::replace(std::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:44:29
- |
-LL | std::ptr::swap::<A>(std::ptr::null_mut(), &mut A);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:46:37
- |
-LL | std::ptr::swap::<A>(&mut A, std::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:49:44
- |
-LL | std::ptr::swap_nonoverlapping::<A>(std::ptr::null_mut(), &mut A, 0);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:51:52
- |
-LL | std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:54:25
- |
-LL | std::ptr::write(std::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:57:35
- |
-LL | std::ptr::write_unaligned(std::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:60:34
- |
-LL | std::ptr::write_volatile(std::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage.rs:63:40
- |
-LL | std::ptr::write_bytes::<usize>(std::ptr::null_mut(), 42, 0);
- | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: aborting due to 22 previous errors
-
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed
deleted file mode 100644
index df7ab16..0000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed
+++ /dev/null
@@ -1,79 +0,0 @@
-#![no_std]
-#![feature(lang_items)]
-
-use core::panic::PanicInfo;
-
-#[lang = "eh_personality"]
-extern "C" fn eh_personality() {}
-
-#[panic_handler]
-fn panic(info: &PanicInfo) -> ! {
- loop {}
-}
-
-fn main() {
- unsafe {
- let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- struct A; // zero sized struct
- assert_eq!(core::mem::size_of::<A>(), 0);
-
- let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
- let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
- let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
- let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- let _a: A = core::ptr::replace(core::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
- let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint
- let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0);
-
- core::ptr::swap::<A>(core::ptr::NonNull::dangling().as_ptr(), &mut A);
- //~^ invalid_null_ptr_usage
- core::ptr::swap::<A>(&mut A, core::ptr::NonNull::dangling().as_ptr());
- //~^ invalid_null_ptr_usage
-
- core::ptr::swap_nonoverlapping::<A>(core::ptr::NonNull::dangling().as_ptr(), &mut A, 0);
- //~^ invalid_null_ptr_usage
- core::ptr::swap_nonoverlapping::<A>(&mut A, core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write(core::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write_unaligned(core::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write_volatile(core::ptr::NonNull::dangling().as_ptr(), A);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write_bytes::<usize>(core::ptr::NonNull::dangling().as_ptr(), 42, 0);
- //~^ invalid_null_ptr_usage
- }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs
deleted file mode 100644
index 38ddfff..0000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-#![no_std]
-#![feature(lang_items)]
-
-use core::panic::PanicInfo;
-
-#[lang = "eh_personality"]
-extern "C" fn eh_personality() {}
-
-#[panic_handler]
-fn panic(info: &PanicInfo) -> ! {
- loop {}
-}
-
-fn main() {
- unsafe {
- let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0);
- //~^ invalid_null_ptr_usage
- let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- core::ptr::copy::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- core::ptr::copy_nonoverlapping::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
- //~^ invalid_null_ptr_usage
- core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- struct A; // zero sized struct
- assert_eq!(core::mem::size_of::<A>(), 0);
-
- let _a: A = core::ptr::read(core::ptr::null());
- //~^ invalid_null_ptr_usage
- let _a: A = core::ptr::read(core::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- let _a: A = core::ptr::read_unaligned(core::ptr::null());
- //~^ invalid_null_ptr_usage
- let _a: A = core::ptr::read_unaligned(core::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- let _a: A = core::ptr::read_volatile(core::ptr::null());
- //~^ invalid_null_ptr_usage
- let _a: A = core::ptr::read_volatile(core::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- let _a: A = core::ptr::replace(core::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
- let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint
- let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0);
-
- core::ptr::swap::<A>(core::ptr::null_mut(), &mut A);
- //~^ invalid_null_ptr_usage
- core::ptr::swap::<A>(&mut A, core::ptr::null_mut());
- //~^ invalid_null_ptr_usage
-
- core::ptr::swap_nonoverlapping::<A>(core::ptr::null_mut(), &mut A, 0);
- //~^ invalid_null_ptr_usage
- core::ptr::swap_nonoverlapping::<A>(&mut A, core::ptr::null_mut(), 0);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write(core::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write_unaligned(core::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write_volatile(core::ptr::null_mut(), A);
- //~^ invalid_null_ptr_usage
-
- core::ptr::write_bytes::<usize>(core::ptr::null_mut(), 42, 0);
- //~^ invalid_null_ptr_usage
- }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr
deleted file mode 100644
index b5dd21c..0000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr
+++ /dev/null
@@ -1,136 +0,0 @@
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:16:60
- |
-LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0);
- | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
- |
- = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:18:60
- |
-LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:21:64
- |
-LL | let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:24:34
- |
-LL | core::ptr::copy::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
- | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:26:75
- |
-LL | core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:29:49
- |
-LL | core::ptr::copy_nonoverlapping::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
- | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:31:90
- |
-LL | core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:37:37
- |
-LL | let _a: A = core::ptr::read(core::ptr::null());
- | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:39:37
- |
-LL | let _a: A = core::ptr::read(core::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:42:47
- |
-LL | let _a: A = core::ptr::read_unaligned(core::ptr::null());
- | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:44:47
- |
-LL | let _a: A = core::ptr::read_unaligned(core::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:47:46
- |
-LL | let _a: A = core::ptr::read_volatile(core::ptr::null());
- | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:49:46
- |
-LL | let _a: A = core::ptr::read_volatile(core::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:52:40
- |
-LL | let _a: A = core::ptr::replace(core::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:57:30
- |
-LL | core::ptr::swap::<A>(core::ptr::null_mut(), &mut A);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:59:38
- |
-LL | core::ptr::swap::<A>(&mut A, core::ptr::null_mut());
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:62:45
- |
-LL | core::ptr::swap_nonoverlapping::<A>(core::ptr::null_mut(), &mut A, 0);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:64:53
- |
-LL | core::ptr::swap_nonoverlapping::<A>(&mut A, core::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:67:26
- |
-LL | core::ptr::write(core::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:70:36
- |
-LL | core::ptr::write_unaligned(core::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:73:35
- |
-LL | core::ptr::write_volatile(core::ptr::null_mut(), A);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
- --> tests/ui/invalid_null_ptr_usage_no_std.rs:76:41
- |
-LL | core::ptr::write_bytes::<usize>(core::ptr::null_mut(), 42, 0);
- | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: aborting due to 22 previous errors
-
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 501811f..7964047 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -119,6 +119,7 @@
#![warn(invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
#![warn(invalid_value)] //~ ERROR: lint `clippy::invalid_ref`
#![warn(invalid_from_utf8_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
+#![warn(invalid_null_arguments)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
#![warn(let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
#![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::maybe_misused_cfg`
#![warn(enum_intrinsics_non_enums)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 7f4b806..aa7b905 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -119,6 +119,7 @@
#![warn(clippy::invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
#![warn(clippy::invalid_ref)] //~ ERROR: lint `clippy::invalid_ref`
#![warn(clippy::invalid_utf8_in_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
+#![warn(clippy::invalid_null_ptr_usage)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
#![warn(clippy::let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
#![warn(clippy::maybe_misused_cfg)] //~ ERROR: lint `clippy::maybe_misused_cfg`
#![warn(clippy::mem_discriminant_non_enum)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index f24eaec..b3c8816 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -343,71 +343,77 @@
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
-error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
+error: lint `clippy::invalid_null_ptr_usage` has been renamed to `invalid_null_arguments`
--> tests/ui/rename.rs:122:9
|
+LL | #![warn(clippy::invalid_null_ptr_usage)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_null_arguments`
+
+error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
+ --> tests/ui/rename.rs:123:9
+ |
LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
- --> tests/ui/rename.rs:123:9
+ --> tests/ui/rename.rs:124:9
|
LL | #![warn(clippy::maybe_misused_cfg)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> tests/ui/rename.rs:124:9
+ --> tests/ui/rename.rs:125:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
- --> tests/ui/rename.rs:125:9
+ --> tests/ui/rename.rs:126:9
|
LL | #![warn(clippy::mismatched_target_os)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> tests/ui/rename.rs:126:9
+ --> tests/ui/rename.rs:127:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
- --> tests/ui/rename.rs:127:9
+ --> tests/ui/rename.rs:128:9
|
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
- --> tests/ui/rename.rs:128:9
+ --> tests/ui/rename.rs:129:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
- --> tests/ui/rename.rs:129:9
+ --> tests/ui/rename.rs:130:9
|
LL | #![warn(clippy::undropped_manually_drops)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> tests/ui/rename.rs:130:9
+ --> tests/ui/rename.rs:131:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> tests/ui/rename.rs:131:9
+ --> tests/ui/rename.rs:132:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
- --> tests/ui/rename.rs:132:9
+ --> tests/ui/rename.rs:133:9
|
LL | #![warn(clippy::vtable_address_comparisons)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
-error: aborting due to 68 previous errors
+error: aborting due to 69 previous errors
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index c0566ef..b68f817 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -122,13 +122,17 @@ fn parse_expected(
// //~|
// //~^
// //~^^^^^
+ // //~v
+ // //~vvvvv
// //~?
// //[rev1]~
// //[rev1,rev2]~^^
static RE: OnceLock<Regex> = OnceLock::new();
let captures = RE
- .get_or_init(|| Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||\^*)").unwrap())
+ .get_or_init(|| {
+ Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||[v\^]*)").unwrap()
+ })
.captures(line)?;
match (test_revision, captures.name("revs")) {
@@ -164,6 +168,8 @@ fn parse_expected(
(true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line")))
} else if line_num_adjust == "?" {
(false, None)
+ } else if line_num_adjust.starts_with('v') {
+ (false, Some(line_num + line_num_adjust.len()))
} else {
(false, Some(line_num - line_num_adjust.len()))
};
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index d7a5f30..f654bd9 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -924,7 +924,14 @@ fn iter_header(
impl Config {
fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec<String>) {
- const FORBIDDEN_REVISION_NAMES: [&str; 9] =
+ const FORBIDDEN_REVISION_NAMES: [&str; 2] = [
+ // `//@ revisions: true false` Implying `--cfg=true` and `--cfg=false` makes it very
+ // weird for the test, since if the test writer wants a cfg of the same revision name
+ // they'd have to use `cfg(r#true)` and `cfg(r#false)`.
+ "true", "false",
+ ];
+
+ const FILECHECK_FORBIDDEN_REVISION_NAMES: [&str; 9] =
["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"];
if let Some(raw) = self.parse_name_value_directive(line, "revisions") {
@@ -933,25 +940,38 @@ fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut
}
let mut duplicates: HashSet<_> = existing.iter().cloned().collect();
- for revision in raw.split_whitespace().map(|r| r.to_string()) {
- if !duplicates.insert(revision.clone()) {
+ for revision in raw.split_whitespace() {
+ if !duplicates.insert(revision.to_string()) {
panic!(
"duplicate revision: `{}` in line `{}`: {}",
revision,
raw,
testfile.display()
);
- } else if matches!(self.mode, Mode::Assembly | Mode::Codegen | Mode::MirOpt)
- && FORBIDDEN_REVISION_NAMES.contains(&revision.as_str())
- {
+ }
+
+ if FORBIDDEN_REVISION_NAMES.contains(&revision) {
panic!(
- "revision name `{revision}` is not permitted in a test suite that uses `FileCheck` annotations\n\
- as it is confusing when used as custom `FileCheck` prefix: `{revision}` in line `{}`: {}",
+ "revision name `{revision}` is not permitted: `{}` in line `{}`: {}",
+ revision,
raw,
testfile.display()
);
}
- existing.push(revision);
+
+ if matches!(self.mode, Mode::Assembly | Mode::Codegen | Mode::MirOpt)
+ && FILECHECK_FORBIDDEN_REVISION_NAMES.contains(&revision)
+ {
+ panic!(
+ "revision name `{revision}` is not permitted in a test suite that uses \
+ `FileCheck` annotations as it is confusing when used as custom `FileCheck` \
+ prefix: `{revision}` in line `{}`: {}",
+ raw,
+ testfile.display()
+ );
+ }
+
+ existing.push(revision.to_string());
}
}
}
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 007318b..4d90f15 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -568,6 +568,13 @@ fn test_assembly_mode_forbidden_revisions() {
}
#[test]
+#[should_panic(expected = "revision name `true` is not permitted")]
+fn test_forbidden_revisions() {
+ let config = cfg().mode("ui").build();
+ parse_rs(&config, "//@ revisions: true");
+}
+
+#[test]
#[should_panic(
expected = "revision name `CHECK` is not permitted in a test suite that uses `FileCheck` annotations"
)]
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 3ec984e..950566b 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -22,6 +22,7 @@
use core::panic;
use std::collections::HashSet;
use std::ffi::OsString;
+use std::fmt::Write;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
@@ -570,18 +571,22 @@ pub fn run_tests(config: Arc<Config>) {
// easy to miss which tests failed, and as such fail to reproduce
// the failure locally.
- println!(
- "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
- config.suite,
- config
- .compare_mode
- .as_ref()
- .map(|c| format!(" compare_mode={:?}", c))
- .unwrap_or_default(),
- config.mode,
- config.host,
- config.target
- );
+ let mut msg = String::from("Some tests failed in compiletest");
+ write!(msg, " suite={}", config.suite).unwrap();
+
+ if let Some(compare_mode) = config.compare_mode.as_ref() {
+ write!(msg, " compare_mode={}", compare_mode).unwrap();
+ }
+
+ if let Some(pass_mode) = config.force_pass_mode.as_ref() {
+ write!(msg, " pass_mode={}", pass_mode).unwrap();
+ }
+
+ write!(msg, " mode={}", config.mode).unwrap();
+ write!(msg, " host={}", config.host).unwrap();
+ write!(msg, " target={}", config.target).unwrap();
+
+ println!("{msg}");
std::process::exit(1);
}
diff --git a/src/tools/miri/.github/workflows/sysroots.yml b/src/tools/miri/.github/workflows/sysroots.yml
index 6a4f44d..11bcaec 100644
--- a/src/tools/miri/.github/workflows/sysroots.yml
+++ b/src/tools/miri/.github/workflows/sysroots.yml
@@ -16,6 +16,7 @@
- uses: actions/checkout@v4
- name: Build the sysroots
run: |
+ rustup toolchain install nightly
cargo install -f rustup-toolchain-install-master
./miri toolchain -c rust-docs # Docs are the only place targets are separated by tier
./miri install
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 57a757f..b8100d0 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -1079,9 +1079,9 @@
[[package]]
name = "ui_test"
-version = "0.28.0"
+version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576"
+checksum = "14bf63f2931a28a04af0bd24c5f850223d29f3a40afae49ed6ce442a65eb8652"
dependencies = [
"annotate-snippets",
"anyhow",
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 728a755..5d8c9a8 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -47,7 +47,7 @@
] }
[dev-dependencies]
-ui_test = "0.28.0"
+ui_test = "0.29.1"
colored = "2"
rustc_version = "0.4"
regex = "1.5.5"
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 4ae901b..201aa1f 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -237,8 +237,7 @@
You can get your test suite's parallelism back by running `cargo miri nextest run -jN`
(note that you will need [`cargo-nextest`](https://nexte.st) installed).
This works because `cargo-nextest` collects a list of all tests then launches a
-separate `cargo miri run` for each test. You will need to specify a `-j` or `--test-threads`;
-by default `cargo miri nextest run` runs one test at a time. For more details, see the
+separate `cargo miri run` for each test. For more information about nextest, see the
[`cargo-nextest` Miri documentation](https://nexte.st/book/miri.html).
Note: This one-test-per-process model means that `cargo miri test` is able to detect data
@@ -432,7 +431,8 @@
* `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated
value from a load. This can help diagnose problems that disappear under
`-Zmiri-disable-weak-memory-emulation`.
-* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules.
+* <a name="-Zmiri-tree-borrows"><!-- The playground links here --></a>
+ `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules.
Tree Borrows is even more experimental than Stacked Borrows. While Tree Borrows
is still sound in the sense of catching all aliasing violations that current versions
of the compiler might exploit, it is likely that the eventual final aliasing model
diff --git a/src/tools/miri/bench-cargo-miri/mse/src/main.rs b/src/tools/miri/bench-cargo-miri/mse/src/main.rs
index e16ccd2..06d5487 100644
--- a/src/tools/miri/bench-cargo-miri/mse/src/main.rs
+++ b/src/tools/miri/bench-cargo-miri/mse/src/main.rs
@@ -10,7 +10,7 @@ fn main() {
}
fn read_i16(buffer: &[u8], index: usize) -> i16 {
- const SIZE: usize = std::mem::size_of::<i16>();
+ const SIZE: usize = size_of::<i16>();
let mut bytes: [u8; SIZE] = [0u8; SIZE];
bytes.copy_from_slice(&buffer[(index * SIZE)..(index * SIZE + SIZE)]);
unsafe { std::mem::transmute(bytes) }
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index d7b4421..71ea07f 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -467,7 +467,7 @@ fn out_filenames() -> Vec<PathBuf> {
if let Some(i) = val.iter().position(|&s| s == "link") {
emit_link_hack = true;
val.remove(i);
- if !val.iter().any(|&s| s == "metadata") {
+ if !val.contains(&"metadata") {
val.push("metadata");
}
}
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index 3327ad1..7155d69 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -166,7 +166,7 @@
UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
- TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd
+ TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync concurrency thread epoll eventfd
TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index b3e207f..cf36b6f 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-f5729cfed3c45e061e8a443677fc1d5ef9277df7
+4ac032f857b46037b55c1fc0fa702450aad37f43
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 0a2d3ac..c263e86 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -170,20 +170,22 @@ fn addr_from_alloc_id_uncached(
// This ensures the interpreted program and native code have the same view of memory.
let base_ptr = match info.kind {
AllocKind::LiveData => {
- if this.tcx.try_get_global_alloc(alloc_id).is_some() {
+ if memory_kind == MiriMemoryKind::Global.into() {
// For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align)
.unwrap_or_else(|| {
panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes", size = info.size)
});
let ptr = prepared_bytes.as_ptr();
- // Store prepared allocation space to be picked up for use later.
+ // Store prepared allocation to be picked up for use later.
global_state
.prepared_alloc_bytes
.try_insert(alloc_id, prepared_bytes)
.unwrap();
ptr
} else {
+ // Non-global allocations are already in memory at this point so
+ // we can just get a pointer to where their data is stored.
this.get_alloc_bytes_unchecked_raw(alloc_id)?
}
}
@@ -381,6 +383,7 @@ fn get_global_alloc_bytes(
align: Align,
) -> InterpResult<'tcx, MiriAllocBytes> {
let this = self.eval_context_ref();
+ assert!(this.tcx.try_get_global_alloc(id).is_some());
if this.machine.native_lib.is_some() {
// In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
// This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index a8a2491..9462996 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -1150,7 +1150,7 @@ fn run_threads(&mut self) -> InterpResult<'tcx, !> {
loop {
if CTRL_C_RECEIVED.load(Relaxed) {
this.machine.handle_abnormal_termination();
- std::process::exit(1);
+ throw_machine_stop!(TerminationInfo::Interrupted);
}
match this.machine.threads.schedule(&this.machine.clock)? {
SchedulingAction::ExecuteStep => {
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 1a12d41..014b129 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -16,6 +16,8 @@ pub enum TerminationInfo {
leak_check: bool,
},
Abort(String),
+ /// Miri was interrupted by a Ctrl+C from the user
+ Interrupted,
UnsupportedInIsolation(String),
StackedBorrowsUb {
msg: String,
@@ -63,6 +65,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Exit { code, .. } => write!(f, "the evaluated program completed with exit code {code}"),
Abort(msg) => write!(f, "{msg}"),
+ Interrupted => write!(f, "interpretation was interrupted"),
UnsupportedInIsolation(msg) => write!(f, "{msg}"),
Int2PtrWithStrictProvenance =>
write!(
@@ -226,6 +229,7 @@ pub fn report_error<'tcx>(
let title = match info {
&Exit { code, leak_check } => return Some((code, leak_check)),
Abort(_) => Some("abnormal termination"),
+ Interrupted => None,
UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) =>
Some("unsupported operation"),
StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } =>
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 36b15db..ed13f67 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -434,7 +434,6 @@ pub fn create_ecx<'tcx>(
/// Evaluates the entry function specified by `entry_id`.
/// Returns `Some(return_code)` if program execution completed.
/// Returns `None` if an evaluation error occurred.
-#[expect(clippy::needless_lifetimes)]
pub fn eval_entry<'tcx>(
tcx: TyCtxt<'tcx>,
entry_id: DefId,
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 12e7d0f..29ed94a 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -14,9 +14,10 @@
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout};
-use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy};
+use rustc_middle::ty::{self, Binder, FloatTy, FnSig, IntTy, Ty, TyCtxt, UintTy};
use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol};
+use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::*;
@@ -994,10 +995,7 @@ fn check_shim<'a, const N: usize>(
exp_abi: Conv,
link_name: Symbol,
args: &'a [OpTy<'tcx>],
- ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]>
- where
- &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>,
- {
+ ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> {
self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?;
if abi.c_variadic {
@@ -1015,6 +1013,80 @@ fn check_shim<'a, const N: usize>(
)
}
+ /// Check that the given `caller_fn_abi` matches the expected ABI described by
+ /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of
+ /// arguments.
+ fn check_shim_abi<'a, const N: usize>(
+ &mut self,
+ link_name: Symbol,
+ caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+ callee_abi: ExternAbi,
+ callee_input_tys: [Ty<'tcx>; N],
+ callee_output_ty: Ty<'tcx>,
+ caller_args: &'a [OpTy<'tcx>],
+ ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> {
+ let this = self.eval_context_mut();
+ let mut inputs_and_output = callee_input_tys.to_vec();
+ inputs_and_output.push(callee_output_ty);
+ let fn_sig_binder = Binder::dummy(FnSig {
+ inputs_and_output: this.machine.tcx.mk_type_list(&inputs_and_output),
+ c_variadic: false,
+ // This does not matter for the ABI.
+ safety: Safety::Safe,
+ abi: callee_abi,
+ });
+ let callee_fn_abi = this.fn_abi_of_fn_ptr(fn_sig_binder, Default::default())?;
+
+ this.check_abi_and_shim_symbol_clash(caller_fn_abi, callee_fn_abi.conv, link_name)?;
+
+ if caller_fn_abi.c_variadic {
+ throw_ub_format!(
+ "ABI mismatch: calling a non-variadic function with a variadic caller-side signature"
+ );
+ }
+
+ if callee_fn_abi.fixed_count != caller_fn_abi.fixed_count {
+ throw_ub_format!(
+ "ABI mismatch: expected {} arguments, found {} arguments ",
+ callee_fn_abi.fixed_count,
+ caller_fn_abi.fixed_count
+ );
+ }
+
+ if callee_fn_abi.can_unwind && !caller_fn_abi.can_unwind {
+ throw_ub_format!(
+ "ABI mismatch: callee may unwind, but caller-side signature prohibits unwinding",
+ );
+ }
+
+ if !this.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
+ throw_ub!(AbiMismatchReturn {
+ caller_ty: caller_fn_abi.ret.layout.ty,
+ callee_ty: callee_fn_abi.ret.layout.ty
+ });
+ }
+
+ if let Some(index) = caller_fn_abi
+ .args
+ .iter()
+ .zip(callee_fn_abi.args.iter())
+ .map(|(caller_arg, callee_arg)| this.check_argument_compat(caller_arg, callee_arg))
+ .collect::<InterpResult<'tcx, Vec<bool>>>()?
+ .into_iter()
+ .position(|b| !b)
+ {
+ throw_ub!(AbiMismatchArgument {
+ caller_ty: caller_fn_abi.args[index].layout.ty,
+ callee_ty: callee_fn_abi.args[index].layout.ty
+ });
+ }
+
+ if let Ok(ops) = caller_args.try_into() {
+ return interp_ok(ops);
+ }
+ unreachable!()
+ }
+
/// Check shim for variadic function.
/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs.
fn check_shim_variadic<'a, const N: usize>(
@@ -1187,6 +1259,18 @@ fn lookup_link_section(&mut self, name: &str) -> InterpResult<'tcx, Vec<ImmTy<'t
interp_ok(array)
}
+
+ fn mangle_internal_symbol<'a>(&'a mut self, name: &'static str) -> &'a str
+ where
+ 'tcx: 'a,
+ {
+ let this = self.eval_context_mut();
+ let tcx = *this.tcx;
+ this.machine
+ .mangle_internal_symbol_cache
+ .entry(name)
+ .or_insert_with(|| mangle_internal_symbol(tcx, name))
+ }
}
impl<'tcx> MiriMachine<'tcx> {
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 9006190..fb99bdc 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -611,6 +611,9 @@ pub struct MiriMachine<'tcx> {
pub(crate) reject_in_isolation_warned: RefCell<FxHashSet<String>>,
/// Remembers which int2ptr casts we have already warned about.
pub(crate) int2ptr_warned: RefCell<FxHashSet<Span>>,
+
+ /// Cache for `mangle_internal_symbol`.
+ pub(crate) mangle_internal_symbol_cache: FxHashMap<&'static str, String>,
}
impl<'tcx> MiriMachine<'tcx> {
@@ -757,6 +760,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx>) -> Self {
native_call_mem_warned: Cell::new(false),
reject_in_isolation_warned: Default::default(),
int2ptr_warned: Default::default(),
+ mangle_internal_symbol_cache: Default::default(),
}
}
@@ -930,6 +934,7 @@ fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
native_call_mem_warned: _,
reject_in_isolation_warned: _,
int2ptr_warned: _,
+ mangle_internal_symbol_cache: _,
} = self;
threads.visit_provenance(visit);
@@ -1540,7 +1545,7 @@ fn stack_mut<'a>(
fn before_terminator(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
ecx.machine.basic_block_count += 1u64; // a u64 that is only incremented by 1 will "never" overflow
ecx.machine.since_gc += 1;
- // Possibly report our progress.
+ // Possibly report our progress. This will point at the terminator we are about to execute.
if let Some(report_progress) = ecx.machine.report_progress {
if ecx.machine.basic_block_count % u64::from(report_progress) == 0 {
ecx.emit_diagnostic(NonHaltingDiagnostic::ProgressReport {
@@ -1559,6 +1564,7 @@ fn before_terminator(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
}
// These are our preemption points.
+ // (This will only take effect after the terminator has been executed.)
ecx.maybe_preempt_active_thread();
// Make sure some time passes.
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 03c6081..52c16a0 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -9,10 +9,9 @@
use rustc_hir::def_id::CrateNum;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::AllocInit;
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{Instance, Ty};
use rustc_middle::{mir, ty};
use rustc_span::Symbol;
-use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::callconv::{Conv, FnAbi};
use self::helpers::{ToHost, ToSoft};
@@ -52,7 +51,7 @@ fn emulate_foreign_item(
// Some shims forward to other MIR bodies.
match link_name.as_str() {
- name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_error_handler") => {
+ name if name == this.mangle_internal_symbol("__rust_alloc_error_handler") => {
// Forward to the right symbol that implements this function.
let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
// in real code, this symbol does not exist without an allocator
@@ -60,11 +59,11 @@ fn emulate_foreign_item(
"`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
);
};
- let name =
- mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind));
- let handler = this
- .lookup_exported_symbol(Symbol::intern(&name))?
- .expect("missing alloc error handler symbol");
+ let name = Symbol::intern(
+ this.mangle_internal_symbol(alloc_error_handler_name(handler_kind)),
+ );
+ let handler =
+ this.lookup_exported_symbol(name)?.expect("missing alloc error handler symbol");
return interp_ok(Some(handler));
}
_ => {}
@@ -138,30 +137,22 @@ fn lookup_exported_symbol(
// Find it if it was not cached.
let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None;
helpers::iter_exported_symbols(tcx, |cnum, def_id| {
+ let attrs = tcx.codegen_fn_attrs(def_id);
+ // Skip over imports of items.
if tcx.is_foreign_item(def_id) {
- // Skip over imports of items
+ return interp_ok(());
+ }
+ // Skip over items without an explicitly defined symbol name.
+ if !(attrs.export_name.is_some()
+ || attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
+ || attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL))
+ {
return interp_ok(());
}
- let attrs = tcx.codegen_fn_attrs(def_id);
- // FIXME use tcx.symbol_name(instance) instead
- let symbol_name = if let Some(export_name) = attrs.export_name {
- export_name
- } else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
- || attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
- {
- tcx.item_name(def_id)
- } else {
- // Skip over items without an explicitly defined symbol name.
- return interp_ok(());
- };
- let symbol_name =
- if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
- Symbol::intern(&mangle_internal_symbol(tcx, symbol_name.as_str()))
- } else {
- symbol_name
- };
- if symbol_name == link_name {
+ let instance = Instance::mono(tcx, def_id);
+ let symbol_name = tcx.symbol_name(instance).name;
+ if symbol_name == link_name.as_str() {
if let Some((original_instance, original_cnum)) = instance_and_crate {
// Make sure we are consistent wrt what is 'first' and 'second'.
let original_span = tcx.def_span(original_instance.def_id()).data();
@@ -505,9 +496,7 @@ fn emulate_foreign_item_inner(
}
// Rust allocation
- name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc")
- || name == "miri_alloc" =>
- {
+ name if name == this.mangle_internal_symbol("__rust_alloc") || name == "miri_alloc" => {
let default = |ecx: &mut MiriInterpCx<'tcx>| {
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
// macro is used, we act like no shim exists, so that the exported function can run.
@@ -540,7 +529,7 @@ fn emulate_foreign_item_inner(
_ => return this.emulate_allocator(default),
}
}
- name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_zeroed") => {
+ name if name == this.mangle_internal_symbol("__rust_alloc_zeroed") => {
return this.emulate_allocator(|this| {
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
@@ -559,7 +548,7 @@ fn emulate_foreign_item_inner(
this.write_pointer(ptr, dest)
});
}
- name if name == mangle_internal_symbol(*this.tcx, "__rust_dealloc")
+ name if name == this.mangle_internal_symbol("__rust_dealloc")
|| name == "miri_dealloc" =>
{
let default = |ecx: &mut MiriInterpCx<'tcx>| {
@@ -592,7 +581,7 @@ fn emulate_foreign_item_inner(
_ => return this.emulate_allocator(default),
}
}
- name if name == mangle_internal_symbol(*this.tcx, "__rust_realloc") => {
+ name if name == this.mangle_internal_symbol("__rust_realloc") => {
return this.emulate_allocator(|this| {
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index fc58d88..18af821 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -144,7 +144,8 @@ fn handle_stack_pop_unwind(
// Directly return to caller of `try`.
StackPopCleanup::Goto {
ret: catch_unwind.ret,
- unwind: mir::UnwindAction::Continue,
+ // `catch_fn` must not unwind.
+ unwind: mir::UnwindAction::Unreachable,
},
)?;
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 0975707..1770b99 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -1,7 +1,7 @@
use std::ffi::OsStr;
use std::str;
-use rustc_abi::Size;
+use rustc_abi::{ExternAbi, Size};
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf;
use rustc_span::Symbol;
@@ -200,7 +200,14 @@ fn emulate_foreign_item_inner(
this.write(fd, buf, count, Some(offset), dest)?;
}
"close" => {
- let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
+ let [fd] = this.check_shim_abi(
+ link_name,
+ abi,
+ ExternAbi::C { unwind: false },
+ [this.tcx.types.i32],
+ this.tcx.types.i32,
+ args,
+ )?;
let result = this.close(fd)?;
this.write_scalar(result, dest)?;
}
diff --git a/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs
new file mode 100644
index 0000000..eb8de04
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs
@@ -0,0 +1,21 @@
+//@ignore-target: windows # File handling is not implemented yet
+//@compile-flags: -Zmiri-disable-isolation
+use std::ffi::{CString, OsStr, c_char, c_int};
+use std::os::unix::ffi::OsStrExt;
+
+extern "C" {
+ fn open(path: *const c_char, oflag: c_int, ...) -> c_int;
+ // correct fd type is i32
+ fn close(fd: u32) -> c_int;
+}
+
+fn main() {
+ let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed");
+ let fd = unsafe {
+ open(c_path.as_ptr(), /* value does not matter */ 0)
+ } as u32;
+ let _ = unsafe {
+ close(fd);
+ //~^ ERROR: calling a function with argument of type i32 passing data of type u32
+ };
+}
diff --git a/src/tools/miri/tests/fail/shims/input_arg_mismatch.stderr b/src/tools/miri/tests/fail/shims/input_arg_mismatch.stderr
new file mode 100644
index 0000000..90d4ce7
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/input_arg_mismatch.stderr
@@ -0,0 +1,17 @@
+error: Undefined Behavior: calling a function with argument of type i32 passing data of type u32
+ --> tests/fail/shims/input_arg_mismatch.rs:LL:CC
+ |
+LL | close(fd);
+ | ^^^^^^^^^ calling a function with argument of type i32 passing data of type u32
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
+ = help: if you think this code should be accepted anyway, please report an issue with Miri
+ = note: BACKTRACE:
+ = note: inside `main` at tests/fail/shims/input_arg_mismatch.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/shims/return_type_mismatch.rs b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs
new file mode 100644
index 0000000..6dbdd3f
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs
@@ -0,0 +1,21 @@
+//@ignore-target: windows # File handling is not implemented yet
+//@compile-flags: -Zmiri-disable-isolation
+use std::ffi::{CString, OsStr, c_char, c_int, c_short};
+use std::os::unix::ffi::OsStrExt;
+
+extern "C" {
+ fn open(path: *const c_char, oflag: c_int, ...) -> c_int;
+ // correct return type is i32
+ fn close(fd: c_int) -> c_short;
+}
+
+fn main() {
+ let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed");
+ let fd = unsafe {
+ open(c_path.as_ptr(), /* value does not matter */ 0)
+ };
+ let _ = unsafe {
+ close(fd);
+ //~^ ERROR: calling a function with return type i32 passing return place of type i16
+ };
+}
diff --git a/src/tools/miri/tests/fail/shims/return_type_mismatch.stderr b/src/tools/miri/tests/fail/shims/return_type_mismatch.stderr
new file mode 100644
index 0000000..062aa7b
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/return_type_mismatch.stderr
@@ -0,0 +1,17 @@
+error: Undefined Behavior: calling a function with return type i32 passing return place of type i16
+ --> tests/fail/shims/return_type_mismatch.rs:LL:CC
+ |
+LL | close(fd);
+ | ^^^^^^^^^ calling a function with return type i32 passing return place of type i16
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
+ = help: if you think this code should be accepted anyway, please report an issue with Miri
+ = note: BACKTRACE:
+ = note: inside `main` at tests/fail/shims/return_type_mismatch.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
index 0ca13b5..f8f1c55 100644
--- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
@@ -64,7 +64,7 @@ fn wait_wrong_val() {
),
-1,
);
- assert_eq!(*libc::__errno_location(), libc::EAGAIN);
+ assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::EAGAIN);
}
}
@@ -85,7 +85,7 @@ fn wait_timeout() {
),
-1,
);
- assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
+ assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT);
}
assert!((200..1000).contains(&start.elapsed().as_millis()));
@@ -124,7 +124,7 @@ fn wait_absolute_timeout() {
),
-1,
);
- assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
+ assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT);
}
assert!((200..1000).contains(&start.elapsed().as_millis()));
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
index 01433ed..d6072c2 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
@@ -56,8 +56,7 @@ fn test_pipe_threaded() {
assert_eq!(res, 5);
assert_eq!(buf, "abcde".as_bytes());
});
- // FIXME: we should yield here once blocking is implemented.
- //thread::yield_now();
+ thread::yield_now();
let data = "abcde".as_bytes().as_ptr();
let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
assert_eq!(res, 5);
@@ -65,14 +64,11 @@ fn test_pipe_threaded() {
// Read and write from different direction
let thread2 = thread::spawn(move || {
- // FIXME: we should yield here once blocking is implemented.
- //thread::yield_now();
+ thread::yield_now();
let data = "12345".as_bytes().as_ptr();
let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
assert_eq!(res, 5);
});
- // FIXME: we should not yield here once blocking is implemented.
- thread::yield_now();
let mut buf: [u8; 5] = [0; 5];
let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
assert_eq!(res, 5);
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index b3b6fe1..05ac5e8 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -1281,7 +1281,6 @@ fn test_non_determinism() {
/// Ensure that the operation is non-deterministic
#[track_caller]
fn ensure_nondet<T: PartialEq + std::fmt::Debug>(f: impl Fn() -> T) {
-
let rounds = 16;
let first = f();
for _ in 1..rounds {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
index 9a7a1a0..4c4174e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
@@ -665,10 +665,6 @@ macro_rules! experimental {
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
rustc_attr!(TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing),
- rustc_attr!(
- TEST, rustc_error, Normal,
- template!(Word, List: "delayed_bug_from_inside_query"), WarnFollowingWordOnly
- ),
rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing),
rustc_attr!(
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
index 4e28aac..7668f41 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
@@ -110,7 +110,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result<String> {
));
}
let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]);
- // Last supported version is:
+ // Last breaking version change is:
// https://github.com/rust-lang/rust/commit/b94cfefc860715fb2adf72a6955423d384c69318
let (mut metadata_portion, bytes_before_version) = match version {
8 => {
@@ -118,7 +118,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result<String> {
let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
(&dot_rustc[12..data_len + 12], 13)
}
- 9 => {
+ 9 | 10 => {
let len_bytes = &dot_rustc[8..16];
let data_len = u64::from_le_bytes(len_bytes.try_into().unwrap()) as usize;
(&dot_rustc[16..data_len + 12], 17)
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index e54747c..a1ccaa4 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -880,9 +880,9 @@
[[package]]
name = "mdbook"
-version = "0.4.47"
+version = "0.4.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84"
+checksum = "8b6fbb4ac2d9fd7aa987c3510309ea3c80004a968d063c42f0d34fea070817c1"
dependencies = [
"ammonia",
"anyhow",
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 831233e..a0b220c 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -15,6 +15,6 @@
mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
[dependencies.mdbook]
-version = "0.4.47"
+version = "0.4.48"
default-features = false
features = ["search"]
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index ea575f2..f70fc91 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -451,7 +451,7 @@
if (!Object.prototype.hasOwnProperty.call(entry, key)) {
continue;
}
- if (key === "displayTypeSignature") {
+ if (key === "displayTypeSignature" && entry.displayTypeSignature !== null) {
const {type, mappedNames, whereClause} =
await entry.displayTypeSignature;
entry.displayType = arrayToCode(type);
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index e866f13..6512077 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -246,7 +246,7 @@ pub(crate) fn format_expr(
| ast::ExprKind::Await(_, _)
| ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape),
ast::ExprKind::MacCall(ref mac) => {
- rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| {
+ rewrite_macro(mac, context, shape, MacroPosition::Expression).or_else(|_| {
wrap_str(
context.snippet(expr.span).to_owned(),
context.config.max_width(),
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 3fb3284..322af97 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -6,7 +6,7 @@
use regex::Regex;
use rustc_ast::visit;
use rustc_ast::{ast, ptr};
-use rustc_span::{BytePos, DUMMY_SP, Span, symbol};
+use rustc_span::{BytePos, DUMMY_SP, Ident, Span, symbol};
use tracing::debug;
use crate::attr::filter_inline_attrs;
@@ -333,12 +333,12 @@ pub(crate) fn from_fn_kind(
defaultness: ast::Defaultness,
) -> FnSig<'a> {
match *fn_kind {
- visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, vis, ast::Fn { sig, generics, .. }) => {
+ visit::FnKind::Fn(visit::FnCtxt::Assoc(..), vis, ast::Fn { sig, generics, .. }) => {
let mut fn_sig = FnSig::from_method_sig(sig, generics, vis);
fn_sig.defaultness = defaultness;
fn_sig
}
- visit::FnKind::Fn(_, _, vis, ast::Fn { sig, generics, .. }) => FnSig {
+ visit::FnKind::Fn(_, vis, ast::Fn { sig, generics, .. }) => FnSig {
decl,
generics,
ext: sig.header.ext,
@@ -750,11 +750,10 @@ fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
(Type(lty), Type(rty))
if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) =>
{
- a.ident.as_str().cmp(b.ident.as_str())
+ lty.ident.as_str().cmp(rty.ident.as_str())
}
- (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => {
- a.ident.as_str().cmp(b.ident.as_str())
- }
+ (Const(ca), Const(cb)) => ca.ident.as_str().cmp(cb.ident.as_str()),
+ (MacCall(..), MacCall(..)) => Ordering::Equal,
(Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => {
a.span.lo().cmp(&b.span.lo())
}
@@ -1105,14 +1104,16 @@ fn from_variant(variant: &'a ast::Variant, context: &RewriteContext<'_>) -> Self
}
pub(crate) fn from_item(item: &'a ast::Item) -> Self {
- let (prefix, def, generics) = match item.kind {
- ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics),
- ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics),
+ let (prefix, def, ident, generics) = match item.kind {
+ ast::ItemKind::Struct(ident, ref def, ref generics) => {
+ ("struct ", def, ident, generics)
+ }
+ ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics),
_ => unreachable!(),
};
StructParts {
prefix,
- ident: item.ident,
+ ident,
vis: &item.vis,
def,
generics: Some(generics),
@@ -1168,6 +1169,7 @@ pub(crate) fn format_trait(
let ast::Trait {
is_auto,
safety,
+ ident,
ref generics,
ref bounds,
ref items,
@@ -1186,13 +1188,13 @@ pub(crate) fn format_trait(
let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
let generics_str =
- rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?;
+ rewrite_generics(context, rewrite_ident(context, ident), generics, shape).ok()?;
result.push_str(&generics_str);
// FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
if !bounds.is_empty() {
// Retrieve *unnormalized* ident (See #6069)
- let source_ident = context.snippet(item.ident.span);
+ let source_ident = context.snippet(ident.span);
let ident_hi = context.snippet_provider.span_after(item.span, source_ident);
let bound_hi = bounds.last().unwrap().span().hi();
let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
@@ -1679,11 +1681,12 @@ fn format_tuple_struct(
Some(result)
}
-pub(crate) enum ItemVisitorKind<'a> {
- Item(&'a ast::Item),
- AssocTraitItem(&'a ast::AssocItem),
- AssocImplItem(&'a ast::AssocItem),
- ForeignItem(&'a ast::ForeignItem),
+#[derive(Clone, Copy)]
+pub(crate) enum ItemVisitorKind {
+ Item,
+ AssocTraitItem,
+ AssocImplItem,
+ ForeignItem,
}
struct TyAliasRewriteInfo<'c, 'g>(
@@ -1695,17 +1698,19 @@ struct TyAliasRewriteInfo<'c, 'g>(
Span,
);
-pub(crate) fn rewrite_type_alias<'a, 'b>(
+pub(crate) fn rewrite_type_alias<'a>(
ty_alias_kind: &ast::TyAlias,
+ vis: &ast::Visibility,
context: &RewriteContext<'a>,
indent: Indent,
- visitor_kind: &ItemVisitorKind<'b>,
+ visitor_kind: ItemVisitorKind,
span: Span,
) -> RewriteResult {
use ItemVisitorKind::*;
let ast::TyAlias {
defaultness,
+ ident,
ref generics,
ref bounds,
ref ty,
@@ -1715,11 +1720,6 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
let rhs_hi = ty
.as_ref()
.map_or(where_clauses.before.span.hi(), |ty| ty.span.hi());
- let (ident, vis) = match visitor_kind {
- Item(i) => (i.ident, &i.vis),
- AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
- ForeignItem(i) => (i.ident, &i.vis),
- };
let rw_info = &TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span);
let op_ty = opaque_ty(ty);
// Type Aliases are formatted slightly differently depending on the context
@@ -1727,14 +1727,14 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
// https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
// https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
match (visitor_kind, &op_ty) {
- (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => {
+ (Item | AssocTraitItem | ForeignItem, Some(op_bounds)) => {
let op = OpaqueType { bounds: op_bounds };
rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis)
}
- (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => {
+ (Item | AssocTraitItem | ForeignItem, None) => {
rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis)
}
- (AssocImplItem(_), _) => {
+ (AssocImplItem, _) => {
let result = if let Some(op_bounds) = op_ty {
let op = OpaqueType { bounds: op_bounds };
rewrite_ty(
@@ -2024,14 +2024,23 @@ pub(crate) struct StaticParts<'a> {
impl<'a> StaticParts<'a> {
pub(crate) fn from_item(item: &'a ast::Item) -> Self {
- let (defaultness, prefix, safety, ty, mutability, expr, generics) = match &item.kind {
- ast::ItemKind::Static(s) => {
- (None, "static", s.safety, &s.ty, s.mutability, &s.expr, None)
- }
+ let (defaultness, prefix, safety, ident, ty, mutability, expr, generics) = match &item.kind
+ {
+ ast::ItemKind::Static(s) => (
+ None,
+ "static",
+ s.safety,
+ s.ident,
+ &s.ty,
+ s.mutability,
+ &s.expr,
+ None,
+ ),
ast::ItemKind::Const(c) => (
Some(c.defaultness),
"const",
ast::Safety::Default,
+ c.ident,
&c.ty,
ast::Mutability::Not,
&c.expr,
@@ -2043,7 +2052,7 @@ pub(crate) fn from_item(item: &'a ast::Item) -> Self {
prefix,
safety,
vis: &item.vis,
- ident: item.ident,
+ ident,
generics,
ty,
mutability,
@@ -2053,7 +2062,7 @@ pub(crate) fn from_item(item: &'a ast::Item) -> Self {
}
}
- pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self {
+ pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self {
let (defaultness, ty, expr_opt, generics) = match &ti.kind {
ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)),
_ => unreachable!(),
@@ -2062,7 +2071,7 @@ pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self {
prefix: "const",
safety: ast::Safety::Default,
vis: &ti.vis,
- ident: ti.ident,
+ ident,
generics,
ty,
mutability: ast::Mutability::Not,
@@ -2072,7 +2081,7 @@ pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self {
}
}
- pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self {
+ pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self {
let (defaultness, ty, expr, generics) = match &ii.kind {
ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)),
_ => unreachable!(),
@@ -2081,7 +2090,7 @@ pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self {
prefix: "const",
safety: ast::Safety::Default,
vis: &ii.vis,
- ident: ii.ident,
+ ident,
generics,
ty,
mutability: ast::Mutability::Not,
@@ -3442,6 +3451,7 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
let ast::Fn {
defaultness,
ref sig,
+ ident,
ref generics,
ref body,
..
@@ -3453,7 +3463,8 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
let inner_attrs = inner_attributes(&self.attrs);
let fn_ctxt = visit::FnCtxt::Foreign;
visitor.visit_fn(
- visit::FnKind::Fn(fn_ctxt, &self.ident, &self.vis, fn_kind),
+ ident,
+ visit::FnKind::Fn(fn_ctxt, &self.vis, fn_kind),
&sig.decl,
self.span,
defaultness,
@@ -3464,7 +3475,7 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
rewrite_fn_base(
context,
shape.indent,
- self.ident,
+ ident,
&FnSig::from_method_sig(sig, generics, &self.vis),
span,
FnBraceStyle::None,
@@ -3483,7 +3494,7 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
vis,
safety,
mut_str,
- rewrite_ident(context, self.ident)
+ rewrite_ident(context, static_foreign_item.ident)
);
// 1 = ;
rewrite_assign_rhs(
@@ -3498,11 +3509,11 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
.map(|s| s + ";")
}
ast::ForeignItemKind::TyAlias(ref ty_alias) => {
- let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span);
- rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
+ let kind = ItemVisitorKind::ForeignItem;
+ rewrite_type_alias(ty_alias, &self.vis, context, shape.indent, kind, self.span)
}
ast::ForeignItemKind::MacCall(ref mac) => {
- rewrite_macro(mac, None, context, shape, MacroPosition::Item)
+ rewrite_macro(mac, context, shape, MacroPosition::Item)
}
}?;
@@ -3562,12 +3573,13 @@ fn rewrite_attrs(
pub(crate) fn rewrite_mod(
context: &RewriteContext<'_>,
item: &ast::Item,
+ ident: Ident,
attrs_shape: Shape,
) -> Option<String> {
let mut result = String::with_capacity(32);
result.push_str(&*format_visibility(context, &item.vis));
result.push_str("mod ");
- result.push_str(rewrite_ident(context, item.ident));
+ result.push_str(rewrite_ident(context, ident));
result.push(';');
rewrite_attrs(context, item, &result, attrs_shape)
}
@@ -3594,7 +3606,7 @@ pub(crate) fn rewrite_extern_crate(
pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
!matches!(
item.kind,
- ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
+ ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
)
}
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index e239ff4..ddf3d2c 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -16,10 +16,7 @@
use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree};
use rustc_ast::{ast, ptr};
use rustc_ast_pretty::pprust;
-use rustc_span::{
- BytePos, DUMMY_SP, Span, Symbol,
- symbol::{self, kw},
-};
+use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol};
use tracing::debug;
use crate::comment::{
@@ -60,7 +57,7 @@ pub(crate) enum MacroArg {
Ty(ptr::P<ast::Ty>),
Pat(ptr::P<ast::Pat>),
Item(ptr::P<ast::Item>),
- Keyword(symbol::Ident, Span),
+ Keyword(Ident, Span),
}
impl MacroArg {
@@ -103,20 +100,12 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
}
/// Rewrite macro name without using pretty-printer if possible.
-fn rewrite_macro_name(
- context: &RewriteContext<'_>,
- path: &ast::Path,
- extra_ident: Option<symbol::Ident>,
-) -> String {
- let name = if path.segments.len() == 1 {
+fn rewrite_macro_name(context: &RewriteContext<'_>, path: &ast::Path) -> String {
+ if path.segments.len() == 1 {
// Avoid using pretty-printer in the common case.
format!("{}!", rewrite_ident(context, path.segments[0].ident))
} else {
format!("{}!", pprust::path_to_string(path))
- };
- match extra_ident {
- Some(ident) if ident.name != kw::Empty => format!("{name} {ident}"),
- _ => name,
}
}
@@ -165,7 +154,6 @@ fn return_macro_parse_failure_fallback(
pub(crate) fn rewrite_macro(
mac: &ast::MacCall,
- extra_ident: Option<symbol::Ident>,
context: &RewriteContext<'_>,
shape: Shape,
position: MacroPosition,
@@ -179,14 +167,7 @@ pub(crate) fn rewrite_macro(
} else {
let guard = context.enter_macro();
let result = catch_unwind(AssertUnwindSafe(|| {
- rewrite_macro_inner(
- mac,
- extra_ident,
- context,
- shape,
- position,
- guard.is_nested(),
- )
+ rewrite_macro_inner(mac, context, shape, position, guard.is_nested())
}));
match result {
Err(..) => {
@@ -207,7 +188,6 @@ pub(crate) fn rewrite_macro(
fn rewrite_macro_inner(
mac: &ast::MacCall,
- extra_ident: Option<symbol::Ident>,
context: &RewriteContext<'_>,
shape: Shape,
position: MacroPosition,
@@ -222,7 +202,7 @@ fn rewrite_macro_inner(
let original_style = macro_style(mac, context);
- let macro_name = rewrite_macro_name(context, &mac.path, extra_ident);
+ let macro_name = rewrite_macro_name(context, &mac.path);
let is_forced_bracket = FORCED_BRACKET_MACROS.contains(&¯o_name[..]);
let style = if is_forced_bracket && !is_nested_macro {
@@ -432,7 +412,7 @@ pub(crate) fn rewrite_macro_def(
shape: Shape,
indent: Indent,
def: &ast::MacroDef,
- ident: symbol::Ident,
+ ident: Ident,
vis: &ast::Visibility,
span: Span,
) -> RewriteResult {
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index a40ee7f..bc5a6d3 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -152,7 +152,7 @@ fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResol
let mut visitor = visitor::CfgIfVisitor::new(self.psess);
visitor.visit_item(&item);
for module_item in visitor.mods() {
- if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind {
+ if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = module_item.item.kind {
self.visit_sub_mod(
&module_item.item,
Module::new(
@@ -178,7 +178,7 @@ fn visit_mod_outside_ast(
continue;
}
- if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+ if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind {
let span = item.span;
self.visit_sub_mod(
&item,
@@ -204,7 +204,7 @@ fn visit_mod_from_ast(
self.visit_cfg_if(Cow::Borrowed(item))?;
}
- if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+ if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind {
let span = item.span;
self.visit_sub_mod(
item,
@@ -248,7 +248,7 @@ fn peek_sub_mod(
if is_mod_decl(item) {
// mod foo;
// Look for an extern file.
- self.find_external_module(item.ident, &item.attrs, sub_mod)
+ self.find_external_module(item.kind.ident().unwrap(), &item.attrs, sub_mod)
} else {
// An internal module (`mod foo { /* ... */ }`);
Ok(Some(SubModKind::Internal(item)))
@@ -291,7 +291,7 @@ fn visit_sub_mod_inner(
self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
}
SubModKind::Internal(item) => {
- self.push_inline_mod_directory(item.ident, &item.attrs);
+ self.push_inline_mod_directory(item.kind.ident().unwrap(), &item.attrs);
self.visit_sub_mod_after_directory_update(sub_mod, None)
}
SubModKind::MultiExternal(mods) => {
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index bafed41..8dc9457 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -307,9 +307,7 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
context,
shape,
),
- PatKind::MacCall(ref mac) => {
- rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
- }
+ PatKind::MacCall(ref mac) => rewrite_macro(mac, context, shape, MacroPosition::Pat),
PatKind::Paren(ref pat) => pat
.rewrite_result(
context,
diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs
index 8a31e0a..2460b61 100644
--- a/src/tools/rustfmt/src/reorder.rs
+++ b/src/tools/rustfmt/src/reorder.rs
@@ -25,14 +25,17 @@
/// Choose the ordering between the given two items.
fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering {
match (&a.kind, &b.kind) {
- (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => {
- a.ident.as_str().cmp(b.ident.as_str())
+ (&ast::ItemKind::Mod(_, a_ident, _), &ast::ItemKind::Mod(_, b_ident, _)) => {
+ a_ident.as_str().cmp(b_ident.as_str())
}
- (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => {
+ (
+ &ast::ItemKind::ExternCrate(ref a_name, a_ident),
+ &ast::ItemKind::ExternCrate(ref b_name, b_ident),
+ ) => {
// `extern crate foo as bar;`
// ^^^ Comparing this.
- let a_orig_name = a_name.unwrap_or(a.ident.name);
- let b_orig_name = b_name.unwrap_or(b.ident.name);
+ let a_orig_name = a_name.unwrap_or(a_ident.name);
+ let b_orig_name = b_name.unwrap_or(b_ident.name);
let result = a_orig_name.as_str().cmp(b_orig_name.as_str());
if result != Ordering::Equal {
return result;
@@ -44,7 +47,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering {
(Some(..), None) => Ordering::Greater,
(None, Some(..)) => Ordering::Less,
(None, None) => Ordering::Equal,
- (Some(..), Some(..)) => a.ident.as_str().cmp(b.ident.as_str()),
+ (Some(..), Some(..)) => a_ident.as_str().cmp(b_ident.as_str()),
}
}
_ => unreachable!(),
@@ -69,7 +72,7 @@ fn rewrite_reorderable_item(
) -> Option<String> {
match item.kind {
ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item, shape),
- ast::ItemKind::Mod(..) => rewrite_mod(context, item, shape),
+ ast::ItemKind::Mod(_, ident, _) => rewrite_mod(context, item, ident, shape),
_ => None,
}
}
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 06a6733..75a5a85 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1018,7 +1018,7 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR
ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape),
ast::TyKind::Never => Ok(String::from("!")),
ast::TyKind::MacCall(ref mac) => {
- rewrite_macro(mac, None, context, shape, MacroPosition::Expression)
+ rewrite_macro(mac, context, shape, MacroPosition::Expression)
}
ast::TyKind::ImplicitSelf => Ok(String::from("")),
ast::TyKind::ImplTrait(_, ref it) => {
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 5749d8c..16d1f51 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -3,7 +3,7 @@
use std::sync::Arc;
use rustc_ast::{ast, token::Delimiter, visit};
-use rustc_span::{BytePos, Pos, Span, symbol};
+use rustc_span::{BytePos, Ident, Pos, Span, symbol};
use tracing::debug;
use crate::attr::*;
@@ -172,7 +172,7 @@ fn visit_stmt(&mut self, stmt: &Stmt<'_>, include_empty_semi: bool) {
get_span_without_attrs(stmt.as_ast_node()),
);
} else {
- self.visit_mac(&mac_stmt.mac, None, MacroPosition::Statement);
+ self.visit_mac(&mac_stmt.mac, MacroPosition::Statement);
}
self.format_missing(stmt.span().hi());
}
@@ -377,6 +377,7 @@ fn unindent_comment_on_closing_brace(&self, b: &ast::Block) -> bool {
// on traits do not get handled here.
pub(crate) fn visit_fn(
&mut self,
+ ident: Ident,
fk: visit::FnKind<'_>,
fd: &ast::FnDecl,
s: Span,
@@ -388,7 +389,6 @@ pub(crate) fn visit_fn(
let rewrite = match fk {
visit::FnKind::Fn(
_,
- ident,
_,
ast::Fn {
body: Some(ref b), ..
@@ -397,7 +397,7 @@ pub(crate) fn visit_fn(
block = b;
self.rewrite_fn_before_block(
indent,
- *ident,
+ ident,
&FnSig::from_fn_kind(&fk, fd, defaultness),
mk_sp(s.lo(), b.span.lo()),
)
@@ -444,7 +444,7 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
let should_visit_node_again = match item.kind {
// For use/extern crate items, skip rewriting attributes but check for a skip attribute.
- ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(_) => {
+ ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(..) => {
if contains_skip(attrs) {
self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span());
false
@@ -497,11 +497,11 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
self.push_rewrite(item.span, rw);
}
- ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
+ ast::ItemKind::TraitAlias(ident, ref generics, ref generic_bounds) => {
let shape = Shape::indented(self.block_indent, self.config);
let rw = format_trait_alias(
&self.get_context(),
- item.ident,
+ ident,
&item.vis,
generics,
generic_bounds,
@@ -509,7 +509,7 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
);
self.push_rewrite(item.span, rw);
}
- ast::ItemKind::ExternCrate(_) => {
+ ast::ItemKind::ExternCrate(..) => {
let rw = rewrite_extern_crate(&self.get_context(), item, self.shape());
let span = if attrs.is_empty() {
item.span
@@ -521,17 +521,17 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => {
self.visit_struct(&StructParts::from_item(item));
}
- ast::ItemKind::Enum(ref def, ref generics) => {
+ ast::ItemKind::Enum(ident, ref def, ref generics) => {
self.format_missing_with_indent(source!(self, item.span).lo());
- self.visit_enum(item.ident, &item.vis, def, generics, item.span);
+ self.visit_enum(ident, &item.vis, def, generics, item.span);
self.last_pos = source!(self, item.span).hi();
}
- ast::ItemKind::Mod(safety, ref mod_kind) => {
+ ast::ItemKind::Mod(safety, ident, ref mod_kind) => {
self.format_missing_with_indent(source!(self, item.span).lo());
- self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs);
+ self.format_mod(mod_kind, safety, &item.vis, item.span, ident, attrs);
}
ast::ItemKind::MacCall(ref mac) => {
- self.visit_mac(mac, Some(item.ident), MacroPosition::Item);
+ self.visit_mac(mac, MacroPosition::Item);
}
ast::ItemKind::ForeignMod(ref foreign_mod) => {
self.format_missing_with_indent(source!(self, item.span).lo());
@@ -544,6 +544,7 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
let ast::Fn {
defaultness,
ref sig,
+ ident,
ref generics,
ref body,
..
@@ -555,7 +556,8 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
_ => visit::FnCtxt::Foreign,
};
self.visit_fn(
- visit::FnKind::Fn(fn_ctxt, &item.ident, &item.vis, fn_kind),
+ ident,
+ visit::FnKind::Fn(fn_ctxt, &item.vis, fn_kind),
&sig.decl,
item.span,
defaultness,
@@ -564,28 +566,26 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
} else {
let indent = self.block_indent;
let rewrite = self
- .rewrite_required_fn(
- indent, item.ident, sig, &item.vis, generics, item.span,
- )
+ .rewrite_required_fn(indent, ident, sig, &item.vis, generics, item.span)
.ok();
self.push_rewrite(item.span, rewrite);
}
}
ast::ItemKind::TyAlias(ref ty_alias) => {
use ItemVisitorKind::Item;
- self.visit_ty_alias_kind(ty_alias, &Item(item), item.span);
+ self.visit_ty_alias_kind(ty_alias, &item.vis, Item, item.span);
}
ast::ItemKind::GlobalAsm(..) => {
let snippet = Some(self.snippet(item.span).to_owned());
self.push_rewrite(item.span, snippet);
}
- ast::ItemKind::MacroDef(ref def) => {
+ ast::ItemKind::MacroDef(ident, ref def) => {
let rewrite = rewrite_macro_def(
&self.get_context(),
self.shape(),
self.block_indent,
def,
- item.ident,
+ ident,
&item.vis,
item.span,
)
@@ -605,11 +605,13 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
fn visit_ty_alias_kind(
&mut self,
ty_kind: &ast::TyAlias,
- visitor_kind: &ItemVisitorKind<'_>,
+ vis: &ast::Visibility,
+ visitor_kind: ItemVisitorKind,
span: Span,
) {
let rewrite = rewrite_type_alias(
ty_kind,
+ vis,
&self.get_context(),
self.block_indent,
visitor_kind,
@@ -619,15 +621,16 @@ fn visit_ty_alias_kind(
self.push_rewrite(span, rewrite);
}
- fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
+ fn visit_assoc_item(&mut self, ai: &ast::AssocItem, visitor_kind: ItemVisitorKind) {
use ItemVisitorKind::*;
- // TODO(calebcartwright): Not sure the skip spans are correct
- let (ai, skip_span, assoc_ctxt) = match visitor_kind {
- AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
+ let assoc_ctxt = match visitor_kind {
+ AssocTraitItem => visit::AssocCtxt::Trait,
// There is no difference between trait and inherent assoc item formatting
- AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl { of_trait: false }),
+ AssocImplItem => visit::AssocCtxt::Impl { of_trait: false },
_ => unreachable!(),
};
+ // TODO(calebcartwright): Not sure the skip spans are correct
+ let skip_span = ai.span;
skip_out_of_file_lines_range_visitor!(self, ai.span);
if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
@@ -637,16 +640,17 @@ fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
// TODO(calebcartwright): consider enabling box_patterns feature gate
match (&ai.kind, visitor_kind) {
- (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
- self.visit_static(&StaticParts::from_trait_item(ai))
+ (ast::AssocItemKind::Const(c), AssocTraitItem) => {
+ self.visit_static(&StaticParts::from_trait_item(ai, c.ident))
}
- (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
- self.visit_static(&StaticParts::from_impl_item(ai))
+ (ast::AssocItemKind::Const(c), AssocImplItem) => {
+ self.visit_static(&StaticParts::from_impl_item(ai, c.ident))
}
(ast::AssocItemKind::Fn(ref fn_kind), _) => {
let ast::Fn {
defaultness,
ref sig,
+ ident,
ref generics,
ref body,
..
@@ -655,7 +659,8 @@ fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
let inner_attrs = inner_attributes(&ai.attrs);
let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
self.visit_fn(
- visit::FnKind::Fn(fn_ctxt, &ai.ident, &ai.vis, fn_kind),
+ ident,
+ visit::FnKind::Fn(fn_ctxt, &ai.vis, fn_kind),
&sig.decl,
ai.span,
defaultness,
@@ -664,35 +669,35 @@ fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
} else {
let indent = self.block_indent;
let rewrite = self
- .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span)
+ .rewrite_required_fn(indent, fn_kind.ident, sig, &ai.vis, generics, ai.span)
.ok();
self.push_rewrite(ai.span, rewrite);
}
}
(ast::AssocItemKind::Type(ref ty_alias), _) => {
- self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
+ self.visit_ty_alias_kind(ty_alias, &ai.vis, visitor_kind, ai.span);
}
(ast::AssocItemKind::MacCall(ref mac), _) => {
- self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
+ self.visit_mac(mac, MacroPosition::Item);
}
_ => unreachable!(),
}
}
pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
- self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
+ self.visit_assoc_item(ti, ItemVisitorKind::AssocTraitItem);
}
pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
- self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
+ self.visit_assoc_item(ii, ItemVisitorKind::AssocImplItem);
}
- fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {
+ fn visit_mac(&mut self, mac: &ast::MacCall, pos: MacroPosition) {
skip_out_of_file_lines_range_visitor!(self, mac.span());
// 1 = ;
let shape = self.shape().saturating_sub_width(1);
- let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok());
+ let rewrite = self.with_context(|ctx| rewrite_macro(mac, ctx, shape, pos).ok());
// As of v638 of the rustc-ap-* crates, the associated span no longer includes
// the trailing semicolon. This determines the correct span to ensure scenarios
// with whitespace between the delimiters and trailing semi (i.e. `foo!(abc) ;`)
diff --git a/src/tools/rustfmt/tests/source/pattern.rs b/src/tools/rustfmt/tests/source/pattern.rs
index ed6ad69..0e5abb5 100644
--- a/src/tools/rustfmt/tests/source/pattern.rs
+++ b/src/tools/rustfmt/tests/source/pattern.rs
@@ -91,7 +91,7 @@ fn issue3728() {
fn literals() {
match 42 {
- const { 1 + 2 } | 4
+ 1 | 2 | 4
| 6 => {}
10 | 11 | 12
| 13 | 14 => {}
diff --git a/src/tools/rustfmt/tests/target/pattern.rs b/src/tools/rustfmt/tests/target/pattern.rs
index e867f65..483725f 100644
--- a/src/tools/rustfmt/tests/target/pattern.rs
+++ b/src/tools/rustfmt/tests/target/pattern.rs
@@ -99,7 +99,7 @@ fn issue3728() {
fn literals() {
match 42 {
- const { 1 + 2 } | 4 | 6 => {}
+ 1 | 2 | 4 | 6 => {}
10 | 11 | 12 | 13 | 14 => {}
_ => {}
}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 1a65506..6036538 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -181,6 +181,8 @@
const EXCEPTIONS_CRANELIFT: ExceptionList = &[
// tidy-alphabetical-start
+ ("cranelift-assembler-x64", "Apache-2.0 WITH LLVM-exception"),
+ ("cranelift-assembler-x64-meta", "Apache-2.0 WITH LLVM-exception"),
("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
("cranelift-bitset", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
@@ -512,6 +514,8 @@
"bitflags",
"bumpalo",
"cfg-if",
+ "cranelift-assembler-x64",
+ "cranelift-assembler-x64-meta",
"cranelift-bforest",
"cranelift-bitset",
"cranelift-codegen",
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index a33e03d..d2ae9b1 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -2873,7 +2873,6 @@
ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs
ui/malformed/issue-69341-malformed-derive-inert.rs
ui/marker_trait_attr/issue-61651-type-mismatch.rs
-ui/match/issue-112438.rs
ui/match/issue-113012.rs
ui/match/issue-11319.rs
ui/match/issue-114691.rs
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 8be25b9..a2453a6 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -72,6 +72,19 @@ fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) -
collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path))
}
+/// Would switching underscores for dashes work?
+fn maybe_suggest_dashes(names: &BTreeSet<String>, feature_name: &str, bad: &mut bool) {
+ let with_dashes = feature_name.replace('_', "-");
+ if names.contains(&with_dashes) {
+ tidy_error!(
+ bad,
+ "the file `{}.md` contains underscores; use dashes instead: `{}.md`",
+ feature_name,
+ with_dashes,
+ );
+ }
+}
+
pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
let lang_features = features.lang;
let lib_features = features
@@ -93,14 +106,13 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
// Check for Unstable Book sections that don't have a corresponding unstable feature
for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names
{
- if !unstable_lang_feature_names.contains(&feature_name) {
- tidy_error!(
- bad,
- "The Unstable Book has a 'library feature' section '{}' which doesn't \
+ tidy_error!(
+ bad,
+ "The Unstable Book has a 'library feature' section '{}' which doesn't \
correspond to an unstable library feature",
- feature_name
- );
- }
+ feature_name
+ );
+ maybe_suggest_dashes(&unstable_lib_feature_names, &feature_name, bad);
}
// Check for Unstable Book sections that don't have a corresponding unstable feature.
@@ -112,7 +124,8 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
"The Unstable Book has a 'language feature' section '{}' which doesn't \
correspond to an unstable language feature",
feature_name
- )
+ );
+ maybe_suggest_dashes(&unstable_lang_feature_names, &feature_name, bad);
}
// List unstable features that don't have Unstable Book sections.
diff --git a/src/version b/src/version
index f634271..59be592 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.87.0
+1.88.0
diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs
new file mode 100644
index 0000000..7436e24
--- /dev/null
+++ b/tests/assembly/cstring-merging.rs
@@ -0,0 +1,27 @@
+//@ only-linux
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 --edition 2024
+
+use std::ffi::CStr;
+
+// CHECK: .section .rodata.str1.1,"aMS"
+// CHECK: .Lanon.{{.+}}:
+// CHECK-NEXT: .asciz "foo"
+#[unsafe(no_mangle)]
+static CSTR: &[u8; 4] = b"foo\0";
+
+// CHECK-NOT: .section
+// CHECK: .Lanon.{{.+}}:
+// CHECK-NEXT: .asciz "bar"
+#[unsafe(no_mangle)]
+pub fn cstr() -> &'static CStr {
+ c"bar"
+}
+
+// CHECK-NOT: .section
+// CHECK: .Lanon.{{.+}}:
+// CHECK-NEXT: .asciz "baz"
+#[unsafe(no_mangle)]
+pub fn manual_cstr() -> &'static str {
+ "baz\0"
+}
diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs
index 186198b..e1a7ad7 100644
--- a/tests/codegen/cast-target-abi.rs
+++ b/tests/codegen/cast-target-abi.rs
@@ -2,7 +2,7 @@
//@ add-core-stubs
//@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64
//@ min-llvm-version: 19
-//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error
+//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir
//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
//@[aarch64] needs-llvm-components: arm
diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
index 404f623..73bc7ef 100644
--- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
+++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
@@ -1,7 +1,7 @@
//@ add-core-stubs
//@ revisions: linux apple
//@ min-llvm-version: 19
-//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error
+//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir
//@[linux] compile-flags: --target x86_64-unknown-linux-gnu
//@[linux] needs-llvm-components: x86
diff --git a/tests/codegen/const-array.rs b/tests/codegen/const-array.rs
index e257d8a..b3df76c 100644
--- a/tests/codegen/const-array.rs
+++ b/tests/codegen/const-array.rs
@@ -2,7 +2,7 @@
#![crate_type = "lib"]
-const LUT: [u8; 2] = [1, 1];
+const LUT: [u8; 4] = [1, 1, 1, 1];
// CHECK-LABEL: @decode
#[no_mangle]
@@ -11,5 +11,5 @@ pub fn decode(i: u8) -> u8 {
// CHECK-NEXT: icmp
// CHECK-NEXT: select
// CHECK-NEXT: ret
- if i < 2 { LUT[i as usize] } else { 2 }
+ if i < 4 { LUT[i as usize] } else { 2 }
}
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
index b9808e4..8a7b1cc 100644
--- a/tests/codegen/debug-vtable.rs
+++ b/tests/codegen/debug-vtable.rs
@@ -15,7 +15,7 @@
// Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled.
// This helps debuggers more reliably map from dyn pointer to concrete type.
-// CHECK: @vtable.2 = private constant <{
+// CHECK: @vtable.2 = private constant [
// CHECK: @vtable.3 = private constant <{
// CHECK: @vtable.4 = private constant <{
diff --git a/tests/codegen/external-no-mangle-statics.rs b/tests/codegen/external-no-mangle-statics.rs
index dc4eca8..49f42ee 100644
--- a/tests/codegen/external-no-mangle-statics.rs
+++ b/tests/codegen/external-no-mangle-statics.rs
@@ -6,72 +6,72 @@
// `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their
// definitions
-// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant
+// CHECK-DAG: @A = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static A: u8 = 0;
-// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global
+// CHECK-DAG: @B = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut B: u8 = 0;
-// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant
+// CHECK-DAG: @C = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static C: u8 = 0;
-// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global
+// CHECK-DAG: @D = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut D: u8 = 0;
mod private {
- // CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant
+ // CHECK-DAG: @E = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static E: u8 = 0;
- // CHECK: @F = {{(dso_local )?}}local_unnamed_addr global
+ // CHECK-DAG: @F = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut F: u8 = 0;
- // CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant
+ // CHECK-DAG: @G = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static G: u8 = 0;
- // CHECK: @H = {{(dso_local )?}}local_unnamed_addr global
+ // CHECK-DAG: @H = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut H: u8 = 0;
}
const HIDDEN: () = {
- // CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant
+ // CHECK-DAG: @I = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static I: u8 = 0;
- // CHECK: @J = {{(dso_local )?}}local_unnamed_addr global
+ // CHECK-DAG: @J = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut J: u8 = 0;
- // CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant
+ // CHECK-DAG: @K = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static K: u8 = 0;
- // CHECK: @L = {{(dso_local )?}}local_unnamed_addr global
+ // CHECK-DAG: @L = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut L: u8 = 0;
};
fn x() {
- // CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant
+ // CHECK-DAG: @M = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
static M: fn() = x;
- // CHECK: @N = {{(dso_local )?}}local_unnamed_addr global
+ // CHECK-DAG: @N = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
static mut N: u8 = 0;
- // CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant
+ // CHECK-DAG: @O = {{(dso_local )?}}local_unnamed_addr constant
#[no_mangle]
pub static O: u8 = 0;
- // CHECK: @P = {{(dso_local )?}}local_unnamed_addr global
+ // CHECK-DAG: @P = {{(dso_local )?}}local_unnamed_addr global
#[no_mangle]
pub static mut P: u8 = 0;
}
diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs
index 196f5ed..f62f694 100644
--- a/tests/codegen/link_section.rs
+++ b/tests/codegen/link_section.rs
@@ -3,7 +3,7 @@
#![crate_type = "lib"]
-// CHECK: @VAR1 = {{(dso_local )?}}constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
+// CHECK: @VAR1 = {{(dso_local )?}}constant [4 x i8] c"\01\00\00\00", section ".test_one"
#[no_mangle]
#[link_section = ".test_one"]
#[cfg(target_endian = "little")]
diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs
index bfbccfe..7d17b3b 100644
--- a/tests/codegen/remap_path_prefix/main.rs
+++ b/tests/codegen/remap_path_prefix/main.rs
@@ -12,7 +12,7 @@
include!("aux_mod.rs");
// Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
+// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant [34 x i8] c"/the/src/remap_path_prefix/main.rs"
pub static FILE_PATH: &'static str = file!();
fn main() {
diff --git a/tests/codegen/slice-last-elements-optimization.rs b/tests/codegen/slice-last-elements-optimization.rs
new file mode 100644
index 0000000..b90f91d
--- /dev/null
+++ b/tests/codegen/slice-last-elements-optimization.rs
@@ -0,0 +1,37 @@
+//@ compile-flags: -Copt-level=3
+//@ only-x86_64
+//@ min-llvm-version: 20
+#![crate_type = "lib"]
+
+// This test verifies that LLVM 20 properly optimizes the bounds check
+// when accessing the last few elements of a slice with proper conditions.
+// Previously, this would generate an unreachable branch to
+// slice_start_index_len_fail even when the bounds check was provably safe.
+
+// CHECK-LABEL: @last_four_initial(
+#[no_mangle]
+pub fn last_four_initial(s: &[u8]) -> &[u8] {
+ // Previously this would generate a branch to slice_start_index_len_fail
+ // that is unreachable. The LLVM 20 fix should eliminate this branch.
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: unreachable
+ let start = if s.len() <= 4 { 0 } else { s.len() - 4 };
+ &s[start..]
+}
+
+// CHECK-LABEL: @last_four_optimized(
+#[no_mangle]
+pub fn last_four_optimized(s: &[u8]) -> &[u8] {
+ // This version was already correctly optimized before the fix in LLVM 20.
+ // CHECK-NOT: slice_start_index_len_fail
+ // CHECK-NOT: unreachable
+ if s.len() <= 4 { &s[0..] } else { &s[s.len() - 4..] }
+}
+
+// Just to verify we're correctly checking for the right thing
+// CHECK-LABEL: @test_bounds_check_happens(
+#[no_mangle]
+pub fn test_bounds_check_happens(s: &[u8], i: usize) -> &[u8] {
+ // CHECK: slice_start_index_len_fail
+ &s[i..]
+}
diff --git a/tests/codegen/uninit-consts.rs b/tests/codegen/uninit-consts.rs
index a58008e..bde71a3 100644
--- a/tests/codegen/uninit-consts.rs
+++ b/tests/codegen/uninit-consts.rs
@@ -11,15 +11,15 @@ pub struct PartiallyUninit {
y: MaybeUninit<[u8; 10]>,
}
-// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant <{ [10 x i8] }> undef
+// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant [10 x i8] undef
// CHECK: [[PARTIALLY_UNINIT:@.*]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4
// This shouldn't contain undef, since it contains more chunks
// than the default value of uninit_const_chunk_threshold.
-// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant <{ [32768 x i8] }> <{ [32768 x i8] c"{{.+}}" }>, align 4
+// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant [32768 x i8] c"{{.+}}", align 4
-// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant <{ [16384 x i8] }> undef
+// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant [16384 x i8] undef
// CHECK-LABEL: @fully_uninit
#[no_mangle]
diff --git a/tests/coverage-run-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage
index f007eb0..0fa9436 100644
--- a/tests/coverage-run-rustdoc/doctest.coverage
+++ b/tests/coverage-run-rustdoc/doctest.coverage
@@ -58,21 +58,21 @@
LL| |//!
LL| |//! doctest with custom main:
LL| |//! ```
- LL| 1|//! fn some_func() {
- LL| 1|//! println!("called some_func()");
- LL| 1|//! }
- LL| |//!
- LL| |//! #[derive(Debug)]
- LL| |//! struct SomeError;
+ LL| |//! fn some_func() {
+ LL| |//! println!("called some_func()");
+ LL| |//! }
+ LL| 1|//!
+ LL| 1|//! #[derive(Debug)]
+ LL| 1|//! struct SomeError;
LL| |//!
LL| |//! extern crate doctest_crate;
LL| |//!
- LL| 1|//! fn doctest_main() -> Result<(), SomeError> {
+ LL| |//! fn doctest_main() -> Result<(), SomeError> {
LL| 1|//! some_func();
LL| 1|//! doctest_crate::fn_run_in_doctests(2);
LL| 1|//! Ok(())
LL| 1|//! }
- LL| |//!
+ LL| 1|//!
LL| |//! // this `main` is not shown as covered, as it clashes with all the other
LL| |//! // `main` functions that were automatically generated for doctests
LL| |//! fn main() -> Result<(), SomeError> {
diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map
index 84fae4a..26536ca 100644
--- a/tests/coverage/abort.cov-map
+++ b/tests/coverage/abort.cov-map
@@ -34,14 +34,14 @@
Highest counter ID seen: c4
Function name: abort::might_abort
-Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 24, 02, 02, 0c, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 3
- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 20)
-- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 36)
+- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15)
- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2)
= (c0 - c1)
Highest counter ID seen: c1
diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map
index b432e63..27d4b03 100644
--- a/tests/coverage/assert-ne.cov-map
+++ b/tests/coverage/assert-ne.cov-map
@@ -1,12 +1,12 @@
Function name: assert_ne::main
-Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 1c, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02]
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 15, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 2
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
- expression 1 operands: lhs = Counter(0), rhs = Counter(2)
Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 21)
- Code(Counter(1)) at (prev + 4, 13) to (start + 0, 19)
- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19)
= (c0 - c1)
diff --git a/tests/coverage/assert-ne.coverage b/tests/coverage/assert-ne.coverage
index 236a8fd..fc43d4a 100644
--- a/tests/coverage/assert-ne.coverage
+++ b/tests/coverage/assert-ne.coverage
@@ -7,7 +7,7 @@
LL| |
LL| 1|fn main() {
LL| 1| assert_ne!(
- LL| 1| Foo(5), // Make sure this expression's span isn't lost.
+ LL| 1| black_box(Foo(5)), // Make sure this expression's span isn't lost.
LL| 1| if black_box(false) {
LL| 0| Foo(0) //
LL| | } else {
diff --git a/tests/coverage/assert-ne.rs b/tests/coverage/assert-ne.rs
index 8a8fe08..9d9fcb7 100644
--- a/tests/coverage/assert-ne.rs
+++ b/tests/coverage/assert-ne.rs
@@ -7,7 +7,7 @@
fn main() {
assert_ne!(
- Foo(5), // Make sure this expression's span isn't lost.
+ black_box(Foo(5)), // Make sure this expression's span isn't lost.
if black_box(false) {
Foo(0) //
} else {
diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map
index 526110e..3aef427 100644
--- a/tests/coverage/assert_not.cov-map
+++ b/tests/coverage/assert_not.cov-map
@@ -1,13 +1,13 @@
Function name: assert_not::main
-Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 12, 01, 02, 05, 00, 14, 01, 01, 05, 00, 14, 01, 01, 05, 00, 16, 01, 01, 01, 00, 02]
+Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 11, 01, 02, 05, 00, 13, 01, 01, 05, 00, 13, 01, 01, 05, 00, 15, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 5
-- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 18)
-- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 20)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 20)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 17)
+- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 19)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 19)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 21)
- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
Highest counter ID seen: c0
diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map
index 5eb69e6..d9196f4 100644
--- a/tests/coverage/async_block.cov-map
+++ b/tests/coverage/async_block.cov-map
@@ -1,5 +1,5 @@
Function name: async_block::main
-Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 00, 14, 01, 16, 02, 07, 0a, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 01, 0d, 00, 13, 02, 07, 09, 00, 22, 01, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
@@ -9,11 +9,11 @@
- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
= (c1 - c0)
- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19)
-- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 1, 22)
+- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19)
= (c1 - c0)
-- Code(Expression(0, Sub)) at (prev + 7, 10) to (start + 2, 6)
+- Code(Expression(0, Sub)) at (prev + 7, 9) to (start + 0, 34)
= (c1 - c0)
-- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
+- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2)
Highest counter ID seen: c1
Function name: async_block::main::{closure#0}
diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage
index 9e32944..4e00024 100644
--- a/tests/coverage/async_block.coverage
+++ b/tests/coverage/async_block.coverage
@@ -15,6 +15,6 @@
LL| 12| }
LL| 16| };
LL| 16| executor::block_on(future);
- LL| 16| }
+ LL| | }
LL| 1|}
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 9144a93..a4ef0ce 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -30,12 +30,23 @@
Highest counter ID seen: c0
Function name: async_closure::main::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
+Highest counter ID seen: c0
+
+Function name: async_closure::main::{closure#0}
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
Highest counter ID seen: c0
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
@@ -47,12 +58,3 @@
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
Highest counter ID seen: c0
-Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
-Number of files: 1
-- file 0 => global file 1
-Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
-Highest counter ID seen: c0
-
diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage
index 7fbea26..5aed131 100644
--- a/tests/coverage/async_closure.coverage
+++ b/tests/coverage/async_closure.coverage
@@ -9,12 +9,14 @@
LL| |
LL| 1|pub fn main() {
LL| 2| let async_closure = async || {};
- ^1
------------------
| async_closure::main::{closure#0}:
| LL| 1| let async_closure = async || {};
------------------
- | async_closure::main::{closure#0}::{closure#1}::<i32>:
+ | async_closure::main::{closure#0}:
+ | LL| 1| let async_closure = async || {};
+ ------------------
+ | async_closure::main::{closure#0}::{closure#0}::<i16>:
| LL| 1| let async_closure = async || {};
------------------
LL| 1| executor::block_on(async_closure());
diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map
index ef6f5a9..c55c589 100644
--- a/tests/coverage/attr/off-on-sandwich.cov-map
+++ b/tests/coverage/attr/off-on-sandwich.cov-map
@@ -1,30 +1,30 @@
Function name: off_on_sandwich::dense_a::dense_b
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 12, 01, 07, 05, 00, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 10, 01, 07, 05, 00, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 18)
+- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 16)
- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6)
Highest counter ID seen: c0
Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 17, 01, 0b, 09, 00, 0a]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 15, 01, 0b, 09, 00, 0a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 23)
+- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 21)
- Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10)
Highest counter ID seen: c0
Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 1b, 01, 07, 0d, 00, 0e]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 19, 01, 07, 0d, 00, 0e]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 27)
+- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 25)
- Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14)
Highest counter ID seen: c0
diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map
index baac007..f08a70a 100644
--- a/tests/coverage/bad_counter_ids.cov-map
+++ b/tests/coverage/bad_counter_ids.cov-map
@@ -1,10 +1,10 @@
Function name: bad_counter_ids::eq_bad
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 1f, 00, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 0f, 00, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 15)
- Code(Zero) at (prev + 3, 1) to (start + 0, 2)
Highest counter ID seen: c0
@@ -20,12 +20,12 @@
Highest counter ID seen: c0
Function name: bad_counter_ids::eq_good
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 01, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 0f, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15)
- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
Highest counter ID seen: c0
@@ -41,12 +41,12 @@
Highest counter ID seen: c0
Function name: bad_counter_ids::ne_bad
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 0f, 00, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 15)
- Code(Zero) at (prev + 3, 1) to (start + 0, 2)
Highest counter ID seen: c0
@@ -62,12 +62,12 @@
Highest counter ID seen: c0
Function name: bad_counter_ids::ne_good
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 1f, 01, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 0f, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 15)
- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
Highest counter ID seen: c0
diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map
index 55f45da..46533df 100644
--- a/tests/coverage/branch/guard.cov-map
+++ b/tests/coverage/branch/guard.cov-map
@@ -1,5 +1,5 @@
Function name: guard::branch_match_guard
-Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 10, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02]
+Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 0e, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 8
@@ -12,7 +12,7 @@
- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4)
- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
Number of file 0 mappings: 13
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
- Code(Expression(0, Sub)) at (prev + 3, 11) to (start + 0, 12)
= (c1 - c3)
- Code(Expression(1, Sub)) at (prev + 1, 20) to (start + 2, 10)
diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map
index db45df2..7f6b174 100644
--- a/tests/coverage/branch/if-let.cov-map
+++ b/tests/coverage/branch/if-let.cov-map
@@ -1,11 +1,11 @@
Function name: if_let::if_let
-Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02]
+Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 7
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 12) to (start + 0, 19)
true = (c0 - c1)
false = c1
diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map
index a6b8653..1d40f03 100644
--- a/tests/coverage/branch/if.cov-map
+++ b/tests/coverage/branch/if.cov-map
@@ -1,5 +1,5 @@
Function name: if::branch_and
-Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 3
@@ -7,7 +7,7 @@
- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
- expression 2 operands: lhs = Counter(0), rhs = Counter(2)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -23,7 +23,7 @@
Highest counter ID seen: c2
Function name: if::branch_not
-Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02]
+Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 7
@@ -35,12 +35,12 @@
- expression 5 operands: lhs = Counter(0), rhs = Counter(4)
- expression 6 operands: lhs = Counter(0), rhs = Counter(4)
Number of file 0 mappings: 18
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9)
true = c1
false = (c0 - c1)
-- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17)
+- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 16)
- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6)
= (c0 - c1)
- Code(Counter(0)) at (prev + 1, 8) to (start + 0, 10)
@@ -68,7 +68,7 @@
Highest counter ID seen: c4
Function name: if::branch_not_as
-Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 10, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02]
+Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 0e, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 5
@@ -78,7 +78,7 @@
- expression 3 operands: lhs = Counter(0), rhs = Counter(3)
- expression 4 operands: lhs = Counter(0), rhs = Counter(3)
Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 20)
- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 0, 8) to (start + 0, 20)
true = (c0 - c1)
@@ -104,7 +104,7 @@
Highest counter ID seen: c3
Function name: if::branch_or
-Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 6
@@ -115,7 +115,7 @@
- expression 4 operands: lhs = Counter(0), rhs = Expression(5, Add)
- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9)
true = c1
diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map
index 622f30e..5d4fc57 100644
--- a/tests/coverage/branch/lazy-boolean.cov-map
+++ b/tests/coverage/branch/lazy-boolean.cov-map
@@ -1,11 +1,11 @@
Function name: lazy_boolean::branch_and
-Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02]
+Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14)
@@ -16,13 +16,13 @@
Highest counter ID seen: c1
Function name: lazy_boolean::branch_or
-Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02]
+Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14)
@@ -34,7 +34,7 @@
Highest counter ID seen: c1
Function name: lazy_boolean::chain
-Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02]
+Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 15
@@ -54,7 +54,7 @@
- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(6)
- expression 14 operands: lhs = Counter(4), rhs = Counter(5)
Number of file 0 mappings: 19
-- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 18)
@@ -69,7 +69,7 @@
true = c3
false = (c2 - c3)
- Code(Counter(3)) at (prev + 0, 40) to (start + 0, 45)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16)
- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10)
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18)
- Branch { true: Counter(4), false: Expression(4, Sub) } at (prev + 0, 13) to (start + 0, 18)
@@ -91,7 +91,7 @@
Highest counter ID seen: c6
Function name: lazy_boolean::nested_mixed
-Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02]
+Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 13
@@ -109,7 +109,7 @@
- expression 11 operands: lhs = Counter(0), rhs = Expression(12, Add)
- expression 12 operands: lhs = Counter(5), rhs = Counter(6)
Number of file 0 mappings: 19
-- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 14) to (start + 0, 19)
@@ -127,7 +127,7 @@
false = ((c1 + c2) - c3)
- Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 51)
= ((c1 + c2) - c3)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16)
- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10)
- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19)
- Branch { true: Counter(4), false: Expression(8, Sub) } at (prev + 0, 14) to (start + 0, 19)
diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map
index 215d715..78507a3 100644
--- a/tests/coverage/branch/let-else.cov-map
+++ b/tests/coverage/branch/let-else.cov-map
@@ -1,11 +1,11 @@
Function name: let_else::let_else
-Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 01, 01, 01, 00, 02]
+Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 7
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
- Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 9) to (start + 0, 16)
true = (c0 - c1)
false = c1
@@ -13,7 +13,7 @@
= (c0 - c1)
- Code(Counter(0)) at (prev + 0, 19) to (start + 0, 24)
- Code(Counter(1)) at (prev + 1, 9) to (start + 1, 15)
-- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 11)
+- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 10)
= (c0 - c1)
- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
Highest counter ID seen: c1
diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map
index d5b4d04..ef71d12 100644
--- a/tests/coverage/branch/match-arms.cov-map
+++ b/tests/coverage/branch/match-arms.cov-map
@@ -1,5 +1,5 @@
Function name: match_arms::guards
-Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 29, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 29, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 29, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 29, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 18, 01, 03, 05, 01, 02]
+Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 0e, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 8
@@ -12,31 +12,31 @@
- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3)
- expression 7 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 12
-- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 14)
- Code(Counter(8)) at (prev + 3, 11) to (start + 0, 16)
-- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 40)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27)
true = c1
false = (c5 - c1)
-- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 40)
- Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 27)
true = c2
false = (c6 - c2)
-- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 40)
- Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 23) to (start + 0, 27)
true = c3
false = (c7 - c3)
-- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 40)
- Branch { true: Counter(4), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 27)
true = c4
false = (c8 - c4)
-- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 24)
+- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 21)
= (c0 - (((c1 + c2) + c3) + c4))
- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2)
Highest counter ID seen: c8
Function name: match_arms::match_arms
-Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 21, 09, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 02, 01, 11, 00, 21, 01, 03, 05, 01, 02]
+Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 3
@@ -44,18 +44,18 @@
- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 7
-- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16)
-- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 33)
-- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33)
-- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
-- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 33)
+- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 32)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 32)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 32)
+- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 32)
= (c0 - ((c1 + c2) + c3))
- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2)
Highest counter ID seen: c3
Function name: match_arms::or_patterns
-Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2e, 01, 03, 05, 01, 02]
+Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -64,16 +64,16 @@
- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
- expression 3 operands: lhs = Counter(0), rhs = Expression(0, Add)
Number of file 0 mappings: 9
-- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16)
- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18)
- Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31)
-- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 46)
+- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 45)
= (c1 + c2)
- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
- Code(Expression(1, Sub)) at (prev + 0, 30) to (start + 0, 31)
= (c0 - ((c1 + c2) + c3))
-- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 46)
+- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 45)
= (c0 - (c1 + c2))
- Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2)
Highest counter ID seen: c3
diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map
index 31322f1..1b0c6d1 100644
--- a/tests/coverage/branch/match-trivial.cov-map
+++ b/tests/coverage/branch/match-trivial.cov-map
@@ -1,19 +1,19 @@
Function name: match_trivial::_uninhabited (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 10]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 0e]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
-- Code(Zero) at (prev + 22, 1) to (start + 1, 16)
+- Code(Zero) at (prev + 22, 1) to (start + 1, 14)
Highest counter ID seen: (none)
Function name: match_trivial::trivial
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 10, 01, 03, 0b, 05, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 0e, 01, 03, 0b, 05, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 11) to (start + 5, 2)
Highest counter ID seen: c0
diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map
index 5ce92c7..67746af 100644
--- a/tests/coverage/branch/while.cov-map
+++ b/tests/coverage/branch/while.cov-map
@@ -1,11 +1,11 @@
Function name: while::while_cond
-Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(1), rhs = Counter(0)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18)
- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16)
- Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 16)
@@ -17,13 +17,13 @@
Highest counter ID seen: c1
Function name: while::while_cond_not
-Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(1), rhs = Counter(0)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18)
- Code(Counter(1)) at (prev + 1, 11) to (start + 0, 20)
- Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 20)
@@ -35,7 +35,7 @@
Highest counter ID seen: c1
Function name: while::while_op_and
-Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
+Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 5
@@ -45,7 +45,7 @@
- expression 3 operands: lhs = Counter(0), rhs = Counter(2)
- expression 4 operands: lhs = Counter(1), rhs = Counter(0)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18)
- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16)
- Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16)
@@ -61,7 +61,7 @@
Highest counter ID seen: c2
Function name: while::while_op_or
-Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
+Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -70,7 +70,7 @@
- expression 2 operands: lhs = Counter(0), rhs = Counter(2)
- expression 3 operands: lhs = Counter(1), rhs = Counter(0)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 14)
- Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18)
- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16)
- Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16)
diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map
index fa20c8c..2d784ba 100644
--- a/tests/coverage/closure.cov-map
+++ b/tests/coverage/closure.cov-map
@@ -1,15 +1,15 @@
Function name: closure::main
-Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02]
+Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0d, 1b, 01, 1a, 05, 02, 0a, 01, 0c, 05, 11, 1b, 01, 1e, 05, 02, 0a, 01, 0c, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 24
-- Code(Counter(0)) at (prev + 9, 1) to (start + 15, 13)
-- Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10)
-- Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13)
-- Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10)
-- Code(Counter(0)) at (prev + 16, 5) to (start + 12, 22)
+- Code(Counter(0)) at (prev + 9, 1) to (start + 13, 27)
+- Code(Counter(0)) at (prev + 26, 5) to (start + 2, 10)
+- Code(Counter(0)) at (prev + 12, 5) to (start + 17, 27)
+- Code(Counter(0)) at (prev + 30, 5) to (start + 2, 10)
+- Code(Counter(0)) at (prev + 12, 5) to (start + 12, 22)
- Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24)
- Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30)
- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41)
diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage
index 3eac52e..2deeb98 100644
--- a/tests/coverage/closure.coverage
+++ b/tests/coverage/closure.coverage
@@ -20,18 +20,18 @@
LL| 1| some_string
LL| 1| .
LL| 1| unwrap_or_else
- LL| 1| (
- LL| 1| ||
+ LL| | (
+ LL| | ||
LL| 0| {
LL| 0| let mut countdown = 0;
LL| 0| if is_false {
LL| 0| countdown = 10;
LL| 0| }
LL| 0| "alt string 1".to_owned()
- LL| 1| }
- LL| 1| )
- LL| 1| );
- LL| 1|
+ LL| 0| }
+ LL| | )
+ LL| | );
+ LL| |
LL| 1| some_string = Some(String::from("the string content"));
LL| 1| let
LL| 1| a
@@ -62,8 +62,8 @@
LL| 1| some_string
LL| 1| .
LL| 1| unwrap_or_else
- LL| 1| (
- LL| 1| ||
+ LL| | (
+ LL| | ||
LL| 1| {
LL| 1| let mut countdown = 0;
LL| 1| if is_false {
@@ -71,9 +71,9 @@
LL| 1| }
LL| 1| "alt string 3".to_owned()
LL| 1| }
- LL| 1| )
- LL| 1| );
- LL| 1|
+ LL| | )
+ LL| | );
+ LL| |
LL| 1| some_string = None;
LL| 1| let
LL| 1| a
diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map
index 653848d..9dd99c8 100644
--- a/tests/coverage/closure_macro.cov-map
+++ b/tests/coverage/closure_macro.cov-map
@@ -8,16 +8,16 @@
Highest counter ID seen: c0
Function name: closure_macro::main
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33)
+- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 32)
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
= (c0 - c1)
-- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84)
+- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52)
- Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
= (c0 - c1)
diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map
index 1bd1460..2548754 100644
--- a/tests/coverage/closure_macro_async.cov-map
+++ b/tests/coverage/closure_macro_async.cov-map
@@ -17,16 +17,16 @@
Highest counter ID seen: c0
Function name: closure_macro_async::test::{closure#0}
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 33)
+- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 32)
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
= (c0 - c1)
-- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84)
+- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52)
- Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
= (c0 - c1)
diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map
index 417637f..c34075a 100644
--- a/tests/coverage/condition/conditions.cov-map
+++ b/tests/coverage/condition/conditions.cov-map
@@ -109,15 +109,17 @@
Highest counter ID seen: c0
Function name: conditions::func_call
-Raw bytes (37): 0x[01, 01, 02, 01, 05, 05, 09, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
+Raw bytes (47): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 25, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 20, 05, 02, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 2
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
-Number of file 0 mappings: 5
-- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 10)
-- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10)
+Number of file 0 mappings: 7
+- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 32)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8)
+- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10)
+- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 9) to (start + 0, 10)
true = c1
false = (c0 - c1)
- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15)
diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map
index c6f2d41..fee3237 100644
--- a/tests/coverage/coroutine.cov-map
+++ b/tests/coverage/coroutine.cov-map
@@ -13,7 +13,7 @@
Highest counter ID seen: c1
Function name: coroutine::main
-Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02]
+Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 2
@@ -21,14 +21,14 @@
- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 9
- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22)
-- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 46)
+- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 45)
- Code(Counter(1)) at (prev + 1, 43) to (start + 0, 45)
-- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 53)
+- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20)
= (c0 - c1)
- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46)
- Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39)
- Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46)
-- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 53)
+- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20)
= (c1 - c2)
- Code(Counter(2)) at (prev + 2, 1) to (start + 0, 2)
Highest counter ID seen: c3
diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map
index 3deacbc..6e2d243 100644
--- a/tests/coverage/holes.cov-map
+++ b/tests/coverage/holes.cov-map
@@ -8,24 +8,24 @@
Highest counter ID seen: (none)
Function name: holes::main
-Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 12, 01, 05, 05, 00, 12, 01, 07, 09, 00, 11, 01, 09, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 04, 05, 00, 12, 01, 04, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02]
+Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 06, 27, 01, 13, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 13
-- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 18)
-- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 18)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 17)
+- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 17)
- Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17)
-- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
+- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17)
- Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15)
- Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15)
-- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13)
-- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2)
+- Code(Counter(0)) at (prev + 10, 5) to (start + 6, 39)
+- Code(Counter(0)) at (prev + 19, 5) to (start + 1, 2)
Highest counter ID seen: c0
Function name: holes::main::_unused_fn (unused)
diff --git a/tests/coverage/holes.coverage b/tests/coverage/holes.coverage
index 1b45c12..a6a02f1 100644
--- a/tests/coverage/holes.coverage
+++ b/tests/coverage/holes.coverage
@@ -84,18 +84,18 @@
LL| 1| // `nested_filter::OnlyBodies` or equivalent.
LL| 1| #[rustfmt::skip]
LL| 1| let _const_block_inside_anon_const =
- LL| 1| [
- LL| 1| 0
- LL| 1| ;
- LL| 1| 7
- LL| 1| +
- LL| 1| const
+ LL| | [
+ LL| | 0
+ LL| | ;
+ LL| | 7
+ LL| | +
+ LL| | const
LL| | {
LL| | 3
- LL| 1| }
- LL| 1| ]
- LL| 1| ;
- LL| 1|
+ LL| | }
+ LL| | ]
+ LL| | ;
+ LL| |
LL| 1| black_box(());
LL| 1|}
diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map
index 49cdc51..65cefe7 100644
--- a/tests/coverage/inline-dead.cov-map
+++ b/tests/coverage/inline-dead.cov-map
@@ -8,14 +8,14 @@
Highest counter ID seen: (none)
Function name: inline_dead::live::<false>
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0d, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 4
- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9)
-- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 15)
+- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 13)
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10)
= (c0 - c1)
- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2)
diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map
index a569ad5..7264391 100644
--- a/tests/coverage/inline.cov-map
+++ b/tests/coverage/inline.cov-map
@@ -15,12 +15,12 @@
Highest counter ID seen: c1
Function name: inline::error
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 14]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 0b]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 20)
+- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 11)
Highest counter ID seen: c0
Function name: inline::length::<char>
diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map
index c188cca..f102310 100644
--- a/tests/coverage/issue-83601.cov-map
+++ b/tests/coverage/issue-83601.cov-map
@@ -1,12 +1,12 @@
Function name: issue_83601::main
-Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 0f, 05, 03, 09, 01, 0f, 02, 02, 05, 03, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
Number of file 0 mappings: 3
-- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28)
-- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 15)
+- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 15)
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2)
= (c1 - c2)
Highest counter ID seen: c1
diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map
index c8f75cd..3bd4e7d 100644
--- a/tests/coverage/issue-84561.cov-map
+++ b/tests/coverage/issue-84561.cov-map
@@ -1,11 +1,11 @@
Function name: <issue_84561::Foo as core::fmt::Debug>::fmt
-Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06]
+Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 24, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 37)
+- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 36)
- Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38)
- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15)
= (c0 - c1)
@@ -59,7 +59,7 @@
Highest counter ID seen: c0
Function name: issue_84561::test3
-Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 09, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 11, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 19, 02, 05, 00, 1f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 05, 06, 35, 06, 05, 03, 06, 39, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 41, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 1a, 05, 09, 03, 0a, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02]
+Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 0d, 05, 05, 00, 0f, 11, 01, 05, 00, 0f, 15, 01, 09, 01, 0f, 19, 02, 05, 00, 0f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 02, 0f, 35, 06, 05, 00, 0f, 39, 04, 05, 00, 0f, 3d, 04, 09, 01, 0f, 41, 05, 08, 00, 0f, 45, 01, 09, 00, 13, 1a, 05, 09, 00, 13, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 00, 17, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 27
@@ -91,13 +91,13 @@
- expression 25 operands: lhs = Counter(30), rhs = Counter(31)
- expression 26 operands: lhs = Counter(31), rhs = Counter(32)
Number of file 0 mappings: 51
-- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
-- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
-- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 31)
-- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31)
-- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 31)
-- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
-- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 31)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 15)
+- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 15)
+- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 15)
+- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 15)
+- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 15)
+- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 15)
+- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 15)
- Code(Counter(7)) at (prev + 1, 5) to (start + 0, 15)
- Code(Expression(0, Sub)) at (prev + 0, 32) to (start + 0, 48)
= (c7 - c8)
@@ -112,14 +112,14 @@
- Code(Counter(12)) at (prev + 5, 13) to (start + 0, 27)
- Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 28)
= (c11 - c12)
-- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 5, 6)
+- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 2, 15)
= (c8 - (c9 + c11))
-- Code(Counter(13)) at (prev + 6, 5) to (start + 3, 6)
-- Code(Counter(14)) at (prev + 4, 5) to (start + 3, 6)
-- Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6)
+- Code(Counter(13)) at (prev + 6, 5) to (start + 0, 15)
+- Code(Counter(14)) at (prev + 4, 5) to (start + 0, 15)
+- Code(Counter(15)) at (prev + 4, 9) to (start + 1, 15)
- Code(Counter(16)) at (prev + 5, 8) to (start + 0, 15)
-- Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10)
-- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 3, 10)
+- Code(Counter(17)) at (prev + 1, 9) to (start + 0, 19)
+- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 0, 19)
= (c16 - c17)
- Code(Expression(12, Add)) at (prev + 5, 8) to (start + 0, 15)
= (c18 + c19)
@@ -144,7 +144,7 @@
- Code(Expression(24, Add)) at (prev + 3, 5) to (start + 0, 15)
= (c28 + c29)
- Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19)
-- Code(Counter(27)) at (prev + 1, 13) to (start + 3, 14)
+- Code(Counter(27)) at (prev + 1, 13) to (start + 0, 23)
- Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19)
- Code(Expression(22, Sub)) at (prev + 2, 13) to (start + 0, 23)
= (c26 - c27)
diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage
index 2a642e2..a55f42a 100644
--- a/tests/coverage/issue-84561.coverage
+++ b/tests/coverage/issue-84561.coverage
@@ -47,32 +47,32 @@
LL| 1| let is_true = std::env::args().len() == 1;
LL| 1|
LL| 1| assert_eq!(
- LL| 1| Foo(1),
- LL| 1| Foo(1)
- LL| 1| );
+ LL| | Foo(1),
+ LL| | Foo(1)
+ LL| | );
LL| 1| assert_ne!(
- LL| 1| Foo(0),
- LL| 1| Foo(1)
- LL| 1| );
+ LL| | Foo(0),
+ LL| | Foo(1)
+ LL| | );
LL| 1| assert_eq!(
- LL| 1| Foo(2),
- LL| 1| Foo(2)
- LL| 1| );
+ LL| | Foo(2),
+ LL| | Foo(2)
+ LL| | );
LL| 1| let bar = Foo(1);
LL| 1| assert_ne!(
- LL| 1| bar,
- LL| 1| Foo(3)
- LL| 1| );
+ LL| | bar,
+ LL| | Foo(3)
+ LL| | );
LL| 1| if is_true {
LL| 1| assert_ne!(
- LL| 1| Foo(0),
- LL| 1| Foo(4)
- LL| 1| );
+ LL| | Foo(0),
+ LL| | Foo(4)
+ LL| | );
LL| | } else {
LL| 0| assert_eq!(
- LL| 0| Foo(3),
- LL| 0| Foo(3)
- LL| 0| );
+ LL| | Foo(3),
+ LL| | Foo(3)
+ LL| | );
LL| | }
LL| 1| if is_true {
LL| 1| assert_ne!(
@@ -106,9 +106,9 @@
LL| 1| assert_ne!(
LL| 1| if is_true {
LL| 1| assert_eq!(
- LL| 1| Foo(3),
- LL| 1| Foo(3)
- LL| 1| );
+ LL| | Foo(3),
+ LL| | Foo(3)
+ LL| | );
LL| 1| Foo(0)
LL| | } else {
LL| 0| assert_ne!(
diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map
index f13e82d..fccc4d6 100644
--- a/tests/coverage/loop-break.cov-map
+++ b/tests/coverage/loop-break.cov-map
@@ -1,12 +1,12 @@
Function name: loop_break::main
-Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 27, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02]
+Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 21, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(1), rhs = Counter(0)
Number of file 0 mappings: 5
- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 11)
-- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 39)
+- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 33)
- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18)
- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
= (c1 - c0)
diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map
index 2cb0f94..2157cd6 100644
--- a/tests/coverage/loops_branches.cov-map
+++ b/tests/coverage/loops_branches.cov-map
@@ -1,5 +1,5 @@
Function name: <loops_branches::DebugTest as core::fmt::Debug>::fmt
-Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 22, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
+Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 21, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -13,7 +13,7 @@
- Code(Zero) at (prev + 1, 23) to (start + 0, 27)
- Code(Zero) at (prev + 0, 28) to (start + 0, 30)
- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14)
-- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30)
+- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29)
- Code(Counter(1)) at (prev + 0, 30) to (start + 0, 31)
- Code(Zero) at (prev + 1, 16) to (start + 1, 10)
- Code(Counter(3)) at (prev + 3, 13) to (start + 0, 14)
@@ -23,7 +23,7 @@
- Code(Zero) at (prev + 1, 27) to (start + 0, 31)
- Code(Zero) at (prev + 0, 32) to (start + 0, 34)
- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
-- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 34)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
- Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35)
= ((c0 + c3) - (c1 + c2))
- Code(Zero) at (prev + 1, 20) to (start + 1, 14)
@@ -33,7 +33,7 @@
Highest counter ID seen: c3
Function name: <loops_branches::DisplayTest as core::fmt::Display>::fmt
-Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 22, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
+Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 21, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -48,7 +48,7 @@
- Code(Zero) at (prev + 1, 23) to (start + 0, 27)
- Code(Zero) at (prev + 0, 28) to (start + 0, 30)
- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14)
-- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30)
+- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29)
- Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31)
- Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14)
- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 23)
@@ -58,7 +58,7 @@
- Code(Zero) at (prev + 1, 27) to (start + 0, 31)
- Code(Zero) at (prev + 0, 32) to (start + 0, 34)
- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
-- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 34)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33)
- Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35)
= ((c0 + c2) - (c1 + c3))
- Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 15)
diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map
index 5862045..bd033fa 100644
--- a/tests/coverage/macro_name_span.cov-map
+++ b/tests/coverage/macro_name_span.cov-map
@@ -1,10 +1,10 @@
Function name: macro_name_span::affected_function
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 3e]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64)
+- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 62)
Highest counter ID seen: c0
Function name: macro_name_span::main
diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map
index c282d53..959d219 100644
--- a/tests/coverage/mcdc/non_control_flow.cov-map
+++ b/tests/coverage/mcdc/non_control_flow.cov-map
@@ -113,15 +113,17 @@
Highest counter ID seen: c0
Function name: non_control_flow::func_call
-Raw bytes (50): 0x[01, 01, 02, 01, 05, 05, 09, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
+Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 29, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 2
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
-Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10)
-- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15)
+Number of file 0 mappings: 8
+- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 32)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8)
+- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10)
+- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 9) to (start + 0, 15)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10)
true = c1
false = (c0 - c1)
diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map
index 04171fd..244b009 100644
--- a/tests/coverage/no_cov_crate.cov-map
+++ b/tests/coverage/no_cov_crate.cov-map
@@ -35,22 +35,22 @@
Highest counter ID seen: c0
Function name: no_cov_crate::nested_fns::outer
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 23, 01, 0c, 05, 00, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 22, 01, 0c, 05, 00, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 35)
+- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 34)
- Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6)
Highest counter ID seen: c0
Function name: no_cov_crate::nested_fns::outer_both_covered
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 17, 01, 0b, 05, 00, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 16, 01, 0b, 05, 00, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 23)
+- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 22)
- Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6)
Highest counter ID seen: c0
diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map
index 4628a24..18b1391 100644
--- a/tests/coverage/panic_unwind.cov-map
+++ b/tests/coverage/panic_unwind.cov-map
@@ -26,14 +26,14 @@
Highest counter ID seen: c3
Function name: panic_unwind::might_panic
-Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 19, 02, 02, 0c, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 3
- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20)
-- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 25)
+- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15)
- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2)
= (c0 - c1)
Highest counter ID seen: c1
diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map
index 69e1342..898d681 100644
--- a/tests/coverage/sort_groups.cov-map
+++ b/tests/coverage/sort_groups.cov-map
@@ -55,13 +55,13 @@
Highest counter ID seen: c1
Function name: sort_groups::main
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 1c, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 28)
- Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6)
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6)
= (c0 - c1)
diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map
index 35b2c36..e45f3de 100644
--- a/tests/coverage/try_error_result.cov-map
+++ b/tests/coverage/try_error_result.cov-map
@@ -41,13 +41,13 @@
Highest counter ID seen: c1
Function name: try_error_result::main
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0a, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 12)
+- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 10)
- Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6)
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11)
= (c0 - c1)
@@ -55,7 +55,7 @@
Highest counter ID seen: c1
Function name: try_error_result::test1
-Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 29, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02]
+Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 11, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -67,13 +67,13 @@
- Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23)
- Code(Counter(1)) at (prev + 7, 9) to (start + 0, 14)
- Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26)
-- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 41)
+- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 17)
= ((c0 + c2) - c1)
- Code(Expression(0, Sub)) at (prev + 0, 41) to (start + 0, 42)
= ((c0 + c2) - c1)
-- Code(Zero) at (prev + 1, 13) to (start + 0, 42)
+- Code(Zero) at (prev + 1, 13) to (start + 0, 17)
- Code(Zero) at (prev + 0, 42) to (start + 0, 43)
-- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 42)
+- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 17)
= (c1 - c0)
- Code(Zero) at (prev + 0, 42) to (start + 0, 43)
- Code(Expression(3, Sub)) at (prev + 3, 5) to (start + 0, 11)
@@ -82,7 +82,7 @@
Highest counter ID seen: c2
Function name: try_error_result::test2
-Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 35, 15, 04, 11, 00, 12, 1e, 02, 11, 04, 12, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 41, 19, 00, 41, 00, 42, 26, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 41, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 60, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 42, 29, 00, 42, 00, 43, 66, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 36, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02]
+Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 17, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 17, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 17, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 17, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 17, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 54
@@ -144,59 +144,59 @@
- Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23)
- Code(Counter(1)) at (prev + 8, 9) to (start + 0, 14)
- Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26)
-- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 47)
+- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 31)
- Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48)
-- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 53)
+- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 28)
= (c3 - c4)
- Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18)
-- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 4, 18)
+- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 3, 39)
= (c3 - (c4 + c5))
- Code(Expression(12, Sub)) at (prev + 5, 17) to (start + 0, 20)
= (c3 - (((c4 + c5) + c6) + c7))
-- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 65)
+- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 41)
= (c3 - (c4 + c5))
- Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66)
-- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 95)
+- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 71)
= (c3 - ((c4 + c5) + c6))
- Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96)
-- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 23)
= (c3 - (((c4 + c5) + c6) + c7))
- Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 20)
= (c16 - (c8 + c9))
-- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 65)
+- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 41)
- Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66)
-- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 96)
+- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 71)
= (c16 - c8)
- Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97)
-- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 23)
= (c16 - (c8 + c9))
- Code(Expression(27, Sub)) at (prev + 4, 17) to (start + 0, 20)
= (c2 - ((c3 + c10) + c11))
-- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 66)
+- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 41)
= (c2 - c3)
- Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67)
-- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 97)
+- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 72)
= (c2 - (c3 + c10))
- Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98)
-- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 23)
= (c2 - ((c3 + c10) + c11))
- Code(Expression(33, Sub)) at (prev + 1, 17) to (start + 0, 20)
= (c17 - (c12 + c13))
-- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54)
+- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 29)
- Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55)
-- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 47)
+- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 22)
= (c17 - c12)
- Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48)
-- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 23)
= (c17 - (c12 + c13))
- Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 20)
= (c18 - (c14 + c15))
-- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 54)
+- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 29)
- Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18)
-- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 47)
+- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 22)
= (c18 - c14)
- Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18)
-- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 32)
+- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 23)
= (c18 - (c14 + c15))
- Code(Expression(40, Sub)) at (prev + 3, 5) to (start + 0, 11)
= (c1 - c2)
diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage
index 7100248..7a89c04 100644
--- a/tests/coverage/try_error_result.coverage
+++ b/tests/coverage/try_error_result.coverage
@@ -86,7 +86,7 @@
LL| 1| .
LL| 1| expect_err(
LL| 1| "call should fail"
- LL| 1| );
+ LL| | );
LL| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
^0 ^0 ^0
LL| 0| assert_eq!(val, 57);
diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map
index 7b9dc0b..29d40a0 100644
--- a/tests/coverage/unicode.cov-map
+++ b/tests/coverage/unicode.cov-map
@@ -1,5 +1,5 @@
Function name: unicode::main
-Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02]
+Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 23, 09, 00, 29, 00, 44, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 2
@@ -12,8 +12,8 @@
- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 27)
- Code(Expression(0, Sub)) at (prev + 0, 28) to (start + 0, 40)
= (c1 - c0)
-- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 37)
-- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 70)
+- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 35)
+- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 68)
- Code(Counter(3)) at (prev + 0, 71) to (start + 2, 6)
- Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6)
= (c0 - c3)
diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage
index 84c5f05..4434995 100644
--- a/tests/coverage/unicode.coverage
+++ b/tests/coverage/unicode.coverage
@@ -15,7 +15,7 @@
LL| [0;35m33[0m| for _İ in 'А'..='Я' { /* Я */ }
^32 ^32
LL| |
- LL| [0;35m1[0m| if 申し訳ございません() && [0;41m申し訳ございません()[0m [0;41m{[0m
+ LL| [0;35m1[0m| if 申し訳ございません() && [0;41m申し訳ございません[0m() [0;41m{[0m
^0
LL| 0|[0;41m println!("true");[0m
LL| 1|[0;41m [0m}
diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map
index 97961bc..0bc18bf 100644
--- a/tests/coverage/unreachable.cov-map
+++ b/tests/coverage/unreachable.cov-map
@@ -1,27 +1,27 @@
Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 47]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 45]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
-- Code(Zero) at (prev + 14, 39) to (start + 0, 71)
+- Code(Zero) at (prev + 14, 39) to (start + 0, 69)
Highest counter ID seen: (none)
Function name: unreachable::unreachable_function (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 25]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 23]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
-- Code(Zero) at (prev + 16, 1) to (start + 1, 37)
+- Code(Zero) at (prev + 16, 1) to (start + 1, 35)
Highest counter ID seen: (none)
Function name: unreachable::unreachable_intrinsic (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2c]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
-- Code(Zero) at (prev + 21, 1) to (start + 1, 44)
+- Code(Zero) at (prev + 21, 1) to (start + 1, 42)
Highest counter ID seen: (none)
diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map
index d296f9b..bf0916e 100644
--- a/tests/coverage/yield.cov-map
+++ b/tests/coverage/yield.cov-map
@@ -1,5 +1,5 @@
Function name: yield::main
-Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 34, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 34, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 34, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 34, 12, 02, 01, 00, 02]
+Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 14, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 14, 12, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 5
@@ -12,22 +12,22 @@
- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22)
- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46)
- Code(Counter(1)) at (prev + 1, 39) to (start + 0, 41)
-- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20)
= (c0 - c1)
- Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46)
- Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39)
- Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46)
-- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20)
= (c1 - c2)
- Code(Counter(2)) at (prev + 3, 9) to (start + 0, 22)
- Code(Counter(2)) at (prev + 8, 11) to (start + 0, 46)
- Code(Counter(4)) at (prev + 1, 39) to (start + 0, 41)
-- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 20)
= (c2 - c4)
- Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46)
- Code(Expression(4, Sub)) at (prev + 1, 39) to (start + 0, 41)
= (c4 - c5)
-- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 20)
- Code(Expression(4, Sub)) at (prev + 2, 1) to (start + 0, 2)
= (c4 - c5)
Highest counter ID seen: c5
diff --git a/tests/crashes/134334.rs b/tests/crashes/134334.rs
deleted file mode 100644
index d99df7b..0000000
--- a/tests/crashes/134334.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #134334
-//@ only-x86_64
-
-#[repr(simd)]
-struct A();
-
-fn main() {
- std::arch::asm!("{}", in(xmm_reg) A());
-}
diff --git a/tests/crashes/134335.rs b/tests/crashes/134335.rs
deleted file mode 100644
index bee6686..0000000
--- a/tests/crashes/134335.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #134335
-//@compile-flags: -Zunstable-options --edition=2024 --crate-type=lib
-pub async fn async_closure(x: &mut i32) {
- let c = async move || {
- *x += 1;
- };
- call_once(c).await;
-}
-
-fn call_once<T>(f: impl FnOnce() -> T) -> T {
- f()
-}
diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs
index 958e9dd..1534aca 100644
--- a/tests/incremental/delayed_span_bug.rs
+++ b/tests/incremental/delayed_span_bug.rs
@@ -1,8 +1,8 @@
//@ revisions: cfail1 cfail2
//@ should-ice
-//@ error-pattern: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]
+//@ error-pattern: delayed bug triggered by #[rustc_delayed_bug_from_inside_query]
#![feature(rustc_attrs)]
-#[rustc_error(delayed_bug_from_inside_query)]
+#[rustc_delayed_bug_from_inside_query]
fn main() {}
diff --git a/tests/incremental/env/env_macro.rs b/tests/incremental/env/env_macro.rs
new file mode 100644
index 0000000..0c02632
--- /dev/null
+++ b/tests/incremental/env/env_macro.rs
@@ -0,0 +1,18 @@
+// Check that changes to environment variables are propagated to `env!`.
+//
+// This test is intentionally written to not use any `#[cfg(rpass*)]`, to
+// _really_ test that we re-compile if the environment variable changes.
+
+//@ revisions: cfail1 rpass2 rpass3 cfail4
+//@ [cfail1]unset-rustc-env:EXAMPLE_ENV
+//@ [rpass2]rustc-env:EXAMPLE_ENV=one
+//@ [rpass2]exec-env:EXAMPLE_ENV=one
+//@ [rpass3]rustc-env:EXAMPLE_ENV=two
+//@ [rpass3]exec-env:EXAMPLE_ENV=two
+//@ [cfail4]unset-rustc-env:EXAMPLE_ENV
+
+fn main() {
+ assert_eq!(env!("EXAMPLE_ENV"), std::env::var("EXAMPLE_ENV").unwrap());
+ //[cfail1]~^ ERROR environment variable `EXAMPLE_ENV` not defined at compile time
+ //[cfail4]~^^ ERROR environment variable `EXAMPLE_ENV` not defined at compile time
+}
diff --git a/tests/incremental/env/option_env_macro.rs b/tests/incremental/env/option_env_macro.rs
new file mode 100644
index 0000000..44c3bfd
--- /dev/null
+++ b/tests/incremental/env/option_env_macro.rs
@@ -0,0 +1,18 @@
+// Check that changes to environment variables are propagated to `option_env!`.
+//
+// This test is intentionally written to not use any `#[cfg(rpass*)]`, to
+// _really_ test that we re-compile if the environment variable changes.
+
+//@ revisions: rpass1 rpass2 rpass3 rpass4
+//@ [rpass1]unset-rustc-env:EXAMPLE_ENV
+//@ [rpass1]unset-exec-env:EXAMPLE_ENV
+//@ [rpass2]rustc-env:EXAMPLE_ENV=one
+//@ [rpass2]exec-env:EXAMPLE_ENV=one
+//@ [rpass3]rustc-env:EXAMPLE_ENV=two
+//@ [rpass3]exec-env:EXAMPLE_ENV=two
+//@ [rpass4]unset-rustc-env:EXAMPLE_ENV
+//@ [rpass4]unset-exec-env:EXAMPLE_ENV
+
+fn main() {
+ assert_eq!(option_env!("EXAMPLE_ENV"), std::env::var("EXAMPLE_ENV").ok().as_deref());
+}
diff --git a/tests/incremental/user-written-closure-synthetic-closure-conflict.rs b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs
new file mode 100644
index 0000000..618604d
--- /dev/null
+++ b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs
@@ -0,0 +1,15 @@
+//@ revisions: rpass1 rpass2
+//@ edition: 2024
+
+#![allow(unused)]
+
+fn main() {
+ #[cfg(rpass1)]
+ async || {};
+
+ #[cfg(rpass2)]
+ || {
+ || ();
+ || ();
+ };
+}
diff --git "a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0431\175.built.after.mir" "b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
similarity index 85%
rename from "tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0431\175.built.after.mir"
rename to "tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
index bd0badd..9070c95 100644
--- "a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173closure\0431\175.built.after.mir"
+++ "b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `foo::{closure#0}::{closure#1}` after built
+// MIR for `foo::{closure#0}::{synthetic#0}` after built
-fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
+fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/async_closure_fake_read_for_by_move.rs
index 3c5aec9..e78671f 100644
--- a/tests/mir-opt/async_closure_fake_read_for_by_move.rs
+++ b/tests/mir-opt/async_closure_fake_read_for_by_move.rs
@@ -7,7 +7,7 @@ enum Foo {
}
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
fn foo(f: &Foo) {
let x = async move || match f {
Foo::Bar if true => {}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
similarity index 80%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
index a9e08d2..c5f538e 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173synthetic\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
+// MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built
-fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
similarity index 80%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
index 4452ae7..e295f9b 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173synthetic\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
+// MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built
-fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs
index cd2e83e..93cc783 100644
--- a/tests/mir-opt/async_closure_shims.rs
+++ b/tests/mir-opt/async_closure_shims.rs
@@ -42,11 +42,11 @@ async fn call_normal_mut<F: Future<Output = ()>>(f: &mut impl FnMut(i32) -> F) {
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
pub fn main() {
block_on(async {
let b = 2i32;
diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine_drop_cleanup.rs
index 33fdd2d..4ae9727 100644
--- a/tests/mir-opt/coroutine_drop_cleanup.rs
+++ b/tests/mir-opt/coroutine_drop_cleanup.rs
@@ -8,7 +8,7 @@
// EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir
fn main() {
- let gen = #[coroutine]
+ let gen_ = #[coroutine]
|| {
let _s = String::new();
yield;
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index 8e1cdb7..542b70b 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -27,10 +27,10 @@
}
+ coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0);
-+ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:33 (#0);
-+ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:33 (#0);
-+ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:33 (#0);
-+ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:33 (#0);
++ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:32 (#0);
++ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:32 (#0);
++ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:32 (#0);
++ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:32 (#0);
+ coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0);
+
bb0: {
diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
index 1a71cb8..30de92f 100644
--- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
@@ -8,7 +8,7 @@
let mut _3: !;
+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:11 (#0);
-+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:17 (#0);
++ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0);
+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0);
+ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0);
+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0);
diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp
new file mode 100644
index 0000000..4d1ab9d
--- /dev/null
+++ b/tests/pretty/hir-lifetimes.pp
@@ -0,0 +1,96 @@
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-lifetimes.pp
+
+// This tests the pretty-printing of lifetimes in lots of ways.
+
+#![allow(unused)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+struct Foo<'a> {
+ x: &'a u32,
+}
+
+impl <'a> Foo<'a> {
+ fn f<'b>(x: &'b u32) { }
+}
+
+impl Foo<'_> {
+ fn a(x: &'_ u32) { }
+
+ fn b(x: &'_ u32) { }
+
+ fn c(x: &'_ u32, y: &'static u32) { }
+
+ // FIXME: `'a` before `self` is omitted
+ fn d<'a>(&self, x: &'a u32) { }
+
+ // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh
+ fn iter1<'a>(&self)
+ -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } }
+
+ fn iter2(&self)
+ -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } }
+}
+
+fn a(x: Foo<'_>) { }
+
+fn b<'a>(x: Foo<'a>) { }
+
+struct Bar<'a, 'b, 'c, T> {
+ x: &'a u32,
+ y: &'b &'c u32,
+ z: T,
+}
+
+fn f1<'a, 'b, T>(x: Bar<'a, 'b, '_, T>) { }
+
+fn f2(x: Bar<'_, '_, '_, u32>) { }
+
+trait MyTrait<'a, 'b> {
+ fn f(&self, x: Foo<'a>, y: Foo<'b>);
+}
+
+impl <'a, 'b, 'c, T> MyTrait<'a, 'b> for Bar<'a, 'b, 'c, T> {
+ fn f(&self, x: Foo<'a>, y: Foo<'b>) { }
+}
+
+fn g(x: &'_ dyn for<'a, 'b> MyTrait<'a, 'b>) { }
+
+trait Blah { }
+
+type T<'a> = dyn Blah + 'a;
+
+type Q<'a> = dyn MyTrait<'a, 'a> + 'a;
+
+fn h<'b, F>(f: F, y: Foo<'b>) where F: for<'d> MyTrait<'d, 'b> { }
+
+// FIXME(?): attr printing is weird
+#[attr = Repr([ReprC])]
+struct S<'a>(&'a u32);
+
+extern "C" {
+ unsafe fn g1(s: S<'_>);
+ unsafe fn g2(s: S<'_>);
+ unsafe fn g3<'a>(s: S<'a>);
+}
+
+struct St<'a> {
+ x: &'a u32,
+}
+
+fn f() { { let _ = St { x: &0 }; }; { let _ = St { x: &0 }; }; }
+
+struct Name<'a>(&'a str);
+
+const A: Name<'_> = Name("a");
+const B: &'_ str = "";
+static C: &'_ str = "";
+static D: &'static str = "";
+
+fn tr(_: Box<dyn Blah>) { }
+
+fn main() { }
diff --git a/tests/pretty/hir-lifetimes.rs b/tests/pretty/hir-lifetimes.rs
new file mode 100644
index 0000000..1379be3
--- /dev/null
+++ b/tests/pretty/hir-lifetimes.rs
@@ -0,0 +1,91 @@
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-lifetimes.pp
+
+// This tests the pretty-printing of lifetimes in lots of ways.
+
+#![allow(unused)]
+
+struct Foo<'a> {
+ x: &'a u32,
+}
+
+impl<'a> Foo<'a> {
+ fn f<'b>(x: &'b u32) {}
+}
+
+impl Foo<'_> {
+ fn a(x: &u32) {}
+
+ fn b(x: &'_ u32) {}
+
+ fn c(x: &'_ u32, y: &'static u32) {}
+
+ // FIXME: `'a` before `self` is omitted
+ fn d<'a>(&'a self, x: &'a u32) {}
+
+ // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh
+ fn iter1<'a>(&self) -> impl Iterator<Item = u32> + 'a { 0..1 }
+
+ fn iter2(&self) -> impl Iterator<Item = u32> + '_ { 0..1 }
+}
+
+fn a(x: Foo<'_>) {}
+
+fn b<'a>(x: Foo<'a>) {}
+
+struct Bar<'a, 'b, 'c, T> {
+ x: &'a u32,
+ y: &'b &'c u32,
+ z: T,
+}
+
+fn f1<'a, 'b, T>(x: Bar<'a, 'b, '_, T>) {}
+
+fn f2(x: Bar<'_, '_, '_, u32>) {}
+
+trait MyTrait<'a, 'b> {
+ fn f(&self, x: Foo<'a>, y: Foo<'b>);
+}
+
+impl<'a, 'b, 'c, T> MyTrait<'a, 'b> for Bar<'a, 'b, 'c, T> {
+ fn f(&self, x: Foo<'a>, y: Foo<'b>) {}
+}
+
+fn g(x: &dyn for<'a, 'b> MyTrait<'a, 'b>) {}
+
+trait Blah {}
+
+type T<'a> = dyn Blah + 'a;
+
+type Q<'a> = dyn MyTrait<'a, 'a> + 'a;
+
+fn h<'b, F>(f: F, y: Foo<'b>) where F: for<'d> MyTrait<'d, 'b> {}
+
+// FIXME(?): attr printing is weird
+#[repr(C)]
+struct S<'a>(&'a u32);
+
+extern "C" {
+ fn g1(s: S);
+ fn g2(s: S<'_>);
+ fn g3<'a>(s: S<'a>);
+}
+
+struct St<'a> { x: &'a u32 }
+
+fn f() {
+ _ = St { x: &0 };
+ _ = St::<'_> { x: &0 };
+}
+
+struct Name<'a>(&'a str);
+
+const A: Name = Name("a");
+const B: &str = "";
+static C: &'_ str = "";
+static D: &'static str = "";
+
+fn tr(_: Box<dyn Blah>) {}
+
+fn main() {}
diff --git a/tests/pretty/hir-struct-expr.pp b/tests/pretty/hir-struct-expr.pp
new file mode 100644
index 0000000..f85d175
--- /dev/null
+++ b/tests/pretty/hir-struct-expr.pp
@@ -0,0 +1,28 @@
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-struct-expr.pp
+
+struct StructWithSomeFields {
+ field_1: i32,
+ field_2: i32,
+ field_3: i32,
+ field_4: i32,
+ field_5: i32,
+ field_6: i32,
+}
+
+fn main() {
+ let a =
+ StructWithSomeFields {
+ field_1: 1,
+ field_2: 2,
+ field_3: 3,
+ field_4: 4,
+ field_5: 5,
+ field_6: 6 };
+ let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a };
+}
diff --git a/tests/pretty/hir-struct-expr.rs b/tests/pretty/hir-struct-expr.rs
new file mode 100644
index 0000000..9580f5d
--- /dev/null
+++ b/tests/pretty/hir-struct-expr.rs
@@ -0,0 +1,24 @@
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-struct-expr.pp
+
+struct StructWithSomeFields {
+ field_1: i32,
+ field_2: i32,
+ field_3: i32,
+ field_4: i32,
+ field_5: i32,
+ field_6: i32,
+}
+
+fn main() {
+ let a = StructWithSomeFields {
+ field_1: 1,
+ field_2: 2,
+ field_3: 3,
+ field_4: 4,
+ field_5: 5,
+ field_6: 6,
+ };
+ let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a };
+}
diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs
index 01a503c..90d2b2f 100644
--- a/tests/pretty/stmt_expr_attributes.rs
+++ b/tests/pretty/stmt_expr_attributes.rs
@@ -1,6 +1,5 @@
//@ pp-exact
-#![feature(inline_const_pat)]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
@@ -206,9 +205,7 @@ fn _11() {
let _ = ();
()
};
- let const {
- #![rustc_dummy]
- } =
+ let _ =
#[rustc_dummy] const {
#![rustc_dummy]
};
diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp
index 31449b5..d6a2c0f 100644
--- a/tests/pretty/tests-are-sorted.pp
+++ b/tests/pretty/tests-are-sorted.pp
@@ -10,7 +10,6 @@
//@ pp-exact:tests-are-sorted.pp
extern crate test;
-#[cfg(test)]
#[rustc_test_marker = "m_test"]
#[doc(hidden)]
pub const m_test: test::TestDescAndFn =
@@ -35,7 +34,6 @@
fn m_test() {}
extern crate test;
-#[cfg(test)]
#[rustc_test_marker = "z_test"]
#[doc(hidden)]
pub const z_test: test::TestDescAndFn =
@@ -61,7 +59,6 @@
fn z_test() {}
extern crate test;
-#[cfg(test)]
#[rustc_test_marker = "a_test"]
#[doc(hidden)]
pub const a_test: test::TestDescAndFn =
diff --git a/tests/run-make/embed-metadata/dep1.rs b/tests/run-make/embed-metadata/dep1.rs
new file mode 100644
index 0000000..be70c39
--- /dev/null
+++ b/tests/run-make/embed-metadata/dep1.rs
@@ -0,0 +1 @@
+pub fn func_dep1() {}
diff --git a/tests/run-make/embed-metadata/foo.rs b/tests/run-make/embed-metadata/foo.rs
new file mode 100644
index 0000000..0cc9ced
--- /dev/null
+++ b/tests/run-make/embed-metadata/foo.rs
@@ -0,0 +1,5 @@
+extern crate dep1;
+
+fn main() {
+ dep1::func_dep1();
+}
diff --git a/tests/run-make/embed-metadata/rmake.rs b/tests/run-make/embed-metadata/rmake.rs
new file mode 100644
index 0000000..acefb18
--- /dev/null
+++ b/tests/run-make/embed-metadata/rmake.rs
@@ -0,0 +1,86 @@
+// Tests the -Zembed-metadata compiler flag.
+// Tracking issue: https://github.com/rust-lang/rust/issues/139165
+
+use run_make_support::rfs::{create_dir, remove_file, rename};
+use run_make_support::{Rustc, dynamic_lib_name, path, run_in_tmpdir, rust_lib_name, rustc};
+
+#[derive(Debug, Copy, Clone)]
+enum LibraryKind {
+ Rlib,
+ Dylib,
+}
+
+impl LibraryKind {
+ fn crate_type(&self) -> &str {
+ match self {
+ LibraryKind::Rlib => "rlib",
+ LibraryKind::Dylib => "dylib",
+ }
+ }
+
+ fn add_extern(&self, rustc: &mut Rustc, dep_name: &str, dep_path: &str) {
+ let dep_path = match self {
+ LibraryKind::Dylib => format!("{dep_path}/{}", dynamic_lib_name(dep_name)),
+ LibraryKind::Rlib => format!("{dep_path}/{}", rust_lib_name(dep_name)),
+ };
+ rustc.extern_(dep_name, dep_path);
+ }
+}
+
+fn main() {
+ // The compiler takes different paths based on if --extern is passed or not, so we test all
+ // combinations (`rlib`/`dylib` x `--extern`/`no --extern`).
+ for kind in [LibraryKind::Rlib, LibraryKind::Dylib] {
+ eprintln!("Testing library kind {kind:?}");
+ lookup_rmeta_in_lib_dir(kind);
+ lookup_rmeta_through_extern(kind);
+ lookup_rmeta_missing(kind);
+ }
+}
+
+// Lookup .rmeta file in the same directory as a rlib/dylib with stub metadata.
+fn lookup_rmeta_in_lib_dir(kind: LibraryKind) {
+ run_in_tmpdir(|| {
+ build_dep_rustc(kind).run();
+ rustc().input("foo.rs").run();
+ });
+}
+
+// Lookup .rmeta file when specifying the dependency using --extern.
+fn lookup_rmeta_through_extern(kind: LibraryKind) {
+ run_in_tmpdir(|| {
+ // Generate libdep1.rlib and libdep1.rmeta in deps
+ create_dir("deps");
+ build_dep_rustc(kind).out_dir("deps").run();
+
+ let mut rustc = rustc();
+ kind.add_extern(&mut rustc, "dep1", "deps");
+ rustc.extern_("dep1", path("deps").join("libdep1.rmeta"));
+ rustc.input("foo.rs").run();
+ });
+}
+
+// Check the error message when the .rmeta file is missing.
+fn lookup_rmeta_missing(kind: LibraryKind) {
+ run_in_tmpdir(|| {
+ create_dir("deps");
+ build_dep_rustc(kind).out_dir("deps").run();
+
+ let mut rustc = rustc();
+ kind.add_extern(&mut rustc, "dep1", "deps");
+ rustc.input("foo.rs").run_fail().assert_stderr_contains("only metadata stub found");
+ });
+}
+
+fn build_dep_rustc(kind: LibraryKind) -> Rustc {
+ let mut dep_rustc = rustc();
+ dep_rustc
+ .arg("-Zembed-metadata=no")
+ .crate_type(kind.crate_type())
+ .input("dep1.rs")
+ .emit("metadata,link");
+ if matches!(kind, LibraryKind::Dylib) {
+ dep_rustc.arg("-Cprefer-dynamic");
+ }
+ dep_rustc
+}
diff --git a/tests/run-make/rustdoc-error-lines/rmake.rs b/tests/run-make/rustdoc-error-lines/rmake.rs
index ea5ec2f..0d8c500 100644
--- a/tests/run-make/rustdoc-error-lines/rmake.rs
+++ b/tests/run-make/rustdoc-error-lines/rmake.rs
@@ -8,11 +8,11 @@ fn main() {
let should_contain = &[
"input.rs - foo (line 5)",
- "input.rs:7:15",
+ "input.rs:8:15",
"input.rs - bar (line 13)",
- "input.rs:15:15",
+ "input.rs:16:15",
"input.rs - bar (line 22)",
- "input.rs:24:15",
+ "input.rs:25:15",
];
for text in should_contain {
assert!(output.contains(text), "output doesn't contains {:?}", text);
diff --git a/tests/rustdoc-json/attrs/automatically_derived.rs b/tests/rustdoc-json/attrs/automatically_derived.rs
new file mode 100644
index 0000000..4e1ab3d
--- /dev/null
+++ b/tests/rustdoc-json/attrs/automatically_derived.rs
@@ -0,0 +1,13 @@
+#[derive(Default)]
+pub struct Derive;
+
+pub struct Manual;
+
+impl Default for Manual {
+ fn default() -> Self {
+ Self
+ }
+}
+
+//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '["#[automatically_derived]"]'
+//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Manual" && @.inner.impl.trait.path == "Default")].attrs' '[]'
diff --git a/tests/rustdoc-ui/doctest/display-output.stdout b/tests/rustdoc-ui/doctest/display-output.stdout
index ad25d1c..45e107b 100644
--- a/tests/rustdoc-ui/doctest/display-output.stdout
+++ b/tests/rustdoc-ui/doctest/display-output.stdout
@@ -6,7 +6,7 @@
---- $DIR/display-output.rs - foo (line 9) stdout ----
warning: unused variable: `x`
- --> $DIR/display-output.rs:11:5
+ --> $DIR/display-output.rs:12:5
|
LL | let x = 12;
| ^ help: if this is intentional, prefix it with an underscore: `_x`
@@ -19,13 +19,13 @@
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
warning: unused variable: `x`
- --> $DIR/display-output.rs:13:8
+ --> $DIR/display-output.rs:14:8
|
LL | fn foo(x: &dyn std::fmt::Display) {}
| ^ help: if this is intentional, prefix it with an underscore: `_x`
warning: function `foo` is never used
- --> $DIR/display-output.rs:13:4
+ --> $DIR/display-output.rs:14:4
|
LL | fn foo(x: &dyn std::fmt::Display) {}
| ^^^
diff --git a/tests/rustdoc-ui/doctest/extern-crate.rs b/tests/rustdoc-ui/doctest/extern-crate.rs
new file mode 100644
index 0000000..0415d33
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/extern-crate.rs
@@ -0,0 +1,23 @@
+//@ check-pass
+//@ compile-flags:--test --test-args=--test-threads=1
+//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// This test ensures that crate imports are placed outside of the `main` function
+// so they work all the time (even in 2015 edition).
+
+/// ```rust
+/// #![feature(test)]
+///
+/// extern crate test;
+/// use test::Bencher;
+///
+/// #[bench]
+/// fn bench_xor_1000_ints(b: &mut Bencher) {
+/// b.iter(|| {
+/// (0..1000).fold(0, |old, new| old ^ new);
+/// });
+/// }
+/// ```
+///
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doctest/extern-crate.stdout b/tests/rustdoc-ui/doctest/extern-crate.stdout
new file mode 100644
index 0000000..b103343
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/extern-crate.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/extern-crate.rs - foo (line 9) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/extract-doctests.stdout b/tests/rustdoc-ui/extract-doctests.stdout
index fa8604c..b11531b 100644
--- a/tests/rustdoc-ui/extract-doctests.stdout
+++ b/tests/rustdoc-ui/extract-doctests.stdout
@@ -1 +1 @@
-{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":"#![allow(unused)]\nfn main() {\nlet\n}","name":"$DIR/extract-doctests.rs - (line 13)"}]}
\ No newline at end of file
+{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 13)"}]}
\ No newline at end of file
diff --git a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
index a05b516..c0d2515 100644
--- a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
+++ b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
@@ -5,11 +5,11 @@
failures:
---- remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) stdout ----
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `is`
+error: expected one of `!` or `::`, found `is`
--> remapped_path/remap-path-prefix-invalid-doctest.rs:11:6
|
LL | this is not real code
- | ^^ expected one of 8 possible tokens
+ | ^^ expected one of `!` or `::`
error: aborting due to 1 previous error
diff --git a/tests/rustdoc/playground.rs b/tests/rustdoc/playground.rs
index db2d166..65dad2a 100644
--- a/tests/rustdoc/playground.rs
+++ b/tests/rustdoc/playground.rs
@@ -24,4 +24,4 @@
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
-//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""
+//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""
diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs
new file mode 100644
index 0000000..3fdd65d
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -Z unstable-options
+//@ ignore-stage1
+
+#![feature(rustc_private)]
+#![deny(rustc::usage_of_type_ir_traits)]
+
+extern crate rustc_type_ir;
+
+use rustc_type_ir::Interner;
+
+fn foo<I: Interner>(cx: I, did: I::DefId) {
+ let _ = cx.trait_is_unsafe(did);
+ //~^ ERROR do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
+}
+
+fn main() {}
diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr
new file mode 100644
index 0000000..df29a49
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr
@@ -0,0 +1,15 @@
+error: do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
+ --> $DIR/import-of-type-ir-traits.rs:12:13
+ |
+LL | let _ = cx.trait_is_unsafe(did);
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler
+note: the lint level is defined here
+ --> $DIR/import-of-type-ir-traits.rs:5:9
+ |
+LL | #![deny(rustc::usage_of_type_ir_traits)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
deleted file mode 100644
index 9082044..0000000
--- a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/bound-lifetime-constrained.rs:48:1
- |
-LL | fn main() { }
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/associated-types/bound-lifetime-constrained.rs b/tests/ui/associated-types/bound-lifetime-constrained.rs
index 1dc3b2f..3a5a77f 100644
--- a/tests/ui/associated-types/bound-lifetime-constrained.rs
+++ b/tests/ui/associated-types/bound-lifetime-constrained.rs
@@ -1,7 +1,7 @@
//@ revisions: func object clause ok
+//@[ok] check-pass
#![allow(dead_code)]
-#![feature(rustc_attrs)]
trait Foo<'a> {
type Item;
@@ -44,5 +44,4 @@ fn clause2<T>() where T: for<'a> Fn() -> <() as Foo<'a>>::Item {
//[clause]~^ ERROR `Output` references lifetime `'a`
}
-#[rustc_error]
-fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error]
+fn main() { }
diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
deleted file mode 100644
index 435e224..0000000
--- a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/bound-lifetime-in-binding-only.rs:71:1
- |
-LL | fn main() { }
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs
index e973e58..2401fe0 100644
--- a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs
+++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs
@@ -1,7 +1,7 @@
//@ revisions: angle paren ok elision
+//@[ok] check-pass
#![allow(dead_code)]
-#![feature(rustc_attrs)]
#![feature(unboxed_closures)]
trait Foo {
@@ -67,5 +67,4 @@ fn ok2<T: for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>>() {
fn ok3<T>() where for<'a> Parameterized<'a>: Foo<Item=&'a i32> {
}
-#[rustc_error]
-fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error]
+fn main() { }
diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
deleted file mode 100644
index 1815a7b..0000000
--- a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/bound-lifetime-in-return-only.rs:49:1
- |
-LL | fn main() { }
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.rs b/tests/ui/associated-types/bound-lifetime-in-return-only.rs
index bf3aa61..8a28f5b 100644
--- a/tests/ui/associated-types/bound-lifetime-in-return-only.rs
+++ b/tests/ui/associated-types/bound-lifetime-in-return-only.rs
@@ -1,7 +1,7 @@
//@ revisions: sig local structure ok elision
+//@[ok] check-pass
#![allow(dead_code)]
-#![feature(rustc_attrs)]
#![feature(unboxed_closures)]
trait Foo {
@@ -45,5 +45,4 @@ fn ok1(_: &dyn for<'a> Fn(&Parameterized<'a>) -> &'a i32) {
fn ok2(_: &dyn for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) {
}
-#[rustc_error]
-fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error]
+fn main() { }
diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr
index f5e696b7..f79afc8 100644
--- a/tests/ui/associated-types/issue-59324.stderr
+++ b/tests/ui/associated-types/issue-59324.stderr
@@ -36,21 +36,6 @@
LL | | &self,
LL | | ) -> Self::AssocType;
| |_________________________^ the trait `Foo` is not implemented for `Bug`
- |
-help: consider further restricting type parameter `Bug` with trait `Foo`
- |
-LL | pub trait ThriftService<Bug: NotFoo + Foo>:
- | +++++
-
-error[E0277]: the trait bound `Bug: Foo` is not satisfied
- --> $DIR/issue-59324.rs:16:5
- |
-LL | / fn get_service(
-LL | |
-LL | |
-LL | | &self,
-LL | | ) -> Self::AssocType;
- | |_________________________^ the trait `Foo` is not implemented for `Bug`
error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/issue-59324.rs:24:29
@@ -65,6 +50,21 @@
| ^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `Bug: Foo` is not satisfied
+ --> $DIR/issue-59324.rs:16:5
+ |
+LL | / fn get_service(
+LL | |
+LL | |
+LL | | &self,
+LL | | ) -> Self::AssocType;
+ | |_________________________^ the trait `Foo` is not implemented for `Bug`
+ |
+help: consider further restricting type parameter `Bug` with trait `Foo`
+ |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+ | +++++
+
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
--> $DIR/issue-59324.rs:20:10
|
LL | ) -> Self::AssocType;
diff --git a/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs
new file mode 100644
index 0000000..ecfc06d
--- /dev/null
+++ b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+//@ compile-flags: -Zinline-mir -Zvalidate-mir
+//@ edition: 2024
+
+// See comment below.
+
+use std::future::Future;
+use std::pin::pin;
+use std::task::{Context, Waker};
+
+fn call_once<T>(f: impl FnOnce() -> T) -> T { f() }
+
+fn main() {
+ let x = async || {};
+ // We first inline `call_once<{async closure}>`.
+ //
+ // This gives us a future whose type is the "FnOnce" flavor of the async closure's
+ // child coroutine. The body of this coroutine is synthetic, which we synthesize in
+ // the by-move body query.
+ let fut = pin!(call_once(x));
+ // We then try to inline that body in this poll call.
+ //
+ // The inliner does some inlinability checks; one of these checks involves checking
+ // the body for the `#[rustc_no_mir_inline]` attribute. Since the synthetic body had
+ // no HIR synthesized, but it's still a local def id, we end up ICEing in the
+ // `local_def_id_to_hir_id` call when trying to read its attrs.
+ fut.poll(&mut Context::from_waker(Waker::noop()));
+}
diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
index 6f323d9..9d323bf 100644
--- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
+++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
@@ -1,6 +1,5 @@
-#![feature(rustc_attrs)]
#![allow(dead_code)]
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
// Original borrow ends at end of function
let mut x = 1;
let y = &mut x;
diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
index db73d4c..444a74c 100644
--- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
+++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
@@ -1,5 +1,5 @@
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
- --> $DIR/borrowck-report-with-custom-diagnostic.rs:8:13
+ --> $DIR/borrowck-report-with-custom-diagnostic.rs:7:13
|
LL | let y = &mut x;
| ------ mutable borrow occurs here
@@ -11,7 +11,7 @@
| - mutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
- --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:21
+ --> $DIR/borrowck-report-with-custom-diagnostic.rs:20:21
|
LL | let y = &x;
| -- immutable borrow occurs here
@@ -23,7 +23,7 @@
| - immutable borrow later used here
error[E0499]: cannot borrow `x` as mutable more than once at a time
- --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:17
+ --> $DIR/borrowck-report-with-custom-diagnostic.rs:35:17
|
LL | let y = &mut x;
| ------ first mutable borrow occurs here
diff --git a/tests/ui/borrowck/mut-borrow-outside-loop.rs b/tests/ui/borrowck/mut-borrow-outside-loop.rs
index c02bfbf..3cc362d 100644
--- a/tests/ui/borrowck/mut-borrow-outside-loop.rs
+++ b/tests/ui/borrowck/mut-borrow-outside-loop.rs
@@ -1,6 +1,6 @@
// ensure borrowck messages are correct outside special case
-#![feature(rustc_attrs)]
-fn main() { #![rustc_error] // rust-lang/rust#49855
+
+fn main() {
let mut void = ();
let first = &mut void;
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs
deleted file mode 100644
index cfc0a97..0000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Combination of `ptr-to-trait-obj-wrap.rs` and `ptr-to-trait-obj-add-auto.rs`.
-//
-// Checks that you *can't* add auto traits to trait object in pointer casts involving wrapping said
-// traits structures.
-
-trait A {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap(a: *const W<dyn A>) -> *const (dyn A + Send) {
- a as _
- //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn unwrap_nested(a: *const W<W<dyn A>>) -> *const W<dyn A + Send> {
- a as _
- //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn rewrap(a: *const W<dyn A>) -> *const X<dyn A + Send> {
- a as _
- //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn rewrap_nested(a: *const W<W<dyn A>>) -> *const W<X<dyn A + Send>> {
- a as _
- //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn wrap(a: *const dyn A) -> *const W<dyn A + Send> {
- a as _
- //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr
deleted file mode 100644
index 42cdbc3..0000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr
+++ /dev/null
@@ -1,48 +0,0 @@
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
- --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:12:5
- |
-LL | a as _
- | ^^^^^^ unsupported cast
- |
- = note: this could allow UB elsewhere
- = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
- --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:17:5
- |
-LL | a as _
- | ^^^^^^ unsupported cast
- |
- = note: this could allow UB elsewhere
- = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
- --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:22:5
- |
-LL | a as _
- | ^^^^^^ unsupported cast
- |
- = note: this could allow UB elsewhere
- = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
- --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:27:5
- |
-LL | a as _
- | ^^^^^^ unsupported cast
- |
- = note: this could allow UB elsewhere
- = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
- --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:32:5
- |
-LL | a as _
- | ^^^^^^ unsupported cast
- |
- = note: this could allow UB elsewhere
- = help: use `transmute` if you're sure this is sound
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0804`.
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs
deleted file mode 100644
index ebe7a06..0000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Combination of `ptr-to-trait-obj-different-args.rs` and `ptr-to-trait-obj-wrap.rs`.
-//
-// Checks that you *can't* change type arguments of trait objects in pointer casts involving
-// wrapping said traits structures.
-
-trait A<T> {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap<F, G>(a: *const W<dyn A<F>>) -> *const dyn A<G> {
- a as _
- //~^ error casting `*const W<(dyn A<F> + 'static)>` as `*const dyn A<G>` is invalid
-}
-
-fn unwrap_nested<F, G>(a: *const W<W<dyn A<F>>>) -> *const W<dyn A<G>> {
- a as _
- //~^ error casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<dyn A<G>>` is invalid
-}
-
-fn rewrap<F, G>(a: *const W<dyn A<F>>) -> *const X<dyn A<G>> {
- a as _
- //~^ error: casting `*const W<(dyn A<F> + 'static)>` as `*const X<dyn A<G>>` is invalid
-}
-
-fn rewrap_nested<F, G>(a: *const W<W<dyn A<F>>>) -> *const W<X<dyn A<G>>> {
- a as _
- //~^ error: casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<X<dyn A<G>>>` is invalid
-}
-
-fn wrap<F, G>(a: *const dyn A<F>) -> *const W<dyn A<G>> {
- a as _
- //~^ error: casting `*const (dyn A<F> + 'static)` as `*const W<dyn A<G>>` is invalid
-}
-
-fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr
deleted file mode 100644
index 4f85b20..0000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error[E0606]: casting `*const W<(dyn A<F> + 'static)>` as `*const dyn A<G>` is invalid
- --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:12:5
- |
-LL | a as _
- | ^^^^^^
- |
- = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<dyn A<G>>` is invalid
- --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:17:5
- |
-LL | a as _
- | ^^^^^^
- |
- = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const W<(dyn A<F> + 'static)>` as `*const X<dyn A<G>>` is invalid
- --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:22:5
- |
-LL | a as _
- | ^^^^^^
- |
- = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<X<dyn A<G>>>` is invalid
- --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:27:5
- |
-LL | a as _
- | ^^^^^^
- |
- = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const (dyn A<F> + 'static)` as `*const W<dyn A<G>>` is invalid
- --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:32:5
- |
-LL | a as _
- | ^^^^^^
- |
- = note: the trait objects may have different vtables
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs
deleted file mode 100644
index b094127..0000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// Combination of `ptr-to-trait-obj-different-regions-misc.rs` and `ptr-to-trait-obj-wrap.rs`.
-//
-// Checks that you *can't* change lifetime arguments of trait objects in pointer casts involving
-// wrapping said traits structures.
-
-trait A<'a> {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const dyn A<'b> {
- a as _
- //~^ error
- //~| error
-}
-
-fn unwrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<dyn A<'b>> {
- a as _
- //~^ error
- //~| error
-}
-
-fn rewrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const X<dyn A<'b>> {
- a as _
- //~^ error: lifetime may not live long enough
- //~| error: lifetime may not live long enough
-}
-
-fn rewrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<X<dyn A<'b>>> {
- a as _
- //~^ error: lifetime may not live long enough
- //~| error: lifetime may not live long enough
-}
-
-fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W<dyn A<'b>> {
- a as _
- //~^ error: lifetime may not live long enough
- //~| error: lifetime may not live long enough
-}
-
-fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr
deleted file mode 100644
index 17a0ca3..0000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr
+++ /dev/null
@@ -1,140 +0,0 @@
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5
- |
-LL | fn unwrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const dyn A<'b> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
- |
- = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5
- |
-LL | fn unwrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const dyn A<'b> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
- |
- = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5
- |
-LL | fn unwrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<dyn A<'b>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
- |
- = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5
- |
-LL | fn unwrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<dyn A<'b>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
- |
- = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5
- |
-LL | fn rewrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const X<dyn A<'b>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
- |
- = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5
- |
-LL | fn rewrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const X<dyn A<'b>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
- |
- = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5
- |
-LL | fn rewrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<X<dyn A<'b>>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
- |
- = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5
- |
-LL | fn rewrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<X<dyn A<'b>>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
- |
- = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5
- |
-LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W<dyn A<'b>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
- |
- = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5
- |
-LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W<dyn A<'b>> {
- | -- -- lifetime `'b` defined here
- | |
- | lifetime `'a` defined here
-LL | a as _
- | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
- |
- = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 10 previous errors
-
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap.rs b/tests/ui/cast/ptr-to-trait-obj-wrap.rs
deleted file mode 100644
index 9809ea8..0000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Checks that various casts of pointers to trait objects wrapped in structures
-// work. Note that the metadata doesn't change when a DST is wrapped in a
-// structure, so these casts *are* fine.
-//
-//@ check-pass
-
-trait A {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap(a: *const W<dyn A>) -> *const dyn A {
- a as _
-}
-
-fn unwrap_nested(a: *const W<W<dyn A>>) -> *const W<dyn A> {
- a as _
-}
-
-fn rewrap(a: *const W<dyn A>) -> *const X<dyn A> {
- a as _
-}
-
-fn rewrap_nested(a: *const W<W<dyn A>>) -> *const W<X<dyn A>> {
- a as _
-}
-
-fn wrap(a: *const dyn A) -> *const W<dyn A> {
- a as _
-}
-
-fn main() {}
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index e7b8f35..b07d630 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -14,7 +14,7 @@
LL | #[cfg(target_vendor = "value")]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+ = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition name: `feature`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index 95af0a9..80f8f36 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -15,7 +15,7 @@
LL | #[cfg(target_vendor = "value")]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+ = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `unk`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index 95af0a9..80f8f36 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -15,7 +15,7 @@
LL | #[cfg(target_vendor = "value")]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+ = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `unk`
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index a9d6748..aa5fd09 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -17,11 +17,16 @@
`aes`
`altivec`
`alu32`
+`amx-avx512`
`amx-bf16`
`amx-complex`
`amx-fp16`
+`amx-fp8`
`amx-int8`
+`amx-movrs`
+`amx-tf32`
`amx-tile`
+`amx-transpose`
`atomics`
`avx`
`avx2`
@@ -152,6 +157,7 @@
`mclass`
`mops`
`movbe`
+`movrs`
`mp`
`mp1e2`
`msa`
@@ -245,6 +251,7 @@
`trustzone`
`ual`
`unaligned-scalar-mem`
+`unaligned-vector-mem`
`v`
`v5te`
`v6`
@@ -317,6 +324,11 @@
`zfinx`
`zhinx`
`zhinxmin`
+`zicntr`
+`zicsr`
+`zifencei`
+`zihintpause`
+`zihpm`
`zk`
`zkn`
`zknd`
@@ -325,7 +337,42 @@
`zkr`
`zks`
`zksed`
-`zksh`, and `zkt`
+`zksh`
+`zkt`
+`zvbb`
+`zvbc`
+`zve32f`
+`zve32x`
+`zve64d`
+`zve64f`
+`zve64x`
+`zvfh`
+`zvfhmin`
+`zvkb`
+`zvkg`
+`zvkn`
+`zvknc`
+`zvkned`
+`zvkng`
+`zvknha`
+`zvknhb`
+`zvks`
+`zvksc`
+`zvksed`
+`zvksg`
+`zvksh`
+`zvkt`
+`zvl1024b`
+`zvl128b`
+`zvl16384b`
+`zvl2048b`
+`zvl256b`
+`zvl32768b`
+`zvl32b`
+`zvl4096b`
+`zvl512b`
+`zvl64b`
+`zvl65536b`, and `zvl8192b`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index ba1900f..4636b69 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -230,7 +230,7 @@
LL | target_vendor = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+ = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/codegen/empty-static-libs-issue-108825.rs b/tests/ui/codegen/empty-static-libs-issue-108825.rs
new file mode 100644
index 0000000..46bd6d6
--- /dev/null
+++ b/tests/ui/codegen/empty-static-libs-issue-108825.rs
@@ -0,0 +1,16 @@
+//! Test that linking a no_std application still outputs the
+//! `native-static-libs: ` note, even though it is empty.
+
+//@ compile-flags: -Cpanic=abort --print=native-static-libs
+//@ build-pass
+//@ error-pattern: note: native-static-libs:
+//@ dont-check-compiler-stderr (libcore links `/defaultlib:msvcrt` or `/defaultlib:libcmt` on MSVC)
+//@ ignore-pass (the note is emitted later in the compilation pipeline, needs build)
+
+#![crate_type = "staticlib"]
+#![no_std]
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
deleted file mode 100644
index eda83e9..0000000
--- a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-fn main() {
- let a = {
- let v = 0;
- &v as *const _ as usize
- };
- let b = {
- let v = 0;
- &v as *const _ as usize
- };
-
- assert_ne!(a, b);
- assert_ne!(a, b);
- let c = a;
- assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
- println!("{a} {b}");
- assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
-}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
deleted file mode 100644
index c7f4631..0000000
--- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-use std::ptr;
-
-fn main() {
- let a: usize = {
- let v = 0;
- ptr::from_ref(&v).expose_provenance()
- };
- let b: usize = {
- let v = 0;
- ptr::from_ref(&v).expose_provenance()
- };
-
- assert_ne!(a, b);
- assert_ne!(a, b);
- let c = a;
- assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
- println!("{a} {b}");
- assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
-}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
deleted file mode 100644
index a02ff30..0000000
--- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-use std::ptr;
-
-fn main() {
- let a: usize = {
- let v = 0;
- ptr::from_ref(&v).addr()
- };
- let b: usize = {
- let v = 0;
- ptr::from_ref(&v).addr()
- };
-
- assert_ne!(a, b);
- assert_ne!(a, b);
- let c = a;
- assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
- println!("{a} {b}");
- assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
-}
diff --git a/tests/ui/codemap_tests/issue-11715.rs b/tests/ui/codemap_tests/issue-11715.rs
index 617d57f..d0daaf4 100644
--- a/tests/ui/codemap_tests/issue-11715.rs
+++ b/tests/ui/codemap_tests/issue-11715.rs
@@ -1,5 +1,4 @@
-#![feature(rustc_attrs)]
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
let mut x = "foo";
let y = &mut x;
let z = &mut x; //~ ERROR cannot borrow
diff --git a/tests/ui/codemap_tests/issue-11715.stderr b/tests/ui/codemap_tests/issue-11715.stderr
index 5d0cf71..6b33056 100644
--- a/tests/ui/codemap_tests/issue-11715.stderr
+++ b/tests/ui/codemap_tests/issue-11715.stderr
@@ -1,5 +1,5 @@
error[E0499]: cannot borrow `x` as mutable more than once at a time
- --> $DIR/issue-11715.rs:5:13
+ --> $DIR/issue-11715.rs:4:13
|
LL | let y = &mut x;
| ------ first mutable borrow occurs here
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
index 9a04155..416145a 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
@@ -29,7 +29,6 @@ macro_rules! generate_s10 {
($expr: expr) => {
#[cfg(feature = $expr)]
//~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")`
- //~| ERROR expected unsuffixed literal, found expression `concat!("nonexistent")`
struct S10;
}
}
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
index 21a3712..d02d0d7 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -65,19 +65,7 @@
|
= note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: expected unsuffixed literal, found expression `concat!("nonexistent")`
- --> $DIR/cfg-attr-syntax-validation.rs:30:25
- |
-LL | #[cfg(feature = $expr)]
- | ^^^^^
-...
-LL | generate_s10!(concat!("nonexistent"));
- | ------------------------------------- in this macro invocation
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
- = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
Some errors have detailed explanations: E0537, E0565.
For more information about an error, try `rustc --explain E0537`.
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
index 794e6fa..7c42be3 100644
--- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
+++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
@@ -1,11 +1,12 @@
// This was triggering an assertion failure in `NodeRange::new`.
+//@ check-pass
+
#![feature(cfg_eval)]
#![feature(stmt_expr_attributes)]
fn f() -> u32 {
#[cfg_eval] #[cfg(not(FALSE))] 0
- //~^ ERROR removing an expression is not supported in this position
}
fn main() {}
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
deleted file mode 100644
index 0699e18..0000000
--- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: removing an expression is not supported in this position
- --> $DIR/invalid-node-range-issue-129166.rs:7:17
- |
-LL | #[cfg_eval] #[cfg(not(FALSE))] 0
- | ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr
index 0c3e455..9582152 100644
--- a/tests/ui/consts/assoc-const-elided-lifetime.stderr
+++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr
@@ -35,8 +35,6 @@
|
LL | impl<'a> Foo<'a> {
| ^^
-LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
- | ^^
help: use the `'static` lifetime
|
LL | const BAR: &'static () = &();
diff --git a/tests/ui/consts/async-block.rs b/tests/ui/consts/async-block.rs
index 40be4d1..1211a15 100644
--- a/tests/ui/consts/async-block.rs
+++ b/tests/ui/consts/async-block.rs
@@ -2,8 +2,8 @@
//@ edition:2018
//@ revisions: with_feature without_feature
+//@[with_feature] check-pass
-#![feature(rustc_attrs)]
#![cfg_attr(with_feature, feature(const_async_blocks))]
use std::future::Future;
@@ -15,5 +15,4 @@
static _FUT: &(dyn Future<Output = ()> + Sync) = &async {};
//[without_feature]~^ `async` block
-#[rustc_error]
-fn main() {} //[with_feature]~ fatal error triggered by #[rustc_error]
+fn main() {}
diff --git a/tests/ui/consts/async-block.with_feature.stderr b/tests/ui/consts/async-block.with_feature.stderr
deleted file mode 100644
index 8228fa2..0000000
--- a/tests/ui/consts/async-block.with_feature.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/async-block.rs:19:1
- |
-LL | fn main() {}
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.rs b/tests/ui/consts/invalid-inline-const-in-match-arm.rs
deleted file mode 100644
index 4fe4b0d..0000000
--- a/tests/ui/consts/invalid-inline-const-in-match-arm.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(inline_const_pat)]
-
-fn main() {
- match () {
- const { (|| {})() } => {}
- //~^ ERROR cannot call non-const closure in constants
- //~| ERROR could not evaluate constant pattern
- }
-}
diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
deleted file mode 100644
index b22f99f..0000000
--- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0015]: cannot call non-const closure in constants
- --> $DIR/invalid-inline-const-in-match-arm.rs:5:17
- |
-LL | const { (|| {})() } => {}
- | ^^^^^^^^^
- |
- = note: closures need an RFC before allowed to be called in constants
- = note: calls in constants are limited to constant functions, tuple structs and tuple variants
-
-error: could not evaluate constant pattern
- --> $DIR/invalid-inline-const-in-match-arm.rs:5:9
- |
-LL | const { (|| {})() } => {}
- | ^^^^^^^^^^^^^^^^^^^ could not evaluate constant
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
index 95d59f9..ccf63f8 100644
--- a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
@@ -16,7 +16,7 @@ impl Bar for Foo<'_> {
const STATIC: &str = "";
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//~| WARN this was previously accepted by the compiler but is being phased out
- //~| ERROR const not compatible with trait
+ //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration
}
fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
index ec01225..33873f5 100644
--- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
@@ -39,21 +39,15 @@
LL | const STATIC: &'static str = "";
| +++++++
-error[E0308]: const not compatible with trait
- --> $DIR/elided-lifetime.rs:16:5
+error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+ --> $DIR/elided-lifetime.rs:16:17
|
+LL | const STATIC: &str;
+ | - lifetimes in impl do not match this const in trait
+...
LL | const STATIC: &str = "";
- | ^^^^^^^^^^^^^^^^^^ lifetime mismatch
- |
- = note: expected reference `&'static _`
- found reference `&_`
-note: the anonymous lifetime as defined here...
- --> $DIR/elided-lifetime.rs:16:19
- |
-LL | const STATIC: &str = "";
- | ^
- = note: ...does not necessarily outlive the static lifetime
+ | ^ lifetimes do not match const in trait
error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
index 025fda4..1e12259 100644
--- a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
@@ -9,7 +9,7 @@ impl Bar<'_> for A {
const STATIC: &str = "";
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//~| WARN this was previously accepted by the compiler but is being phased out
- //~| ERROR const not compatible with trait
+ //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration
}
struct B;
@@ -17,4 +17,17 @@ impl Bar<'static> for B {
const STATIC: &str = "";
}
+struct C;
+impl Bar<'_> for C {
+ // make ^^ not cause
+ const STATIC: &'static str = {
+ struct B;
+ impl Bar<'static> for B {
+ const STATIC: &str = "";
+ // ^ to emit a future incompat warning
+ }
+ ""
+ };
+}
+
fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
index b8e2f41..116f28e 100644
--- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
@@ -21,25 +21,15 @@
LL | const STATIC: &'static str = "";
| +++++++
-error[E0308]: const not compatible with trait
- --> $DIR/static-trait-impl.rs:9:5
+error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+ --> $DIR/static-trait-impl.rs:9:17
|
+LL | const STATIC: &'a str;
+ | - lifetimes in impl do not match this const in trait
+...
LL | const STATIC: &str = "";
- | ^^^^^^^^^^^^^^^^^^ lifetime mismatch
- |
- = note: expected reference `&_`
- found reference `&_`
-note: the anonymous lifetime as defined here...
- --> $DIR/static-trait-impl.rs:9:19
- |
-LL | const STATIC: &str = "";
- | ^
-note: ...does not necessarily outlive the anonymous lifetime as defined here
- --> $DIR/static-trait-impl.rs:8:10
- |
-LL | impl Bar<'_> for A {
- | ^^
+ | ^ lifetimes do not match const in trait
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs
index 289767b..57b55e9 100644
--- a/tests/ui/custom_test_frameworks/full.rs
+++ b/tests/ui/custom_test_frameworks/full.rs
@@ -25,4 +25,17 @@ fn run(&self) -> Option<String> {
const TEST_1: IsFoo = IsFoo("hello");
#[test_case]
-const TEST_2: IsFoo = IsFoo("foo");
+static TEST_2: IsFoo = IsFoo("foo");
+
+// FIXME: `test_case` is currently ignored on anything other than
+// fn/const/static. This should be an error. Compare this with `#[test]` and
+// #[bench] whose expanders emit "error: expected a non-associated function,
+// found […]" if applied to invalid items.
+#[test_case]
+struct _S;
+
+// FIXME: as above.
+#[test_case]
+impl _S {
+ fn _f() {}
+}
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
index 8980ef9..f928e11 100644
--- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
@@ -13,14 +13,16 @@
//! - Original impl PR: <https://github.com/rust-lang/rust/pull/21248>.
//! - RFC 507 "Release channels":
//! <https://github.com/rust-lang/rfcs/blob/c017755b9bfa0421570d92ba38082302e0f3ad4f/text/0507-release-channels.md>.
-#![feature(rustc_attrs)]
//@ revisions: without_flag with_flag
+//@ check-pass
+//@ compile-flags: -Zunleash-the-miri-inside-of-you
//@[with_flag] compile-flags: -Awarnings
-//@ check-pass
+fn non_constant() {}
+const fn constant() { non_constant() }
-#[rustc_error(warn)]
fn main() {}
-//[without_flag]~^ WARN unexpected annotation used with `#[rustc_error(...)]`!
+
+//[without_flag]~? WARN skipping const checks
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
index 3f33ccb..08ae11f 100644
--- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
@@ -1,8 +1,10 @@
-warning: unexpected annotation used with `#[rustc_error(...)]`!
- --> $DIR/allow-non-lint-warnings.rs:25:1
+warning: skipping const checks
|
-LL | fn main() {}
- | ^^^^^^^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/allow-non-lint-warnings.rs:24:23
+ |
+LL | const fn constant() { non_constant() }
+ | ^^^^^^^^^^^^^^
warning: 1 warning emitted
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs
index 2c13066..f9b5176 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs
@@ -17,4 +17,13 @@ impl Mop {
//~| ERROR: unconstrained opaque type
}
+fn funky(_: [(); {
+ impl Foo for fn() {
+ type Bar = impl Sized;
+ //~^ ERROR: `impl Trait` in associated types is unstable
+ //~| ERROR: unconstrained opaque type
+ }
+ 0
+}]) {}
+
fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
index 7dfd79c..01d25c1 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
@@ -18,6 +18,16 @@
= help: add `#![feature(impl_trait_in_assoc_type)]` 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]: `impl Trait` in associated types is unstable
+ --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:22:20
+ |
+LL | type Bar = impl Sized;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(impl_trait_in_assoc_type)]` 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]: inherent associated types are unstable
--> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:5
|
@@ -44,6 +54,14 @@
|
= note: `Bop` must be used in combination with a concrete type within the same impl
-error: aborting due to 5 previous errors
+error: unconstrained opaque type
+ --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:22:20
+ |
+LL | type Bar = impl Sized;
+ | ^^^^^^^^^^
+ |
+ = note: `Bar` must be used in combination with a concrete type within the same impl
+
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.rs b/tests/ui/feature-gates/feature-gate-inline_const_pat.rs
deleted file mode 100644
index 3d0df28..0000000
--- a/tests/ui/feature-gates/feature-gate-inline_const_pat.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
- let const { () } = ();
- //~^ ERROR inline-const in pattern position is experimental [E0658]
-}
diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr b/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr
deleted file mode 100644
index 7d7376f..0000000
--- a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: inline-const in pattern position is experimental
- --> $DIR/feature-gate-inline_const_pat.rs:2:9
- |
-LL | let const { () } = ();
- | ^^^^^
- |
- = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
- = help: add `#![feature(inline_const_pat)]` 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 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs
new file mode 100644
index 0000000..738cab5
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs
@@ -0,0 +1,6 @@
+//@ only-x86_64
+#[target_feature(enable = "movrs")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr
new file mode 100644
index 0000000..16fe7aa
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the target feature `movrs` is currently unstable
+ --> $DIR/feature-gate-movrs_target_feature.rs:2:18
+ |
+LL | #[target_feature(enable = "movrs")]
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #137976 <https://github.com/rust-lang/rust/issues/137976> for more information
+ = help: add `#![feature(movrs_target_feature)]` 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 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
index 7ae4a8d..025b4b5 100644
--- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
+++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
@@ -1,7 +1,6 @@
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
-#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable
fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
index 8c3a8eb..0f760e0 100644
--- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
+++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
@@ -7,18 +7,9 @@
= help: add `#![feature(rustc_attrs)]` 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]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
- --> $DIR/feature-gate-rustc-attrs-1.rs:4:1
- |
-LL | #[rustc_error]
- | ^^^^^^^^^^^^^^
- |
- = help: add `#![feature(rustc_attrs)]` 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]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable
(note that the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized)
- --> $DIR/feature-gate-rustc-attrs-1.rs:5:1
+ --> $DIR/feature-gate-rustc-attrs-1.rs:4:1
|
LL | #[rustc_nonnull_optimization_guaranteed]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,6 +17,6 @@
= help: add `#![feature(rustc_attrs)]` 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 3 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
index ec70a20..d332fba 100644
--- a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
+++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
@@ -1,38 +1,42 @@
-//@ check-pass
-#![feature(type_alias_impl_trait)]
use std::fmt::Debug;
-type Foo = impl Debug;
+type Foo = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
struct Bar(Foo);
-#[define_opaque(Foo)]
+#[define_opaque(Foo)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
fn define() -> Bar {
Bar(42)
}
-type Foo2 = impl Debug;
+type Foo2 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
-#[define_opaque(Foo2)]
+#[define_opaque(Foo2)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
fn define2() {
let x = || -> Foo2 { 42 };
}
-type Foo3 = impl Debug;
+type Foo3 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
-#[define_opaque(Foo3)]
+#[define_opaque(Foo3)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
fn define3(x: Foo3) {
let y: i32 = x;
}
-#[define_opaque(Foo3)]
+#[define_opaque(Foo3)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
fn define3_1() {
define3(42)
}
-type Foo4 = impl Debug;
+type Foo4 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
-#[define_opaque(Foo4)]
+#[define_opaque(Foo4)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
fn define4(_: Foo4) {
let y: Foo4 = 42;
}
+type Foo5 = [(); {
+ type Foo = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
+ //~^ ERROR unconstrained opaque type
+ 0
+}];
+
fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
new file mode 100644
index 0000000..bab60eb
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
@@ -0,0 +1,111 @@
+error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:6:3
+ |
+LL | #[define_opaque(Foo)]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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 `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:13:3
+ |
+LL | #[define_opaque(Foo2)]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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 `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:20:3
+ |
+LL | #[define_opaque(Foo3)]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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 `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:24:3
+ |
+LL | #[define_opaque(Foo3)]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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 `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:31:3
+ |
+LL | #[define_opaque(Foo4)]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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]: `impl Trait` in type aliases is unstable
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:3:12
+ |
+LL | type Foo = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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]: `impl Trait` in type aliases is unstable
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:11:13
+ |
+LL | type Foo2 = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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]: `impl Trait` in type aliases is unstable
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:18:13
+ |
+LL | type Foo3 = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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]: `impl Trait` in type aliases is unstable
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:29:13
+ |
+LL | type Foo4 = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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]: `impl Trait` in type aliases is unstable
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:37:16
+ |
+LL | type Foo = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` 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: unconstrained opaque type
+ --> $DIR/feature-gate-type_alias_impl_trait.rs:37:16
+ |
+LL | type Foo = impl Debug;
+ | ^^^^^^^^^^
+ |
+ = note: `Foo` must be used in combination with a concrete type within the same crate
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
index f943ea0..f79001f 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
@@ -1,7 +1,5 @@
//@ run-pass
#![allow(non_contiguous_range_endpoints)]
-#![feature(inline_const_pat)]
-
fn main() {
let mut if_lettable = vec![];
let mut first_or = vec![];
@@ -16,7 +14,6 @@ fn main() {
match x {
1 | -3..0 => first_or.push(x),
y @ (0..5 | 6) => or_two.push(y),
- y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
y @ -5.. => range_from.push(y),
y @ ..-7 => assert_eq!(y, -8),
y => bottom.push(y),
@@ -25,6 +22,6 @@ fn main() {
assert_eq!(if_lettable, [-1, 0, 2, 4]);
assert_eq!(first_or, [-3, -2, -1, 1]);
assert_eq!(or_two, [0, 2, 3, 4, 6]);
- assert_eq!(range_from, [-5, -4, 7]);
+ assert_eq!(range_from, [-5, -4, 5, 7]);
assert_eq!(bottom, [-7, -6]);
}
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
index 4d7c9f1..c5705d5 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
@@ -18,8 +18,6 @@
//~^ error: expected a pattern range bound, found an expression
1 | -3..0 => first_or.push(x),
y @ (0..5 | 6) => or_two.push(y),
- y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
- //~^ error: inline-const in pattern position is experimental [E0658]
y @ -5.. => range_from.push(y),
y @ ..-7 => assert_eq!(y, -8),
y => bottom.push(y),
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
index 62be2ef..5cd98fa 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
@@ -11,10 +11,6 @@
LL ~ match x as i32 {
LL ~ 0..VAL => errors_only.push(x),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | 0..const { 5+1 } => errors_only.push(x),
- | +++++++ +
error[E0408]: variable `n` is not bound in all patterns
--> $DIR/range_pat_interactions1.rs:10:25
@@ -24,17 +20,6 @@
| |
| variable not in all patterns
-error[E0658]: inline-const in pattern position is experimental
- --> $DIR/range_pat_interactions1.rs:21:20
- |
-LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
- | ^^^^^
- |
- = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
- = help: add `#![feature(inline_const_pat)]` 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 2 previous errors
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0408, E0658.
-For more information about an error, try `rustc --explain E0408`.
+For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
deleted file mode 100644
index 0dbdb8f..0000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-fn main() {
- let mut first_or = Vec::<i32>::new();
- let mut or_two = Vec::<i32>::new();
- let mut range_from = Vec::<i32>::new();
- let mut bottom = Vec::<i32>::new();
- let mut errors_only = Vec::<i32>::new();
-
- for x in -9 + 1..=(9 - 2) {
- match x as i32 {
- 0..=(5+1) => errors_only.push(x),
- //~^ error: expected a pattern range bound, found an expression
- //~| error: range pattern bounds cannot have parentheses
- 1 | -3..0 => first_or.push(x),
- y @ (0..5 | 6) => or_two.push(y),
- y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
- //~^ error: inline-const in pattern position is experimental
- y @ -5.. => range_from.push(y),
- y @ ..-7 => assert_eq!(y, -8),
- y => bottom.push(y),
- }
- }
-}
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
deleted file mode 100644
index dbe7f44..0000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error: range pattern bounds cannot have parentheses
- --> $DIR/range_pat_interactions2.rs:10:17
- |
-LL | 0..=(5+1) => errors_only.push(x),
- | ^ ^
- |
-help: remove these parentheses
- |
-LL - 0..=(5+1) => errors_only.push(x),
-LL + 0..=5+1 => errors_only.push(x),
- |
-
-error: expected a pattern range bound, found an expression
- --> $DIR/range_pat_interactions2.rs:10:18
- |
-LL | 0..=(5+1) => errors_only.push(x),
- | ^^^ not a pattern
- |
- = note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
-help: consider extracting the expression into a `const`
- |
-LL + const VAL: /* Type */ = 5+1;
-LL ~ match x as i32 {
-LL ~ 0..=(VAL) => errors_only.push(x),
- |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | 0..=(const { 5+1 }) => errors_only.push(x),
- | +++++++ +
-
-error[E0658]: inline-const in pattern position is experimental
- --> $DIR/range_pat_interactions2.rs:15:20
- |
-LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
- | ^^^^^
- |
- = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
- = help: add `#![feature(inline_const_pat)]` 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 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs b/tests/ui/half-open-range-patterns/range_pat_interactions3.rs
deleted file mode 100644
index 2f27780..0000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-fn main() {
- let mut first_or = Vec::<i32>::new();
- let mut or_two = Vec::<i32>::new();
- let mut range_from = Vec::<i32>::new();
- let mut bottom = Vec::<i32>::new();
-
- for x in -9 + 1..=(9 - 2) {
- match x as i32 {
- 8.. => bottom.push(x),
- 1 | -3..0 => first_or.push(x),
- y @ (0..5 | 6) => or_two.push(y),
- y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
- //~^ inline-const in pattern position is experimental
- y @ -5.. => range_from.push(y),
- y @ ..-7 => assert_eq!(y, -8),
- y => bottom.push(y),
- }
- }
-}
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
deleted file mode 100644
index dc7dc0e..0000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: inline-const in pattern position is experimental
- --> $DIR/range_pat_interactions3.rs:12:20
- |
-LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
- | ^^^^^
- |
- = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
- = help: add `#![feature(inline_const_pat)]` 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 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs
index 2c277ae..89fe3c1 100644
--- a/tests/ui/impl-trait/impl_trait_projections.rs
+++ b/tests/ui/impl-trait/impl_trait_projections.rs
@@ -35,4 +35,9 @@ fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
panic!()
}
+fn parametrized_value_in_anon_const_is_disallowed() -> [(); None::<impl Sized>] {
+ //~^ ERROR `impl Trait` is not allowed in paths
+ loop {}
+}
+
fn main() {}
diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr
index 5e0b80f..21f4561 100644
--- a/tests/ui/impl-trait/impl_trait_projections.stderr
+++ b/tests/ui/impl-trait/impl_trait_projections.stderr
@@ -30,6 +30,14 @@
|
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
-error: aborting due to 4 previous errors
+error[E0562]: `impl Trait` is not allowed in paths
+ --> $DIR/impl_trait_projections.rs:38:68
+ |
+LL | fn parametrized_value_in_anon_const_is_disallowed() -> [(); None::<impl Sized>] {
+ | ^^^^^^^^^^
+ |
+ = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs b/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs
new file mode 100644
index 0000000..ab54d5f
--- /dev/null
+++ b/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs
@@ -0,0 +1,25 @@
+// Ensure we don't misclassify `impl Trait` as TAIT/ATPIT if located inside an anon const in a
+// type alias/assoc type.
+// issue: <https://github.com/rust-lang/rust/issues/139055>
+//@ check-pass
+#![forbid(unstable_features)]
+
+struct Girder<const N: usize>;
+
+type Alias = Girder<{
+ fn pass(input: impl Sized) -> impl Sized { input }
+ 0
+}>;
+
+trait Trait {
+ type Assoc;
+}
+
+impl Trait for () {
+ type Assoc = [(); {
+ fn pass(input: impl Sized) -> impl Sized { input }
+ 0
+ }];
+}
+
+fn main() {}
diff --git a/tests/ui/imports/glob-resolve1.stderr b/tests/ui/imports/glob-resolve1.stderr
index 75e6568..23b0db0 100644
--- a/tests/ui/imports/glob-resolve1.stderr
+++ b/tests/ui/imports/glob-resolve1.stderr
@@ -58,6 +58,11 @@
LL | import();
| ^^^^^^ not found in this scope
|
+note: function `bar::import` exists but is inaccessible
+ --> $DIR/glob-resolve1.rs:7:5
+ |
+LL | fn fpriv() {}
+ | ^^^^^^^^^^ not accessible
help: consider importing this function
|
LL + use other::import;
diff --git a/tests/ui/imports/issue-4366-2.stderr b/tests/ui/imports/issue-4366-2.stderr
index 412423f..b1c0092 100644
--- a/tests/ui/imports/issue-4366-2.stderr
+++ b/tests/ui/imports/issue-4366-2.stderr
@@ -16,6 +16,11 @@
LL | foo();
| ^^^ not a function
|
+note: function `m1::foo` exists but is inaccessible
+ --> $DIR/issue-4366-2.rs:21:5
+ |
+LL | fn foo() {}
+ | ^^^^^^^^ not accessible
help: consider importing this function instead
|
LL + use foo::foo;
diff --git a/tests/ui/imports/issue-4366.stderr b/tests/ui/imports/issue-4366.stderr
index e63399d..54b7f31 100644
--- a/tests/ui/imports/issue-4366.stderr
+++ b/tests/ui/imports/issue-4366.stderr
@@ -4,6 +4,11 @@
LL | fn sub() -> isize { foo(); 1 }
| ^^^ not found in this scope
|
+note: function `m1::foo` exists but is inaccessible
+ --> $DIR/issue-4366.rs:23:5
+ |
+LL | fn foo() {}
+ | ^^^^^^^^ not accessible
help: consider importing this function
|
LL + use foo::foo;
diff --git a/tests/ui/imports/show-private-items-issue-138626.rs b/tests/ui/imports/show-private-items-issue-138626.rs
new file mode 100644
index 0000000..d9708fc
--- /dev/null
+++ b/tests/ui/imports/show-private-items-issue-138626.rs
@@ -0,0 +1,19 @@
+pub mod one {
+ mod foo {
+ pub struct Foo;
+ }
+
+ pub use self::foo::Foo;
+}
+
+pub mod two {
+ mod foo {
+ mod bar {
+ pub struct Foo;
+ }
+ }
+
+ pub use crate::two::foo::Foo; //~ ERROR unresolved import `crate::two::foo::Foo` [E0432]
+}
+
+fn main() {}
diff --git a/tests/ui/imports/show-private-items-issue-138626.stderr b/tests/ui/imports/show-private-items-issue-138626.stderr
new file mode 100644
index 0000000..b664462
--- /dev/null
+++ b/tests/ui/imports/show-private-items-issue-138626.stderr
@@ -0,0 +1,20 @@
+error[E0432]: unresolved import `crate::two::foo::Foo`
+ --> $DIR/show-private-items-issue-138626.rs:16:13
+ |
+LL | pub use crate::two::foo::Foo;
+ | ^^^^^^^^^^^^^^^^^^^^ no `Foo` in `two::foo`
+ |
+note: struct `two::foo::bar::Foo` exists but is inaccessible
+ --> $DIR/show-private-items-issue-138626.rs:12:13
+ |
+LL | pub struct Foo;
+ | ^^^^^^^^^^^^^^^ not accessible
+help: consider importing this struct through its public re-export instead
+ |
+LL - pub use crate::two::foo::Foo;
+LL + pub use one::Foo;
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr
index 7d09af9..7770cc8 100644
--- a/tests/ui/infinite/infinite-autoderef.stderr
+++ b/tests/ui/infinite/infinite-autoderef.stderr
@@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Box<_>` to `_`
- --> $DIR/infinite-autoderef.rs:16:13
+ --> $DIR/infinite-autoderef.rs:16:22
|
LL | x = Box::new(x);
- | ^^^^^^^^^^^
+ | ^
error: aborting due to 1 previous error
diff --git a/tests/ui/inline-const/collect-scopes-in-pat.rs b/tests/ui/inline-const/collect-scopes-in-pat.rs
deleted file mode 100644
index 16baf92..0000000
--- a/tests/ui/inline-const/collect-scopes-in-pat.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ compile-flags: -Zlint-mir
-//@ check-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
- match 1 {
- const {
- || match 0 {
- x => 0,
- };
- 0
- } => (),
- _ => (),
- }
-}
diff --git a/tests/ui/inline-const/const-block-pat-liveness.rs b/tests/ui/inline-const/const-block-pat-liveness.rs
deleted file mode 100644
index 26393a4..0000000
--- a/tests/ui/inline-const/const-block-pat-liveness.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! This test used to ICE because const blocks didn't have a body
-//! anymore, making a lot of logic very fragile around handling the
-//! HIR of a const block.
-//! https://github.com/rust-lang/rust/issues/125846
-
-//@ check-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
- match 0 {
- const {
- let a = 10_usize;
- *&a
- }
- | _ => {}
- }
-}
diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs
deleted file mode 100644
index 889c015..0000000
--- a/tests/ui/inline-const/const-match-pat-generic.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![feature(inline_const_pat)]
-
-// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
-
-fn foo<const V: usize>() {
- match 0 {
- const { V } => {},
- //~^ ERROR constant pattern cannot depend on generic parameters
- _ => {},
- }
-}
-
-const fn f(x: usize) -> usize {
- x + 1
-}
-
-fn bar<const V: usize>() {
- match 0 {
- const { f(V) } => {},
- //~^ ERROR constant pattern cannot depend on generic parameters
- _ => {},
- }
-}
-
-fn main() {
- foo::<1>();
- bar::<1>();
-}
diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr
deleted file mode 100644
index 7d9e1d9..0000000
--- a/tests/ui/inline-const/const-match-pat-generic.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0158]: constant pattern cannot depend on generic parameters
- --> $DIR/const-match-pat-generic.rs:7:9
- |
-LL | const { V } => {},
- | ^^^^^^^^^^^ `const` depends on a generic parameter
-
-error[E0158]: constant pattern cannot depend on generic parameters
- --> $DIR/const-match-pat-generic.rs:19:9
- |
-LL | const { f(V) } => {},
- | ^^^^^^^^^^^^^^ `const` depends on a generic parameter
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/inline-const/const-match-pat-inference.rs b/tests/ui/inline-const/const-match-pat-inference.rs
deleted file mode 100644
index 3d35338..0000000
--- a/tests/ui/inline-const/const-match-pat-inference.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ check-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
- match 1u64 {
- 0 => (),
- const { 0 + 1 } => (),
- const { 2 - 1 } ..= const { u64::MAX } => (),
- }
-}
diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.rs b/tests/ui/inline-const/const-match-pat-lifetime-err.rs
deleted file mode 100644
index 7f450eb..0000000
--- a/tests/ui/inline-const/const-match-pat-lifetime-err.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-#![feature(inline_const_pat)]
-
-use std::marker::PhantomData;
-
-#[derive(PartialEq, Eq)]
-pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
-
-#[derive(PartialEq, Eq)]
-pub struct CovariantRef<'a, T: ?Sized>(&'a T);
-
-impl<'a, T: ?Sized> InvariantRef<'a, T> {
- pub const fn new(r: &'a T) -> Self {
- InvariantRef(r, PhantomData)
- }
-}
-
-impl<'a> InvariantRef<'a, ()> {
- pub const NEW: Self = InvariantRef::new(&());
-}
-
-impl<'a> CovariantRef<'a, ()> {
- pub const NEW: Self = CovariantRef(&());
-}
-
-fn match_invariant_ref<'a>() {
- let y = ();
- match InvariantRef::new(&y) {
- //~^ ERROR `y` does not live long enough [E0597]
- const { InvariantRef::<'a>::NEW } => (),
- }
-}
-
-fn match_covariant_ref<'a>() {
- // Unclear if we should error here (should we be able to subtype the type of
- // `y.0`), but using the associated const directly in the pattern also
- // errors.
- let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),);
- //~^ ERROR lifetime may not live long enough
- match y.0 {
- const { CovariantRef::<'a>::NEW } => (),
- }
-}
-
-fn main() {
- match_invariant_ref();
- match_covariant_ref();
-}
diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr
deleted file mode 100644
index 7eea184..0000000
--- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0597]: `y` does not live long enough
- --> $DIR/const-match-pat-lifetime-err.rs:27:29
- |
-LL | fn match_invariant_ref<'a>() {
- | -- lifetime `'a` defined here
-LL | let y = ();
- | - binding `y` declared here
-LL | match InvariantRef::new(&y) {
- | ^^ borrowed value does not live long enough
-LL |
-LL | const { InvariantRef::<'a>::NEW } => (),
- | ----------------------- using this value as a constant requires that `y` is borrowed for `'a`
-LL | }
-LL | }
- | - `y` dropped here while still borrowed
-
-error: lifetime may not live long enough
- --> $DIR/const-match-pat-lifetime-err.rs:37:12
- |
-LL | fn match_covariant_ref<'a>() {
- | -- lifetime `'a` defined here
-...
-LL | let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs
deleted file mode 100644
index 7f1011e..0000000
--- a/tests/ui/inline-const/const-match-pat-lifetime.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//@ run-pass
-
-#![feature(inline_const_pat)]
-
-use std::marker::PhantomData;
-
-// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
-fn issue_78174() {
- match "foo" {
- const { concat!("fo", "o") } => (),
- _ => unreachable!(),
- }
-}
-
-#[derive(PartialEq, Eq)]
-pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
-
-impl<'a, T: ?Sized> InvariantRef<'a, T> {
- pub const fn new(r: &'a T) -> Self {
- InvariantRef(r, PhantomData)
- }
-}
-
-fn match_invariant_ref<'a>() {
- match const { InvariantRef::<'a, _>::new(&()) } {
- const { InvariantRef::<'a, ()>::new(&()) } => {
- }
- }
-}
-
-fn main() {
- issue_78174();
- match_invariant_ref();
-}
diff --git a/tests/ui/inline-const/const-match-pat-range.rs b/tests/ui/inline-const/const-match-pat-range.rs
deleted file mode 100644
index 7202c0c..0000000
--- a/tests/ui/inline-const/const-match-pat-range.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-//@ build-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
- const N: u32 = 10;
- let x: u32 = 3;
-
- match x {
- 1 ..= const { N + 1 } => {},
- _ => {},
- }
-
- match x {
- const { N - 1 } ..= 10 => {},
- _ => {},
- }
-
- match x {
- const { N - 1 } ..= const { N + 1 } => {},
- _ => {},
- }
-
- match x {
- .. const { N + 1 } => {},
- _ => {},
- }
-
- match x {
- const { N - 1 } .. => {},
- _ => {},
- }
-
- match x {
- ..= const { N + 1 } => {},
- _ => {}
- }
-}
diff --git a/tests/ui/inline-const/const-match-pat.rs b/tests/ui/inline-const/const-match-pat.rs
deleted file mode 100644
index 1580ef2..0000000
--- a/tests/ui/inline-const/const-match-pat.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ run-pass
-
-#![feature(inline_const_pat)]
-const MMIO_BIT1: u8 = 4;
-const MMIO_BIT2: u8 = 5;
-
-fn main() {
- let s = match read_mmio() {
- 0 => "FOO",
- const { 1 << MMIO_BIT1 } => "BAR",
- const { 1 << MMIO_BIT2 } => "BAZ",
- _ => unreachable!(),
- };
-
- assert_eq!("BAZ", s);
-}
-
-fn read_mmio() -> i32 {
- 1 << 5
-}
diff --git a/tests/ui/inline-const/in-pat-recovery.rs b/tests/ui/inline-const/in-pat-recovery.rs
new file mode 100644
index 0000000..0d912af
--- /dev/null
+++ b/tests/ui/inline-const/in-pat-recovery.rs
@@ -0,0 +1,11 @@
+// While `feature(inline_const_pat)` has been removed from the
+// compiler, we should still make sure that the resulting error
+// message is acceptable.
+fn main() {
+ match 1 {
+ const { 1 + 7 } => {}
+ //~^ `inline_const_pat` has been removed
+ 2 => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/inline-const/in-pat-recovery.stderr b/tests/ui/inline-const/in-pat-recovery.stderr
new file mode 100644
index 0000000..e1f2e68
--- /dev/null
+++ b/tests/ui/inline-const/in-pat-recovery.stderr
@@ -0,0 +1,10 @@
+error: `inline_const_pat` has been removed
+ --> $DIR/in-pat-recovery.rs:6:15
+ |
+LL | const { 1 + 7 } => {}
+ | ^^^^^^^^^
+ |
+ = help: use a named `const`-item or an `if`-guard instead
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/inline-const/pat-match-fndef.rs b/tests/ui/inline-const/pat-match-fndef.rs
deleted file mode 100644
index 013a4a6..0000000
--- a/tests/ui/inline-const/pat-match-fndef.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(inline_const_pat)]
-
-fn uwu() {}
-
-fn main() {
- let x = [];
- match x[123] {
- const { uwu } => {}
- //~^ ERROR `fn() {uwu}` cannot be used in patterns
- _ => {}
- }
-}
diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr
deleted file mode 100644
index 220437a..0000000
--- a/tests/ui/inline-const/pat-match-fndef.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fn item `fn() {uwu}` cannot be used in patterns
- --> $DIR/pat-match-fndef.rs:8:9
- |
-LL | const { uwu } => {}
- | ^^^^^^^^^^^^^ fn item can't be used in patterns
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/inline-const/pat-unsafe-err.rs b/tests/ui/inline-const/pat-unsafe-err.rs
deleted file mode 100644
index b906def..0000000
--- a/tests/ui/inline-const/pat-unsafe-err.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(inline_const_pat)]
-
-const unsafe fn require_unsafe() -> usize {
- 1
-}
-
-fn main() {
- match () {
- const {
- require_unsafe();
- //~^ ERROR [E0133]
- } => (),
- }
-
- match 1 {
- const {
- require_unsafe()
- //~^ ERROR [E0133]
- }..=4 => (),
- _ => (),
- }
-}
diff --git a/tests/ui/inline-const/pat-unsafe-err.stderr b/tests/ui/inline-const/pat-unsafe-err.stderr
deleted file mode 100644
index 786c7f3..0000000
--- a/tests/ui/inline-const/pat-unsafe-err.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
- --> $DIR/pat-unsafe-err.rs:10:13
- |
-LL | require_unsafe();
- | ^^^^^^^^^^^^^^^^ call to unsafe function
- |
- = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
- --> $DIR/pat-unsafe-err.rs:17:13
- |
-LL | require_unsafe()
- | ^^^^^^^^^^^^^^^^ call to unsafe function
- |
- = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs
deleted file mode 100644
index 4b05f3a..0000000
--- a/tests/ui/inline-const/pat-unsafe.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//@ check-pass
-
-#![warn(unused_unsafe)]
-#![feature(inline_const_pat)]
-
-const unsafe fn require_unsafe() -> usize {
- 1
-}
-
-fn main() {
- unsafe {
- match () {
- const {
- require_unsafe();
- unsafe {}
- //~^ WARNING unnecessary `unsafe` block
- } => (),
- }
-
- match 1 {
- const {
- unsafe {}
- //~^ WARNING unnecessary `unsafe` block
- require_unsafe()
- }..=4 => (),
- _ => (),
- }
- }
-}
diff --git a/tests/ui/inline-const/pat-unsafe.stderr b/tests/ui/inline-const/pat-unsafe.stderr
deleted file mode 100644
index 5946027..0000000
--- a/tests/ui/inline-const/pat-unsafe.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-warning: unnecessary `unsafe` block
- --> $DIR/pat-unsafe.rs:15:17
- |
-LL | unsafe {}
- | ^^^^^^ unnecessary `unsafe` block
- |
-note: the lint level is defined here
- --> $DIR/pat-unsafe.rs:3:9
- |
-LL | #![warn(unused_unsafe)]
- | ^^^^^^^^^^^^^
-
-warning: unnecessary `unsafe` block
- --> $DIR/pat-unsafe.rs:22:17
- |
-LL | unsafe {}
- | ^^^^^^ unnecessary `unsafe` block
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs
index f6c1df5..f144094 100644
--- a/tests/ui/layout/reprc-power-alignment.rs
+++ b/tests/ui/layout/reprc-power-alignment.rs
@@ -148,5 +148,29 @@ pub struct I {
d: f32,
e: f64,
}
-
+#[repr(C)]
+pub struct J {
+ a: u8,
+ b: I,
+}
+// The lint also ignores diagnosing #[repr(align(n))].
+#[repr(C, align(8))]
+pub struct K {
+ a: u8,
+ b: u8,
+ c: f64,
+ d: f32,
+ e: f64,
+}
+#[repr(C)]
+pub struct L {
+ a: u8,
+ b: K,
+}
+#[repr(C, align(8))]
+pub struct M {
+ a: u8,
+ b: K,
+ c: L,
+}
fn main() { }
diff --git a/tests/ui/lint/dead-code/anon-const-in-pat.rs b/tests/ui/lint/dead-code/anon-const-in-pat.rs
deleted file mode 100644
index e2d8c90..0000000
--- a/tests/ui/lint/dead-code/anon-const-in-pat.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//@ check-pass
-#![feature(inline_const_pat)]
-#![deny(dead_code)]
-
-const fn one() -> i32 {
- 1
-}
-
-const fn two() -> i32 {
- 2
-}
-
-const fn three() -> i32 {
- 3
-}
-
-fn inline_const() {
- // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern
- match 1 {
- const { one() } => {}
- _ => {}
- }
-}
-
-fn inline_const_range() {
- match 1 {
- 1 ..= const { two() } => {}
- _ => {}
- }
-}
-
-struct S<const C: i32>;
-
-fn const_generic_arg() {
- match S::<3> {
- S::<{three()}> => {}
- }
-}
-
-fn main() {
- inline_const();
- inline_const_range();
- const_generic_arg();
-}
diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs
new file mode 100644
index 0000000..69e322e
--- /dev/null
+++ b/tests/ui/lint/inline-exported.rs
@@ -0,0 +1,30 @@
+//! Ensure the unused_attributes lint fires for externally exported functions with `#[inline]`,
+//! because `#[inline]` is ignored for such functions.
+
+#![crate_type = "lib"]
+
+#![feature(linkage)]
+#![feature(naked_functions)]
+#![deny(unused_attributes)]
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[no_mangle]
+fn no_mangle() {}
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[export_name = "export_name"]
+fn export_name() {}
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[linkage = "external"]
+fn external_linkage() {}
+
+#[inline]
+fn normal() {}
+
+#[inline]
+#[linkage = "internal"] // not exported
+fn internal_linkage() {}
diff --git a/tests/ui/lint/inline-exported.stderr b/tests/ui/lint/inline-exported.stderr
new file mode 100644
index 0000000..dcf63cc
--- /dev/null
+++ b/tests/ui/lint/inline-exported.stderr
@@ -0,0 +1,31 @@
+error: `#[inline]` is ignored on externally exported functions
+ --> $DIR/inline-exported.rs:10:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+ |
+ = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+note: the lint level is defined here
+ --> $DIR/inline-exported.rs:8:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: `#[inline]` is ignored on externally exported functions
+ --> $DIR/inline-exported.rs:15:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+ |
+ = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
+error: `#[inline]` is ignored on externally exported functions
+ --> $DIR/inline-exported.rs:20:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+ |
+ = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs
new file mode 100644
index 0000000..7948f0d
--- /dev/null
+++ b/tests/ui/lint/invalid_null_args.rs
@@ -0,0 +1,136 @@
+// check-fail
+// run-rustfix
+
+use std::ptr;
+use std::mem;
+
+unsafe fn null_ptr() {
+ ptr::write(
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ ptr::null_mut() as *mut u32,
+ mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+ );
+
+ let null_ptr = ptr::null_mut();
+ ptr::write(
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ null_ptr as *mut u32,
+ mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+ );
+
+ let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::copy::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ ptr::copy::<usize>(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::copy_nonoverlapping::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ ptr::copy_nonoverlapping::<usize>(
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ ptr::NonNull::dangling().as_ptr(),
+ ptr::null_mut(),
+ 0
+ );
+
+ #[derive(Copy, Clone)]
+ struct A(usize);
+ let mut v = A(200);
+
+ let _a: A = ptr::read(ptr::null());
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ let _a: A = ptr::read(ptr::null_mut());
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ let _a: A = ptr::read_unaligned(ptr::null());
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ let _a: A = ptr::read_unaligned(ptr::null_mut());
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ let _a: A = ptr::read_volatile(ptr::null());
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ let _a: A = ptr::read_volatile(ptr::null_mut());
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ let _a: A = ptr::replace(ptr::null_mut(), v);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::swap::<A>(ptr::null_mut(), &mut v);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ ptr::swap::<A>(&mut v, ptr::null_mut());
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::write(ptr::null_mut(), v);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::write_unaligned(ptr::null_mut(), v);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::write_volatile(ptr::null_mut(), v);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ // with indirections
+ let const_ptr = null_ptr as *const u8;
+ let _a: u8 = ptr::read(const_ptr);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+}
+
+unsafe fn zst() {
+ struct Zst; // zero-sized type
+
+ std::slice::from_raw_parts::<()>(ptr::null(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+ std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
+ //~^ ERROR calling this function with a null pointer is undefined behavior
+
+ ptr::read::<()>(ptr::null());
+ ptr::read::<Zst>(ptr::null());
+
+ ptr::write(ptr::null_mut(), ());
+ ptr::write(ptr::null_mut(), Zst);
+
+ ptr::copy(ptr::null::<()>(), ptr::null_mut::<()>(), 1);
+ ptr::copy(ptr::null::<Zst>(), ptr::null_mut::<Zst>(), 1);
+}
+
+unsafe fn not_invalid() {
+ // Simplified false-positive from std quicksort implementation
+
+ let mut a = ptr::null_mut();
+ let mut b = ();
+
+ loop {
+ if false {
+ break;
+ }
+
+ a = &raw mut b;
+ }
+
+ ptr::write(a, ());
+}
+
+fn main() {}
diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr
new file mode 100644
index 0000000..f95bc2a
--- /dev/null
+++ b/tests/ui/lint/invalid_null_args.stderr
@@ -0,0 +1,330 @@
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:8:5
+ |
+LL | / ptr::write(
+LL | |
+LL | | ptr::null_mut() as *mut u32,
+ | | --------------- null pointer originates from here
+LL | | mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+LL | | );
+ | |_____^
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+ = note: `#[deny(invalid_null_arguments)]` on by default
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:15:5
+ |
+LL | / ptr::write(
+LL | |
+LL | | null_ptr as *mut u32,
+LL | | mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+LL | | );
+ | |_____^
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+note: null pointer originates from here
+ --> $DIR/invalid_null_args.rs:14:20
+ |
+LL | let null_ptr = ptr::null_mut();
+ | ^^^^^^^^^^^^^^^
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:21:23
+ |
+LL | let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:23:23
+ |
+LL | let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:25:23
+ |
+LL | let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:27:23
+ |
+LL | let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:30:23
+ |
+LL | let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:33:5
+ |
+LL | ptr::copy::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+ | ^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:35:5
+ |
+LL | ptr::copy::<usize>(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:38:5
+ |
+LL | ptr::copy_nonoverlapping::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:40:5
+ |
+LL | / ptr::copy_nonoverlapping::<usize>(
+LL | |
+LL | | ptr::NonNull::dangling().as_ptr(),
+LL | | ptr::null_mut(),
+ | | --------------- null pointer originates from here
+LL | | 0
+LL | | );
+ | |_____^
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:51:17
+ |
+LL | let _a: A = ptr::read(ptr::null());
+ | ^^^^^^^^^^-----------^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:53:17
+ |
+LL | let _a: A = ptr::read(ptr::null_mut());
+ | ^^^^^^^^^^---------------^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:56:17
+ |
+LL | let _a: A = ptr::read_unaligned(ptr::null());
+ | ^^^^^^^^^^^^^^^^^^^^-----------^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:58:17
+ |
+LL | let _a: A = ptr::read_unaligned(ptr::null_mut());
+ | ^^^^^^^^^^^^^^^^^^^^---------------^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:61:17
+ |
+LL | let _a: A = ptr::read_volatile(ptr::null());
+ | ^^^^^^^^^^^^^^^^^^^-----------^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:63:17
+ |
+LL | let _a: A = ptr::read_volatile(ptr::null_mut());
+ | ^^^^^^^^^^^^^^^^^^^---------------^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:66:17
+ |
+LL | let _a: A = ptr::replace(ptr::null_mut(), v);
+ | ^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:69:5
+ |
+LL | ptr::swap::<A>(ptr::null_mut(), &mut v);
+ | ^^^^^^^^^^^^^^^---------------^^^^^^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:71:5
+ |
+LL | ptr::swap::<A>(&mut v, ptr::null_mut());
+ | ^^^^^^^^^^^^^^^^^^^^^^^---------------^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:74:5
+ |
+LL | ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:76:5
+ |
+LL | ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:79:5
+ |
+LL | ptr::write(ptr::null_mut(), v);
+ | ^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:82:5
+ |
+LL | ptr::write_unaligned(ptr::null_mut(), v);
+ | ^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:85:5
+ |
+LL | ptr::write_volatile(ptr::null_mut(), v);
+ | ^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:88:5
+ |
+LL | ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:93:18
+ |
+LL | let _a: u8 = ptr::read(const_ptr);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+note: null pointer originates from here
+ --> $DIR/invalid_null_args.rs:14:20
+ |
+LL | let null_ptr = ptr::null_mut();
+ | ^^^^^^^^^^^^^^^
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:100:5
+ |
+LL | std::slice::from_raw_parts::<()>(ptr::null(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:102:5
+ |
+LL | std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:104:5
+ |
+LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+ --> $DIR/invalid_null_args.rs:106:5
+ |
+LL | std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+ | |
+ | null pointer originates from here
+ |
+ = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: aborting due to 31 previous errors
+
diff --git a/tests/ui/match/issue-112438.rs b/tests/ui/match/issue-112438.rs
deleted file mode 100644
index b2febe2..0000000
--- a/tests/ui/match/issue-112438.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ run-pass
-#![feature(inline_const_pat)]
-#![allow(dead_code)]
-fn foo<const V: usize>() {
- match 0 {
- const { 1 << 5 } | _ => {}
- }
-}
-
-fn main() {}
diff --git a/tests/ui/match/validate-range-endpoints.rs b/tests/ui/match/validate-range-endpoints.rs
index 46d4239..678cedf 100644
--- a/tests/ui/match/validate-range-endpoints.rs
+++ b/tests/ui/match/validate-range-endpoints.rs
@@ -1,4 +1,3 @@
-#![feature(inline_const_pat)]
#![allow(overlapping_range_endpoints)]
fn main() {
@@ -17,8 +16,6 @@ fn main() {
// There isn't really a way to detect these
1..=TOO_BIG => {}
//~^ ERROR lower range bound must be less than or equal to upper
- 1..=const { 256 } => {}
- //~^ ERROR lower range bound must be less than or equal to upper
_ => {}
}
diff --git a/tests/ui/match/validate-range-endpoints.stderr b/tests/ui/match/validate-range-endpoints.stderr
index 2d05388..6a8a81a 100644
--- a/tests/ui/match/validate-range-endpoints.stderr
+++ b/tests/ui/match/validate-range-endpoints.stderr
@@ -1,59 +1,53 @@
error: literal out of range for `u8`
- --> $DIR/validate-range-endpoints.rs:7:12
+ --> $DIR/validate-range-endpoints.rs:6:12
|
LL | 1..257 => {}
| ^^^ this value does not fit into the type `u8` whose range is `0..=255`
error: literal out of range for `u8`
- --> $DIR/validate-range-endpoints.rs:9:13
+ --> $DIR/validate-range-endpoints.rs:8:13
|
LL | 1..=256 => {}
| ^^^ this value does not fit into the type `u8` whose range is `0..=255`
error[E0030]: lower range bound must be less than or equal to upper
- --> $DIR/validate-range-endpoints.rs:18:9
+ --> $DIR/validate-range-endpoints.rs:17:9
|
LL | 1..=TOO_BIG => {}
| ^^^^^^^^^^^ lower bound larger than upper bound
-error[E0030]: lower range bound must be less than or equal to upper
- --> $DIR/validate-range-endpoints.rs:20:9
- |
-LL | 1..=const { 256 } => {}
- | ^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
-
error: literal out of range for `u64`
- --> $DIR/validate-range-endpoints.rs:26:32
+ --> $DIR/validate-range-endpoints.rs:23:32
|
LL | 10000000000000000000..=99999999999999999999 => {}
| ^^^^^^^^^^^^^^^^^^^^ this value does not fit into the type `u64` whose range is `0..=18446744073709551615`
error: literal out of range for `i8`
- --> $DIR/validate-range-endpoints.rs:32:12
+ --> $DIR/validate-range-endpoints.rs:29:12
|
LL | 0..129 => {}
| ^^^ this value does not fit into the type `i8` whose range is `-128..=127`
error: literal out of range for `i8`
- --> $DIR/validate-range-endpoints.rs:34:13
+ --> $DIR/validate-range-endpoints.rs:31:13
|
LL | 0..=128 => {}
| ^^^ this value does not fit into the type `i8` whose range is `-128..=127`
error: literal out of range for `i8`
- --> $DIR/validate-range-endpoints.rs:36:9
+ --> $DIR/validate-range-endpoints.rs:33:9
|
LL | -129..0 => {}
| ^^^^ this value does not fit into the type `i8` whose range is `-128..=127`
error: literal out of range for `i8`
- --> $DIR/validate-range-endpoints.rs:38:9
+ --> $DIR/validate-range-endpoints.rs:35:9
|
LL | -10000..=-20 => {}
| ^^^^^^ this value does not fit into the type `i8` whose range is `-128..=127`
error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered
- --> $DIR/validate-range-endpoints.rs:49:11
+ --> $DIR/validate-range-endpoints.rs:46:11
|
LL | match 0i8 {
| ^^^ patterns `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered
@@ -66,7 +60,7 @@
|
error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` not covered
- --> $DIR/validate-range-endpoints.rs:53:11
+ --> $DIR/validate-range-endpoints.rs:50:11
|
LL | match 0i8 {
| ^^^ pattern `i8::MIN..=-17_i8` not covered
@@ -78,7 +72,7 @@
LL + i8::MIN..=-17_i8 => todo!()
|
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
Some errors have detailed explanations: E0004, E0030.
For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/mir/inline-causes-trimmed-paths.rs b/tests/ui/mir/inline-causes-trimmed-paths.rs
new file mode 100644
index 0000000..d626ab4
--- /dev/null
+++ b/tests/ui/mir/inline-causes-trimmed-paths.rs
@@ -0,0 +1,36 @@
+//@ build-pass
+//@ compile-flags: -Zinline-mir
+
+trait Storage {
+ type Buffer: ?Sized;
+}
+
+struct Array<const N: usize>;
+impl<const N: usize> Storage for Array<N> {
+ type Buffer = [(); N];
+}
+
+struct Slice;
+impl Storage for Slice {
+ type Buffer = [()];
+}
+
+struct Wrap<S: Storage> {
+ _b: S::Buffer,
+}
+
+fn coerce<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice>
+where
+ Array<N>: Storage,
+{
+ coerce_again(this)
+}
+
+fn coerce_again<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice> {
+ this
+}
+
+fn main() {
+ let inner: Wrap<Array<1>> = Wrap { _b: [(); 1] };
+ let _: &Wrap<Slice> = coerce(&inner);
+}
diff --git a/tests/ui/mir/issue-75053.rs b/tests/ui/mir/issue-75053.rs
index 9b247fa..4bc481b 100644
--- a/tests/ui/mir/issue-75053.rs
+++ b/tests/ui/mir/issue-75053.rs
@@ -1,6 +1,7 @@
+//@ check-pass
//@ compile-flags: -Z mir-opt-level=3
-#![feature(type_alias_impl_trait, rustc_attrs)]
+#![feature(type_alias_impl_trait)]
use std::marker::PhantomData;
@@ -43,8 +44,6 @@ fn my_index(self) -> Self::O {
}
}
-#[rustc_error]
fn main() {
- //~^ ERROR
let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
}
diff --git a/tests/ui/mir/issue-75053.stderr b/tests/ui/mir/issue-75053.stderr
deleted file mode 100644
index 91032bc..0000000
--- a/tests/ui/mir/issue-75053.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/issue-75053.rs:47:1
- |
-LL | fn main() {
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/mir/var_debug_ref.rs b/tests/ui/mir/var_debug_ref.rs
new file mode 100644
index 0000000..1dcf38b
--- /dev/null
+++ b/tests/ui/mir/var_debug_ref.rs
@@ -0,0 +1,24 @@
+// Regression test for #138942, where a function was incorrectly internalized, despite the fact
+// that it was referenced by a var debug info from another code generation unit.
+//
+//@ build-pass
+//@ revisions: limited full
+//@ compile-flags: -Ccodegen-units=4
+//@[limited] compile-flags: -Cdebuginfo=limited
+//@[full] compile-flags: -Cdebuginfo=full
+trait Fun {
+ const FUN: &'static fn();
+}
+impl Fun for () {
+ const FUN: &'static fn() = &(detail::f as fn());
+}
+mod detail {
+ // Place `f` in a distinct module to generate a separate code generation unit.
+ #[inline(never)]
+ pub(super) fn f() {}
+}
+fn main() {
+ // SingleUseConsts represents "x" using VarDebugInfoContents::Const.
+ // It is the only reference to `f` remaining.
+ let x = <() as ::Fun>::FUN;
+}
diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs
index 1ec460a..9289a8e 100644
--- a/tests/ui/occurs-check-2.rs
+++ b/tests/ui/occurs-check-2.rs
@@ -4,6 +4,6 @@
let g;
g = f;
- f = Box::new(g);
//~^ ERROR overflow assigning `Box<_>` to `_`
+ f = Box::new(g);
}
diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr
index 54307a6..5f29696 100644
--- a/tests/ui/occurs-check-2.stderr
+++ b/tests/ui/occurs-check-2.stderr
@@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Box<_>` to `_`
- --> $DIR/occurs-check-2.rs:7:9
+ --> $DIR/occurs-check-2.rs:6:9
|
-LL | f = Box::new(g);
- | ^^^^^^^^^^^
+LL | g = f;
+ | ^
error: aborting due to 1 previous error
diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr
index 77b67ec..eb05c94 100644
--- a/tests/ui/occurs-check-3.stderr
+++ b/tests/ui/occurs-check-3.stderr
@@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Clam<_>` to `_`
- --> $DIR/occurs-check-3.rs:6:9
+ --> $DIR/occurs-check-3.rs:6:17
|
LL | c = Clam::A(c);
- | ^^^^^^^^^^
+ | ^
error: aborting due to 1 previous error
diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr
index 30468d6..ea7c541 100644
--- a/tests/ui/occurs-check.stderr
+++ b/tests/ui/occurs-check.stderr
@@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Box<_>` to `_`
- --> $DIR/occurs-check.rs:3:9
+ --> $DIR/occurs-check.rs:3:18
|
LL | f = Box::new(f);
- | ^^^^^^^^^^^
+ | ^
error: aborting due to 1 previous error
diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs
index 2d0c6db..937390a 100644
--- a/tests/ui/parser/attribute/attr-bad-meta-4.rs
+++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs
@@ -2,7 +2,6 @@
($attr_item: meta) => {
#[cfg($attr_item)]
//~^ ERROR expected unsuffixed literal, found `meta` metavariable
- //~| ERROR expected unsuffixed literal, found `meta` metavariable
struct S;
}
}
@@ -11,7 +10,6 @@
#[cfg(feature = -1)]
//~^ ERROR expected unsuffixed literal, found `-`
-//~| ERROR expected unsuffixed literal, found `-`
fn handler() {}
fn main() {}
diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr
index dea574f..9c6ab5a 100644
--- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr
+++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr
@@ -1,5 +1,5 @@
error: expected unsuffixed literal, found `-`
- --> $DIR/attr-bad-meta-4.rs:12:17
+ --> $DIR/attr-bad-meta-4.rs:11:17
|
LL | #[cfg(feature = -1)]
| ^
@@ -15,25 +15,5 @@
|
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: expected unsuffixed literal, found `meta` metavariable
- --> $DIR/attr-bad-meta-4.rs:3:15
- |
-LL | #[cfg($attr_item)]
- | ^^^^^^^^^^
-...
-LL | mac!(an(arbitrary token stream));
- | -------------------------------- in this macro invocation
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
- = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: expected unsuffixed literal, found `-`
- --> $DIR/attr-bad-meta-4.rs:12:17
- |
-LL | #[cfg(feature = -1)]
- | ^
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/closure-return-syntax.rs b/tests/ui/parser/closure-return-syntax.rs
index c6a08ab..6865d8c 100644
--- a/tests/ui/parser/closure-return-syntax.rs
+++ b/tests/ui/parser/closure-return-syntax.rs
@@ -1,7 +1,21 @@
// Test that we cannot parse a closure with an explicit return type
// unless it uses braces.
-fn main() {
+fn needs_braces_1() {
let x = || -> i32 22;
//~^ ERROR expected `{`, found `22`
}
+
+// Check other delimiters too.
+
+fn needs_braces_2() {
+ let x = || -> (i32, i32) (1, 2);
+ //~^ ERROR expected `{`, found `(`
+}
+
+fn needs_braces_3() {
+ let c = || -> [i32; 2] [1, 2];
+ //~^ ERROR expected `{`, found `[`
+}
+
+fn main() {}
diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr
index aacc31e..763f19c 100644
--- a/tests/ui/parser/closure-return-syntax.stderr
+++ b/tests/ui/parser/closure-return-syntax.stderr
@@ -2,12 +2,40 @@
--> $DIR/closure-return-syntax.rs:5:23
|
LL | let x = || -> i32 22;
- | ^^ expected `{`
+ | --- ^^
+ | |
+ | explicit return type requires closure body to be enclosed in braces
|
-help: you might have meant to write this as part of a block
+help: wrap the expression in curly braces
|
LL | let x = || -> i32 { 22 };
| + +
-error: aborting due to 1 previous error
+error: expected `{`, found `(`
+ --> $DIR/closure-return-syntax.rs:12:34
+ |
+LL | let x = || -> (i32, i32) (1, 2);
+ | ---------- ^
+ | |
+ | explicit return type requires closure body to be enclosed in braces
+ |
+help: wrap the expression in curly braces
+ |
+LL | let x = || -> (i32, i32) { (1, 2) };
+ | + +
+
+error: expected `{`, found `[`
+ --> $DIR/closure-return-syntax.rs:17:32
+ |
+LL | let c = || -> [i32; 2] [1, 2];
+ | -------- ^
+ | |
+ | explicit return type requires closure body to be enclosed in braces
+ |
+help: wrap the expression in curly braces
+ |
+LL | let c = || -> [i32; 2] { [1, 2] };
+ | + +
+
+error: aborting due to 3 previous errors
diff --git a/tests/ui/parser/issues/issue-103451.rs b/tests/ui/parser/issues/issue-103451.rs
index 6b09282..687dbc6 100644
--- a/tests/ui/parser/issues/issue-103451.rs
+++ b/tests/ui/parser/issues/issue-103451.rs
@@ -1,4 +1,4 @@
-//@ error-pattern: this file contains an unclosed delimiter
struct R { }
+//~vv ERROR this file contains an unclosed delimiter
struct S {
x: [u8; R
diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs
index 7200ea1..dcc03fe 100644
--- a/tests/ui/parser/issues/issue-10636-2.rs
+++ b/tests/ui/parser/issues/issue-10636-2.rs
@@ -1,7 +1,7 @@
-//@ error-pattern: mismatched closing delimiter: `}`
// FIXME(31528) we emit a bunch of silly errors here due to continuing past the
// first one. This would be easy-ish to address by better recovery in tokenisation.
+//~vvvvv ERROR mismatched closing delimiter: `}`
pub fn trace_option(option: Option<isize>) {
option.map(|some| 42;
diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr
index 2af57a5..e96c004f 100644
--- a/tests/ui/parser/issues/issue-24375.stderr
+++ b/tests/ui/parser/issues/issue-24375.stderr
@@ -16,10 +16,6 @@
LL ~ match z {
LL ~ VAL => {}
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { tmp[0] } => {}
- | +++++++ +
error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
index 7952d29..0c0fbd7 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
@@ -1,5 +1,4 @@
// Fixed in #66054.
// ignore-tidy-trailing-newlines
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: aborting due to 1 previous error
+//~v ERROR this file contains an unclosed delimiter
#[Ѕ
\ No newline at end of file
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
index 14f5469..28fd78d 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4
+ --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4
|
LL | #[Ѕ
| - ^
diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs
index a219f66..a8c7d6e 100644
--- a/tests/ui/parser/issues/issue-62524.rs
+++ b/tests/ui/parser/issues/issue-62524.rs
@@ -1,6 +1,7 @@
// ignore-tidy-trailing-newlines
-//@ error-pattern: aborting due to 1 previous error
+
#![allow(uncommon_codepoints)]
+//~vv ERROR this file contains an unclosed delimiter
y![
Ϥ,
\ No newline at end of file
diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr
index d83a49a..c1ff6e7 100644
--- a/tests/ui/parser/issues/issue-62524.stderr
+++ b/tests/ui/parser/issues/issue-62524.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-62524.rs:6:3
+ --> $DIR/issue-62524.rs:7:3
|
LL | y![
| - unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs
index 9f196e4..4a8a168 100644
--- a/tests/ui/parser/issues/issue-62554.rs
+++ b/tests/ui/parser/issues/issue-62554.rs
@@ -1,5 +1,4 @@
-//@ error-pattern:this file contains an unclosed delimiter
-
fn main() {}
+//~v ERROR this file contains an unclosed delimiter
fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr
index d4aaef1..50515c4 100644
--- a/tests/ui/parser/issues/issue-62554.stderr
+++ b/tests/ui/parser/issues/issue-62554.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-62554.rs:5:89
+ --> $DIR/issue-62554.rs:4:89
|
LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
| - - - - -^
diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs
index 5b1627a..c49cbe4 100644
--- a/tests/ui/parser/issues/issue-62894.rs
+++ b/tests/ui/parser/issues/issue-62894.rs
@@ -1,6 +1,6 @@
// Regression test for #62894, shouldn't crash.
-//@ error-pattern: this file contains an unclosed delimiter
+//~vvv ERROR this file contains an unclosed delimiter
fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
fn main() {}
diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs
index 5c666d8..a091e4e 100644
--- a/tests/ui/parser/issues/issue-62973.rs
+++ b/tests/ui/parser/issues/issue-62973.rs
@@ -1,8 +1,10 @@
// ignore-tidy-trailing-newlines
-//@ error-pattern: aborting due to 3 previous errors
fn main() {}
+//~vvv ERROR mismatched closing delimiter: `)`
+//~vv ERROR mismatched closing delimiter: `)`
+//~vvv ERROR this file contains an unclosed delimiter
fn p() { match s { v, E { [) {) }
diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr
index 4931839..ea3e2be 100644
--- a/tests/ui/parser/issues/issue-62973.stderr
+++ b/tests/ui/parser/issues/issue-62973.stderr
@@ -1,5 +1,5 @@
error: mismatched closing delimiter: `)`
- --> $DIR/issue-62973.rs:6:27
+ --> $DIR/issue-62973.rs:8:27
|
LL | fn p() { match s { v, E { [) {) }
| ^^ mismatched closing delimiter
@@ -7,7 +7,7 @@
| unclosed delimiter
error: mismatched closing delimiter: `)`
- --> $DIR/issue-62973.rs:6:30
+ --> $DIR/issue-62973.rs:8:30
|
LL | fn p() { match s { v, E { [) {) }
| ^^ mismatched closing delimiter
@@ -15,7 +15,7 @@
| unclosed delimiter
error: this file contains an unclosed delimiter
- --> $DIR/issue-62973.rs:8:2
+ --> $DIR/issue-62973.rs:10:2
|
LL | fn p() { match s { v, E { [) {) }
| - - - - missing open `(` for this delimiter
diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs
index 3be9606..48abe63 100644
--- a/tests/ui/parser/issues/issue-63116.rs
+++ b/tests/ui/parser/issues/issue-63116.rs
@@ -1,3 +1,4 @@
// fixed by #66361
-//@ error-pattern: aborting due to 2 previous errors
+//~vv ERROR mismatched closing delimiter: `]`
+//~v ERROR this file contains an unclosed delimiter
impl W <s(f;Y(;]
diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr
index e0f7dd1..e5bad84 100644
--- a/tests/ui/parser/issues/issue-63116.stderr
+++ b/tests/ui/parser/issues/issue-63116.stderr
@@ -1,5 +1,5 @@
error: mismatched closing delimiter: `]`
- --> $DIR/issue-63116.rs:3:14
+ --> $DIR/issue-63116.rs:4:14
|
LL | impl W <s(f;Y(;]
| ^ ^ mismatched closing delimiter
@@ -7,7 +7,7 @@
| unclosed delimiter
error: this file contains an unclosed delimiter
- --> $DIR/issue-63116.rs:3:18
+ --> $DIR/issue-63116.rs:4:18
|
LL | impl W <s(f;Y(;]
| - -^
diff --git a/tests/ui/parser/issues/issue-63135.rs b/tests/ui/parser/issues/issue-63135.rs
index 112dd4c..63eca5b 100644
--- a/tests/ui/parser/issues/issue-63135.rs
+++ b/tests/ui/parser/issues/issue-63135.rs
@@ -1,3 +1,2 @@
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: aborting due to 1 previous error
+//~v ERROR this file contains an unclosed delimiter
fn i(n{...,f #
diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr
index d627590..061ec17 100644
--- a/tests/ui/parser/issues/issue-63135.stderr
+++ b/tests/ui/parser/issues/issue-63135.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-63135.rs:3:16
+ --> $DIR/issue-63135.rs:2:16
|
LL | fn i(n{...,f #
| - - ^
diff --git a/tests/ui/parser/issues/issue-81804.rs b/tests/ui/parser/issues/issue-81804.rs
index 7c9e6e9..57951ca 100644
--- a/tests/ui/parser/issues/issue-81804.rs
+++ b/tests/ui/parser/issues/issue-81804.rs
@@ -1,6 +1,5 @@
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: this file contains an unclosed delimiter
-
fn main() {}
+//~vv ERROR mismatched closing delimiter: `}`
+//~v ERROR this file contains an unclosed delimiter
fn p([=(}
diff --git a/tests/ui/parser/issues/issue-81804.stderr b/tests/ui/parser/issues/issue-81804.stderr
index 6caaaa7..f12c6a6 100644
--- a/tests/ui/parser/issues/issue-81804.stderr
+++ b/tests/ui/parser/issues/issue-81804.stderr
@@ -1,5 +1,5 @@
error: mismatched closing delimiter: `}`
- --> $DIR/issue-81804.rs:6:8
+ --> $DIR/issue-81804.rs:5:8
|
LL | fn p([=(}
| ^^ mismatched closing delimiter
@@ -7,7 +7,7 @@
| unclosed delimiter
error: this file contains an unclosed delimiter
- --> $DIR/issue-81804.rs:6:11
+ --> $DIR/issue-81804.rs:5:11
|
LL | fn p([=(}
| -- ^
diff --git a/tests/ui/parser/issues/issue-81827.rs b/tests/ui/parser/issues/issue-81827.rs
index a2bd345..7dfeec1 100644
--- a/tests/ui/parser/issues/issue-81827.rs
+++ b/tests/ui/parser/issues/issue-81827.rs
@@ -1,10 +1,7 @@
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: mismatched closing delimiter: `]`
-
#![crate_name="0"]
-
-
fn main() {}
+//~vv ERROR mismatched closing delimiter: `]`
+//~v ERROR this file contains an unclosed delimiter
fn r()->i{0|{#[cfg(r(0{]0
diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr
index d12c74b..986ed6b 100644
--- a/tests/ui/parser/issues/issue-81827.stderr
+++ b/tests/ui/parser/issues/issue-81827.stderr
@@ -1,5 +1,5 @@
error: mismatched closing delimiter: `]`
- --> $DIR/issue-81827.rs:10:23
+ --> $DIR/issue-81827.rs:7:23
|
LL | fn r()->i{0|{#[cfg(r(0{]0
| - ^^ mismatched closing delimiter
@@ -8,7 +8,7 @@
| closing delimiter possibly meant for this
error: this file contains an unclosed delimiter
- --> $DIR/issue-81827.rs:10:27
+ --> $DIR/issue-81827.rs:7:27
|
LL | fn r()->i{0|{#[cfg(r(0{]0
| - - - ^
diff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs
index bced05e..6baf882 100644
--- a/tests/ui/parser/issues/issue-84104.rs
+++ b/tests/ui/parser/issues/issue-84104.rs
@@ -1,2 +1,2 @@
-//@ error-pattern: this file contains an unclosed delimiter
+//~v ERROR this file contains an unclosed delimiter
#[i=i::<ښܖ<
diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs
index 560475b..4522790 100644
--- a/tests/ui/parser/issues/issue-84148-2.rs
+++ b/tests/ui/parser/issues/issue-84148-2.rs
@@ -1,2 +1,2 @@
-//@ error-pattern: this file contains an unclosed delimiter
+//~v ERROR this file contains an unclosed delimiter
fn f(t:for<>t?
diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs
index ecc5048..0dd1843 100644
--- a/tests/ui/parser/issues/issue-88770.rs
+++ b/tests/ui/parser/issues/issue-88770.rs
@@ -1,7 +1,6 @@
// Regression test for the ICE described in #88770.
-//@ error-pattern:this file contains an unclosed delimiter
-
+//~vvvv ERROR this file contains an unclosed delimiter
fn m(){print!("",(c for&g
u
e
diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr
index 5b54072..137cfea 100644
--- a/tests/ui/parser/issues/issue-88770.stderr
+++ b/tests/ui/parser/issues/issue-88770.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-88770.rs:8:3
+ --> $DIR/issue-88770.rs:7:3
|
LL | fn m(){print!("",(c for&g
| - - - unclosed delimiter
diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs
index 9c57b0e..8519193 100644
--- a/tests/ui/parser/mbe_missing_right_paren.rs
+++ b/tests/ui/parser/mbe_missing_right_paren.rs
@@ -1,3 +1,3 @@
// ignore-tidy-trailing-newlines
-//@ error-pattern: this file contains an unclosed delimiter
+//~v ERROR this file contains an unclosed delimiter
macro_rules! abc(ؼ
\ No newline at end of file
diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs
index bbf4519..311a16c 100644
--- a/tests/ui/parser/missing_right_paren.rs
+++ b/tests/ui/parser/missing_right_paren.rs
@@ -1,4 +1,3 @@
// ignore-tidy-trailing-newlines
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: aborting due to 1 previous error
+//~v ERROR this file contains an unclosed delimiter
fn main((ؼ
\ No newline at end of file
diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr
index 4815f04..97ccb40 100644
--- a/tests/ui/parser/missing_right_paren.stderr
+++ b/tests/ui/parser/missing_right_paren.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/missing_right_paren.rs:4:11
+ --> $DIR/missing_right_paren.rs:3:11
|
LL | fn main((ؼ
| -- ^
diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr
index dcc1945..69bc510 100644
--- a/tests/ui/parser/recover/recover-pat-exprs.stderr
+++ b/tests/ui/parser/recover/recover-pat-exprs.stderr
@@ -17,10 +17,6 @@
LL | x => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.y } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:6:9
@@ -42,10 +38,6 @@
LL | x.y => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.0 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:7:9
@@ -68,10 +60,6 @@
LL | x.0 => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x._0 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:8:9
@@ -94,10 +82,6 @@
LL | x._0 => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.0.1 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:9:9
@@ -120,10 +104,6 @@
LL | x.0.1 => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.4.y.17.__z } => (),
- | +++++++ +
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
--> $DIR/recover-pat-exprs.rs:12:12
@@ -173,10 +153,6 @@
LL ~ match 0 {
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x[0] } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:24:9
@@ -197,10 +173,6 @@
LL | x[0] => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x[..] } => (),
- | +++++++ +
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
--> $DIR/recover-pat-exprs.rs:27:12
@@ -247,10 +219,6 @@
LL ~ match 0 {
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.f() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:38:9
@@ -271,10 +239,6 @@
LL | x.f() => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x._f() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:39:9
@@ -296,10 +260,6 @@
LL | x._f() => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x? } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:40:9
@@ -322,10 +282,6 @@
LL | x? => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { ().f() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:41:9
@@ -348,10 +304,6 @@
LL | ().f() => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { (0, x)?.f() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:42:9
@@ -374,10 +326,6 @@
LL | (0, x)?.f() => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.f().g() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:43:9
@@ -400,10 +348,6 @@
LL | x.f().g() => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { 0.f()?.g()?? } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:50:9
@@ -423,10 +367,6 @@
LL ~ match 0 {
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x as usize } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:51:9
@@ -447,10 +387,6 @@
LL | x as usize => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { 0 as usize } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:52:9
@@ -472,10 +408,6 @@
LL | 0 as usize => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.f().0.4 as f32 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:59:9
@@ -495,10 +427,6 @@
LL ~ match 0 {
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { 1 + 1 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:60:9
@@ -519,10 +447,6 @@
LL | 1 + 1 => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { (1 + 2) * 3 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:63:9
@@ -545,10 +469,6 @@
LL |
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.0 > 2 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:64:9
@@ -571,10 +491,6 @@
LL | x.0 > 2 => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { x.0 == 2 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:69:13
@@ -594,10 +510,6 @@
LL ~ match (0, 0) {
LL ~ (x, VAL) if x != 0 => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | (x, const { y.0 > 2 }) if x != 0 => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:70:13
@@ -618,10 +530,6 @@
LL | (x, y.0 > 2) if x != 0 => (),
LL ~ (x, VAL) if x != 0 || x != 1 => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | (x, const { y.0 > 2 }) if x != 0 || x != 1 => (),
- | +++++++ +
error: left-hand side of `@` must be a binding
--> $DIR/recover-pat-exprs.rs:83:9
@@ -658,10 +566,6 @@
LL ~ match u8::MAX {
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { u8::MAX.abs() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:86:17
@@ -684,10 +588,6 @@
LL |
LL ~ z @ w @ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | z @ w @ const { v.u() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:88:9
@@ -710,10 +610,6 @@
LL |
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { y.ilog(3) } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:90:9
@@ -736,10 +632,6 @@
LL |
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { n + 1 } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:92:10
@@ -762,10 +654,6 @@
LL |
LL ~ (VAL) => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | (const { "".f() + 14 * 8 }) => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:95:9
@@ -788,10 +676,6 @@
LL | 0 | ((1) | 2) | 3 => (),
LL ~ VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { f?() } => (),
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:101:9
diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr
index 0c65b16..ec7fcda 100644
--- a/tests/ui/parser/recover/recover-pat-issues.stderr
+++ b/tests/ui/parser/recover/recover-pat-issues.stderr
@@ -16,10 +16,6 @@
LL ~ match foo {
LL ~ Foo(VAL) => true,
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | Foo(const { "hi".to_owned() }) => true,
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-issues.rs:14:20
@@ -39,10 +35,6 @@
LL ~ match bar {
LL ~ Bar { baz: BAZ } => true,
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | Bar { baz: const { "hi".to_owned() } } => true,
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-issues.rs:25:11
@@ -62,10 +54,6 @@
LL ~ match foo.as_slice() {
LL ~ &[VAL] => {}
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | &[const { "foo".to_string() }] => {}
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-issues.rs:36:17
@@ -79,10 +67,6 @@
LL + const VAL: /* Type */ = MAGIC.0 as usize;
LL ~ if let Some(VAL) = None::<usize> {}
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | if let Some(const { MAGIC.0 as usize }) = None::<usize> {}
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-issues.rs:41:13
@@ -96,10 +80,6 @@
LL + const VAL: /* Type */ = -1.some(4);
LL ~ if let (VAL) = (0, Some(4)) {}
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | if let (const { -1.some(4) }) = (0, Some(4)) {}
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-issues.rs:44:13
@@ -113,10 +93,6 @@
LL + const VAL: /* Type */ = -1.Some(4);
LL ~ if let (VAL) = (0, Some(4)) {}
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | if let (const { -1.Some(4) }) = (0, Some(4)) {}
- | +++++++ +
error: aborting due to 6 previous errors
diff --git a/tests/ui/parser/recover/recover-pat-lets.stderr b/tests/ui/parser/recover/recover-pat-lets.stderr
index 5525272..ab79e4e 100644
--- a/tests/ui/parser/recover/recover-pat-lets.stderr
+++ b/tests/ui/parser/recover/recover-pat-lets.stderr
@@ -34,10 +34,6 @@
LL + const VAL: /* Type */ = 1 + 1;
LL ~ let Some(VAL) = x else {
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | let Some(const { 1 + 1 }) = x else {
- | +++++++ +
error: expected a pattern, found an expression
--> $DIR/recover-pat-lets.rs:17:17
@@ -51,10 +47,6 @@
LL + const VAL: /* Type */ = 1 + 1;
LL ~ if let Some(VAL) = x {
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | if let Some(const { 1 + 1 }) = x {
- | +++++++ +
error: aborting due to 5 previous errors
diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr
index e8f3235..6c17182 100644
--- a/tests/ui/parser/recover/recover-pat-ranges.stderr
+++ b/tests/ui/parser/recover/recover-pat-ranges.stderr
@@ -98,10 +98,6 @@
LL |
LL ~ ..=VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | ..=const { 1 + 2 } => (),
- | +++++++ +
error: expected a pattern range bound, found an expression
--> $DIR/recover-pat-ranges.rs:15:10
@@ -119,10 +115,6 @@
LL |
LL ~ (VAL).. => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | (const { -4 + 0 }).. => (),
- | +++++++ +
error: expected a pattern range bound, found an expression
--> $DIR/recover-pat-ranges.rs:18:10
@@ -140,10 +132,6 @@
LL |
LL ~ (VAL)...1 * 2 => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | (const { 1 + 4 })...1 * 2 => (),
- | +++++++ +
error: expected a pattern range bound, found an expression
--> $DIR/recover-pat-ranges.rs:18:19
@@ -161,10 +149,6 @@
LL |
LL ~ (1 + 4)...VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | (1 + 4)...const { 1 * 2 } => (),
- | +++++++ +
error: expected a pattern range bound, found an expression
--> $DIR/recover-pat-ranges.rs:24:9
@@ -182,10 +166,6 @@
LL |
LL ~ VAL..="y".z() => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | const { 0.x() }..="y".z() => (),
- | +++++++ +
error: expected a pattern range bound, found an expression
--> $DIR/recover-pat-ranges.rs:24:17
@@ -203,10 +183,6 @@
LL |
LL ~ 0.x()..=VAL => (),
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | 0.x()..=const { "y".z() } => (),
- | +++++++ +
warning: `...` range patterns are deprecated
--> $DIR/recover-pat-ranges.rs:18:16
diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr
index f939e51..ebc1cbf 100644
--- a/tests/ui/parser/recover/recover-pat-wildcards.stderr
+++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr
@@ -84,10 +84,6 @@
LL ~ match 9 {
LL ~ 4..=(VAL) => ()
|
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
- |
-LL | 4..=(const { 2 + _ }) => ()
- | +++++++ +
error: aborting due to 11 previous errors
diff --git a/tests/ui/parser/unbalanced-doublequote.rs b/tests/ui/parser/unbalanced-doublequote.rs
index d9c9361..43e23a7 100644
--- a/tests/ui/parser/unbalanced-doublequote.rs
+++ b/tests/ui/parser/unbalanced-doublequote.rs
@@ -1,6 +1,4 @@
-//@ error-pattern: unterminated double quote string
-
-
+//~vv ERROR unterminated double quote string
fn main() {
"
}
diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr
index d40b982..60057edd 100644
--- a/tests/ui/parser/unbalanced-doublequote.stderr
+++ b/tests/ui/parser/unbalanced-doublequote.stderr
@@ -1,5 +1,5 @@
error[E0765]: unterminated double quote string
- --> $DIR/unbalanced-doublequote.rs:5:5
+ --> $DIR/unbalanced-doublequote.rs:3:5
|
LL | / "
LL | | }
diff --git a/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs
index 6679651..aa52fe9 100644
--- a/tests/ui/parser/use-unclosed-brace.rs
+++ b/tests/ui/parser/use-unclosed-brace.rs
@@ -1,4 +1,3 @@
-//@ error-pattern: this file contains an unclosed delimiter
use foo::{bar, baz;
use std::fmt::Display;
@@ -7,4 +6,5 @@ mod bar { }
mod baz { }
+//~v ERROR this file contains an unclosed delimiter
fn main() {}
diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs
index dde44df..5869767 100644
--- a/tests/ui/pattern/non-structural-match-types.rs
+++ b/tests/ui/pattern/non-structural-match-types.rs
@@ -1,14 +1,29 @@
//@ edition:2021
-
-#![allow(unreachable_code)]
#![feature(const_async_blocks)]
-#![feature(inline_const_pat)]
-fn main() {
- match loop {} {
- const { || {} } => {} //~ ERROR cannot be used in patterns
+struct AnyOption<T>(T);
+impl<T> AnyOption<T> {
+ const NONE: Option<T> = None;
+}
+
+fn uwu() {}
+fn defines() {
+ match Some(uwu) {
+ AnyOption::<_>::NONE => {}
+ //~^ ERROR constant of non-structural type
+ _ => {}
}
- match loop {} {
- const { async {} } => {} //~ ERROR cannot be used in patterns
+
+ match Some(|| {}) {
+ AnyOption::<_>::NONE => {}
+ //~^ ERROR constant of non-structural type
+ _ => {}
+ }
+
+ match Some(async {}) {
+ AnyOption::<_>::NONE => {}
+ //~^ ERROR constant of non-structural type
+ _ => {}
}
}
+fn main() {}
diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr
index 3588751..da675a9 100644
--- a/tests/ui/pattern/non-structural-match-types.stderr
+++ b/tests/ui/pattern/non-structural-match-types.stderr
@@ -1,14 +1,42 @@
-error: closure `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns
- --> $DIR/non-structural-match-types.rs:9:9
- |
-LL | const { || {} } => {}
- | ^^^^^^^^^^^^^^^ closure can't be used in patterns
-
-error: `async` block `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns
+error: constant of non-structural type `Option<fn() {uwu}>` in a pattern
--> $DIR/non-structural-match-types.rs:12:9
|
-LL | const { async {} } => {}
- | ^^^^^^^^^^^^^^^^^^ `async` block can't be used in patterns
+LL | impl<T> AnyOption<T> {
+ | --------------------
+LL | const NONE: Option<T> = None;
+ | --------------------- constant defined here
+...
+LL | AnyOption::<_>::NONE => {}
+ | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
+ |
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-error: aborting due to 2 previous errors
+error: constant of non-structural type `Option<{closure@$DIR/non-structural-match-types.rs:17:16: 17:18}>` in a pattern
+ --> $DIR/non-structural-match-types.rs:18:9
+ |
+LL | impl<T> AnyOption<T> {
+ | --------------------
+LL | const NONE: Option<T> = None;
+ | --------------------- constant defined here
+...
+LL | AnyOption::<_>::NONE => {}
+ | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
+ |
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+
+error: constant of non-structural type `Option<{async block@$DIR/non-structural-match-types.rs:23:16: 23:21}>` in a pattern
+ --> $DIR/non-structural-match-types.rs:24:9
+ |
+LL | impl<T> AnyOption<T> {
+ | --------------------
+LL | const NONE: Option<T> = None;
+ | --------------------- constant defined here
+...
+LL | AnyOption::<_>::NONE => {}
+ | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
+ |
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+ = note: `ResumeTy` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+
+error: aborting due to 3 previous errors
diff --git a/tests/ui/pin-macro/pin_move.rs b/tests/ui/pin-macro/pin_move.rs
new file mode 100644
index 0000000..0f6d34f
--- /dev/null
+++ b/tests/ui/pin-macro/pin_move.rs
@@ -0,0 +1,26 @@
+//@ edition:2024
+
+use core::marker::PhantomPinned;
+use core::pin::pin;
+
+fn a() {
+ struct NotCopy<T>(T);
+ #[allow(unused_mut)]
+ let mut pointee = NotCopy(PhantomPinned);
+ pin!(pointee);
+ let _moved = pointee;
+ //~^ ERROR use of moved value
+}
+
+fn b() {
+ struct NotCopy<T>(T);
+ let mut pointee = NotCopy(PhantomPinned);
+ pin!(*&mut pointee);
+ //~^ ERROR cannot move
+ let _moved = pointee;
+}
+
+fn main() {
+ a();
+ b();
+}
diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr
new file mode 100644
index 0000000..c9b8ad9
--- /dev/null
+++ b/tests/ui/pin-macro/pin_move.stderr
@@ -0,0 +1,38 @@
+error[E0382]: use of moved value: `pointee`
+ --> $DIR/pin_move.rs:11:18
+ |
+LL | let mut pointee = NotCopy(PhantomPinned);
+ | ----------- move occurs because `pointee` has type `a::NotCopy<PhantomPinned>`, which does not implement the `Copy` trait
+LL | pin!(pointee);
+ | ------- value moved here
+LL | let _moved = pointee;
+ | ^^^^^^^ value used here after move
+ |
+note: if `a::NotCopy<PhantomPinned>` implemented `Clone`, you could clone the value
+ --> $DIR/pin_move.rs:7:5
+ |
+LL | struct NotCopy<T>(T);
+ | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL | pin!(pointee);
+ | ------- you could clone this value
+
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/pin_move.rs:18:10
+ |
+LL | pin!(*&mut pointee);
+ | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy<PhantomPinned>`, which does not implement the `Copy` trait
+ |
+note: if `b::NotCopy<PhantomPinned>` implemented `Clone`, you could clone the value
+ --> $DIR/pin_move.rs:16:5
+ |
+LL | struct NotCopy<T>(T);
+ | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+LL | let mut pointee = NotCopy(PhantomPinned);
+LL | pin!(*&mut pointee);
+ | ------------- you could clone this value
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0382, E0507.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs
index 81018e4..eacaa63 100644
--- a/tests/ui/precondition-checks/copy-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires
//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
+#![allow(invalid_null_arguments)]
+
use std::ptr;
fn main() {
diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs
index 694853f..1fadd90 100644
--- a/tests/ui/precondition-checks/copy.rs
+++ b/tests/ui/precondition-checks/copy.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: ptr::copy requires
//@ revisions: null_src null_dst misaligned_src misaligned_dst
+#![allow(invalid_null_arguments)]
+
use std::ptr;
fn main() {
diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs
index e14881d..ada8932 100644
--- a/tests/ui/precondition-checks/read_volatile.rs
+++ b/tests/ui/precondition-checks/read_volatile.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
//@ revisions: null misaligned
+#![allow(invalid_null_arguments)]
+
use std::ptr;
fn main() {
diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs
index 2808cee..44afbd8 100644
--- a/tests/ui/precondition-checks/replace.rs
+++ b/tests/ui/precondition-checks/replace.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: ptr::replace requires
//@ revisions: null misaligned
+#![allow(invalid_null_arguments)]
+
use std::ptr;
fn main() {
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
index 3801639..9b9ded6 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires
//@ revisions: null misaligned toolarge
+#![allow(invalid_null_arguments)]
+
fn main() {
unsafe {
#[cfg(null)]
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs
index a3690fa..96578c1 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires
//@ revisions: null misaligned toolarge
+#![allow(invalid_null_arguments)]
+
fn main() {
unsafe {
#[cfg(null)]
diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs
index 52e4a3c..ea1f6f3 100644
--- a/tests/ui/precondition-checks/swap-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires
//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
+#![allow(invalid_null_arguments)]
+
use std::ptr;
fn main() {
diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs
index ac0b89b..0d5ecb0 100644
--- a/tests/ui/precondition-checks/write_volatile.rs
+++ b/tests/ui/precondition-checks/write_volatile.rs
@@ -3,6 +3,8 @@
//@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
//@ revisions: null misaligned
+#![allow(invalid_null_arguments)]
+
use std::ptr;
fn main() {
diff --git a/tests/ui/precondition-checks/zero-size-null.rs b/tests/ui/precondition-checks/zero-size-null.rs
index 43a8117..55d768f 100644
--- a/tests/ui/precondition-checks/zero-size-null.rs
+++ b/tests/ui/precondition-checks/zero-size-null.rs
@@ -7,8 +7,10 @@
fn main() {
unsafe {
+ #[expect(invalid_null_arguments)] // false-positive, copy of 0
ptr::copy_nonoverlapping::<u8>(ptr::null(), ptr::null_mut(), 0);
ptr::copy_nonoverlapping::<()>(ptr::null(), ptr::null_mut(), 123);
+ #[expect(invalid_null_arguments)] // false-positive, copy of 0
ptr::copy::<u8>(ptr::null(), ptr::null_mut(), 0);
ptr::copy::<()>(ptr::null(), ptr::null_mut(), 123);
ptr::swap::<()>(ptr::null_mut(), ptr::null_mut());
diff --git a/tests/ui/privacy/privacy-ns1.stderr b/tests/ui/privacy/privacy-ns1.stderr
index 3396330..c782c67 100644
--- a/tests/ui/privacy/privacy-ns1.stderr
+++ b/tests/ui/privacy/privacy-ns1.stderr
@@ -7,6 +7,14 @@
LL | Bar();
| ^^^
|
+note: these functions exist but are inaccessible
+ --> $DIR/privacy-ns1.rs:14:5
+ |
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo3::Bar`: not accessible
help: a unit struct with a similar name exists
|
LL - Bar();
@@ -26,6 +34,14 @@
LL | Bar();
| ^^^
|
+note: these functions exist but are inaccessible
+ --> $DIR/privacy-ns1.rs:14:5
+ |
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo3::Bar`: not accessible
help: a unit struct with a similar name exists
|
LL - Bar();
@@ -45,6 +61,14 @@
LL | let _x: Box<Bar>;
| ^^^
|
+note: these traits exist but are inaccessible
+ --> $DIR/privacy-ns1.rs:25:5
+ |
+LL | trait Bar {
+ | ^^^^^^^^^ `foo2::Bar`: not accessible
+...
+LL | trait Bar {
+ | ^^^^^^^^^ `foo3::Bar`: not accessible
help: a struct with a similar name exists
|
LL - let _x: Box<Bar>;
diff --git a/tests/ui/privacy/privacy-ns2.stderr b/tests/ui/privacy/privacy-ns2.stderr
index ac98682..fe1f0c9 100644
--- a/tests/ui/privacy/privacy-ns2.stderr
+++ b/tests/ui/privacy/privacy-ns2.stderr
@@ -4,6 +4,14 @@
LL | Bar();
| ^^^ not a function, tuple struct or tuple variant
|
+note: these functions exist but are inaccessible
+ --> $DIR/privacy-ns2.rs:14:5
+ |
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo3::Bar`: not accessible
help: consider importing this function instead
|
LL + use foo2::Bar;
@@ -18,6 +26,14 @@
LL | Bar();
| ^^^
|
+note: these functions exist but are inaccessible
+ --> $DIR/privacy-ns2.rs:14:5
+ |
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL | fn Bar() { }
+ | ^^^^^^^^ `foo3::Bar`: not accessible
help: a unit struct with a similar name exists
|
LL - Bar();
@@ -34,6 +50,14 @@
LL | let _x : Bar();
| ^^^^^ not a type
|
+note: these traits exist but are inaccessible
+ --> $DIR/privacy-ns2.rs:31:5
+ |
+LL | trait Bar {
+ | ^^^^^^^^^ `foo2::Bar`: not accessible
+...
+LL | trait Bar {
+ | ^^^^^^^^^ `foo3::Bar`: not accessible
help: use `=` if you meant to assign
|
LL - let _x : Bar();
diff --git a/tests/ui/proc-macro/cfg-attr-trace.rs b/tests/ui/proc-macro/cfg-attr-trace.rs
index b4927f7..140dd10 100644
--- a/tests/ui/proc-macro/cfg-attr-trace.rs
+++ b/tests/ui/proc-macro/cfg-attr-trace.rs
@@ -3,6 +3,7 @@
//@ check-pass
//@ proc-macro: test-macros.rs
+#![feature(cfg_boolean_literals)]
#![feature(cfg_eval)]
#[macro_use]
@@ -10,8 +11,13 @@
#[cfg_eval]
#[test_macros::print_attr]
-#[cfg_attr(FALSE, test_macros::print_attr)]
-#[cfg_attr(all(), test_macros::print_attr)]
+#[cfg_attr(false, test_macros::print_attr)]
+#[cfg_attr(true, test_macros::print_attr)]
struct S;
+#[cfg_eval]
+#[test_macros::print_attr]
+#[cfg(true)]
+struct Z;
+
fn main() {}
diff --git a/tests/ui/proc-macro/cfg-attr-trace.stdout b/tests/ui/proc-macro/cfg-attr-trace.stdout
index 394c388..52f9ff4 100644
--- a/tests/ui/proc-macro/cfg-attr-trace.stdout
+++ b/tests/ui/proc-macro/cfg-attr-trace.stdout
@@ -4,59 +4,75 @@
Punct {
ch: '#',
spacing: Alone,
- span: #0 bytes(271..272),
+ span: #0 bytes(305..306),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "test_macros",
- span: #0 bytes(289..300),
+ span: #0 bytes(322..333),
},
Punct {
ch: ':',
spacing: Joint,
- span: #0 bytes(300..301),
+ span: #0 bytes(333..334),
},
Punct {
ch: ':',
spacing: Alone,
- span: #0 bytes(301..302),
+ span: #0 bytes(334..335),
},
Ident {
ident: "print_attr",
- span: #0 bytes(302..312),
+ span: #0 bytes(335..345),
},
],
- span: #0 bytes(272..314),
+ span: #0 bytes(306..347),
},
Ident {
ident: "struct",
- span: #0 bytes(315..321),
+ span: #0 bytes(348..354),
},
Ident {
ident: "S",
- span: #0 bytes(322..323),
+ span: #0 bytes(355..356),
},
Punct {
ch: ';',
spacing: Alone,
- span: #0 bytes(323..324),
+ span: #0 bytes(356..357),
},
]
PRINT-ATTR INPUT (DISPLAY): struct S;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
- span: #0 bytes(315..321),
+ span: #0 bytes(348..354),
},
Ident {
ident: "S",
- span: #0 bytes(322..323),
+ span: #0 bytes(355..356),
},
Punct {
ch: ';',
spacing: Alone,
- span: #0 bytes(323..324),
+ span: #0 bytes(356..357),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct Z;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: #0 bytes(411..417),
+ },
+ Ident {
+ ident: "Z",
+ span: #0 bytes(418..419),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #0 bytes(419..420),
},
]
diff --git a/tests/ui/proc-macro/no-macro-use-attr.rs b/tests/ui/proc-macro/no-macro-use-attr.rs
index d44f51b..2520037 100644
--- a/tests/ui/proc-macro/no-macro-use-attr.rs
+++ b/tests/ui/proc-macro/no-macro-use-attr.rs
@@ -1,10 +1,9 @@
+//@ check-pass
//@ proc-macro: test-macros.rs
-#![feature(rustc_attrs)]
#![warn(unused_extern_crates)]
extern crate test_macros;
//~^ WARN unused extern crate
-#[rustc_error]
-fn main() {} //~ ERROR fatal error triggered by #[rustc_error]
+fn main() {}
diff --git a/tests/ui/proc-macro/no-macro-use-attr.stderr b/tests/ui/proc-macro/no-macro-use-attr.stderr
index 3dda3cc..49136724 100644
--- a/tests/ui/proc-macro/no-macro-use-attr.stderr
+++ b/tests/ui/proc-macro/no-macro-use-attr.stderr
@@ -10,11 +10,5 @@
LL | #![warn(unused_extern_crates)]
| ^^^^^^^^^^^^^^^^^^^^
-error: fatal error triggered by #[rustc_error]
- --> $DIR/no-macro-use-attr.rs:10:1
- |
-LL | fn main() {}
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error; 1 warning emitted
+warning: 1 warning emitted
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
index c80a332..6fd6cb4 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -5,19 +5,19 @@
stream: TokenStream [
Ident {
ident: "struct",
- span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4),
+ span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5),
},
Ident {
ident: "S",
- span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4),
+ span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4),
+ span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5),
},
],
- span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5),
+ span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4),
},
]
#![feature /* 0#0 */(prelude_import)]
@@ -59,7 +59,7 @@
struct S /* 0#0 */;
macro inner /* 0#3 */ { () => { print_bang! { struct S; } } }
-struct S /* 0#4 */;
+struct S /* 0#5 */;
// OK, not a duplicate definition of `S`
fn main /* 0#0 */() {}
@@ -70,7 +70,7 @@
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner")
-crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
+crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
@@ -83,9 +83,9 @@
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
-#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
-#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
+#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
+#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
#6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
-#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
-#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent)
+#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent)
+#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
*/
diff --git a/tests/ui/resolve/auxiliary/macro_helpers.rs b/tests/ui/resolve/auxiliary/macro_helpers.rs
new file mode 100644
index 0000000..43aa336
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/macro_helpers.rs
@@ -0,0 +1,16 @@
+/* macro namespace. */
+
+extern crate proc_macro;
+use proc_macro::*;
+use std::str::FromStr;
+
+const ERROR: &str = "fn helper() { \"helper\" }";
+// https://doc.rust-lang.org/nightly/std/prelude/v1/index.html#attributes
+// NOTE: all the bang macros in std are currently unstable.
+#[proc_macro_attribute] pub fn test // lang.
+ (_: TokenStream, _: TokenStream) -> TokenStream {
+ TokenStream::from_str("fn test_macro() { \"\" }").unwrap() }
+// https://doc.rust-lang.org/nightly/reference/attributes.html#built-in-attributes-index
+#[proc_macro_attribute] pub fn global_allocator // lang.
+ (_: TokenStream, _: TokenStream) -> TokenStream {
+ TokenStream::from_str("fn global_allocator_macro() { \"\" }").unwrap() }
diff --git a/tests/ui/resolve/issue-21221-1.stderr b/tests/ui/resolve/issue-21221-1.stderr
index ccf03af..dafa41b 100644
--- a/tests/ui/resolve/issue-21221-1.stderr
+++ b/tests/ui/resolve/issue-21221-1.stderr
@@ -19,6 +19,17 @@
LL | fn getMul() -> Mul {
| ^^^ not found in this scope
|
+note: these items exist but are inaccessible
+ --> $DIR/issue-21221-1.rs:10:5
+ |
+LL | enum Mul {
+ | ^^^^^^^^ `mul3::Mul`: not accessible
+...
+LL | type Mul = String;
+ | ^^^^^^^^^^^^^^^^^^ `mul4::Mul`: not accessible
+...
+LL | struct Mul{
+ | ^^^^^^^^^^ `mul5::Mul`: not accessible
help: consider importing one of these traits
|
LL + use std::ops::Mul;
diff --git a/tests/ui/resolve/prelude-order.rs b/tests/ui/resolve/prelude-order.rs
new file mode 100644
index 0000000..a3f1942
--- /dev/null
+++ b/tests/ui/resolve/prelude-order.rs
@@ -0,0 +1,89 @@
+//@ proc-macro:macro_helpers.rs
+//@ compile-flags: --crate-type=lib
+
+/* There are 5 preludes and 3 namespaces. Test the order in which they are resolved.
+ * See https://doc.rust-lang.org/nightly/reference/names/preludes.html.
+ *
+ * Macros cannot be in the type or value namespace.
+ * Tools and extern crates cannot be in the macro or value namespace.
+ *
+ * Test the following truth tables:
+
+Type:
+| ...... | tool | extern | macro | lang | libs |
+| tool | N/A | mirror
+| extern | extern | N/A | universe
+| macro | N/A | N/A | N/A |
+| lang | tool | extern | N/A | N/A |
+| libs | tool | extern | N/A | X | N/A |
+
+Macro:
+| ...... | tool | extern | macro | lang | libs |
+| tool | N/A | mirror
+| extern | N/A | N/A | universe
+| macro | N/A | N/A | N/A |
+| lang | N/A | N/A | macro | N/A |
+| libs | N/A | N/A | macro | X | N/A |
+
+Value: N/A. Only libs has items in the value namespace.
+
+† ambiguous
+X don't care (controlled namespace with no overlap)
+
+* Types are tested with `#[name::inner]`. Macros are tested with `#[name]`.
+* WARNING: I have found in testing that attribute macros give ambiguity errors in some contexts
+* instead of choosing a prelude. Have not been able to replicate.
+*
+* There should be 7 total tests.
+* See `rustc_resolve::ident::visit_scopes` for more information,
+* and for a definition of "controlled namespace".
+*/
+
+#![feature(register_tool)]
+
+/* tool prelude */
+#![register_tool(type_ns)] // extern prelude. type.
+#![register_tool(i8)] // lang prelude. type.
+#![register_tool(Sync)] // libs prelude. type.
+
+/* extern prelude */
+extern crate macro_helpers as type_ns; // tool prelude. type.
+extern crate macro_helpers as usize; // lang prelude. type.
+extern crate macro_helpers as Option; // libs prelude. type.
+
+/* macro_use prelude */
+#[macro_use]
+extern crate macro_helpers as _;
+
+/* lang and libs implicitly in scope */
+
+// tool/extern -> extern
+#[type_ns::inner] //~ ERROR could not find `inner` in `type_ns`
+fn t1() {}
+
+// tool/lang -> tool
+#[i8::inner] // ok
+fn t2() {}
+
+// tool/libs -> tool
+#[Sync::not_real] // ok
+fn t3() {}
+
+// extern/lang -> extern
+#[usize::inner] //~ ERROR could not find `inner` in `usize`
+fn e1() {} // NOTE: testing with `-> usize` isn't valid, crates aren't considered in that scope
+ // (unless they have generic arguments, for some reason.)
+
+// extern/libs -> extern
+// https://github.com/rust-lang/rust/issues/139095
+fn e2() -> Option<i32> { None } //~ ERROR: expected type, found crate
+
+// macro/libs -> macro
+#[test] //~ ERROR mismatched types
+fn m1() {}
+
+// macro/lang -> macro
+#[global_allocator] //~ ERROR mismatched types
+fn m2() {}
+
+// lang/libs: no items that currently overlap, in either macro or type ns.
diff --git a/tests/ui/resolve/prelude-order.stderr b/tests/ui/resolve/prelude-order.stderr
new file mode 100644
index 0000000..1b9cc94
--- /dev/null
+++ b/tests/ui/resolve/prelude-order.stderr
@@ -0,0 +1,47 @@
+error[E0433]: failed to resolve: could not find `inner` in `type_ns`
+ --> $DIR/prelude-order.rs:61:12
+ |
+LL | #[type_ns::inner]
+ | ^^^^^ could not find `inner` in `type_ns`
+
+error[E0433]: failed to resolve: could not find `inner` in `usize`
+ --> $DIR/prelude-order.rs:73:10
+ |
+LL | #[usize::inner]
+ | ^^^^^ could not find `inner` in `usize`
+
+error[E0573]: expected type, found crate `Option`
+ --> $DIR/prelude-order.rs:79:12
+ |
+LL | fn e2() -> Option<i32> { None }
+ | ^^^^^^^^^^^ not a type
+ |
+help: consider importing this enum instead
+ |
+LL + use std::option::Option;
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/prelude-order.rs:82:1
+ |
+LL | #[test]
+ | ^^^^^^^- help: try adding a return type: `-> &'static str`
+ | |
+ | expected `()`, found `&str`
+ |
+ = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> $DIR/prelude-order.rs:86:1
+ |
+LL | #[global_allocator]
+ | ^^^^^^^^^^^^^^^^^^^- help: try adding a return type: `-> &'static str`
+ | |
+ | expected `()`, found `&str`
+ |
+ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0433, E0573.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
index 0858434..c575626 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
@@ -1,5 +1,5 @@
error[E0658]: use of unstable library feature `structural_match`
- --> $DIR/feature-gate.rs:29:6
+ --> $DIR/feature-gate.rs:27:6
|
LL | impl std::marker::StructuralPartialEq for Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
index 711b07f..6940816 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
@@ -3,11 +3,10 @@
// used in a match.
//@ revisions: with_gate no_gate
-
+//@[with_gate] check-pass
// gate-test-structural_match
#![allow(unused)]
-#![feature(rustc_attrs)]
#![cfg_attr(with_gate, feature(structural_match))]
@@ -17,8 +16,7 @@ struct Foo {
const FOO: Foo = Foo { x: 0 };
-#[rustc_error]
-fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error]
+fn main() {
let y = Foo { x: 1 };
match y {
FOO => { }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
deleted file mode 100644
index 505b7d7..0000000
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/feature-gate.rs:21:1
- |
-LL | fn main() {
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rustc-error.rs b/tests/ui/rustc-error.rs
deleted file mode 100644
index 69d5794..0000000
--- a/tests/ui/rustc-error.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(rustc_attrs)]
-
-#[rustc_error]
-fn main() {
- //~^ ERROR fatal error triggered by #[rustc_error]
-}
diff --git a/tests/ui/rustc-error.stderr b/tests/ui/rustc-error.stderr
deleted file mode 100644
index 6745119..0000000
--- a/tests/ui/rustc-error.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/rustc-error.rs:4:1
- |
-LL | fn main() {
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs
new file mode 100644
index 0000000..2bc70de
--- /dev/null
+++ b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/rust/issues/138937>.
+
+// Previously, we'd take the normalized param env's clauses which included
+// `<PF as TraitC>::Value = i32`, which comes from the supertraits of `TraitD`
+// after normalizing `<PF as TraitC>::Value = <PF as TraitD>::Scalar`. Since
+// `normalize_param_env_or_error` ends up re-elaborating `PF: TraitD`, we'd
+// end up with both versions of this predicate (normalized and unnormalized).
+// Since these projections preds are not equal, we'd fail with ambiguity.
+
+trait TraitB<T> {}
+
+trait TraitC: TraitB<Self::Value> {
+ type Value;
+}
+
+trait TraitD: TraitC<Value = Self::Scalar> {
+ type Scalar;
+}
+
+trait TraitE {
+ fn apply<PF: TraitD<Scalar = i32>>(&self);
+}
+
+fn main() {}
diff --git a/tests/ui/simd/empty-simd-vector-in-operand.rs b/tests/ui/simd/empty-simd-vector-in-operand.rs
new file mode 100644
index 0000000..2a2a6c0
--- /dev/null
+++ b/tests/ui/simd/empty-simd-vector-in-operand.rs
@@ -0,0 +1,15 @@
+// Regression test for issue #134224.
+//@ only-x86_64
+
+#![feature(repr_simd)]
+
+#[repr(simd)]
+struct A();
+//~^ ERROR SIMD vector cannot be empty
+
+fn main() {
+ unsafe {
+ std::arch::asm!("{}", in(xmm_reg) A());
+ //~^ use of empty SIMD vector `A`
+ }
+}
diff --git a/tests/ui/simd/empty-simd-vector-in-operand.stderr b/tests/ui/simd/empty-simd-vector-in-operand.stderr
new file mode 100644
index 0000000..7210ddd
--- /dev/null
+++ b/tests/ui/simd/empty-simd-vector-in-operand.stderr
@@ -0,0 +1,15 @@
+error[E0075]: SIMD vector cannot be empty
+ --> $DIR/empty-simd-vector-in-operand.rs:7:1
+ |
+LL | struct A();
+ | ^^^^^^^^
+
+error: use of empty SIMD vector `A`
+ --> $DIR/empty-simd-vector-in-operand.rs:12:43
+ |
+LL | std::arch::asm!("{}", in(xmm_reg) A());
+ | ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0075`.
diff --git a/tests/ui/sized/dont-incompletely-prefer-built-in.rs b/tests/ui/sized/dont-incompletely-prefer-built-in.rs
new file mode 100644
index 0000000..f5bf0c8
--- /dev/null
+++ b/tests/ui/sized/dont-incompletely-prefer-built-in.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+struct W<T: ?Sized>(T);
+
+fn is_sized<T: Sized>(x: *const T) {}
+
+fn dummy<T: ?Sized>() -> *const T { todo!() }
+
+fn non_param_where_bound<T: ?Sized>()
+where
+ W<T>: Sized,
+{
+ let x: *const W<_> = dummy();
+ is_sized::<W<_>>(x);
+ let _: *const W<T> = x;
+}
+
+fn main() {}
diff --git a/tests/ui/span/range-2.rs b/tests/ui/span/range-2.rs
index c4bb16f..2e82521 100644
--- a/tests/ui/span/range-2.rs
+++ b/tests/ui/span/range-2.rs
@@ -1,6 +1,6 @@
// Test range syntax - borrow errors.
-#![feature(rustc_attrs)]
-pub fn main() { #![rustc_error] // rust-lang/rust#49855
+
+pub fn main() {
let r = {
let a = 42;
let b = 42;
diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs
index 60ccaa8..fe6c353 100644
--- a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs
+++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs
@@ -1,7 +1,6 @@
-#![feature(rustc_attrs)]
use std::ops::FnMut;
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
let mut f;
{
let c = 1;
diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
index 225f83b..bb62982 100644
--- a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
+++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
@@ -1,5 +1,5 @@
error[E0597]: `c` does not live long enough
- --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21
+ --> $DIR/regionck-unboxed-closure-lifetimes.rs:7:21
|
LL | let c = 1;
| - binding `c` declared here
diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout
index 21df1fd..12e7a55 100644
--- a/tests/ui/stable-mir-print/async-closure.stdout
+++ b/tests/ui/stable-mir-print/async-closure.stdout
@@ -56,7 +56,7 @@
unreachable;
}
}
-fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
+fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
let mut _0: Poll<()>;
let _3: i32;
let mut _4: &i32;
diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr
index dbc9e7d..24e3894 100644
--- a/tests/ui/stats/input-stats.stderr
+++ b/tests/ui/stats/input-stats.stderr
@@ -10,9 +10,9 @@
ast-stats-1 - Normal 32 ( 0.5%) 1
ast-stats-1 WherePredicate 72 ( 1.1%) 1 72
ast-stats-1 - BoundPredicate 72 ( 1.1%) 1
+ast-stats-1 ForeignItem 80 ( 1.2%) 1 80
+ast-stats-1 - Fn 80 ( 1.2%) 1
ast-stats-1 Local 80 ( 1.2%) 1 80
-ast-stats-1 ForeignItem 88 ( 1.3%) 1 88
-ast-stats-1 - Fn 88 ( 1.3%) 1
ast-stats-1 Arm 96 ( 1.4%) 2 48
ast-stats-1 FnDecl 120 ( 1.8%) 5 24
ast-stats-1 Param 160 ( 2.4%) 4 40
@@ -23,37 +23,37 @@
ast-stats-1 Block 192 ( 2.9%) 6 32
ast-stats-1 FieldDef 208 ( 3.1%) 2 104
ast-stats-1 Variant 208 ( 3.1%) 2 104
-ast-stats-1 AssocItem 352 ( 5.3%) 4 88
-ast-stats-1 - Fn 176 ( 2.6%) 2
-ast-stats-1 - Type 176 ( 2.6%) 2
-ast-stats-1 GenericBound 352 ( 5.3%) 4 88
-ast-stats-1 - Trait 352 ( 5.3%) 4
-ast-stats-1 GenericParam 480 ( 7.2%) 5 96
+ast-stats-1 AssocItem 320 ( 4.8%) 4 80
+ast-stats-1 - Fn 160 ( 2.4%) 2
+ast-stats-1 - Type 160 ( 2.4%) 2
+ast-stats-1 GenericBound 352 ( 5.2%) 4 88
+ast-stats-1 - Trait 352 ( 5.2%) 4
+ast-stats-1 GenericParam 480 ( 7.1%) 5 96
ast-stats-1 Pat 504 ( 7.5%) 7 72
ast-stats-1 - Struct 72 ( 1.1%) 1
ast-stats-1 - Wild 72 ( 1.1%) 1
-ast-stats-1 - Ident 360 ( 5.4%) 5
+ast-stats-1 - Ident 360 ( 5.3%) 5
ast-stats-1 Expr 576 ( 8.6%) 8 72
ast-stats-1 - Match 72 ( 1.1%) 1
ast-stats-1 - Path 72 ( 1.1%) 1
ast-stats-1 - Struct 72 ( 1.1%) 1
ast-stats-1 - Lit 144 ( 2.1%) 2
ast-stats-1 - Block 216 ( 3.2%) 3
-ast-stats-1 PathSegment 744 (11.1%) 31 24
-ast-stats-1 Ty 896 (13.4%) 14 64
+ast-stats-1 PathSegment 744 (11.0%) 31 24
+ast-stats-1 Ty 896 (13.3%) 14 64
ast-stats-1 - Ptr 64 ( 1.0%) 1
ast-stats-1 - Ref 64 ( 1.0%) 1
ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2
ast-stats-1 - Path 640 ( 9.5%) 10
-ast-stats-1 Item 1_224 (18.3%) 9 136
-ast-stats-1 - Enum 136 ( 2.0%) 1
-ast-stats-1 - ForeignMod 136 ( 2.0%) 1
-ast-stats-1 - Impl 136 ( 2.0%) 1
-ast-stats-1 - Trait 136 ( 2.0%) 1
-ast-stats-1 - Fn 272 ( 4.1%) 2
-ast-stats-1 - Use 408 ( 6.1%) 3
+ast-stats-1 Item 1_296 (19.2%) 9 144
+ast-stats-1 - Enum 144 ( 2.1%) 1
+ast-stats-1 - ForeignMod 144 ( 2.1%) 1
+ast-stats-1 - Impl 144 ( 2.1%) 1
+ast-stats-1 - Trait 144 ( 2.1%) 1
+ast-stats-1 - Fn 288 ( 4.3%) 2
+ast-stats-1 - Use 432 ( 6.4%) 3
ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total 6_704 116
+ast-stats-1 Total 6_736 116
ast-stats-1
ast-stats-2 POST EXPANSION AST STATS
ast-stats-2 Name Accumulated Size Count Item Size
@@ -61,12 +61,12 @@
ast-stats-2 Crate 40 ( 0.5%) 1 40
ast-stats-2 GenericArgs 40 ( 0.5%) 1 40
ast-stats-2 - AngleBracketed 40 ( 0.5%) 1
-ast-stats-2 ExprField 48 ( 0.7%) 1 48
+ast-stats-2 ExprField 48 ( 0.6%) 1 48
ast-stats-2 WherePredicate 72 ( 1.0%) 1 72
ast-stats-2 - BoundPredicate 72 ( 1.0%) 1
+ast-stats-2 ForeignItem 80 ( 1.1%) 1 80
+ast-stats-2 - Fn 80 ( 1.1%) 1
ast-stats-2 Local 80 ( 1.1%) 1 80
-ast-stats-2 ForeignItem 88 ( 1.2%) 1 88
-ast-stats-2 - Fn 88 ( 1.2%) 1
ast-stats-2 Arm 96 ( 1.3%) 2 48
ast-stats-2 FnDecl 120 ( 1.6%) 5 24
ast-stats-2 InlineAsm 120 ( 1.6%) 1 120
@@ -81,13 +81,13 @@
ast-stats-2 Block 192 ( 2.6%) 6 32
ast-stats-2 FieldDef 208 ( 2.8%) 2 104
ast-stats-2 Variant 208 ( 2.8%) 2 104
-ast-stats-2 AssocItem 352 ( 4.8%) 4 88
-ast-stats-2 - Fn 176 ( 2.4%) 2
-ast-stats-2 - Type 176 ( 2.4%) 2
+ast-stats-2 AssocItem 320 ( 4.3%) 4 80
+ast-stats-2 - Fn 160 ( 2.2%) 2
+ast-stats-2 - Type 160 ( 2.2%) 2
ast-stats-2 GenericBound 352 ( 4.8%) 4 88
ast-stats-2 - Trait 352 ( 4.8%) 4
ast-stats-2 GenericParam 480 ( 6.5%) 5 96
-ast-stats-2 Pat 504 ( 6.9%) 7 72
+ast-stats-2 Pat 504 ( 6.8%) 7 72
ast-stats-2 - Struct 72 ( 1.0%) 1
ast-stats-2 - Wild 72 ( 1.0%) 1
ast-stats-2 - Ident 360 ( 4.9%) 5
@@ -96,30 +96,30 @@
ast-stats-2 - Match 72 ( 1.0%) 1
ast-stats-2 - Path 72 ( 1.0%) 1
ast-stats-2 - Struct 72 ( 1.0%) 1
-ast-stats-2 - Lit 144 ( 2.0%) 2
+ast-stats-2 - Lit 144 ( 1.9%) 2
ast-stats-2 - Block 216 ( 2.9%) 3
-ast-stats-2 PathSegment 864 (11.8%) 36 24
-ast-stats-2 Ty 896 (12.2%) 14 64
+ast-stats-2 PathSegment 864 (11.7%) 36 24
+ast-stats-2 Ty 896 (12.1%) 14 64
ast-stats-2 - Ptr 64 ( 0.9%) 1
ast-stats-2 - Ref 64 ( 0.9%) 1
ast-stats-2 - ImplicitSelf 128 ( 1.7%) 2
-ast-stats-2 - Path 640 ( 8.7%) 10
-ast-stats-2 Item 1_496 (20.3%) 11 136
-ast-stats-2 - Enum 136 ( 1.8%) 1
-ast-stats-2 - ExternCrate 136 ( 1.8%) 1
-ast-stats-2 - ForeignMod 136 ( 1.8%) 1
-ast-stats-2 - Impl 136 ( 1.8%) 1
-ast-stats-2 - Trait 136 ( 1.8%) 1
-ast-stats-2 - Fn 272 ( 3.7%) 2
-ast-stats-2 - Use 544 ( 7.4%) 4
+ast-stats-2 - Path 640 ( 8.6%) 10
+ast-stats-2 Item 1_584 (21.4%) 11 144
+ast-stats-2 - Enum 144 ( 1.9%) 1
+ast-stats-2 - ExternCrate 144 ( 1.9%) 1
+ast-stats-2 - ForeignMod 144 ( 1.9%) 1
+ast-stats-2 - Impl 144 ( 1.9%) 1
+ast-stats-2 - Trait 144 ( 1.9%) 1
+ast-stats-2 - Fn 288 ( 3.9%) 2
+ast-stats-2 - Use 576 ( 7.8%) 4
ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total 7_352 127
+ast-stats-2 Total 7_400 127
ast-stats-2
hir-stats HIR STATS
hir-stats Name Accumulated Size Count Item Size
hir-stats ----------------------------------------------------------------
hir-stats ForeignItemRef 24 ( 0.3%) 1 24
-hir-stats Lifetime 24 ( 0.3%) 1 24
+hir-stats Lifetime 28 ( 0.3%) 1 28
hir-stats Mod 32 ( 0.4%) 1 32
hir-stats ExprField 40 ( 0.4%) 1 40
hir-stats TraitItemRef 56 ( 0.6%) 2 28
@@ -155,7 +155,7 @@
hir-stats Ty 720 ( 8.0%) 15 48
hir-stats - Ptr 48 ( 0.5%) 1
hir-stats - Ref 48 ( 0.5%) 1
-hir-stats - Path 624 ( 7.0%) 13
+hir-stats - Path 624 ( 6.9%) 13
hir-stats Expr 768 ( 8.6%) 12 64
hir-stats - InlineAsm 64 ( 0.7%) 1
hir-stats - Match 64 ( 0.7%) 1
@@ -174,5 +174,5 @@
hir-stats Path 1_240 (13.8%) 31 40
hir-stats PathSegment 1_920 (21.4%) 40 48
hir-stats ----------------------------------------------------------------
-hir-stats Total 8_976 180
+hir-stats Total 8_980 180
hir-stats
diff --git a/tests/ui/std/channel-stack-overflow-issue-102246.rs b/tests/ui/std/channel-stack-overflow-issue-102246.rs
index 984ebdd..7bf6647 100644
--- a/tests/ui/std/channel-stack-overflow-issue-102246.rs
+++ b/tests/ui/std/channel-stack-overflow-issue-102246.rs
@@ -10,9 +10,16 @@
// Ref: https://github.com/rust-lang/rust/issues/102246
use std::sync::mpsc::channel;
-use std::thread;
+use std::thread::Builder;
const N: usize = 32_768;
+const SLOTS: usize = 32;
+// Use a stack size that's smaller than N * SLOTS, proving the allocation is on the heap.
+//
+// The test explicitly specifies the stack size, because not all platforms have the same default
+// size.
+const STACK_SIZE: usize = (N*SLOTS) - 1;
+
struct BigStruct {
_data: [u8; N],
}
@@ -20,10 +27,13 @@ struct BigStruct {
fn main() {
let (sender, receiver) = channel::<BigStruct>();
- let thread1 = thread::spawn(move || {
+ let thread1 = Builder::new().stack_size(STACK_SIZE).spawn(move || {
sender.send(BigStruct { _data: [0u8; N] }).unwrap();
- });
-
+ }).expect("thread1 should spawn successfully");
thread1.join().unwrap();
- for _data in receiver.try_iter() {}
+
+ let thread2 = Builder::new().stack_size(STACK_SIZE).spawn(move || {
+ for _data in receiver.try_iter() {}
+ }).expect("thread2 should spawn successfully");
+ thread2.join().unwrap();
}
diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.rs b/tests/ui/structs/struct-construct-with-call-issue-138931.rs
new file mode 100644
index 0000000..5d50eb1
--- /dev/null
+++ b/tests/ui/structs/struct-construct-with-call-issue-138931.rs
@@ -0,0 +1,25 @@
+struct PersonOnlyName {
+ name: String
+}
+
+struct PersonWithAge {
+ name: String,
+ age: u8,
+ height: u8,
+}
+
+
+
+fn main() {
+ let wilfred = PersonOnlyName("Name1".to_owned());
+ //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonOnlyName` [E0423]
+
+ let bill = PersonWithAge( //~ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423]
+ "Name2".to_owned(),
+ 20,
+ 180,
+ );
+
+ let person = PersonWithAge("Name3".to_owned());
+ //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423]
+}
diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr
new file mode 100644
index 0000000..acae01d
--- /dev/null
+++ b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr
@@ -0,0 +1,58 @@
+error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonOnlyName`
+ --> $DIR/struct-construct-with-call-issue-138931.rs:14:19
+ |
+LL | / struct PersonOnlyName {
+LL | | name: String
+LL | | }
+ | |_- `PersonOnlyName` defined here
+...
+LL | let wilfred = PersonOnlyName("Name1".to_owned());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: use struct literal syntax instead of calling
+ |
+LL - let wilfred = PersonOnlyName("Name1".to_owned());
+LL + let wilfred = PersonOnlyName{name: "Name1".to_owned()};
+ |
+
+error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge`
+ --> $DIR/struct-construct-with-call-issue-138931.rs:17:16
+ |
+LL | / struct PersonWithAge {
+LL | | name: String,
+LL | | age: u8,
+LL | | height: u8,
+LL | | }
+ | |_- `PersonWithAge` defined here
+...
+LL | let bill = PersonWithAge(
+ | ________________^
+LL | | "Name2".to_owned(),
+LL | | 20,
+LL | | 180,
+LL | | );
+ | |_____^
+ |
+help: use struct literal syntax instead of calling
+ |
+LL ~ let bill = PersonWithAge{name: "Name2".to_owned(),
+LL ~ age: 20,
+LL ~ height: 180};
+ |
+
+error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge`
+ --> $DIR/struct-construct-with-call-issue-138931.rs:23:18
+ |
+LL | / struct PersonWithAge {
+LL | | name: String,
+LL | | age: u8,
+LL | | height: u8,
+LL | | }
+ | |_- `PersonWithAge` defined here
+...
+LL | let person = PersonWithAge("Name3".to_owned());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/suggestions/attribute-typos.rs b/tests/ui/suggestions/attribute-typos.rs
index 7c8231b..4c2336e 100644
--- a/tests/ui/suggestions/attribute-typos.rs
+++ b/tests/ui/suggestions/attribute-typos.rs
@@ -4,8 +4,8 @@ fn foo() {}
#[tests] //~ ERROR cannot find attribute `tests` in this scope
fn bar() {}
-#[rustc_err]
-//~^ ERROR cannot find attribute `rustc_err` in this scope
+#[rustc_dumm]
+//~^ ERROR cannot find attribute `rustc_dumm` in this scope
//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
fn main() {}
diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr
index b871c9b..a1a01c0 100644
--- a/tests/ui/suggestions/attribute-typos.stderr
+++ b/tests/ui/suggestions/attribute-typos.stderr
@@ -1,14 +1,14 @@
error: attributes starting with `rustc` are reserved for use by the `rustc` compiler
--> $DIR/attribute-typos.rs:7:3
|
-LL | #[rustc_err]
- | ^^^^^^^^^
+LL | #[rustc_dumm]
+ | ^^^^^^^^^^
-error: cannot find attribute `rustc_err` in this scope
+error: cannot find attribute `rustc_dumm` in this scope
--> $DIR/attribute-typos.rs:7:3
|
-LL | #[rustc_err]
- | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
+LL | #[rustc_dumm]
+ | ^^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_dummy`
error: cannot find attribute `tests` in this scope
--> $DIR/attribute-typos.rs:4:3
diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr
index dc8a530..05ae49d 100644
--- a/tests/ui/target-feature/invalid-attribute.stderr
+++ b/tests/ui/target-feature/invalid-attribute.stderr
@@ -98,6 +98,12 @@
LL | trait Baz {}
| ------------ not a function definition
+error: cannot use `#[inline(always)]` with `#[target_feature]`
+ --> $DIR/invalid-attribute.rs:69:1
+ |
+LL | #[inline(always)]
+ | ^^^^^^^^^^^^^^^^^
+
error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:74:1
|
@@ -163,12 +169,6 @@
LL | #[target_feature(disable = "baz")]
| ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
-error: cannot use `#[inline(always)]` with `#[target_feature]`
- --> $DIR/invalid-attribute.rs:69:1
- |
-LL | #[inline(always)]
- | ^^^^^^^^^^^^^^^^^
-
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/invalid-attribute.rs:81:1
|
diff --git a/tests/ui/thread-local/spawn-hook-atexit.rs b/tests/ui/thread-local/spawn-hook-atexit.rs
new file mode 100644
index 0000000..b084e0b
--- /dev/null
+++ b/tests/ui/thread-local/spawn-hook-atexit.rs
@@ -0,0 +1,24 @@
+// Regression test for https://github.com/rust-lang/rust/issues/138696
+//@ only-unix
+//@ needs-threads
+//@ run-pass
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+fn main() {
+ std::thread::spawn(|| {
+ unsafe { libc::atexit(spawn_in_atexit) };
+ })
+ .join()
+ .unwrap();
+}
+
+extern "C" fn spawn_in_atexit() {
+ std::thread::spawn(|| {
+ println!("Thread spawned in atexit");
+ })
+ .join()
+ .unwrap();
+}
diff --git a/tests/ui/traits/const-traits/feature-gate.gated.stderr b/tests/ui/traits/const-traits/feature-gate.gated.stderr
deleted file mode 100644
index 12f9355..0000000
--- a/tests/ui/traits/const-traits/feature-gate.gated.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/feature-gate.rs:22:1
- |
-LL | fn main() {}
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/traits/const-traits/feature-gate.rs b/tests/ui/traits/const-traits/feature-gate.rs
index c36ec35..921dfb0 100644
--- a/tests/ui/traits/const-traits/feature-gate.rs
+++ b/tests/ui/traits/const-traits/feature-gate.rs
@@ -1,8 +1,8 @@
//@ revisions: stock gated
+//@[gated] check-pass
// gate-test-const_trait_impl
#![cfg_attr(gated, feature(const_trait_impl))]
-#![feature(rustc_attrs)]
struct S;
#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder
@@ -18,5 +18,4 @@ macro_rules! discard { ($ty:ty) => {} }
discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental
discard! { impl const T } //[stock]~ ERROR const trait impls are experimental
-#[rustc_error]
-fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]
+fn main() {}
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr
new file mode 100644
index 0000000..f4930bf
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/incomplete-infer-via-sized-wc.rs:15:5
+ |
+LL | is_sized::<MaybeSized<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr
new file mode 100644
index 0000000..f4930bf
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/incomplete-infer-via-sized-wc.rs:15:5
+ |
+LL | is_sized::<MaybeSized<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.rs b/tests/ui/traits/incomplete-infer-via-sized-wc.rs
new file mode 100644
index 0000000..9dcddea
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.rs
@@ -0,0 +1,19 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+struct MaybeSized<T: ?Sized>(T);
+
+fn is_sized<T: Sized>() -> Box<T> { todo!() }
+
+fn foo<T: ?Sized>()
+where
+ MaybeSized<T>: Sized,
+{
+ is_sized::<MaybeSized<_>>();
+ //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs
new file mode 100644
index 0000000..8a8f7b9
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+trait Trait<T>: Sized {}
+impl<T> Trait<T> for T {}
+
+fn is_sized<T: Sized>() {}
+
+fn normal_ref<'a, 'b, T>()
+where
+ &'a u32: Trait<T>,
+{
+ is_sized::<&'b u32>();
+}
+
+struct MyRef<'a, U: ?Sized = ()>(&'a u32, U);
+fn my_ref<'a, 'b, T>()
+where
+ MyRef<'a>: Trait<T>,
+{
+ is_sized::<MyRef<'b>>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr
new file mode 100644
index 0000000..dd9393f
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23
+ |
+LL | (MyType<'a, T>,): Sized,
+ | ^^^^^ lifetime mismatch
+ |
+ = note: expected trait `<MyType<'a, T> as Sized>`
+ found trait `<MyType<'static, T> as Sized>`
+note: the lifetime `'a` as defined here...
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | ^^
+ = note: ...does not necessarily outlive the static lifetime
+
+error: lifetime may not live long enough
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | -- lifetime `'a` defined here
+...
+LL | is_sized::<(MyType<'a, T>,)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr
new file mode 100644
index 0000000..0586187
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr
@@ -0,0 +1,25 @@
+error[E0478]: lifetime bound not satisfied
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23
+ |
+LL | (MyType<'a, T>,): Sized,
+ | ^^^^^
+ |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | ^^
+ = note: but lifetime parameter must outlive the static lifetime
+
+error: lifetime may not live long enough
+ --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5
+ |
+LL | fn foo<'a, T: ?Sized>()
+ | -- lifetime `'a` defined here
+...
+LL | is_sized::<(MyType<'a, T>,)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs
new file mode 100644
index 0000000..ae7a6c9
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs
@@ -0,0 +1,26 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+struct MyType<'a, T: ?Sized>(&'a (), T);
+
+fn is_sized<T>() {}
+
+fn foo<'a, T: ?Sized>()
+where
+ (MyType<'a, T>,): Sized,
+ //[current]~^ ERROR mismatched types
+ //[next]~^^ ERROR lifetime bound not satisfied
+ MyType<'static, T>: Sized,
+{
+ // Preferring the builtin `Sized` impl of tuples
+ // requires proving `MyType<'a, T>: Sized` which
+ // can only be proven by using the where-clause,
+ // adding an unnecessary `'static` constraint.
+ is_sized::<(MyType<'a, T>,)>();
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr
index 272c563..9e8eb1a 100644
--- a/tests/ui/traits/mutual-recursion-issue-75860.stderr
+++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr
@@ -2,7 +2,7 @@
--> $DIR/mutual-recursion-issue-75860.rs:9:33
|
LL | let left = |o_a: Option<_>| o_a.unwrap();
- | ^^^
+ | ^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs
new file mode 100644
index 0000000..f8fa410
--- /dev/null
+++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs
@@ -0,0 +1,24 @@
+//@compile-flags: --edition 2021
+
+fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize {
+ //~^ ERROR expected trait, found builtin type `usize`
+ //~| ERROR expected a type, found a trait [E0782]
+ 0
+}
+
+fn create_adder<'a>(x: i32) -> usize + 'a {
+ //~^ ERROR expected trait, found builtin type `usize`
+ //~| ERROR expected a type, found a trait [E0782]
+ move |y| x + y
+}
+
+struct Struct<'a>{
+ x: usize + 'a,
+ //~^ ERROR expected trait, found builtin type `usize`
+ //~| ERROR expected a type, found a trait [E0782]
+}
+
+
+fn main() {
+
+}
diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr
new file mode 100644
index 0000000..0d1ce85
--- /dev/null
+++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr
@@ -0,0 +1,40 @@
+error[E0404]: expected trait, found builtin type `usize`
+ --> $DIR/suggestion-trait-object-issue-139174.rs:3:36
+ |
+LL | fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize {
+ | ^^^^^ not a trait
+
+error[E0404]: expected trait, found builtin type `usize`
+ --> $DIR/suggestion-trait-object-issue-139174.rs:9:32
+ |
+LL | fn create_adder<'a>(x: i32) -> usize + 'a {
+ | ^^^^^ not a trait
+
+error[E0404]: expected trait, found builtin type `usize`
+ --> $DIR/suggestion-trait-object-issue-139174.rs:16:8
+ |
+LL | x: usize + 'a,
+ | ^^^^^ not a trait
+
+error[E0782]: expected a type, found a trait
+ --> $DIR/suggestion-trait-object-issue-139174.rs:3:36
+ |
+LL | fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize {
+ | ^^^^^^^^^^
+
+error[E0782]: expected a type, found a trait
+ --> $DIR/suggestion-trait-object-issue-139174.rs:9:32
+ |
+LL | fn create_adder<'a>(x: i32) -> usize + 'a {
+ | ^^^^^^^^^^
+
+error[E0782]: expected a type, found a trait
+ --> $DIR/suggestion-trait-object-issue-139174.rs:16:8
+ |
+LL | x: usize + 'a,
+ | ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0404, E0782.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs
index 296bdd7..88a9d07 100644
--- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs
+++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs
@@ -8,5 +8,5 @@
#![feature(rustc_attrs)]
-#[rustc_error(delayed_bug_from_inside_query)]
+#[rustc_delayed_bug_from_inside_query]
fn main() {}
diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr
index aec1b89..1c8d279 100644
--- a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr
+++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]
+error: internal compiler error: delayed bug triggered by #[rustc_delayed_bug_from_inside_query]
--> $DIR/span_delayed_bug.rs:12:1
|
LL | fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-53096.rs b/tests/ui/type-alias-impl-trait/issue-53096.rs
index c24f1bf..60e455a 100644
--- a/tests/ui/type-alias-impl-trait/issue-53096.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53096.rs
@@ -1,4 +1,5 @@
-#![feature(rustc_attrs)]
+//@ check-pass
+
#![feature(type_alias_impl_trait)]
pub type Foo = impl Fn() -> usize;
@@ -8,5 +9,4 @@ pub const fn bar() -> Foo {
}
const BAZR: Foo = bar();
-#[rustc_error]
-fn main() {} //~ ERROR
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr
deleted file mode 100644
index 5349089..0000000
--- a/tests/ui/type-alias-impl-trait/issue-53096.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/issue-53096.rs:12:1
- |
-LL | fn main() {}
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/issue-60407.rs b/tests/ui/type-alias-impl-trait/issue-60407.rs
index 5b8ff6b..53280c2 100644
--- a/tests/ui/type-alias-impl-trait/issue-60407.rs
+++ b/tests/ui/type-alias-impl-trait/issue-60407.rs
@@ -1,4 +1,6 @@
-#![feature(type_alias_impl_trait, rustc_attrs)]
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
pub type Debuggable = impl core::fmt::Debug;
@@ -9,8 +11,6 @@ pub fn foo() -> Debuggable {
static mut TEST: Option<Debuggable> = None;
-#[rustc_error]
fn main() {
- //~^ ERROR
unsafe { TEST = Some(foo()) }
}
diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr
deleted file mode 100644
index f517d5b..0000000
--- a/tests/ui/type-alias-impl-trait/issue-60407.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
- --> $DIR/issue-60407.rs:13:1
- |
-LL | fn main() {
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
index 1998624..53b7667 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
@@ -1,9 +1,10 @@
#![feature(type_alias_impl_trait)]
-//@ known-bug: #109268
type Foo = impl Fn() -> Foo;
+#[define_opaque(Foo)]
fn crash(x: Foo) -> Foo {
+ //~^ ERROR overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
x
}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
index ad96a0e..ee8922b 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
@@ -1,10 +1,9 @@
-error: unconstrained opaque type
- --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:4:12
+error[E0275]: overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
+ --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21
|
-LL | type Foo = impl Fn() -> Foo;
- | ^^^^^^^^^^^^^^^^
- |
- = note: `Foo` must be used in combination with a concrete type within the same crate
+LL | fn crash(x: Foo) -> Foo {
+ | ^^^
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
index 761cc83..d0c62d2 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
@@ -1,13 +1,13 @@
#![feature(type_alias_impl_trait)]
-//@ known-bug: #109268
pub trait Bar<T> {
type Item;
}
type Foo = impl Bar<Foo, Item = Foo>;
-
+#[define_opaque(Foo)]
fn crash(x: Foo) -> Foo {
+ //~^ ERROR overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
x
}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
index e5bb816..40bd651 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
@@ -1,10 +1,9 @@
-error: unconstrained opaque type
- --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:8:12
+error[E0275]: overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
+ --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:9:21
|
-LL | type Foo = impl Bar<Foo, Item = Foo>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `Foo` must be used in combination with a concrete type within the same crate
+LL | fn crash(x: Foo) -> Foo {
+ | ^^^
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
index 52942af..de3d23b 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
@@ -1,9 +1,9 @@
#![feature(type_alias_impl_trait)]
-//@ known-bug: #109268
type Foo<'a> = impl Fn() -> Foo<'a>;
-
+#[define_opaque(Foo)]
fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
+ //~^ ERROR overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
x
}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
index 157310b..f9e26fd 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
@@ -1,10 +1,9 @@
-error: unconstrained opaque type
- --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:4:16
+error[E0275]: overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
+ --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:5:40
|
-LL | type Foo<'a> = impl Fn() -> Foo<'a>;
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: `Foo` must be used in combination with a concrete type within the same crate
+LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
+ | ^^^^^^^
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs
deleted file mode 100644
index ed19b10..0000000
--- a/tests/ui/type/pattern_types/const_block.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(pattern_types)]
-#![feature(pattern_type_macro)]
-#![feature(inline_const_pat)]
-//@ check-pass
-
-use std::pat::pattern_type;
-
-fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-
-fn main() {}
diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs
index 763e949..b0fdcf9 100644
--- a/tests/ui/unresolved/unresolved-import.rs
+++ b/tests/ui/unresolved/unresolved-import.rs
@@ -31,6 +31,8 @@ mod food {
mod zug {
pub mod baz {
+ //~^ NOTE module `food::zug::baz` exists but is inaccessible
+ //~| NOTE not accessible
pub struct Foobar;
}
}
diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr
index c65fe84..4001695 100644
--- a/tests/ui/unresolved/unresolved-import.stderr
+++ b/tests/ui/unresolved/unresolved-import.stderr
@@ -26,6 +26,12 @@
| | |
| | help: a similar name exists in the module: `bag`
| no `baz` in `food`
+ |
+note: module `food::zug::baz` exists but is inaccessible
+ --> $DIR/unresolved-import.rs:33:9
+ |
+LL | pub mod baz {
+ | ^^^^^^^^^^^ not accessible
error[E0432]: unresolved import `food::beens`
--> $DIR/unresolved-import.rs:19:12
@@ -37,13 +43,13 @@
| help: a similar name exists in the module: `beans`
error[E0432]: unresolved import `MyEnum`
- --> $DIR/unresolved-import.rs:44:9
+ --> $DIR/unresolved-import.rs:46:9
|
LL | use MyEnum::*;
| ^^^^^^ help: a similar path exists: `self::MyEnum`
error[E0432]: unresolved import `Enum`
- --> $DIR/unresolved-import.rs:55:9
+ --> $DIR/unresolved-import.rs:57:9
|
LL | use Enum::*;
| ^^^^ help: a similar path exists: `self::Enum`
diff --git a/tests/ui/unsafe/const_pat_in_layout_restricted.rs b/tests/ui/unsafe/const_pat_in_layout_restricted.rs
deleted file mode 100644
index 2ba173e..0000000
--- a/tests/ui/unsafe/const_pat_in_layout_restricted.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Check that ref mut patterns within a const pattern don't get considered
-// unsafe because they're within a pattern for a layout constrained stuct.
-//@ check-pass
-
-#![feature(rustc_attrs)]
-#![feature(inline_const_pat)]
-
-#[rustc_layout_scalar_valid_range_start(3)]
-struct Gt2(i32);
-
-fn main() {
- match unsafe { Gt2(5) } {
- Gt2(
- const {
- || match () {
- ref mut y => (),
- };
- 4
- },
- ) => (),
- _ => (),
- }
-}
diff --git a/tests/ui/variance/variance-uniquearc.rs b/tests/ui/variance/variance-uniquearc.rs
new file mode 100644
index 0000000..0358951
--- /dev/null
+++ b/tests/ui/variance/variance-uniquearc.rs
@@ -0,0 +1,27 @@
+// regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164
+// see also the test for UniqueRc` in variance-uniquerc.rs
+//
+// inline comments explain how this code *would* compile if UniqueArc was still covariant
+
+#![feature(unique_rc_arc)]
+
+use std::sync::UniqueArc;
+
+fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
+ let r = UniqueArc::new(""); // UniqueArc<&'static str>
+ let w = UniqueArc::downgrade(&r); // Weak<&'static str>
+ let mut r = r; // [IF COVARIANT]: ==>> UniqueArc<&'a str>
+ *r = x; // assign the &'a str
+ let _r = UniqueArc::into_arc(r); // Arc<&'a str>, but we only care to activate the weak
+ let r = w.upgrade().unwrap(); // Arc<&'static str>
+ *r // &'static str, coerces to &'b str
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+ let s = String::from("Hello World!");
+ let r = extend_lifetime(&s);
+ println!("{r}");
+ drop(s);
+ println!("{r}");
+}
diff --git a/tests/ui/variance/variance-uniquearc.stderr b/tests/ui/variance/variance-uniquearc.stderr
new file mode 100644
index 0000000..55076da
--- /dev/null
+++ b/tests/ui/variance/variance-uniquearc.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/variance-uniquearc.rs:17:5
+ |
+LL | fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | *r // &'static str, coerces to &'b str
+ | ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/variance/variance-uniquerc.rs b/tests/ui/variance/variance-uniquerc.rs
index 0c395ab..2e9738f 100644
--- a/tests/ui/variance/variance-uniquerc.rs
+++ b/tests/ui/variance/variance-uniquerc.rs
@@ -1,5 +1,5 @@
// regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164
-// we should also test UniqueArc once implemented
+// see also the test for UniqueArc in variance-uniquearc.rs
//
// inline comments explain how this code *would* compile if UniqueRc was still covariant
diff --git a/triagebot.toml b/triagebot.toml
index ebbcfa4..59f8159 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -254,6 +254,16 @@
"compiler/rustc_attr_data_structures",
]
+[autolabel."F-autodiff"]
+trigger_files = [
+ "src/tools/enzyme",
+ "src/doc/unstable-book/src/compiler-flags/autodiff.md",
+ "compiler/rustc_ast/src/expand/autodiff_attrs.rs",
+ "compiler/rustc_monomorphize/src/partitioning/autodiff.rs",
+ "compiler/rustc_codegen_llvm/src/builder/autodiff.rs",
+ "compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs",
+]
+
[autolabel."T-rustdoc-frontend"]
trigger_labels = [
"A-rustdoc-search",
@@ -581,12 +591,12 @@
]
[notify-zulip."I-prioritize"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
+zulip_stream = 245100 # #t-compiler/prioritization/alerts
topic = "#{number} {title}"
message_on_add = """\
@*WG-prioritization/alerts* issue #{number} has been requested for prioritization.
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#assign-priority-to-unprioritized-issues-with-i-prioritize-label)
+# [Procedure](https://forge.rust-lang.org/compiler/prioritization.html)
- Priority?
- Regression?
- Notify people/groups?
@@ -1092,12 +1102,29 @@
[mentions."compiler/rustc_attr_data_structures"]
cc = ["@jdonszelmann"]
+[mentions."src/tools/enzyme"]
+cc = ["@ZuseZ4"]
+[mentions."src/doc/unstable-book/src/compiler-flags/autodiff.md"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_ast/src/expand/autodiff_attrs.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_ast/src/expand/typetree.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_builtin_macros/src/autodiff.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_monomorphize/src/partitioning/autodiff.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_codegen_llvm/src/builder/autodiff.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs"]
+cc = ["@ZuseZ4"]
+
[assign]
warn_non_default_branch.enable = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
"jyn514",
- "ChrisDenton",
+ "saethlin",
]
[[assign.warn_non_default_branch.exceptions]]
@@ -1133,7 +1160,6 @@
]
libs = [
"@Mark-Simulacrum",
- "@Amanieu",
"@Noratrieb",
"@workingjubilee",
"@joboet",