From cd7c161294eac4c2cce5c503f1c5b05ce24864a7 Mon Sep 17 00:00:00 2001 From: Antoine PLASKOWSKI Date: Tue, 2 May 2023 20:36:48 +0200 Subject: [PATCH 01/13] Add known issue of let binding to format_args doc --- library/core/src/macros/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7c93c93b4a019..a9818371f9ea8 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -868,6 +868,14 @@ pub(crate) mod builtin { /// let s = fmt::format(format_args!("hello {}", "world")); /// assert_eq!(s, format!("hello {}", "world")); /// ``` + /// + /// # Lifetime limitation + /// + /// Except when no formatting arguments are used, + /// the produced `fmt::Arguments` value borrows temporary values, + /// which means it can only be used within the same expression + /// and cannot be stored for later use. + /// This is a known limitation, see [#92698](https://github.com/rust-lang/rust/issues/92698). #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "format_args_macro")] #[allow_internal_unsafe] From 213748749e32d3ec7e136f0aa73f205700e274c1 Mon Sep 17 00:00:00 2001 From: Mohammad Omidvar Date: Mon, 12 Feb 2024 19:44:35 +0000 Subject: [PATCH 02/13] Add APIs for fetching foreign items including foreign modules, their ABIs, and their items --- Cargo.lock | 1 + compiler/rustc_smir/Cargo.toml | 1 + compiler/rustc_smir/src/rustc_internal/mod.rs | 4 + compiler/rustc_smir/src/rustc_smir/context.rs | 62 ++++++++++++- .../rustc_smir/src/rustc_smir/convert/ty.rs | 80 ++++++++++------ compiler/stable_mir/src/compiler_interface.rs | 13 ++- compiler/stable_mir/src/lib.rs | 7 +- compiler/stable_mir/src/ty.rs | 36 ++++++- tests/ui-fulldeps/stable-mir/check_foreign.rs | 93 +++++++++++++++++++ 9 files changed, 259 insertions(+), 38 deletions(-) create mode 100644 tests/ui-fulldeps/stable-mir/check_foreign.rs diff --git a/Cargo.lock b/Cargo.lock index d552bb655b40a..46661b9c3115d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4559,6 +4559,7 @@ dependencies = [ "rustc_data_structures", "rustc_hir", "rustc_middle", + "rustc_session", "rustc_span", "rustc_target", "scoped-tls", diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index c9e23efcb10c6..1e0a60bc371ac 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -9,6 +9,7 @@ rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } +rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } scoped-tls = "1.0" diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 43987fcf10fc9..6bb8c5452b989 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -85,6 +85,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::AdtDef(self.create_def_id(did)) } + pub fn foreign_module_def(&mut self, did: DefId) -> stable_mir::ty::ForeignModuleDef { + stable_mir::ty::ForeignModuleDef(self.create_def_id(did)) + } + pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef { stable_mir::ty::ForeignDef(self.create_def_id(did)) } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 94a1fb33f99c5..24dd7ad6d7eba 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -22,10 +22,10 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef}; use stable_mir::mir::Body; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs, - LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, VariantDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, + ForeignItemKind, GenericArgs, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, VariantDef, }; -use stable_mir::{Crate, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; +use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; use std::cell::RefCell; use std::iter; @@ -67,6 +67,39 @@ impl<'tcx> Context for TablesWrapper<'tcx> { tables.tcx.is_mir_available(def_id) } + fn foreign_modules(&self, crate_num: CrateNum) -> Vec { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + tcx.foreign_modules(crate_num.internal(&mut *tables, tcx)) + .keys() + .map(|mod_def_id| tables.foreign_module_def(*mod_def_id)) + .collect() + } + + fn foreign_module( + &self, + mod_def: stable_mir::ty::ForeignModuleDef, + ) -> stable_mir::ty::ForeignModule { + let mut tables = self.0.borrow_mut(); + let def_id = tables[mod_def.def_id()]; + let mod_def = tables.tcx.foreign_modules(def_id.krate).get(&def_id).unwrap(); + mod_def.stable(&mut *tables) + } + + fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec { + let mut tables = self.0.borrow_mut(); + let def_id = tables[mod_def.def_id()]; + tables + .tcx + .foreign_modules(def_id.krate) + .get(&def_id) + .unwrap() + .foreign_items + .iter() + .map(|item_def| tables.foreign_def(*item_def)) + .collect() + } + fn all_trait_decls(&self) -> stable_mir::TraitDecls { let mut tables = self.0.borrow_mut(); tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect() @@ -225,6 +258,29 @@ impl<'tcx> Context for TablesWrapper<'tcx> { tables.tcx.is_foreign_item(tables[item]) } + fn foreign_item_kind(&self, def: ForeignDef) -> Option { + let (def_id, hir_kind) = { + let tables = self.0.borrow(); + let def_id = tables[def.def_id()]; + let hir_kind = tables + .tcx + .hir() + .expect_foreign_item(rustc_hir::OwnerId { def_id: def_id.as_local()? }) + .kind; + (def_id, hir_kind) + }; + let kind = match hir_kind { + rustc_hir::ForeignItemKind::Fn(..) => { + ForeignItemKind::Fn(self.0.borrow_mut().fn_def(def_id)) + } + rustc_hir::ForeignItemKind::Static(..) => { + ForeignItemKind::Static(self.0.borrow_mut().static_def(def_id)) + } + rustc_hir::ForeignItemKind::Type => ForeignItemKind::Type(self.def_ty(def.def_id())), + }; + Some(kind) + } + fn adt_kind(&self, def: AdtDef) -> AdtKind { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 959a17d24b7ce..29081418200e7 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -202,41 +202,13 @@ where impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { type T = stable_mir::ty::FnSig; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - use rustc_target::spec::abi; - use stable_mir::ty::{Abi, FnSig}; + use stable_mir::ty::FnSig; FnSig { inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(), c_variadic: self.c_variadic, unsafety: self.unsafety.stable(tables), - abi: match self.abi { - abi::Abi::Rust => Abi::Rust, - abi::Abi::C { unwind } => Abi::C { unwind }, - abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind }, - abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind }, - abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind }, - abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind }, - abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind }, - abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind }, - abi::Abi::Win64 { unwind } => Abi::Win64 { unwind }, - abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind }, - abi::Abi::PtxKernel => Abi::PtxKernel, - abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt, - abi::Abi::X86Interrupt => Abi::X86Interrupt, - abi::Abi::EfiApi => Abi::EfiApi, - abi::Abi::AvrInterrupt => Abi::AvrInterrupt, - abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, - abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, - abi::Abi::Wasm => Abi::Wasm, - abi::Abi::System { unwind } => Abi::System { unwind }, - abi::Abi::RustIntrinsic => Abi::RustIntrinsic, - abi::Abi::RustCall => Abi::RustCall, - abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic, - abi::Abi::Unadjusted => Abi::Unadjusted, - abi::Abi::RustCold => Abi::RustCold, - abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM, - abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS, - }, + abi: self.abi.stable(tables), } } } @@ -832,3 +804,51 @@ impl<'tcx> Stable<'tcx> for ty::Movability { } } } + +impl<'tcx> Stable<'tcx> for rustc_target::spec::abi::Abi { + type T = stable_mir::ty::Abi; + + fn stable(&self, _: &mut Tables<'_>) -> Self::T { + use rustc_target::spec::abi; + use stable_mir::ty::Abi; + match *self { + abi::Abi::Rust => Abi::Rust, + abi::Abi::C { unwind } => Abi::C { unwind }, + abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind }, + abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind }, + abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind }, + abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind }, + abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind }, + abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind }, + abi::Abi::Win64 { unwind } => Abi::Win64 { unwind }, + abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind }, + abi::Abi::PtxKernel => Abi::PtxKernel, + abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt, + abi::Abi::X86Interrupt => Abi::X86Interrupt, + abi::Abi::EfiApi => Abi::EfiApi, + abi::Abi::AvrInterrupt => Abi::AvrInterrupt, + abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, + abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, + abi::Abi::Wasm => Abi::Wasm, + abi::Abi::System { unwind } => Abi::System { unwind }, + abi::Abi::RustIntrinsic => Abi::RustIntrinsic, + abi::Abi::RustCall => Abi::RustCall, + abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic, + abi::Abi::Unadjusted => Abi::Unadjusted, + abi::Abi::RustCold => Abi::RustCold, + abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM, + abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS, + } + } +} + +impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { + type T = stable_mir::ty::ForeignModule; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + stable_mir::ty::ForeignModule { + def_id: tables.foreign_module_def(self.def_id), + abi: self.abi.stable(tables), + } + } +} diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index fb83dae571423..f55e0f9481fe2 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -11,9 +11,10 @@ use crate::mir::mono::{Instance, InstanceDef, StaticDef}; use crate::mir::Body; use crate::target::MachineInfo; use crate::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs, - GenericPredicates, Generics, ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, - TraitDef, Ty, TyKind, VariantDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, + ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, + ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyKind, + VariantDef, }; use crate::{ mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, @@ -31,6 +32,9 @@ pub trait Context { fn mir_body(&self, item: DefId) -> mir::Body; /// Check whether the body of a function is available. fn has_body(&self, item: DefId) -> bool; + fn foreign_modules(&self, crate_num: CrateNum) -> Vec; + fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule; + fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec; fn all_trait_decls(&self) -> TraitDecls; fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls; fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; @@ -66,6 +70,9 @@ pub trait Context { /// Returns whether this is a foreign item. fn is_foreign_item(&self, item: DefId) -> bool; + /// Returns the kind of a given foreign item. + fn foreign_item_kind(&self, def: ForeignDef) -> Option; + /// Returns the kind of a given algebraic data type fn adt_kind(&self, def: AdtDef) -> AdtKind; diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 4f57f532a40c9..d849c834ae00e 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -30,7 +30,7 @@ pub use crate::error::*; use crate::mir::pretty::function_name; use crate::mir::Body; use crate::mir::Mutability; -use crate::ty::{ImplDef, IndexedVal, Span, TraitDef, Ty}; +use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; pub mod abi; #[macro_use] @@ -86,6 +86,11 @@ pub struct Crate { } impl Crate { + /// The list of foreign modules in this crate. + pub fn foreign_modules(&self) -> Vec { + with(|cx| cx.foreign_modules(self.id)) + } + /// The list of traits declared in this crate. pub fn trait_decls(&self) -> TraitDecls { with(|cx| cx.trait_decls(self.id)) diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index bdda929534705..f043ce9d898d4 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -4,9 +4,9 @@ use super::{ with, DefId, Error, Symbol, }; use crate::abi::Layout; -use crate::crate_def::CrateDef; use crate::mir::alloc::{read_target_int, read_target_uint, AllocId}; use crate::target::MachineInfo; +use crate::{crate_def::CrateDef, mir::mono::StaticDef}; use crate::{Filename, Opaque}; use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Range; @@ -539,11 +539,45 @@ pub enum Movability { Movable, } +crate_def! { + pub ForeignModuleDef; +} + +impl ForeignModuleDef { + pub fn module(&self) -> ForeignModule { + with(|cx| cx.foreign_module(*self)) + } +} + +pub struct ForeignModule { + pub def_id: ForeignModuleDef, + pub abi: Abi, +} + +impl ForeignModule { + pub fn items(&self) -> Vec { + with(|cx| cx.foreign_items(self.def_id)) + } +} + crate_def! { /// Hold information about a ForeignItem in a crate. pub ForeignDef; } +impl ForeignDef { + pub fn kind(&self) -> Option { + with(|cx| cx.foreign_item_kind(*self)) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum ForeignItemKind { + Fn(FnDef), + Static(StaticDef), + Type(Ty), +} + crate_def! { /// Hold information about a function definition in a crate. pub FnDef; diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs new file mode 100644 index 0000000000000..22770a56e3292 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs @@ -0,0 +1,93 @@ +// run-pass +//! Test retrieval and kinds of foreign items. + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_span; +extern crate stable_mir; + +use rustc_smir::rustc_internal; +use stable_mir::{ + ty::{Abi, ForeignItemKind}, + *, +}; +use std::assert_matches::assert_matches; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_foreign() -> ControlFlow<()> { + let mods = + local_crate().foreign_modules().into_iter().map(|def| def.module()).collect::>(); + assert_eq!(mods.len(), 2); + + let rust_mod = mods.iter().find(|m| matches!(m.abi, Abi::Rust)).unwrap(); + assert_eq!(rust_mod.items().len(), 1); + + let c_mod = mods.iter().find(|m| matches!(m.abi, Abi::C { .. })).unwrap(); + let c_items = c_mod.items(); + assert_eq!(c_items.len(), 3); + for item in c_items { + let kind = item.kind().unwrap(); + match item.name().as_str() { + "foo" => assert_matches!(kind, ForeignItemKind::Fn(..)), + "bar" => assert_matches!(kind, ForeignItemKind::Static(..)), + "Baz" => assert_matches!(kind, ForeignItemKind::Type(..)), + name => unreachable!("Unexpected item {name}"), + }; + } + ControlFlow::Continue(()) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "foreign_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "-Cpanic=abort".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, || test_foreign()).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + #![feature(extern_types)] + #![allow(unused)] + extern "Rust" {{ + fn rust_foo(x: i32) -> i32; + }} + extern "C" {{ + fn foo(x: i32) -> i32; + static bar: i32; + type Baz; + }} + "# + )?; + Ok(()) +} From a261f8edd8de496c1bbb8b1e220148776ccf35cb Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 15 Nov 2023 10:08:36 +0000 Subject: [PATCH 03/13] Move windows_sys.lst to bindings.txt --- .../std/src/sys/pal/windows/c/{windows_sys.lst => bindings.txt} | 1 - 1 file changed, 1 deletion(-) rename library/std/src/sys/pal/windows/c/{windows_sys.lst => bindings.txt} (99%) diff --git a/library/std/src/sys/pal/windows/c/windows_sys.lst b/library/std/src/sys/pal/windows/c/bindings.txt similarity index 99% rename from library/std/src/sys/pal/windows/c/windows_sys.lst rename to library/std/src/sys/pal/windows/c/bindings.txt index f91e1054a040b..1e4d696a0018c 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.lst +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2593,4 +2593,3 @@ Windows.Win32.System.Threading.WakeConditionVariable Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE Windows.Win32.UI.Shell.GetUserProfileDirectoryW // tidy-alphabetical-end - From adcbeb7fdb4157d108fd939697d0991840c7a58f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 8 Dec 2023 15:01:38 +0000 Subject: [PATCH 04/13] Add windows_sys readme --- library/std/src/sys/pal/windows/c/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 library/std/src/sys/pal/windows/c/README.md diff --git a/library/std/src/sys/pal/windows/c/README.md b/library/std/src/sys/pal/windows/c/README.md new file mode 100644 index 0000000000000..d458e55efbcdd --- /dev/null +++ b/library/std/src/sys/pal/windows/c/README.md @@ -0,0 +1,9 @@ +The `windows_sys.rs` file is autogenerated from `bindings.txt` and must not +be edited manually. + +To add bindings, edit `bindings.txt` then regenerate using the following command: + + ./x run generate-windows-sys && ./x fmt library/std + +If you need to override generated functions or types then add them to +`library/std/src/sys/pal/windows/c.rs`. From 846315ddc95fbe02841c88c540e85f60cb670230 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 8 Dec 2023 15:22:34 +0000 Subject: [PATCH 05/13] Automatically sort windows_sys bindings --- .../std/src/sys/pal/windows/c/bindings.txt | 2 - .../std/src/sys/pal/windows/c/windows_sys.rs | 7 +-- src/tools/generate-windows-sys/src/main.rs | 47 ++++++++++++------- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 1e4d696a0018c..726f1c3df8294 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -1,7 +1,6 @@ --out windows_sys.rs --config flatten std --filter -// tidy-alphabetical-start !Windows.Win32.Foundation.INVALID_HANDLE_VALUE Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED Windows.Wdk.Storage.FileSystem.FILE_CONTAINS_EXTENDED_CREATE_INFORMATION @@ -2592,4 +2591,3 @@ Windows.Win32.System.Threading.WakeAllConditionVariable Windows.Win32.System.Threading.WakeConditionVariable Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE Windows.Win32.UI.Shell.GetUserProfileDirectoryW -// tidy-alphabetical-end diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index b38b70c8983e6..c386b66a722df 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -1,9 +1,3 @@ -// This file is autogenerated. -// -// To add bindings, edit windows_sys.lst then use `./x run generate-windows-sys` to -// regenerate the bindings. -// -// ignore-tidy-filelength // Bindings generated by `windows-bindgen` 0.52.0 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] @@ -4351,3 +4345,4 @@ impl ::core::clone::Clone for XSAVE_FORMAT { *self } } +// ignore-tidy-filelength diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index dc95d969aede9..c8913910bd6e7 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -1,34 +1,49 @@ use std::env; use std::error::Error; use std::fs; -use std::io::{self, Read, Seek, Write}; +use std::io::{Read, Seek, SeekFrom, Write}; use std::path::PathBuf; -/// This is printed to the file before the rest of the contents. -const PRELUDE: &str = r#"// This file is autogenerated. -// -// To add bindings, edit windows_sys.lst then use `./x run generate-windows-sys` to -// regenerate the bindings. -// -// ignore-tidy-filelength -"#; - fn main() -> Result<(), Box> { let mut path: PathBuf = env::args_os().nth(1).expect("a path to the rust repository is required").into(); path.push("library/std/src/sys/pal/windows/c"); env::set_current_dir(&path)?; - let info = windows_bindgen::bindgen(["--etc", "windows_sys.lst"])?; + sort_bindings("bindings.txt")?; + + let info = windows_bindgen::bindgen(["--etc", "bindings.txt"])?; println!("{info}"); - // add some gunk to the output file. - let mut f = fs::File::options().read(true).write(true).open("windows_sys.rs")?; + let mut f = std::fs::File::options().append(true).open("windows_sys.rs")?; + writeln!(&mut f, "// ignore-tidy-filelength")?; + + Ok(()) +} + +fn sort_bindings(file_name: &str) -> Result<(), Box> { + let mut f = fs::File::options().read(true).write(true).open(file_name)?; let mut bindings = String::new(); f.read_to_string(&mut bindings)?; - f.seek(io::SeekFrom::Start(0))?; - f.write_all(PRELUDE.as_bytes())?; - f.write_all(bindings.as_bytes())?; + f.set_len(0)?; + f.seek(SeekFrom::Start(0))?; + let mut lines = bindings.split_inclusive('\n'); + for line in &mut lines { + f.write(line.as_bytes())?; + if line.contains("--filter") { + break; + } + } + let mut bindings = Vec::new(); + for line in &mut lines { + if !line.trim().is_empty() { + bindings.push(line); + } + } + bindings.sort_by(|a, b| a.to_lowercase().cmp(&b.to_lowercase())); + for line in bindings { + f.write(line.as_bytes())?; + } Ok(()) } From 55f9aed9c706e62f10138f27cf46255ea4667078 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 14 Feb 2024 14:45:38 +0000 Subject: [PATCH 06/13] Move all the heavy lifting from `TyCtxtAt::create_def` into `TyCtxt::create_def` --- compiler/rustc_middle/src/ty/context.rs | 30 ++++++++++++++----------- compiler/rustc_resolve/src/lib.rs | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5c04a34a3ba99..18958ac6d41a6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1046,6 +1046,22 @@ impl<'tcx> TyCtxtAt<'tcx> { name: Symbol, def_kind: DefKind, ) -> TyCtxtFeed<'tcx, LocalDefId> { + let feed = self.tcx.create_def(parent, name, def_kind); + + feed.def_span(self.span); + feed + } +} + +impl<'tcx> TyCtxt<'tcx> { + /// `tcx`-dependent operations performed for every created definition. + pub fn create_def( + self, + parent: LocalDefId, + name: Symbol, + def_kind: DefKind, + ) -> TyCtxtFeed<'tcx, LocalDefId> { + let data = def_kind.def_path_data(name); // The following call has the side effect of modifying the tables inside `definitions`. // These very tables are relied on by the incr. comp. engine to decode DepNodes and to // decode the on-disk cache. @@ -1060,18 +1076,6 @@ impl<'tcx> TyCtxtAt<'tcx> { // 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. - let def_id = self.tcx.create_def(parent, name, def_kind); - - let feed = self.tcx.feed_local_def_id(def_id); - feed.def_span(self.span); - feed - } -} - -impl<'tcx> TyCtxt<'tcx> { - /// `tcx`-dependent operations performed for every created definition. - pub fn create_def(self, parent: LocalDefId, name: Symbol, def_kind: DefKind) -> LocalDefId { - let data = def_kind.def_path_data(name); let def_id = self.untracked.definitions.write().create_def(parent, data); // This function modifies `self.definitions` using a side-effect. @@ -1091,7 +1095,7 @@ impl<'tcx> TyCtxt<'tcx> { feed.visibility(ty::Visibility::Restricted(parent_mod)); } - def_id + feed } pub fn iter_local_def_id(self) -> impl Iterator + 'tcx { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6b07bfdec671f..bf811c7a4bb87 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1245,7 +1245,7 @@ impl<'tcx> Resolver<'_, 'tcx> { ); // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()` - let def_id = self.tcx.create_def(parent, name, def_kind); + let def_id = self.tcx.create_def(parent, name, def_kind).def_id(); // Create the definition. if expn_id != ExpnId::root() { From fa1e35c833ad47cd5e1c49329eca46003d20d64d Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 15 Feb 2024 02:35:37 +0900 Subject: [PATCH 07/13] Remove unnecessary else block from `thread_local!` expanded code --- library/std/src/sys/pal/common/thread_local/fast_local.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/common/thread_local/fast_local.rs b/library/std/src/sys/pal/common/thread_local/fast_local.rs index 0fdca27852ca6..04c0dd6f75090 100644 --- a/library/std/src/sys/pal/common/thread_local/fast_local.rs +++ b/library/std/src/sys/pal/common/thread_local/fast_local.rs @@ -94,7 +94,8 @@ pub macro thread_local_inner { if let $crate::option::Option::Some(init) = init { if let $crate::option::Option::Some(value) = init.take() { return value; - } else if $crate::cfg!(debug_assertions) { + } + if $crate::cfg!(debug_assertions) { $crate::unreachable!("missing default value"); } } From 2e691a5c12f4d96da6938f26cbf3de7d404edc87 Mon Sep 17 00:00:00 2001 From: Mohammad Omidvar Date: Wed, 14 Feb 2024 17:38:36 +0000 Subject: [PATCH 08/13] Rewrite foreign item kind query using `DefKind` --- compiler/rustc_smir/src/rustc_smir/context.rs | 34 +++++++------------ compiler/stable_mir/src/compiler_interface.rs | 2 +- compiler/stable_mir/src/ty.rs | 2 +- tests/ui-fulldeps/stable-mir/check_foreign.rs | 2 +- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 24dd7ad6d7eba..0d1424bbc0bd1 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -258,27 +258,19 @@ impl<'tcx> Context for TablesWrapper<'tcx> { tables.tcx.is_foreign_item(tables[item]) } - fn foreign_item_kind(&self, def: ForeignDef) -> Option { - let (def_id, hir_kind) = { - let tables = self.0.borrow(); - let def_id = tables[def.def_id()]; - let hir_kind = tables - .tcx - .hir() - .expect_foreign_item(rustc_hir::OwnerId { def_id: def_id.as_local()? }) - .kind; - (def_id, hir_kind) - }; - let kind = match hir_kind { - rustc_hir::ForeignItemKind::Fn(..) => { - ForeignItemKind::Fn(self.0.borrow_mut().fn_def(def_id)) - } - rustc_hir::ForeignItemKind::Static(..) => { - ForeignItemKind::Static(self.0.borrow_mut().static_def(def_id)) - } - rustc_hir::ForeignItemKind::Type => ForeignItemKind::Type(self.def_ty(def.def_id())), - }; - Some(kind) + fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { + let mut tables = self.0.borrow_mut(); + let def_id = tables[def.def_id()]; + let tcx = tables.tcx; + use rustc_hir::def::DefKind; + match tcx.def_kind(def_id) { + DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)), + DefKind::Static(..) => ForeignItemKind::Static(tables.static_def(def_id)), + DefKind::ForeignTy => ForeignItemKind::Type( + tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)), + ), + def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind), + } } fn adt_kind(&self, def: AdtDef) -> AdtKind { diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index f55e0f9481fe2..59c79ddf8da36 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -71,7 +71,7 @@ pub trait Context { fn is_foreign_item(&self, item: DefId) -> bool; /// Returns the kind of a given foreign item. - fn foreign_item_kind(&self, def: ForeignDef) -> Option; + fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind; /// Returns the kind of a given algebraic data type fn adt_kind(&self, def: AdtDef) -> AdtKind; diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index f043ce9d898d4..658e8aa28b544 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -566,7 +566,7 @@ crate_def! { } impl ForeignDef { - pub fn kind(&self) -> Option { + pub fn kind(&self) -> ForeignItemKind { with(|cx| cx.foreign_item_kind(*self)) } } diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs index 22770a56e3292..e6c59354d5e25 100644 --- a/tests/ui-fulldeps/stable-mir/check_foreign.rs +++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs @@ -43,7 +43,7 @@ fn test_foreign() -> ControlFlow<()> { let c_items = c_mod.items(); assert_eq!(c_items.len(), 3); for item in c_items { - let kind = item.kind().unwrap(); + let kind = item.kind(); match item.name().as_str() { "foo" => assert_matches!(kind, ForeignItemKind::Fn(..)), "bar" => assert_matches!(kind, ForeignItemKind::Static(..)), From 01c974ff98a293c9792779bbe4428f1e9b55a05b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 14 Feb 2024 18:02:55 +0000 Subject: [PATCH 09/13] Do not report overflow errors on ConstArgHasType goals --- .../src/traits/fulfill.rs | 27 ++++++++++-------- tests/ui/codegen/overflow-during-mono.rs | 28 +++++++++++++++++++ tests/ui/codegen/overflow-during-mono.stderr | 11 ++++++++ 3 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 tests/ui/codegen/overflow-during-mono.rs create mode 100644 tests/ui/codegen/overflow-during-mono.stderr diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 5ef7a202a1253..7ad9427463418 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -423,6 +423,21 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::AliasRelate(..) => { bug!("AliasRelate is only used by the new solver") } + // Compute `ConstArgHasType` above the overflow check below. + // This is because this is not ever a useful obligation to report + // as the cause of an overflow. + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( + DefineOpaqueTypes::No, + ct.ty(), + ty, + ) { + Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), + Err(_) => ProcessResult::Error(FulfillmentErrorCode::SelectionError( + SelectionError::Unimplemented, + )), + } + } // General case overflow check. Allow `process_trait_obligation` // and `process_projection_obligation` to handle checking for @@ -650,18 +665,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( - DefineOpaqueTypes::No, - ct.ty(), - ty, - ) { - Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), - Err(_) => ProcessResult::Error(FulfillmentErrorCode::SelectionError( - SelectionError::Unimplemented, - )), - } - } }, } } diff --git a/tests/ui/codegen/overflow-during-mono.rs b/tests/ui/codegen/overflow-during-mono.rs new file mode 100644 index 0000000000000..e45db18e4074f --- /dev/null +++ b/tests/ui/codegen/overflow-during-mono.rs @@ -0,0 +1,28 @@ +// build-fail +//~^ ERROR overflow evaluating the requirement + +#![recursion_limit = "32"] + +fn quicksort, I: IntoIterator, T: Ord>( + i: I, +) -> Vec { + let mut i = i.into_iter(); + + match i.next() { + Some(x) => { + let less = i.clone().filter(|y| y < &x); + let greater = i.filter(|y| &x <= y); + + let mut v = quicksort(less); + let u = quicksort(greater); + v.push(x); + v.extend(u); + v + } + None => vec![], + } +} + +fn main() { + println!("{:?}", quicksort([5i32, 1, 6, 3, 6, 1, 9, 0, -1, 6, 8])); +} diff --git a/tests/ui/codegen/overflow-during-mono.stderr b/tests/ui/codegen/overflow-during-mono.stderr new file mode 100644 index 0000000000000..f7a3e2df3dbaa --- /dev/null +++ b/tests/ui/codegen/overflow-during-mono.stderr @@ -0,0 +1,11 @@ +error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`) + = note: required for `Filter, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator` + = note: 31 redundant requirements hidden + = note: required for `Filter, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator` + = note: required for `Filter, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `IntoIterator` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. From 9cccf208997e0e8a9909b9d174be7b8b3e4f6e83 Mon Sep 17 00:00:00 2001 From: Peter Hall Date: Wed, 14 Feb 2024 12:13:25 +0000 Subject: [PATCH 10/13] Clarified docs on non-atomic oprations on owned/mut refs to atomics --- library/core/src/sync/atomic.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1dec2bf40cc9a..e9a0d9e1d287c 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -27,8 +27,9 @@ //! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`. //! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating //! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference -//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not* -//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.) +//! ends. A Rust atomic type that is exclusively owned or behind a mutable reference does *not* +//! correspond to an “atomic object” in C++, since the underlying primitive can be mutably accessed, +//! for example with `get_mut`, to perform non-atomic operations. //! //! [cpp]: https://en.cppreference.com/w/cpp/atomic //! From 64a9c9cfea7f454bcc48852f0e1b99074d615ddc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Feb 2024 08:31:46 +1100 Subject: [PATCH 11/13] Reinstate some delayed bugs. These were changed to `has_errors` assertions in #121071 because that seemed reasonable, but evidently not. Fixes #121103. Fixes #121108. --- compiler/rustc_ast_lowering/src/expr.rs | 4 +++- compiler/rustc_mir_transform/src/lib.rs | 3 ++- tests/ui/lowering/issue-121108.rs | 9 +++++++++ tests/ui/lowering/issue-121108.stderr | 25 +++++++++++++++++++++++++ tests/ui/mir/issue-121103.rs | 3 +++ tests/ui/mir/issue-121103.stderr | 15 +++++++++++++++ 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lowering/issue-121108.rs create mode 100644 tests/ui/lowering/issue-121108.stderr create mode 100644 tests/ui/mir/issue-121103.rs create mode 100644 tests/ui/mir/issue-121103.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 73d1d891bb989..942aae3d53600 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -323,7 +323,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), - ExprKind::Err => hir::ExprKind::Err(self.dcx().has_errors().unwrap()), + ExprKind::Err => { + hir::ExprKind::Err(self.dcx().span_delayed_bug(e.span, "lowered ExprKind::Err")) + } ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), ExprKind::Paren(_) | ExprKind::ForLoop { .. } => { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index c11fd5fcc90c5..b4fa7f3bea6a0 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -265,7 +265,8 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { let body = &tcx.mir_const(def).borrow(); if body.return_ty().references_error() { - assert!(tcx.dcx().has_errors().is_some(), "mir_const_qualif: MIR had errors"); + // It's possible to reach here without an error being emitted (#121103). + tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors"); return Default::default(); } diff --git a/tests/ui/lowering/issue-121108.rs b/tests/ui/lowering/issue-121108.rs new file mode 100644 index 0000000000000..6b2dd24e4a842 --- /dev/null +++ b/tests/ui/lowering/issue-121108.rs @@ -0,0 +1,9 @@ +#![derive(Clone, Copy)] //~ ERROR `derive` attribute cannot be used at crate level + +use std::ptr::addr_of; + +const UNINHABITED_VARIANT: () = unsafe { + let v = *addr_of!(data).cast(); //~ ERROR cannot determine resolution for the macro `addr_of` +}; + +fn main() {} diff --git a/tests/ui/lowering/issue-121108.stderr b/tests/ui/lowering/issue-121108.stderr new file mode 100644 index 0000000000000..c2c5746d6f142 --- /dev/null +++ b/tests/ui/lowering/issue-121108.stderr @@ -0,0 +1,25 @@ +error: `derive` attribute cannot be used at crate level + --> $DIR/issue-121108.rs:1:1 + | +LL | #![derive(Clone, Copy)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | use std::ptr::addr_of; + | ------- the inner attribute doesn't annotate this `use` import + | +help: perhaps you meant to use an outer attribute + | +LL - #![derive(Clone, Copy)] +LL + #[derive(Clone, Copy)] + | + +error: cannot determine resolution for the macro `addr_of` + --> $DIR/issue-121108.rs:6:14 + | +LL | let v = *addr_of!(data).cast(); + | ^^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mir/issue-121103.rs b/tests/ui/mir/issue-121103.rs new file mode 100644 index 0000000000000..e06361a6964c0 --- /dev/null +++ b/tests/ui/mir/issue-121103.rs @@ -0,0 +1,3 @@ +fn main(_: as lib2::TypeFn>::Output) {} +//~^ ERROR failed to resolve: use of undeclared crate or module `lib2` +//~| ERROR failed to resolve: use of undeclared crate or module `lib2` diff --git a/tests/ui/mir/issue-121103.stderr b/tests/ui/mir/issue-121103.stderr new file mode 100644 index 0000000000000..913eee9e0c503 --- /dev/null +++ b/tests/ui/mir/issue-121103.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `lib2` + --> $DIR/issue-121103.rs:1:38 + | +LL | fn main(_: as lib2::TypeFn>::Output) {} + | ^^^^ use of undeclared crate or module `lib2` + +error[E0433]: failed to resolve: use of undeclared crate or module `lib2` + --> $DIR/issue-121103.rs:1:13 + | +LL | fn main(_: as lib2::TypeFn>::Output) {} + | ^^^^ use of undeclared crate or module `lib2` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. From a8d869e1d151d70137af8e7a03155cb6ac93139c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 13 Feb 2024 11:52:27 +0100 Subject: [PATCH 12/13] rustdoc: cross-crate re-exports: correctly render late-bound params in source order even if early-bound params are present --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/inline.rs | 50 +++++++++---- src/librustdoc/clean/mod.rs | 71 +++++++++---------- src/librustdoc/clean/types.rs | 7 +- src/librustdoc/json/conversions.rs | 25 +++---- .../early-late-bound-lifetime-params.rs | 17 +++++ .../early-late-bound-lifetime-params.rs | 17 +++++ 7 files changed, 119 insertions(+), 70 deletions(-) create mode 100644 tests/rustdoc/inline_cross/auxiliary/early-late-bound-lifetime-params.rs create mode 100644 tests/rustdoc/inline_cross/early-late-bound-lifetime-params.rs diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 9de547ba6dcef..8cc4201c3fc25 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -334,7 +334,7 @@ where match br { // We only care about named late bound regions, as we need to add them // to the 'for<>' section - ty::BrNamed(_, name) => Some(GenericParamDef::lifetime(name)), + ty::BrNamed(def_id, name) => Some(GenericParamDef::lifetime(def_id, name)), _ => None, } }) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 23a059c6e0302..e2f2c9a5e5663 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -18,8 +18,8 @@ use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ - self, clean_bound_vars, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, - clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, + self, clean_bound_vars, clean_generics, clean_impl_item, clean_middle_assoc_item, + clean_middle_field, clean_middle_ty, clean_poly_fn_sig, clean_trait_ref_with_bindings, clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes, AttributesExt, ImplKind, ItemId, Type, }; @@ -72,7 +72,9 @@ pub(crate) fn try_inline( } Res::Def(DefKind::Fn, did) => { record_extern_fqn(cx, did, ItemType::Function); - cx.with_param_env(did, |cx| clean::FunctionItem(build_external_function(cx, did))) + cx.with_param_env(did, |cx| { + clean::enter_impl_trait(cx, |cx| clean::FunctionItem(build_function(cx, did))) + }) } Res::Def(DefKind::Struct, did) => { record_extern_fqn(cx, did, ItemType::Struct); @@ -274,18 +276,38 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds } } -fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box { - let sig = cx.tcx.fn_sig(did).instantiate_identity(); - let predicates = cx.tcx.explicit_predicates_of(did); +pub(crate) fn build_function<'tcx>( + cx: &mut DocContext<'tcx>, + def_id: DefId, +) -> Box { + let sig = cx.tcx.fn_sig(def_id).instantiate_identity(); + // The generics need to be cleaned before the signature. + let mut generics = + clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id)); + let bound_vars = clean_bound_vars(sig.bound_vars()); + + // At the time of writing early & late-bound params are stored separately in rustc, + // namely in `generics.params` and `bound_vars` respectively. + // + // To reestablish the original source code order of the generic parameters, we + // need to manually sort them by their definition span after concatenation. + // + // See also: + // * https://rustc-dev-guide.rust-lang.org/bound-vars-and-params.html + // * https://rustc-dev-guide.rust-lang.org/what-does-early-late-bound-mean.html + let has_early_bound_params = !generics.params.is_empty(); + let has_late_bound_params = !bound_vars.is_empty(); + generics.params.extend(bound_vars); + if has_early_bound_params && has_late_bound_params { + // If this ever becomes a performances bottleneck either due to the sorting + // or due to the query calls, consider inserting the late-bound lifetime params + // right after the last early-bound lifetime param followed by only sorting + // the slice of lifetime params. + generics.params.sort_by_key(|param| cx.tcx.def_ident_span(param.def_id).unwrap()); + } + + let decl = clean_poly_fn_sig(cx, Some(def_id), sig); - let (generics, decl) = clean::enter_impl_trait(cx, |cx| { - // NOTE: generics need to be cleaned before the decl! - let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); - // FIXME: This does not place parameters in source order (late-bound ones come last) - generics.params.extend(clean_bound_vars(sig.bound_vars())); - let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig); - (generics, decl) - }); Box::new(clean::Function { decl, generics }) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f4527d1e55e85..c4a9243816e5c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -525,7 +525,6 @@ fn clean_generic_param_def<'tcx>( ( def.name, GenericParamDefKind::Type { - did: def.def_id, bounds: ThinVec::new(), // These are filled in from the where-clauses. default: default.map(Box::new), synthetic, @@ -557,7 +556,7 @@ fn clean_generic_param_def<'tcx>( ), }; - GenericParamDef { name, kind } + GenericParamDef { name, def_id: def.def_id, kind } } fn clean_generic_param<'tcx>( @@ -596,7 +595,6 @@ fn clean_generic_param<'tcx>( ( param.name.ident().name, GenericParamDefKind::Type { - did: param.def_id.to_def_id(), bounds, default: default.map(|t| clean_ty(t, cx)).map(Box::new), synthetic, @@ -614,7 +612,7 @@ fn clean_generic_param<'tcx>( ), }; - GenericParamDef { name, kind } + GenericParamDef { name, def_id: param.def_id.to_def_id(), kind } } /// Synthetic type-parameters are inserted after normal ones. @@ -646,8 +644,8 @@ pub(crate) fn clean_generics<'tcx>( let param = clean_generic_param(cx, Some(gens), param); match param.kind { GenericParamDefKind::Lifetime { .. } => unreachable!(), - GenericParamDefKind::Type { did, ref bounds, .. } => { - cx.impl_trait_bounds.insert(did.into(), bounds.to_vec()); + GenericParamDefKind::Type { ref bounds, .. } => { + cx.impl_trait_bounds.insert(param.def_id.into(), bounds.to_vec()); } GenericParamDefKind::Const { .. } => unreachable!(), } @@ -1064,8 +1062,11 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attrib match literal.kind { ast::LitKind::Int(a, _) => { let gen = func.generics.params.remove(0); - if let GenericParamDef { name, kind: GenericParamDefKind::Const { ty, .. } } = - gen + if let GenericParamDef { + name, + kind: GenericParamDefKind::Const { ty, .. }, + .. + } = gen { func.decl .inputs @@ -1169,7 +1170,7 @@ fn clean_fn_decl_with_args<'tcx>( FnDecl { inputs: args, output, c_variadic: decl.c_variadic } } -fn clean_fn_decl_from_did_and_sig<'tcx>( +fn clean_poly_fn_sig<'tcx>( cx: &mut DocContext<'tcx>, did: Option, sig: ty::PolyFnSig<'tcx>, @@ -1359,16 +1360,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } } ty::AssocKind::Fn => { - let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity(); - let mut generics = clean_ty_generics( - cx, - tcx.generics_of(assoc_item.def_id), - tcx.explicit_predicates_of(assoc_item.def_id), - ); - // FIXME: This does not place parameters in source order (late-bound ones come last) - generics.params.extend(clean_bound_vars(sig.bound_vars())); - - let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig); + let mut item = inline::build_function(cx, assoc_item.def_id); if assoc_item.fn_has_self_parameter { let self_ty = match assoc_item.container { @@ -1377,12 +1369,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } ty::TraitContainer => tcx.types.self_param, }; - let self_arg_ty = sig.input(0).skip_binder(); + let self_arg_ty = + tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder(); if self_arg_ty == self_ty { - decl.inputs.values[0].type_ = Generic(kw::SelfUpper); + item.decl.inputs.values[0].type_ = Generic(kw::SelfUpper); } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() { if ty == self_ty { - match decl.inputs.values[0].type_ { + match item.decl.inputs.values[0].type_ { BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper), _ => unreachable!(), } @@ -1399,9 +1392,9 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( ty::ImplContainer => Some(assoc_item.defaultness(tcx)), ty::TraitContainer => None, }; - MethodItem(Box::new(Function { generics, decl }), defaultness) + MethodItem(item, defaultness) } else { - TyMethodItem(Box::new(Function { generics, decl })) + TyMethodItem(item) } } ty::AssocKind::Type => { @@ -2109,7 +2102,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::FnDef(..) | ty::FnPtr(_) => { // FIXME: should we merge the outer and inner binders somehow? let sig = bound_ty.skip_binder().fn_sig(cx.tcx); - let decl = clean_fn_decl_from_did_and_sig(cx, None, sig); + let decl = clean_poly_fn_sig(cx, None, sig); let generic_params = clean_bound_vars(sig.bound_vars()); BareFunction(Box::new(BareFunctionDecl { @@ -2192,10 +2185,10 @@ pub(crate) fn clean_middle_ty<'tcx>( .iter() .flat_map(|pred| pred.bound_vars()) .filter_map(|var| match var { - ty::BoundVariableKind::Region(ty::BrNamed(_, name)) + ty::BoundVariableKind::Region(ty::BrNamed(def_id, name)) if name != kw::UnderscoreLifetime => { - Some(GenericParamDef::lifetime(name)) + Some(GenericParamDef::lifetime(def_id, name)) } _ => None, }) @@ -3167,20 +3160,22 @@ fn clean_bound_vars<'tcx>( bound_vars .into_iter() .filter_map(|var| match var { - ty::BoundVariableKind::Region(ty::BrNamed(_, name)) + ty::BoundVariableKind::Region(ty::BrNamed(def_id, name)) if name != kw::UnderscoreLifetime => { - Some(GenericParamDef::lifetime(name)) + Some(GenericParamDef::lifetime(def_id, name)) + } + ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name)) => { + Some(GenericParamDef { + name, + def_id, + kind: GenericParamDefKind::Type { + bounds: ThinVec::new(), + default: None, + synthetic: false, + }, + }) } - ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(did, name)) => Some(GenericParamDef { - name, - kind: GenericParamDefKind::Type { - did, - bounds: ThinVec::new(), - default: None, - synthetic: false, - }, - }), // FIXME(non_lifetime_binders): Support higher-ranked const parameters. ty::BoundVariableKind::Const => None, _ => None, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 96b4d1a45f6ea..9b7ec6e109a79 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1326,7 +1326,7 @@ impl WherePredicate { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericParamDefKind { Lifetime { outlives: ThinVec }, - Type { did: DefId, bounds: ThinVec, default: Option>, synthetic: bool }, + Type { bounds: ThinVec, default: Option>, synthetic: bool }, // Option> makes this type smaller than `Option` would. Const { ty: Box, default: Option>, is_host_effect: bool }, } @@ -1340,12 +1340,13 @@ impl GenericParamDefKind { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct GenericParamDef { pub(crate) name: Symbol, + pub(crate) def_id: DefId, pub(crate) kind: GenericParamDefKind, } impl GenericParamDef { - pub(crate) fn lifetime(name: Symbol) -> Self { - Self { name, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } } + pub(crate) fn lifetime(def_id: DefId, name: Symbol) -> Self { + Self { name, def_id, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } } } pub(crate) fn is_synthetic_param(&self) -> bool { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 32d7a80863d6d..cb50a27326fe5 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -456,7 +456,7 @@ impl FromWithTcx for GenericParamDefKind { Lifetime { outlives } => GenericParamDefKind::Lifetime { outlives: outlives.into_iter().map(convert_lifetime).collect(), }, - Type { did: _, bounds, default, synthetic } => GenericParamDefKind::Type { + Type { bounds, default, synthetic } => GenericParamDefKind::Type { bounds: bounds.into_tcx(tcx), default: default.map(|x| (*x).into_tcx(tcx)), synthetic, @@ -486,19 +486,16 @@ impl FromWithTcx for WherePredicate { outlives: outlives.iter().map(|lt| lt.0.to_string()).collect(), } } - clean::GenericParamDefKind::Type { - did: _, - bounds, - default, - synthetic, - } => GenericParamDefKind::Type { - bounds: bounds - .into_iter() - .map(|bound| bound.into_tcx(tcx)) - .collect(), - default: default.map(|ty| (*ty).into_tcx(tcx)), - synthetic, - }, + clean::GenericParamDefKind::Type { bounds, default, synthetic } => { + GenericParamDefKind::Type { + bounds: bounds + .into_iter() + .map(|bound| bound.into_tcx(tcx)) + .collect(), + default: default.map(|ty| (*ty).into_tcx(tcx)), + synthetic, + } + } clean::GenericParamDefKind::Const { ty, default, diff --git a/tests/rustdoc/inline_cross/auxiliary/early-late-bound-lifetime-params.rs b/tests/rustdoc/inline_cross/auxiliary/early-late-bound-lifetime-params.rs new file mode 100644 index 0000000000000..70f7a84a8dcc9 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/early-late-bound-lifetime-params.rs @@ -0,0 +1,17 @@ +// Here, `'a` and `'c` are late-bound and `'b`, `'d`, `T` and `N` are early-bound. + +pub fn f<'a, 'b, 'c, 'd, T, const N: usize>(_: impl Copy) +where + 'b:, + 'd:, +{} + +pub struct Ty; + +impl Ty { + pub fn f<'a, 'b, 'c, 'd, T, const N: usize>(_: impl Copy) + where + 'b:, + 'd:, + {} +} diff --git a/tests/rustdoc/inline_cross/early-late-bound-lifetime-params.rs b/tests/rustdoc/inline_cross/early-late-bound-lifetime-params.rs new file mode 100644 index 0000000000000..09cc8a79072b9 --- /dev/null +++ b/tests/rustdoc/inline_cross/early-late-bound-lifetime-params.rs @@ -0,0 +1,17 @@ +// Check that we correctly render late-bound lifetime params in source order +// even if early-bound generic params are present. +// +// For context, at the time of writing early- and late-bound params are stored +// separately in rustc and therefore rustdoc needs to manually merge them. + +#![crate_name = "usr"] +// aux-crate:dep=early-late-bound-lifetime-params.rs +// edition:2021 + +// @has usr/fn.f.html +// @has - '//pre[@class="rust item-decl"]' "fn f<'a, 'b, 'c, 'd, T, const N: usize>(_: impl Copy)" +pub use dep::f; + +// @has usr/struct.Ty.html +// @has - '//*[@id="method.f"]' "fn f<'a, 'b, 'c, 'd, T, const N: usize>(_: impl Copy)" +pub use dep::Ty; From e6a21f549ebf1437a59e9a0bb3c8e41172d1dcf7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Feb 2024 01:07:20 +0000 Subject: [PATCH 13/13] Enforce coroutine-closure layouts are identical --- .../src/transform/validate.rs | 20 +++++++++++++++++++ compiler/rustc_middle/src/mir/query.rs | 6 ++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b5c70538c52d3..1ff72516324c3 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -98,6 +98,26 @@ impl<'tcx> MirPass<'tcx> for Validator { } } } + + // Enforce that coroutine-closure layouts are identical. + if let Some(layout) = body.coroutine_layout() + && let Some(by_move_body) = body.coroutine_by_move_body() + && let Some(by_move_layout) = by_move_body.coroutine_layout() + { + if layout != by_move_layout { + // If this turns out not to be true, please let compiler-errors know. + // It is possible to support, but requires some changes to the layout + // computation code. + cfg_checker.fail( + Location::START, + format!( + "Coroutine layout differs from by-move coroutine layout:\n\ + layout: {layout:#?}\n\ + by_move_layout: {by_move_layout:#?}", + ), + ); + } + } } } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 90b6df1dd1f5e..8bd872c1b19e1 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -86,7 +86,8 @@ rustc_index::newtype_index! { pub struct CoroutineSavedLocal {} } -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct CoroutineSavedTy<'tcx> { pub ty: Ty<'tcx>, /// Source info corresponding to the local in the original MIR body. @@ -96,7 +97,8 @@ pub struct CoroutineSavedTy<'tcx> { } /// The layout of coroutine state. -#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, PartialEq, Eq)] +#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct CoroutineLayout<'tcx> { /// The type of every local stored inside the coroutine. pub field_tys: IndexVec>,