From 92fd960ca4144d43f5753019d950193cba9d4194 Mon Sep 17 00:00:00 2001 From: bendn Date: Sun, 16 Feb 2025 17:18:53 +0700 Subject: stabilize (const_)ptr_sub_ptr --- compiler/rustc_serialize/src/lib.rs | 1 - library/alloc/src/lib.rs | 1 - library/core/src/intrinsics/mod.rs | 1 + library/core/src/ptr/const_ptr.rs | 11 ++++----- library/core/src/ptr/mut_ptr.rs | 11 ++++----- library/core/src/ptr/non_null.rs | 10 ++++---- .../intrinsics/ptr_offset_from_unsigned_neg.rs | 2 -- src/tools/miri/tests/pass/ptr_offset.rs | 1 - tests/ui/consts/offset_from.rs | 3 --- tests/ui/consts/offset_from_ub.rs | 1 - tests/ui/consts/offset_from_ub.stderr | 28 +++++++++++----------- 11 files changed, 27 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 47f72298e22..9e9b78cfdd5 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -13,7 +13,6 @@ #![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(never_type)] -#![feature(ptr_sub_ptr)] #![feature(rustdoc_internals)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 1bb0f761064..6e4612b709c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -136,7 +136,6 @@ #![feature(pointer_like_trait)] #![feature(ptr_internals)] #![feature(ptr_metadata)] -#![feature(ptr_sub_ptr)] #![feature(set_ptr_value)] #![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 99c42f3626e..7cc604901ef 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3675,6 +3675,7 @@ pub const unsafe fn ptr_offset_from(_ptr: *const T, _base: *const T) -> isize #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] pub const unsafe fn ptr_offset_from_unsigned(_ptr: *const T, _base: *const T) -> usize { unimplemented!() } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 974946a7818..14693de0ae0 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -723,7 +723,6 @@ impl *const T { /// to [`sub`](#method.sub)). The following are all equivalent, assuming /// that their safety preconditions are met: /// ```rust - /// # #![feature(ptr_sub_ptr)] /// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { unsafe { /// ptr.sub_ptr(origin) == count /// # && @@ -752,8 +751,6 @@ impl *const T { /// # Examples /// /// ``` - /// #![feature(ptr_sub_ptr)] - /// /// let a = [0; 5]; /// let ptr1: *const i32 = &a[1]; /// let ptr2: *const i32 = &a[3]; @@ -767,8 +764,8 @@ impl *const T { /// // This would be incorrect, as the pointers are not correctly ordered: /// // ptr1.sub_ptr(ptr2) /// ``` - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub_ptr(self, origin: *const T) -> usize @@ -812,8 +809,8 @@ impl *const T { /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub_ptr(self, origin: *const U) -> usize { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 94ebd0d2522..6f9019ae088 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -895,7 +895,6 @@ impl *mut T { /// to [`sub`](#method.sub)). The following are all equivalent, assuming /// that their safety preconditions are met: /// ```rust - /// # #![feature(ptr_sub_ptr)] /// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { unsafe { /// ptr.sub_ptr(origin) == count /// # && @@ -924,8 +923,6 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_sub_ptr)] - /// /// let mut a = [0; 5]; /// let p: *mut i32 = a.as_mut_ptr(); /// unsafe { @@ -940,8 +937,8 @@ impl *mut T { /// /// // This would be incorrect, as the pointers are not correctly ordered: /// // ptr1.offset_from(ptr2) - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub_ptr(self, origin: *const T) -> usize @@ -962,8 +959,8 @@ impl *mut T { /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub_ptr(self, origin: *mut U) -> usize { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index f4ac00062d7..befb3ccb14b 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -856,7 +856,6 @@ impl NonNull { /// to [`sub`](#method.sub)). The following are all equivalent, assuming /// that their safety preconditions are met: /// ```rust - /// # #![feature(ptr_sub_ptr)] /// # unsafe fn blah(ptr: std::ptr::NonNull, origin: std::ptr::NonNull, count: usize) -> bool { unsafe { /// ptr.sub_ptr(origin) == count /// # && @@ -885,7 +884,6 @@ impl NonNull { /// # Examples /// /// ``` - /// #![feature(ptr_sub_ptr)] /// use std::ptr::NonNull; /// /// let a = [0; 5]; @@ -903,8 +901,8 @@ impl NonNull { /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn sub_ptr(self, subtracted: NonNull) -> usize where T: Sized, @@ -925,8 +923,8 @@ impl NonNull { /// ignoring the metadata. #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn byte_sub_ptr(self, origin: NonNull) -> usize { // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`. unsafe { self.as_ptr().byte_sub_ptr(origin.as_ptr()) } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs index 13eb5bfb342..13874398f7b 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs @@ -1,6 +1,4 @@ //@normalize-stderr-test: "\d+ < \d+" -> "$$ADDR < $$ADDR" -#![feature(ptr_sub_ptr)] - fn main() { let arr = [0u8; 8]; let ptr1 = arr.as_ptr(); diff --git a/src/tools/miri/tests/pass/ptr_offset.rs b/src/tools/miri/tests/pass/ptr_offset.rs index 92b275b0032..a8a0d2836e7 100644 --- a/src/tools/miri/tests/pass/ptr_offset.rs +++ b/src/tools/miri/tests/pass/ptr_offset.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(ptr_sub_ptr)] use std::{mem, ptr}; fn main() { diff --git a/tests/ui/consts/offset_from.rs b/tests/ui/consts/offset_from.rs index 7737b5ab0b8..c06314ac7df 100644 --- a/tests/ui/consts/offset_from.rs +++ b/tests/ui/consts/offset_from.rs @@ -1,8 +1,5 @@ //@ run-pass -#![feature(const_ptr_sub_ptr)] -#![feature(ptr_sub_ptr)] - struct Struct { field: (), } diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs index 88356900605..39384bf0c8b 100644 --- a/tests/ui/consts/offset_from_ub.rs +++ b/tests/ui/consts/offset_from_ub.rs @@ -1,5 +1,4 @@ //@ normalize-stderr: "\d+ bytes" -> "$$BYTES bytes" -#![feature(const_ptr_sub_ptr)] #![feature(core_intrinsics)] use std::intrinsics::{ptr_offset_from, ptr_offset_from_unsigned}; diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index 1379365cc25..8cfbdd13190 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:19:27 + --> $DIR/offset_from_ub.rs:18:27 | LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation @@ -12,67 +12,67 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `NOT_PTR` - --> $DIR/offset_from_ub.rs:25:14 + --> $DIR/offset_from_ub.rs:24:14 | LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:32:14 + --> $DIR/offset_from_ub.rs:31:14 | LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:39:14 + --> $DIR/offset_from_ub.rs:38:14 | LL | unsafe { ptr_offset_from(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:48:14 + --> $DIR/offset_from_ub.rs:47:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:57:14 + --> $DIR/offset_from_ub.rs:56:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:66:14 + --> $DIR/offset_from_ub.rs:65:14 | LL | unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:73:14 + --> $DIR/offset_from_ub.rs:72:14 | LL | unsafe { ptr_offset_from(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far ahead of second error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:79:14 + --> $DIR/offset_from_ub.rs:78:14 | LL | unsafe { ptr_offset_from(ptr1, ptr2) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:87:14 + --> $DIR/offset_from_ub.rs:86:14 | LL | unsafe { ptr_offset_from(ptr1, ptr2) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:94:14 + --> $DIR/offset_from_ub.rs:93:14 | LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8 error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:101:14 + --> $DIR/offset_from_ub.rs:100:14 | LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second @@ -85,7 +85,7 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR1` - --> $DIR/offset_from_ub.rs:110:14 + --> $DIR/offset_from_ub.rs:109:14 | LL | unsafe { ptr2.offset_from(ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR2` - --> $DIR/offset_from_ub.rs:116:14 + --> $DIR/offset_from_ub.rs:115:14 | LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 51d9a6c617b6e7357b506e59a4b4a64e5e63a825 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 29 Jan 2025 06:31:50 +0000 Subject: Track where crate dependencies come from in `creader` Introduce an enum that represents the different possible sources for dependencies, and use them where possible. This will enable more fine grained control and provides better context than passing the `dep_root` tuple. Use this to ensure that injected crates always show up as private by default. --- compiler/rustc_metadata/src/creader.rs | 93 ++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index c2dda21bb72..9efe18af863 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -162,6 +162,39 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { } } +/// Reason that a crate is being sourced as a dependency. +#[derive(Clone, Copy)] +enum CrateOrigin<'a> { + /// This crate was a dependency of another crate. + IndirectDependency { + dep_root: &'a CratePaths, + /// Dependency info about this crate. + dep: &'a CrateDep, + }, + /// Injected by `rustc`. + Injected, + /// Provided by `extern crate foo` or as part of the extern prelude. + Extern, +} + +impl<'a> CrateOrigin<'a> { + /// Return the dependency root, if any. + fn dep_root(&self) -> Option<&'a CratePaths> { + match self { + CrateOrigin::IndirectDependency { dep_root, .. } => Some(dep_root), + _ => None, + } + } + + /// Return dependency information, if any. + fn dep(&self) -> Option<&'a CrateDep> { + match self { + CrateOrigin::IndirectDependency { dep, .. } => Some(dep), + _ => None, + } + } +} + impl CStore { pub fn from_tcx(tcx: TyCtxt<'_>) -> FreezeReadGuard<'_, CStore> { FreezeReadGuard::map(tcx.untracked().cstore.read(), |cstore| { @@ -497,7 +530,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &self, name: Symbol, private_dep: Option, - dep_root: Option<&CratePaths>, + origin: CrateOrigin<'_>, ) -> bool { // Standard library crates are never private. if STDLIB_STABLE_CRATES.contains(&name) { @@ -505,12 +538,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { return false; } + if matches!(origin, CrateOrigin::Injected) { + return true; + } + let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep); // Any descendants of `std` should be private. These crates are usually not marked // private in metadata, so we ignore that field. if extern_private.is_none() - && let Some(dep) = dep_root + && let Some(dep) = origin.dep_root() && STDLIB_STABLE_CRATES.contains(&dep.name) { return true; @@ -528,7 +565,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { fn register_crate( &mut self, host_lib: Option, - dep_root: Option<&CratePaths>, + origin: CrateOrigin<'_>, lib: Library, dep_kind: CrateDepKind, name: Symbol, @@ -540,7 +577,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - let private_dep = self.is_private_dep(name, private_dep, dep_root); + let private_dep = self.is_private_dep(name, private_dep, origin); // Claim this crate number and cache it let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?; @@ -556,7 +593,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Maintain a reference to the top most crate. // Stash paths for top-most crate locally if necessary. let crate_paths; - let dep_root = if let Some(dep_root) = dep_root { + let dep_root = if let Some(dep_root) = origin.dep_root() { dep_root } else { crate_paths = CratePaths::new(crate_root.name(), source.clone()); @@ -664,17 +701,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { name: Symbol, span: Span, dep_kind: CrateDepKind, + origin: CrateOrigin<'_>, ) -> Option { self.used_extern_options.insert(name); - match self.maybe_resolve_crate(name, dep_kind, None) { + match self.maybe_resolve_crate(name, dep_kind, origin) { Ok(cnum) => { self.cstore.set_used_recursively(cnum); Some(cnum) } Err(err) => { debug!("failed to resolve crate {} {:?}", name, dep_kind); - let missing_core = - self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); + let missing_core = self + .maybe_resolve_crate(sym::core, CrateDepKind::Explicit, CrateOrigin::Extern) + .is_err(); err.report(self.sess, span, missing_core); None } @@ -685,15 +724,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &'b mut self, name: Symbol, mut dep_kind: CrateDepKind, - dep_of: Option<(&'b CratePaths, &'b CrateDep)>, + origin: CrateOrigin<'b>, ) -> Result { info!("resolving crate `{}`", name); if !name.as_str().is_ascii() { return Err(CrateError::NonAsciiName(name)); } - let dep_root = dep_of.map(|d| d.0); - let dep = dep_of.map(|d| d.1); + let dep_root = origin.dep_root(); + let dep = origin.dep(); let hash = dep.map(|d| d.hash); let host_hash = dep.map(|d| d.host_hash).flatten(); let extra_filename = dep.map(|d| &d.extra_filename[..]); @@ -736,7 +775,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to // `public-dependency` here. - let private_dep = self.is_private_dep(name, private_dep, dep_root); + let private_dep = self.is_private_dep(name, private_dep, origin); let data = self.cstore.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; @@ -747,7 +786,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } (LoadResult::Loaded(library), host_library) => { info!("register newly loaded library for `{}`", name); - self.register_crate(host_library, dep_root, library, dep_kind, name, private_dep) + self.register_crate(host_library, origin, library, dep_kind, name, private_dep) } _ => panic!(), } @@ -823,7 +862,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly, _ => dep.kind, }; - let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((dep_root, &dep)))?; + let cnum = self.maybe_resolve_crate( + dep.name, + dep_kind, + CrateOrigin::IndirectDependency { dep_root, dep: &dep }, + )?; crate_num_map.push(cnum); } @@ -917,7 +960,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { }; info!("panic runtime not found -- loading {}", name); - let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { + let Some(cnum) = + self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + else { return; }; let data = self.cstore.get_crate_data(cnum); @@ -946,7 +991,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("loading profiler"); let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); - let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { + let Some(cnum) = + self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + else { return; }; let data = self.cstore.get_crate_data(cnum); @@ -1059,7 +1106,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { if entry.force { let name_interned = Symbol::intern(name); if !self.used_extern_options.contains(&name_interned) { - self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit); + self.resolve_crate( + name_interned, + DUMMY_SP, + CrateDepKind::Explicit, + CrateOrigin::Extern, + ); } } } @@ -1185,6 +1237,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("{:?}", CrateDump(self.cstore)); } + /// Process an `extern crate foo` AST node. pub fn process_extern_crate( &mut self, item: &ast::Item, @@ -1210,7 +1263,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind)?; + let cnum = self.resolve_crate(name, item.span, dep_kind, CrateOrigin::Extern)?; let path_len = definitions.def_path(def_id).data.len(); self.cstore.update_extern_crate( @@ -1229,7 +1282,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?; + let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?; self.cstore.update_extern_crate( cnum, @@ -1246,7 +1299,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { - self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok() + self.maybe_resolve_crate(name, CrateDepKind::Explicit, CrateOrigin::Extern).ok() } } -- cgit 1.4.1-3-g733a5 From 83d70c029860e619f8cb91f15bfc34f7f2d7965f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 29 Jan 2025 23:45:36 +0000 Subject: Improve debugging for metadata structures I had to do a lot of debug by printing; having these `Debug` traits in place made it easier. Additionally, add some more information to existing `info!` statements. --- compiler/rustc_metadata/src/creader.rs | 3 ++- compiler/rustc_metadata/src/locator.rs | 10 ++++++---- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 9efe18af863..582572586cf 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -147,6 +147,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { writeln!(fmt, " cnum: {cnum}")?; writeln!(fmt, " hash: {}", data.hash())?; writeln!(fmt, " reqd: {:?}", data.dep_kind())?; + writeln!(fmt, " priv: {:?}", data.is_private_dep())?; let CrateSource { dylib, rlib, rmeta } = data.source(); if let Some(dylib) = dylib { writeln!(fmt, " dylib: {}", dylib.0.display())?; @@ -770,7 +771,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { match result { (LoadResult::Previous(cnum), None) => { - info!("library for `{}` was loaded previously", name); + info!("library for `{}` was loaded previously, cnum {cnum}", name); // When `private_dep` is none, it indicates the directly dependent crate. If it is // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2ddabeb49f7..3f3e58384cb 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -260,7 +260,7 @@ pub(crate) struct CrateLocator<'a> { crate_rejections: CrateRejections, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub(crate) struct CratePaths { pub(crate) name: Symbol, source: CrateSource, @@ -272,7 +272,7 @@ impl CratePaths { } } -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub(crate) enum CrateFlavor { Rlib, Rmeta, @@ -893,13 +893,13 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor { // ------------------------------------------ Error reporting ------------------------------------- -#[derive(Clone)] +#[derive(Clone, Debug)] struct CrateMismatch { path: PathBuf, got: String, } -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] struct CrateRejections { via_hash: Vec, via_triple: Vec, @@ -912,6 +912,7 @@ struct CrateRejections { /// Candidate rejection reasons collected during crate search. /// If no candidate is accepted, then these reasons are presented to the user, /// otherwise they are ignored. +#[derive(Debug)] pub(crate) struct CombinedLocatorError { crate_name: Symbol, dep_root: Option, @@ -921,6 +922,7 @@ pub(crate) struct CombinedLocatorError { crate_rejections: CrateRejections, } +#[derive(Debug)] pub(crate) enum CrateError { NonAsciiName(Symbol), ExternLocationNotExist(Symbol, PathBuf), diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e8dcda875e6..0516179f62c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1936,6 +1936,10 @@ impl CrateMetadata { self.root.needs_panic_runtime } + pub(crate) fn is_private_dep(&self) -> bool { + self.private_dep + } + pub(crate) fn is_panic_runtime(&self) -> bool { self.root.panic_runtime } -- cgit 1.4.1-3-g733a5 From efff15afeabedacc2798d214dac404061df1555d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 13:40:58 -0800 Subject: compiler: Align::max_for_offset -> Align::max_aligned_factor No functional changes. --- compiler/rustc_abi/src/lib.rs | 17 ++++++++--------- compiler/rustc_ty_utils/src/layout.rs | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 098638b6bcf..761df0ba1ce 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -810,20 +810,19 @@ impl Align { self.bits().try_into().unwrap() } - /// Computes the best alignment possible for the given offset - /// (the largest power of two that the offset is a multiple of). + /// Obtain the greatest factor of `size` that is an alignment + /// (the largest power of two the Size is a multiple of). /// - /// N.B., for an offset of `0`, this happens to return `2^64`. + /// Note that all numbers are factors of 0 #[inline] - pub fn max_for_offset(offset: Size) -> Align { - Align { pow2: offset.bytes().trailing_zeros() as u8 } + pub fn max_aligned_factor(size: Size) -> Align { + Align { pow2: size.bytes().trailing_zeros() as u8 } } - /// Lower the alignment, if necessary, such that the given offset - /// is aligned to it (the offset is a multiple of the alignment). + /// Reduces Align to an aligned factor of `size`. #[inline] - pub fn restrict_for_offset(self, offset: Size) -> Align { - self.min(Align::max_for_offset(offset)) + pub fn restrict_for_offset(self, size: Size) -> Align { + self.min(Align::max_aligned_factor(size)) } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b6a14d147ca..e95c95ed6c5 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -534,7 +534,7 @@ fn layout_of_uncached<'tcx>( ( BackendRepr::Memory { sized: true }, AbiAndPrefAlign { - abi: Align::max_for_offset(size), + abi: Align::max_aligned_factor(size), pref: dl.vector_align(size).pref, }, ) -- cgit 1.4.1-3-g733a5 From 5c474fd99b97b0d86d410dfe25b876b374b436fa Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 18:53:15 -0800 Subject: compiler: `BackendRepr::inherent_{size,align} -> scalar_{size,align}` This pair of fn was introduced to perform invariant checks for scalars. Their current behavior doesn't mesh as well with checking SIMD types, so change the name of the fn to reflect their actual use-case and refactor the corresponding checks. Also simplify the returns from Option to Option, because every site was mapping away the "preferred" alignment anyways. --- compiler/rustc_abi/src/layout.rs | 37 ++++++++++------- compiler/rustc_abi/src/lib.rs | 53 +++++++++++++------------ compiler/rustc_ty_utils/src/layout/invariant.rs | 51 +++++++++++++----------- 3 files changed, 78 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 53243266f99..3f83787ea37 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -310,10 +310,10 @@ impl LayoutCalculator { let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; - // If all the non-ZST fields have the same ABI and union ABI optimizations aren't - // disabled, we can use that common ABI for the union as a whole. + // If all the non-ZST fields have the same repr and union repr optimizations aren't + // disabled, we can use that common repr for the union as a whole. struct AbiMismatch; - let mut common_non_zst_abi_and_align = if repr.inhibits_union_abi_opt() { + let mut common_non_zst_repr_and_align = if repr.inhibits_union_abi_opt() { // Can't optimize Err(AbiMismatch) } else { @@ -337,14 +337,14 @@ impl LayoutCalculator { continue; } - if let Ok(common) = common_non_zst_abi_and_align { + if let Ok(common) = common_non_zst_repr_and_align { // Discard valid range information and allow undef let field_abi = field.backend_repr.to_union(); if let Some((common_abi, common_align)) = common { if common_abi != field_abi { // Different fields have different ABI: disable opt - common_non_zst_abi_and_align = Err(AbiMismatch); + common_non_zst_repr_and_align = Err(AbiMismatch); } else { // Fields with the same non-Aggregate ABI should also // have the same alignment @@ -357,7 +357,7 @@ impl LayoutCalculator { } } else { // First non-ZST field: record its ABI and alignment - common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi))); + common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi))); } } } @@ -376,16 +376,25 @@ impl LayoutCalculator { // If all non-ZST fields have the same ABI, we may forward that ABI // for the union as a whole, unless otherwise inhibited. - let abi = match common_non_zst_abi_and_align { + let backend_repr = match common_non_zst_repr_and_align { Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true }, - Ok(Some((abi, _))) => { - if abi.inherent_align(dl).map(|a| a.abi) != Some(align.abi) { - // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt + Ok(Some((repr, _))) => match repr { + // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(_, _) + if repr.scalar_align(dl).unwrap() != align.abi => + { BackendRepr::Memory { sized: true } - } else { - abi } - } + // Vectors require at least element alignment, else disable the opt + BackendRepr::Vector { element, count: _ } if element.align(dl).abi > align.abi => { + BackendRepr::Memory { sized: true } + } + // the alignment tests passed and we can use this + BackendRepr::Scalar(..) + | BackendRepr::ScalarPair(..) + | BackendRepr::Vector { .. } + | BackendRepr::Memory { .. } => repr, + }, }; let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else { @@ -400,7 +409,7 @@ impl LayoutCalculator { Ok(LayoutData { variants: Variants::Single { index: only_variant_idx }, fields: FieldsShape::Union(union_field_count), - backend_repr: abi, + backend_repr, largest_niche: None, uninhabited: false, align, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 761df0ba1ce..43a7141472c 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1454,37 +1454,38 @@ impl BackendRepr { matches!(*self, BackendRepr::Scalar(s) if s.is_bool()) } - /// Returns the fixed alignment of this ABI, if any is mandated. - pub fn inherent_align(&self, cx: &C) -> Option { - Some(match *self { - BackendRepr::Scalar(s) => s.align(cx), - BackendRepr::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)), - BackendRepr::Vector { element, count } => { - cx.data_layout().vector_align(element.size(cx) * count) - } - BackendRepr::Memory { .. } => return None, - }) + /// The psABI alignment for a `Scalar` or `ScalarPair` + /// + /// `None` for other variants. + pub fn scalar_align(&self, cx: &C) -> Option { + match *self { + BackendRepr::Scalar(s) => Some(s.align(cx).abi), + BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi), + // The align of a Vector can vary in surprising ways + BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None, + } } - /// Returns the fixed size of this ABI, if any is mandated. - pub fn inherent_size(&self, cx: &C) -> Option { - Some(match *self { - BackendRepr::Scalar(s) => { - // No padding in scalars. - s.size(cx) - } + /// The psABI size for a `Scalar` or `ScalarPair` + /// + /// `None` for other variants + pub fn scalar_size(&self, cx: &C) -> Option { + match *self { + // No padding in scalars. + BackendRepr::Scalar(s) => Some(s.size(cx)), + // May have some padding between the pair. BackendRepr::ScalarPair(s1, s2) => { - // May have some padding between the pair. let field2_offset = s1.size(cx).align_to(s2.align(cx).abi); - (field2_offset + s2.size(cx)).align_to(self.inherent_align(cx)?.abi) - } - BackendRepr::Vector { element, count } => { - // No padding in vectors, except possibly for trailing padding - // to make the size a multiple of align (e.g. for vectors of size 3). - (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi) + let size = (field2_offset + s2.size(cx)).align_to( + self.scalar_align(cx) + // We absolutely must have an answer here or everything is FUBAR. + .unwrap(), + ); + Some(size) } - BackendRepr::Memory { .. } => return None, - }) + // The size of a Vector can vary in surprising ways + BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None, + } } /// Discard validity range information and allow undef. diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 5ea6716c5ca..cbbe993b62f 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -69,31 +69,30 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou } fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { - // Verify the ABI mandated alignment and size. - let align = layout.backend_repr.inherent_align(cx).map(|align| align.abi); - let size = layout.backend_repr.inherent_size(cx); - let Some((align, size)) = align.zip(size) else { - assert_matches!( - layout.layout.backend_repr(), - BackendRepr::Memory { .. }, - "ABI unexpectedly missing alignment and/or size in {layout:#?}" + // Verify the ABI-mandated alignment and size for scalars. + let align = layout.backend_repr.scalar_align(cx); + let size = layout.backend_repr.scalar_size(cx); + if let Some(align) = align { + assert_eq!( + layout.layout.align().abi, + align, + "alignment mismatch between ABI and layout in {layout:#?}" ); - return; - }; - assert_eq!( - layout.layout.align().abi, - align, - "alignment mismatch between ABI and layout in {layout:#?}" - ); - assert_eq!( - layout.layout.size(), - size, - "size mismatch between ABI and layout in {layout:#?}" - ); + } + if let Some(size) = size { + assert_eq!( + layout.layout.size(), + size, + "size mismatch between ABI and layout in {layout:#?}" + ); + } // Verify per-ABI invariants match layout.layout.backend_repr() { BackendRepr::Scalar(_) => { + // These must always be present for `Scalar` types. + let align = align.unwrap(); + let size = size.unwrap(); // Check that this matches the underlying field. let inner = skip_newtypes(cx, layout); assert!( @@ -235,9 +234,15 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou "`ScalarPair` second field with bad ABI in {inner:#?}", ); } - BackendRepr::Vector { element, .. } => { - assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`. - // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair. + BackendRepr::Vector { element, count } => { + let align = layout.align.abi; + let size = layout.size; + let element_align = element.align(cx).abi; + let element_size = element.size(cx); + // Currently, vectors must always be aligned to at least their elements: + assert!(align >= element_align); + // And the size has to be element * count plus alignment padding, of course + assert!(size == (element_size * count).align_to(align)); } BackendRepr::Memory { .. } => {} // Nothing to check. } -- cgit 1.4.1-3-g733a5 From 79f41c773aaad6a10c2c752d223bd5aba0371f9b Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 19 Feb 2025 14:53:31 -0800 Subject: compiler: split vector_align into cabi and llvmlike Introduce a pair of functions that actually describe what they do, because it wasn't clear the alignment is sometimes a forgery. --- compiler/rustc_abi/src/callconv/reg.rs | 2 +- compiler/rustc_abi/src/lib.rs | 23 ++++++++++++++--------- compiler/rustc_ty_utils/src/layout.rs | 7 +++++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs index 66f47c52c15..8cf140dbaad 100644 --- a/compiler/rustc_abi/src/callconv/reg.rs +++ b/compiler/rustc_abi/src/callconv/reg.rs @@ -57,7 +57,7 @@ impl Reg { 128 => dl.f128_align.abi, _ => panic!("unsupported float: {self:?}"), }, - RegKind::Vector => dl.vector_align(self.size).abi, + RegKind::Vector => dl.llvmlike_vector_align(self.size).abi, } } } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 43a7141472c..094a25129ae 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -408,16 +408,21 @@ impl TargetDataLayout { } } + /// psABI-mandated alignment for a vector type, if any #[inline] - pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { - for &(size, align) in &self.vector_align { - if size == vec_size { - return align; - } - } - // Default to natural alignment, which is what LLVM does. - // That is, use the size, rounded up to a power of 2. - AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap()) + fn cabi_vector_align(&self, vec_size: Size) -> Option { + self.vector_align + .iter() + .find(|(size, _align)| *size == vec_size) + .map(|(_size, align)| *align) + } + + /// an alignment resembling the one LLVM would pick for a vector + #[inline] + pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { + self.cabi_vector_align(vec_size).unwrap_or(AbiAndPrefAlign::new( + Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(), + )) } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index e95c95ed6c5..0b5683bb84b 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -535,11 +535,14 @@ fn layout_of_uncached<'tcx>( BackendRepr::Memory { sized: true }, AbiAndPrefAlign { abi: Align::max_aligned_factor(size), - pref: dl.vector_align(size).pref, + pref: dl.llvmlike_vector_align(size).pref, }, ) } else { - (BackendRepr::Vector { element: e_abi, count: e_len }, dl.vector_align(size)) + ( + BackendRepr::Vector { element: e_abi, count: e_len }, + dl.llvmlike_vector_align(size), + ) }; let size = size.align_to(align.abi); -- cgit 1.4.1-3-g733a5 From 46f7a7d378972b4034118f798657a6d35091a4ca Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 19:27:26 -0800 Subject: rust-analyzer: use new function in (incorrect) layout computation This is only to fix the build. --- src/tools/rust-analyzer/crates/hir-ty/src/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index f5a7b658123..a72bcad50a0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -179,7 +179,7 @@ fn layout_of_simd_ty( .size .checked_mul(e_len, dl) .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?; - let align = dl.vector_align(size); + let align = dl.llvmlike_vector_align(size); let size = size.align_to(align.abi); // Compute the placement of the vector fields: -- cgit 1.4.1-3-g733a5 From ad962ed131aa3bfebc55b381bc93bae93667d3ee Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 21 Feb 2025 16:50:23 +0100 Subject: stabilize `unsigned_is_multiple_of` --- library/core/src/num/uint_macros.rs | 4 ++-- library/coretests/tests/lib.rs | 1 - src/tools/miri/src/lib.rs | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 74d3ae699f6..6139d8540de 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -3274,14 +3274,14 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// #![feature(unsigned_is_multiple_of)] #[doc = concat!("assert!(6_", stringify!($SelfT), ".is_multiple_of(2));")] #[doc = concat!("assert!(!5_", stringify!($SelfT), ".is_multiple_of(2));")] /// #[doc = concat!("assert!(0_", stringify!($SelfT), ".is_multiple_of(0));")] #[doc = concat!("assert!(!6_", stringify!($SelfT), ".is_multiple_of(0));")] /// ``` - #[unstable(feature = "unsigned_is_multiple_of", issue = "128101")] + #[stable(feature = "unsigned_is_multiple_of", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unsigned_is_multiple_of", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] #[rustc_inherit_overflow_checks] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 25c7d10e0bd..08577eeeb62 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -87,7 +87,6 @@ #![feature(try_blocks)] #![feature(try_find)] #![feature(try_trait_v2)] -#![feature(unsigned_is_multiple_of)] #![feature(unsize)] #![feature(unsized_tuple_coercion)] #![feature(unwrap_infallible)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 44e4f1a2932..3b89f4a20d7 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -16,7 +16,6 @@ #![feature(unqualified_local_imports)] #![feature(derive_coerce_pointee)] #![feature(arbitrary_self_types)] -#![feature(unsigned_is_multiple_of)] #![feature(extract_if)] // Configure clippy and other lints #![allow( -- cgit 1.4.1-3-g733a5 From 1412cfc987b2b6691367c2e7428c083bb207d722 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 29 Jan 2025 23:54:15 +0000 Subject: Inject `compiler_builtins` during postprocessing rather than via AST `compiler_builtins` is currently injected as `extern crate compiler_builtins as _`. This has made gating via diagnostics difficult because it appears in the crate graph as a non-private dependency, and there isn't an easy way to differentiate between the injected AST and user-specified `extern crate compiler_builtins`. Resolve this by injecting `compiler_builtins` during postprocessing rather than early in the AST. Most of the time this isn't even needed because it shows up in `std` or `core`'s crate graph, but injection is still needed to ensure `#![no_core]` works correctly. A similar change was attempted at [1] but this encountered errors building `proc_macro` and `rustc-std-workspace-std`. Similar failures showed up while working on this patch, which were traced back to `compiler_builtins` showing up in the graph twice (once via dependency and once via injection). This is resolved by not injecting if a `#![compiler_builtins]` crate already exists. [1]: https://github.com/rust-lang/rust/pull/113634 --- .../src/standard_library_imports.rs | 49 ++++++---------------- compiler/rustc_metadata/messages.ftl | 3 ++ compiler/rustc_metadata/src/creader.rs | 38 +++++++++++++++++ compiler/rustc_metadata/src/errors.rs | 6 +++ compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++ tests/ui/extern-flag/empty-extern-arg.stderr | 8 +--- .../proc-macro/issue-59191-replace-root-with-fn.rs | 3 +- .../issue-59191-replace-root-with-fn.stderr | 13 +++--- tests/ui/proc-macro/meta-macro-hygiene.stdout | 1 - .../ui/proc-macro/nonterminal-token-hygiene.stdout | 1 - 10 files changed, 73 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 1a3f4d2d449..6933ca09349 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -19,16 +19,12 @@ pub fn inject( let edition = sess.psess.edition; // the first name in this list is the crate name of the crate with the prelude - let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) { + let name: Symbol = if attr::contains_name(pre_configured_attrs, sym::no_core) { return 0; } else if attr::contains_name(pre_configured_attrs, sym::no_std) { - if attr::contains_name(pre_configured_attrs, sym::compiler_builtins) { - &[sym::core] - } else { - &[sym::core, sym::compiler_builtins] - } + sym::core } else { - &[sym::std] + sym::std }; let expn_id = resolver.expansion_for_ast_pass( @@ -43,36 +39,16 @@ pub fn inject( let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features); let cx = ExtCtxt::new(sess, ecfg, resolver, None); - // .rev() to preserve ordering above in combination with insert(0, ...) - for &name in names.iter().rev() { - let ident_span = if edition >= Edition2018 { span } else { call_site }; - let item = if name == sym::compiler_builtins { - // compiler_builtins is a private implementation detail. We only - // need to insert it into the crate graph for linking and should not - // expose any of its public API. - // - // FIXME(#113634) We should inject this during post-processing like - // we do for the panic runtime, profiler runtime, etc. - cx.item( - span, - Ident::new(kw::Underscore, ident_span), - thin_vec![], - ast::ItemKind::ExternCrate(Some(name)), - ) - } else { - cx.item( - span, - Ident::new(name, ident_span), - thin_vec![cx.attr_word(sym::macro_use, span)], - ast::ItemKind::ExternCrate(None), - ) - }; - krate.items.insert(0, item); - } + let ident_span = if edition >= Edition2018 { span } else { call_site }; - // The crates have been injected, the assumption is that the first one is - // the one with the prelude. - let name = names[0]; + let item = cx.item( + span, + Ident::new(name, ident_span), + thin_vec![cx.attr_word(sym::macro_use, span)], + ast::ItemKind::ExternCrate(None), + ); + + krate.items.insert(0, item); let root = (edition == Edition2015).then_some(kw::PathRoot); @@ -88,6 +64,7 @@ pub fn inject( .map(|&symbol| Ident::new(symbol, span)) .collect(); + // Inject the relevant crate's prelude. let use_item = cx.item( span, Ident::empty(), diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 6fc84b06647..df0a25712cc 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -47,6 +47,9 @@ metadata_crate_dep_rustc_driver = metadata_crate_location_unknown_type = extern location for {$crate_name} is of an unknown type: {$path} +metadata_crate_not_compiler_builtins = + the crate `{$crate_name}` resolved as `compiler_builtins` but is not `#![compiler_builtins]` + metadata_crate_not_panic_runtime = the crate `{$crate_name}` is not a panic runtime diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 582572586cf..a935bc3662d 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1118,6 +1118,43 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } + /// Inject the `compiler_builtins` crate if it is not already in the graph. + fn inject_compiler_builtins(&mut self, krate: &ast::Crate) { + // `compiler_builtins` does not get extern builtins, nor do `#![no_core]` crates + if attr::contains_name(&krate.attrs, sym::compiler_builtins) + || attr::contains_name(&krate.attrs, sym::no_core) + { + info!("`compiler_builtins` unneeded"); + return; + } + + // If a `#![compiler_builtins]` crate already exists, avoid injecting it twice. This is + // the common case since usually it appears as a dependency of `std` or `alloc`. + for (cnum, cmeta) in self.cstore.iter_crate_data() { + if cmeta.is_compiler_builtins() { + info!("`compiler_builtins` already exists (cnum = {cnum}); skipping injection"); + return; + } + } + + // `compiler_builtins` is not yet in the graph; inject it. Error on resolution failure. + let Some(cnum) = self.resolve_crate( + sym::compiler_builtins, + krate.spans.inner_span.shrink_to_lo(), + CrateDepKind::Explicit, + CrateOrigin::Injected, + ) else { + info!("`compiler_builtins` not resolved"); + return; + }; + + // Sanity check that the loaded crate is `#![compiler_builtins]` + let cmeta = self.cstore.get_crate_data(cnum); + if !cmeta.is_compiler_builtins() { + self.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() }); + } + } + fn inject_dependency_if( &mut self, krate: CrateNum, @@ -1227,6 +1264,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } pub fn postprocess(&mut self, krate: &ast::Crate) { + self.inject_compiler_builtins(krate); self.inject_forced_externs(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index a77f9bc623b..2ad6389c0b4 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -332,6 +332,12 @@ pub struct CrateNotPanicRuntime { pub crate_name: Symbol, } +#[derive(Diagnostic)] +#[diag(metadata_crate_not_compiler_builtins)] +pub struct CrateNotCompilerBuiltins { + pub crate_name: Symbol, +} + #[derive(Diagnostic)] #[diag(metadata_no_panic_strategy)] pub struct NoPanicStrategy { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 0516179f62c..ef0267eb3d9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1948,6 +1948,10 @@ impl CrateMetadata { self.root.profiler_runtime } + pub(crate) fn is_compiler_builtins(&self) -> bool { + self.root.compiler_builtins + } + pub(crate) fn needs_allocator(&self) -> bool { self.root.needs_allocator } diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index b9a128e02e1..79efcc5d8b0 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -7,11 +7,5 @@ error: unwinding panics are not supported without std = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem -error: requires `sized` lang_item - --> $DIR/empty-extern-arg.rs:6:11 - | -LL | fn main() {} - | ^^ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs index c1b55fd99df..6afafb7114a 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -3,7 +3,8 @@ //@ edition:2018 //@ proc-macro: issue-59191.rs -//@ error-pattern: requires `sized` lang_item +//@ needs-unwind (affects error output) +//@ error-pattern: error: `#[panic_handler]` function required #![feature(custom_inner_attributes)] #![issue_59191::no_main] diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr index 2d0c92ff297..3cd98d9c72b 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr @@ -1,10 +1,9 @@ -error: requires `sized` lang_item - --> $DIR/issue-59191-replace-root-with-fn.rs:9:1 - | -LL | #![issue_59191::no_main] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +error: `#[panic_handler]` function required, but not found + +error: unwinding panics are not supported without std | - = note: this error originates in the attribute macro `issue_59191::no_main` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index fae8446515a..1ee7179e84c 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -20,7 +20,6 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#1 */; -extern crate compiler_builtins /* NNN */ as _ /* 0#1 */; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index e7dda7d3c16..c80a33206fb 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -39,7 +39,6 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#2 */; -extern crate compiler_builtins /* NNN */ as _ /* 0#2 */; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; -- cgit 1.4.1-3-g733a5 From cb1d076d42e9285488436688b8879225ab6db80e Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 14 Jan 2025 20:04:59 +0000 Subject: Partially revert ed63539282 ("Mark dependencies ... private by default") Remove the portion of ed63539282 that automatically sets crates private based on whether they are dependencies of `std`. Instead, this is controlled by dependency configuration in `Cargo.toml`. --- compiler/rustc_metadata/src/creader.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index a935bc3662d..b94e32e17d4 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -32,7 +32,7 @@ use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; use rustc_span::edition::Edition; -use rustc_span::{DUMMY_SP, Ident, STDLIB_STABLE_CRATES, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, Target, TargetTuple}; use tracing::{debug, info, trace}; @@ -533,27 +533,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { private_dep: Option, origin: CrateOrigin<'_>, ) -> bool { - // Standard library crates are never private. - if STDLIB_STABLE_CRATES.contains(&name) { - tracing::info!("returning false for {name} is private"); - return false; - } - if matches!(origin, CrateOrigin::Injected) { return true; } let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep); - - // Any descendants of `std` should be private. These crates are usually not marked - // private in metadata, so we ignore that field. - if extern_private.is_none() - && let Some(dep) = origin.dep_root() - && STDLIB_STABLE_CRATES.contains(&dep.name) - { - return true; - } - match (extern_private, private_dep) { // Explicit non-private via `--extern`, explicit non-private from metadata, or // unspecified with default to public. -- cgit 1.4.1-3-g733a5 From 8c1b49d5e92c035661459063a645b78a47b6346a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 28 Jan 2025 22:25:23 +0000 Subject: Use `public-dependencies` in all sysroot crates In [1], most dependencies of `std` and other sysroot crates were marked private, but this did not happen for `alloc` and `test`. Update these here, marking public standard library crates as the only non-private dependencies. [1]: https://github.com/rust-lang/rust/pull/111076 --- .../0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 2 +- library/alloc/Cargo.toml | 4 +++- library/sysroot/Cargo.toml | 8 +++++--- library/test/Cargo.toml | 6 ++++-- 4 files changed, 13 insertions(+), 7 deletions(-) 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 index e3a9512dda9..eb1fc4b0ad5 100644 --- 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 @@ -15,7 +15,7 @@ index 7165c3e48af..968552ad435 100644 edition = "2021" [dependencies] - core = { path = "../core" } + core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] } diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index c1d7f324f17..395cff13189 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "alloc" version = "0.0.0" @@ -9,7 +11,7 @@ autobenches = false edition = "2021" [dependencies] -core = { path = "../core" } +core = { path = "../core", public = true } compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } [dev-dependencies] diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index aa6c3dc32e2..45a9eda445d 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "sysroot" version = "0.0.0" @@ -5,10 +7,10 @@ edition = "2021" # this is a dummy crate to ensure that all required crates appear in the sysroot [dependencies] -proc_macro = { path = "../proc_macro" } +proc_macro = { path = "../proc_macro", public = true } profiler_builtins = { path = "../profiler_builtins", optional = true } -std = { path = "../std" } -test = { path = "../test" } +std = { path = "../std", public = true } +test = { path = "../test", public = true } # Forward features to the `std` crate as necessary [features] diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 75cc7c00e38..241ef324b00 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "test" version = "0.0.0" @@ -5,8 +7,8 @@ edition = "2021" [dependencies] getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } -std = { path = "../std" } -core = { path = "../core" } +std = { path = "../std", public = true } +core = { path = "../core", public = true } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2.150", default-features = false } -- cgit 1.4.1-3-g733a5 From aca5b5dd5260d4e2c1bf584fc6ba36b5fba239cb Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 28 Jan 2025 23:20:36 +0000 Subject: If the parent dependency is private, treat dependents as private Currently, marking a dependency private does not automatically make all its child dependencies private. Resolve this by making its children private by default as well. This also resolves some FIXMEs for tests that are intended to fail but previously passed. [1]: https://github.com/rust-lang/rust/pull/135501#issuecomment-2620242419 --- compiler/rustc_metadata/src/creader.rs | 31 ++++++++++++++++++---- .../ui/privacy/pub-priv-dep/reexport_from_priv.rs | 3 +-- .../privacy/pub-priv-dep/reexport_from_priv.stderr | 14 ++++++++++ tests/ui/privacy/pub-priv-dep/shared_indirect.rs | 3 +-- .../ui/privacy/pub-priv-dep/shared_indirect.stderr | 14 ++++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr create mode 100644 tests/ui/privacy/pub-priv-dep/shared_indirect.stderr diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b94e32e17d4..58ff2425748 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -168,7 +168,10 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { enum CrateOrigin<'a> { /// This crate was a dependency of another crate. IndirectDependency { + /// Where this dependency was included from. dep_root: &'a CratePaths, + /// True if the parent is private, meaning the dependent should also be private. + parent_private: bool, /// Dependency info about this crate. dep: &'a CrateDep, }, @@ -194,6 +197,17 @@ impl<'a> CrateOrigin<'a> { _ => None, } } + + /// `Some(true)` if the dependency is private or its parent is private, `Some(false)` if the + /// dependency is not private, `None` if it could not be determined. + fn private_dep(&self) -> Option { + match self { + CrateOrigin::IndirectDependency { parent_private, dep, .. } => { + Some(dep.is_private || *parent_private) + } + _ => None, + } + } } impl CStore { @@ -585,7 +599,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &crate_paths }; - let cnum_map = self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind)?; + let cnum_map = + self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind, private_dep)?; let raw_proc_macros = if crate_root.is_proc_macro_crate() { let temp_root; @@ -722,7 +737,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let host_hash = dep.map(|d| d.host_hash).flatten(); let extra_filename = dep.map(|d| &d.extra_filename[..]); let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; - let private_dep = dep.map(|d| d.is_private); + let private_dep = origin.private_dep(); let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { (LoadResult::Previous(cnum), None) @@ -819,6 +834,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { metadata: &MetadataBlob, krate: CrateNum, dep_kind: CrateDepKind, + parent_is_private: bool, ) -> Result { debug!( "resolving deps of external crate `{}` with dep root `{}`", @@ -837,11 +853,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { crate_num_map.push(krate); for dep in deps { info!( - "resolving dep `{}`->`{}` hash: `{}` extra filename: `{}`", + "resolving dep `{}`->`{}` hash: `{}` extra filename: `{}` private {}", crate_root.name(), dep.name, dep.hash, - dep.extra_filename + dep.extra_filename, + dep.is_private, ); let dep_kind = match dep_kind { CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly, @@ -850,7 +867,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let cnum = self.maybe_resolve_crate( dep.name, dep_kind, - CrateOrigin::IndirectDependency { dep_root, dep: &dep }, + CrateOrigin::IndirectDependency { + dep_root, + parent_private: parent_is_private, + dep: &dep, + }, )?; crate_num_map.push(cnum); } diff --git a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs index 3c6e9825e72..136e0ceeb5b 100644 --- a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs +++ b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs @@ -1,6 +1,5 @@ //@ aux-crate:priv:reexport=reexport.rs //@ compile-flags: -Zunstable-options -//@ check-pass // Checks the behavior of a reexported item from a private dependency. @@ -9,7 +8,7 @@ extern crate reexport; -// FIXME: This should trigger. pub fn leaks_priv() -> reexport::Shared { + //~^ ERROR type `Shared` from private dependency 'shared' in public interface reexport::Shared } diff --git a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr new file mode 100644 index 00000000000..f1573283ff2 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr @@ -0,0 +1,14 @@ +error: type `Shared` from private dependency 'shared' in public interface + --> $DIR/reexport_from_priv.rs:11:1 + | +LL | pub fn leaks_priv() -> reexport::Shared { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/reexport_from_priv.rs:7:9 + | +LL | #![deny(exported_private_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/privacy/pub-priv-dep/shared_indirect.rs b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs index 34b624b4a1a..2fe66ae80cf 100644 --- a/tests/ui/privacy/pub-priv-dep/shared_indirect.rs +++ b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs @@ -1,7 +1,6 @@ //@ aux-crate:priv:shared=shared.rs //@ aux-crate:priv:indirect1=indirect1.rs //@ compile-flags: -Zunstable-options -//@ check-pass // A shared dependency, where it is only indirectly public. // @@ -23,7 +22,7 @@ extern crate shared; extern crate indirect1; -// FIXME: This should trigger. pub fn leaks_priv() -> shared::Shared { + //~^ ERROR type `Shared` from private dependency 'shared' in public interface shared::Shared } diff --git a/tests/ui/privacy/pub-priv-dep/shared_indirect.stderr b/tests/ui/privacy/pub-priv-dep/shared_indirect.stderr new file mode 100644 index 00000000000..dbc534713d1 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/shared_indirect.stderr @@ -0,0 +1,14 @@ +error: type `Shared` from private dependency 'shared' in public interface + --> $DIR/shared_indirect.rs:25:1 + | +LL | pub fn leaks_priv() -> shared::Shared { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/shared_indirect.rs:20:9 + | +LL | #![deny(exported_private_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + -- cgit 1.4.1-3-g733a5 From 93925809eb2f4be76c7babcc7cdb73d10ef977bd Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 30 Jan 2025 02:52:39 +0000 Subject: Replace some instances of `pub` with `pub(crate)` The recent fixes to private dependencies exposed some cases in the UEFI module where private dependencies are exposed in a public interface. These do not need to be crate-public, so change them to `pub(crate)`. --- library/std/src/sys/pal/uefi/process.rs | 2 +- library/std/src/sys/pal/uefi/time.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs index 9efe9a314f2..c73a6350357 100644 --- a/library/std/src/sys/pal/uefi/process.rs +++ b/library/std/src/sys/pal/uefi/process.rs @@ -388,7 +388,7 @@ mod uefi_command_internal { } } - pub fn start_image(&mut self) -> io::Result { + pub(crate) fn start_image(&mut self) -> io::Result { self.update_st_crc32()?; // Use our system table instead of the default one diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index 495ff2dc930..c4ff3015ac6 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -84,7 +84,7 @@ pub(crate) mod system_time_internal { // This algorithm is based on the one described in the post // https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html - pub const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration { + pub(crate) const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration { assert!(t.month <= 12); assert!(t.month != 0); -- cgit 1.4.1-3-g733a5 From 2a6daaf89a12dcb3467b057ec1a3d539623cd32c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 05:33:06 +0000 Subject: Make asm a named field --- compiler/rustc_ast_lowering/src/item.rs | 4 +++- compiler/rustc_codegen_cranelift/src/global_asm.rs | 2 +- compiler/rustc_codegen_ssa/src/mono_item.rs | 2 +- compiler/rustc_hir/src/hir.rs | 6 +++--- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir/src/target.rs | 2 +- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_analysis/src/collect/type_of.rs | 6 +++--- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_incremental/src/persist/dirty_clean.rs | 2 +- compiler/rustc_lint/src/types.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- src/librustdoc/html/render/span_map.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs | 4 ++-- src/tools/clippy/clippy_lints/src/missing_doc.rs | 2 +- src/tools/clippy/clippy_lints/src/missing_inline.rs | 2 +- 23 files changed, 30 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index bc2db415469..a7a03f7d6db 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -251,7 +251,9 @@ impl<'hir> LoweringContext<'_, 'hir> { .arena .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), }, - ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)), + ItemKind::GlobalAsm(asm) => { + hir::ItemKind::GlobalAsm { asm: self.lower_inline_asm(span, asm) } + } ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { // We lower // diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 54745b0d8c1..0a23f63d6ba 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 5f95b6615bd..a4d5f8bb701 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir_item(item_id); - if let hir::ItemKind::GlobalAsm(asm) = item.kind { + if let hir::ItemKind::GlobalAsm { asm } = item.kind { let operands: Vec<_> = asm .operands .iter() diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index eafc60f9d72..7cd30372783 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3848,7 +3848,7 @@ impl<'hir> Item<'hir> { expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]), ItemKind::ForeignMod { abi, items }, (*abi, items); - expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm(asm), asm; + expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm }, asm; expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>), ItemKind::TyAlias(ty, generics), (ty, generics); @@ -4015,7 +4015,7 @@ pub enum ItemKind<'hir> { /// An external module, e.g. `extern { .. }`. ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). - GlobalAsm(&'hir InlineAsm<'hir>), + GlobalAsm { asm: &'hir InlineAsm<'hir> }, /// A type alias, e.g., `type Foo = Bar`. TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), /// An enum definition, e.g., `enum Foo {C, D}`. @@ -4081,7 +4081,7 @@ impl ItemKind<'_> { ItemKind::Macro(..) => "macro", ItemKind::Mod(..) => "module", ItemKind::ForeignMod { .. } => "extern block", - ItemKind::GlobalAsm(..) => "global asm item", + ItemKind::GlobalAsm { .. } => "global asm item", ItemKind::TyAlias(..) => "type alias", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index bd96fe9ee32..5a002423a0c 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -573,7 +573,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_id(item.hir_id())); walk_list!(visitor, visit_foreign_item_ref, items); } - ItemKind::GlobalAsm(asm) => { + ItemKind::GlobalAsm { asm } => { try_visit!(visitor.visit_id(item.hir_id())); try_visit!(visitor.visit_inline_asm(asm, item.hir_id())); } diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index f3e8f059c9e..70e95a84e68 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -110,7 +110,7 @@ impl Target { ItemKind::Macro(..) => Target::MacroDef, ItemKind::Mod(..) => Target::Mod, ItemKind::ForeignMod { .. } => Target::ForeignMod, - ItemKind::GlobalAsm(..) => Target::GlobalAsm, + ItemKind::GlobalAsm { .. } => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, ItemKind::Enum(..) => Target::Enum, ItemKind::Struct(..) => Target::Struct, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index b1b046d7175..fbe3b60c520 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -897,7 +897,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } DefKind::GlobalAsm => { let it = tcx.hir().expect_item(def_id); - let hir::ItemKind::GlobalAsm(asm) = it.kind else { + let hir::ItemKind::GlobalAsm { asm } = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) }; InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 5bb77c096dc..d2334c8cec5 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -680,7 +680,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { | hir::ItemKind::Use(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(_) - | hir::ItemKind::GlobalAsm(_) => {} + | hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::ForeignMod { items, .. } => { for item in *items { let item = tcx.hir_foreign_item(item.id); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 759c981a8f7..b5333f393bc 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Static(..) - | hir::ItemKind::GlobalAsm(..) => { + | hir::ItemKind::GlobalAsm { .. } => { // These sorts of items have no lifetime parameters at all. intravisit::walk_item(self, item); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 717713d9339..19b78f48cfc 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -59,7 +59,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx // Anon consts outside the type system. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) => { let ty = tcx.typeck(def_id).node_type(hir_id); @@ -83,7 +83,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx } } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) => { let ty = tcx.typeck(def_id).node_type(hir_id); @@ -318,7 +318,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ | ItemKind::Macro(..) | ItemKind::Mod(..) | ItemKind::ForeignMod { .. } - | ItemKind::GlobalAsm(..) + | ItemKind::GlobalAsm { .. } | ItemKind::ExternCrate(..) | ItemKind::Use(..) => { span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 34124a6aa11..b485b426c28 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -692,7 +692,7 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::GlobalAsm(asm) => { + hir::ItemKind::GlobalAsm { asm } => { self.head("global_asm!"); self.print_inline_asm(asm); self.end() diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9d5184acb3c..c1ed5b0aa50 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -277,7 +277,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti Some(fcx.next_ty_var(span)) } Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. }) - | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => { + | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm }, span, .. }) => { asm.operands.iter().find_map(|(op, _op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } | hir::InlineAsmOperand::SymFn { anon_const } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 118a6fed036..56858679af6 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -261,7 +261,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { HirItem::ForeignMod { .. } => ("ItemForeignMod", LABELS_HIR_ONLY), // Module-level inline assembly (from global_asm!) - HirItem::GlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY), + HirItem::GlobalAsm { .. } => ("ItemGlobalAsm", LABELS_HIR_ONLY), // A type alias, e.g., `type Foo = Bar` HirItem::TyAlias(..) => ("ItemTy", LABELS_HIR_ONLY), diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 68b1f435a4c..4930cc35c9c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1740,7 +1740,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions { hir::ItemKind::Impl(..) | hir::ItemKind::TraitAlias(..) | hir::ItemKind::Trait(..) - | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::GlobalAsm { .. } | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Mod(..) | hir::ItemKind::Macro(..) diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 40dd6aa73fd..832f8026614 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -1166,7 +1166,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::Macro(..) => "macro", ItemKind::Mod(..) => "mod", ItemKind::ForeignMod { .. } => "foreign mod", - ItemKind::GlobalAsm(..) => "global asm", + ItemKind::GlobalAsm { .. } => "global asm", ItemKind::TyAlias(..) => "ty", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1195c25e130..bf56f468179 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -479,7 +479,7 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; let item = tcx.hir_item(item_id); - if let hir::ItemKind::GlobalAsm(asm) = item.kind { + if let hir::ItemKind::GlobalAsm { asm } = item.kind { for (op, op_sp) in asm.operands { match op { hir::InlineAsmOperand::Const { .. } => { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 1fe44bd3d21..fd465717bf7 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -246,7 +246,7 @@ impl<'tcx> ReachableContext<'tcx> { | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) - | hir::ItemKind::GlobalAsm(..) => {} + | hir::ItemKind::GlobalAsm { .. } => {} } } Node::TraitItem(trait_method) => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6faa2c1a00d..41725d0c6a4 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -645,7 +645,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // The interface is empty, and no nested items. hir::ItemKind::Use(..) | hir::ItemKind::ExternCrate(..) - | hir::ItemKind::GlobalAsm(..) => {} + | hir::ItemKind::GlobalAsm { .. } => {} // The interface is empty, and all nested items are processed by `visit_item`. hir::ItemKind::Mod(..) => {} hir::ItemKind::Macro(macro_def, _) => { diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 658d5965b3d..ce9c42c01cc 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -288,7 +288,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { | ItemKind::Use(_, _) | ItemKind::ExternCrate(_) | ItemKind::ForeignMod { .. } - | ItemKind::GlobalAsm(_) + | ItemKind::GlobalAsm { .. } // We already have "visit_mod" above so no need to check it here. | ItemKind::Mod(_) => {} } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index f606a3d8a92..7b6921afa08 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -439,7 +439,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } // If we're inlining, skip private items. _ if self.inlining && !is_pub => {} - hir::ItemKind::GlobalAsm(..) => {} + hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} hir::ItemKind::Use(path, kind) => { for &res in &path.res { diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index aff40fa846b..c0ae4960e10 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -362,7 +362,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { } } else if let ItemKind::ForeignMod { .. } = item.kind { continue; - } else if let ItemKind::GlobalAsm(_) = item.kind { + } else if let ItemKind::GlobalAsm { .. } = item.kind { continue; } else if let ItemKind::Use(path, use_kind) = item.kind { if path.segments.is_empty() { @@ -467,7 +467,7 @@ fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleIte ItemKind::Macro(..) => Macro, ItemKind::Mod(..) => Mod, ItemKind::ForeignMod { .. } => ForeignMod, - ItemKind::GlobalAsm(..) => GlobalAsm, + ItemKind::GlobalAsm { .. } => GlobalAsm, ItemKind::TyAlias(..) => TyAlias, ItemKind::Enum(..) => Enum, ItemKind::Struct(..) => Struct, diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 06e92985e66..47a9e17b3cf 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -217,7 +217,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::Union(..) => {}, hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } - | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::GlobalAsm { .. } | hir::ItemKind::Impl { .. } | hir::ItemKind::Use(..) => note_prev_span_then_ret!(self.prev_span, it.span), } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index fdc0930e957..3cf1a80607e 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) | hir::ItemKind::TraitAlias(..) - | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::GlobalAsm { .. } | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::ExternCrate(..) -- cgit 1.4.1-3-g733a5 From 37060aae13d0fe771f9d3222f1c644820a9d2837 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 16:14:34 +0000 Subject: Initial cleanups of InlineAsmCtxt --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsicck.rs | 90 ++++++++-------------- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 7 +- 3 files changed, 39 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index fbe3b60c520..0d34b657dfc 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -900,7 +900,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { let hir::ItemKind::GlobalAsm { asm } = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) }; - InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id); + InlineAsmCtxt::new_global_asm(tcx, def_id).check_asm(asm); } _ => {} } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 90e93bdbb50..00f2d46931f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -16,10 +16,11 @@ use rustc_target::asm::{ use crate::errors::RegisterTypeUnstable; -pub struct InlineAsmCtxt<'a, 'tcx> { +pub struct InlineAsmCtxt<'a, 'tcx: 'a> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - get_operand_ty: Box) -> Ty<'tcx> + 'a>, + target_features: &'tcx FxIndexSet, + expr_ty: Box) -> Ty<'tcx> + 'a>, } enum NonAsmTypeReason<'tcx> { @@ -29,14 +30,15 @@ enum NonAsmTypeReason<'tcx> { } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { - pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { + pub fn new_global_asm(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { InlineAsmCtxt { tcx, typing_env: ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env: ty::ParamEnv::empty(), }, - get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), + target_features: tcx.asm_target_features(def_id), + expr_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), } } @@ -45,9 +47,19 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn new_in_fn( tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a, + def_id: LocalDefId, + expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, ) -> Self { - InlineAsmCtxt { tcx, typing_env, get_operand_ty: Box::new(get_operand_ty) } + InlineAsmCtxt { + tcx, + typing_env, + target_features: tcx.asm_target_features(def_id), + expr_ty: Box::new(expr_ty), + } + } + + fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> { + (self.expr_ty)(expr) } // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` @@ -139,9 +151,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { template: &[InlineAsmTemplatePiece], is_input: bool, tied_input: Option<(&'tcx hir::Expr<'tcx>, Option)>, - target_features: &FxIndexSet, ) -> Option { - let ty = (self.get_operand_ty)(expr); + let ty = self.expr_ty(expr); if ty.has_non_region_infer() { bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty); } @@ -229,7 +240,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Some((in_expr, Some(in_asm_ty))) = tied_input { if in_asm_ty != asm_ty { let msg = "incompatible types for asm inout argument"; - let in_expr_ty = (self.get_operand_ty)(in_expr); + let in_expr_ty = self.expr_ty(in_expr); self.tcx .dcx() .struct_span_err(vec![in_expr.span, expr.span], msg) @@ -291,7 +302,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // (!). In that case we still need the earlier check to verify that the // register class is usable at all. if let Some(feature) = feature { - if !target_features.contains(feature) { + if !self.target_features.contains(feature) { let msg = format!("`{feature}` target feature is not enabled"); self.tcx .dcx() @@ -351,14 +362,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { Some(asm_ty) } - pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) { - let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id()); + pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { let Some(asm_arch) = self.tcx.sess.asm_arch else { self.tcx.dcx().delayed_bug("target architecture does not support asm"); return; }; let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); - for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { + for (idx, &(op, op_sp)) in asm.operands.iter().enumerate() { // Validate register classes against currently enabled target // features. We check that at least one type is available for // the enabled features. @@ -381,12 +391,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Err(msg) = reg.validate( asm_arch, self.tcx.sess.relocation_model(), - target_features, + self.target_features, &self.tcx.sess.target, op.is_clobber(), ) { let msg = format!("cannot use register `{}`: {}", reg.name(), msg); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); continue; } } @@ -401,7 +411,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { { match feature { Some(feature) => { - if target_features.contains(&feature) { + if self.target_features.contains(&feature) { missing_required_features.clear(); break; } else { @@ -426,7 +436,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { reg_class.name(), feature ); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -440,7 +450,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { .intersperse(", ") .collect::(), ); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -448,52 +458,21 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } } - match *op { + match op { hir::InlineAsmOperand::In { reg, expr } => { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - true, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, true, None); } hir::InlineAsmOperand::Out { reg, late: _, expr } => { if let Some(expr) = expr { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - false, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); } } hir::InlineAsmOperand::InOut { reg, late: _, expr } => { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - false, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); } hir::InlineAsmOperand::SplitInOut { reg, late: _, in_expr, out_expr } => { - let in_ty = self.check_asm_operand_type( - idx, - reg, - in_expr, - asm.template, - true, - None, - target_features, - ); + let in_ty = + self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None); if let Some(out_expr) = out_expr { self.check_asm_operand_type( idx, @@ -502,7 +481,6 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, Some((in_expr, in_ty)), - target_features, ); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index cf61659479b..bce9fbbd6d1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len()); for (asm, hir_id) in deferred_asm_checks.drain(..) { let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id); - let get_operand_ty = |expr| { + let expr_ty = |expr: &hir::Expr<'tcx>| { let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.resolve_vars_if_possible(ty); if ty.has_non_region_infer() { @@ -113,9 +113,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { InlineAsmCtxt::new_in_fn( self.tcx, self.infcx.typing_env(self.param_env), - get_operand_ty, + enclosing_id, + expr_ty, ) - .check_asm(asm, enclosing_id); + .check_asm(asm); } } -- cgit 1.4.1-3-g733a5 From 6ba39f7dc709a90bcb125974964a7e464ed86ff2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 16:09:46 +0000 Subject: Make a fake body to store typeck results for global_asm --- compiler/rustc_ast_lowering/src/asm.rs | 18 +------- compiler/rustc_ast_lowering/src/item.rs | 5 ++- compiler/rustc_borrowck/src/universal_regions.rs | 29 ++++++++++--- compiler/rustc_codegen_cranelift/src/global_asm.rs | 6 +-- compiler/rustc_codegen_ssa/src/mono_item.rs | 9 ++-- compiler/rustc_hir/src/hir.rs | 25 +++++++++-- compiler/rustc_hir/src/intravisit.rs | 14 ++++-- compiler/rustc_hir_analysis/src/check/check.rs | 9 ---- .../rustc_hir_analysis/src/check/intrinsicck.rs | 50 +++++++++++----------- .../rustc_hir_analysis/src/collect/generics_of.rs | 3 +- compiler/rustc_hir_analysis/src/collect/type_of.rs | 35 +-------------- compiler/rustc_hir_pretty/src/lib.rs | 6 +-- compiler/rustc_hir_typeck/src/expr.rs | 7 ++- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 8 +--- compiler/rustc_hir_typeck/src/lib.rs | 14 +++--- compiler/rustc_hir_typeck/src/writeback.rs | 9 ++-- compiler/rustc_lint/src/builtin.rs | 8 +++- compiler/rustc_middle/src/hir/map.rs | 3 +- compiler/rustc_middle/src/thir.rs | 4 +- compiler/rustc_middle/src/thir/visit.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 6 ++- compiler/rustc_mir_build/src/builder/expr/into.rs | 17 ++------ compiler/rustc_mir_build/src/builder/mod.rs | 5 ++- compiler/rustc_mir_build/src/check_unsafety.rs | 5 ++- compiler/rustc_mir_build/src/thir/cx/expr.rs | 9 +--- compiler/rustc_mir_build/src/thir/cx/mod.rs | 40 +++++++++-------- compiler/rustc_mir_build/src/thir/print.rs | 6 +-- compiler/rustc_monomorphize/src/collector.rs | 13 +++--- .../src/operators/numeric_arithmetic.rs | 2 +- src/tools/clippy/clippy_utils/src/hir_utils.rs | 5 ++- tests/crashes/111709-2.rs | 15 ------- tests/crashes/111709.rs | 25 ----------- tests/crashes/96304.rs | 6 --- tests/ui/asm/asm-with-nested-closure.rs | 11 +++++ tests/ui/asm/global-asm-with-lifetimes.rs | 8 ++++ tests/ui/asm/inline-asm-with-lifetimes.bad.stderr | 17 ++++++++ tests/ui/asm/inline-asm-with-lifetimes.rs | 22 ++++++++++ 37 files changed, 244 insertions(+), 232 deletions(-) delete mode 100644 tests/crashes/111709-2.rs delete mode 100644 tests/crashes/111709.rs delete mode 100644 tests/crashes/96304.rs create mode 100644 tests/ui/asm/asm-with-nested-closure.rs create mode 100644 tests/ui/asm/global-asm-with-lifetimes.rs create mode 100644 tests/ui/asm/inline-asm-with-lifetimes.bad.stderr create mode 100644 tests/ui/asm/inline-asm-with-lifetimes.rs diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 96c230ec243..cfd32fc066f 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -1,13 +1,12 @@ use std::collections::hash_map::Entry; use std::fmt::Write; -use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_session::parse::feature_err; -use rustc_span::{Span, kw, sym}; +use rustc_span::{Span, sym}; use rustc_target::asm; use super::LoweringContext; @@ -230,20 +229,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - // Wrap the expression in an AnonConst. - let parent_def_id = self.current_hir_id_owner.def_id; - let node_id = self.next_node_id(); - self.create_def( - parent_def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - *op_sp, - ); - let anon_const = AnonConst { id: node_id, value: P(expr) }; - hir::InlineAsmOperand::SymFn { - anon_const: self.lower_anon_const_to_anon_const(&anon_const), - } + hir::InlineAsmOperand::SymFn { expr: self.lower_expr(&expr) } } } InlineAsmOperand::Label { block } => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a7a03f7d6db..1d3db64b47e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -252,7 +252,10 @@ impl<'hir> LoweringContext<'_, 'hir> { .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), }, ItemKind::GlobalAsm(asm) => { - hir::ItemKind::GlobalAsm { asm: self.lower_inline_asm(span, asm) } + 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, .. }) => { // We lower diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 9a68eeb3326..a71ca37bf13 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -126,6 +126,11 @@ pub(crate) enum DefiningTy<'tcx> { /// The MIR represents an inline const. The signature has no inputs and a /// single return value found via `InlineConstArgs::ty`. InlineConst(DefId, GenericArgsRef<'tcx>), + + // Fake body for a global asm. Not particularly useful or interesting, + // but we need it so we can properly store the typeck results of the asm + // operands, which aren't associated with a body otherwise. + GlobalAsm(DefId), } impl<'tcx> DefiningTy<'tcx> { @@ -138,9 +143,10 @@ impl<'tcx> DefiningTy<'tcx> { DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(), DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(), - DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { - ty::List::empty() - } + DefiningTy::FnDef(..) + | DefiningTy::Const(..) + | DefiningTy::InlineConst(..) + | DefiningTy::GlobalAsm(_) => ty::List::empty(), } } @@ -152,7 +158,10 @@ impl<'tcx> DefiningTy<'tcx> { DefiningTy::Closure(..) | DefiningTy::CoroutineClosure(..) | DefiningTy::Coroutine(..) => 1, - DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0, + DefiningTy::FnDef(..) + | DefiningTy::Const(..) + | DefiningTy::InlineConst(..) + | DefiningTy::GlobalAsm(_) => 0, } } @@ -171,7 +180,8 @@ impl<'tcx> DefiningTy<'tcx> { | DefiningTy::Coroutine(def_id, ..) | DefiningTy::FnDef(def_id, ..) | DefiningTy::Const(def_id, ..) - | DefiningTy::InlineConst(def_id, ..) => def_id, + | DefiningTy::InlineConst(def_id, ..) + | DefiningTy::GlobalAsm(def_id) => def_id, } } } @@ -411,6 +421,7 @@ impl<'tcx> UniversalRegions<'tcx> { tcx.def_path_str_with_args(def_id, args), )); } + DefiningTy::GlobalAsm(_) => unreachable!(), } } @@ -633,6 +644,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::InlineConst(self.mir_def.to_def_id(), args) } } + + BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()), } } @@ -666,6 +679,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args, + + DefiningTy::GlobalAsm(_) => ty::List::empty(), }; let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); @@ -802,6 +817,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let ty = args.as_inline_const().ty(); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } + + DefiningTy::GlobalAsm(def_id) => { + ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()])) + } }; // FIXME(#129952): We probably want a more principled approach here. diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 0a23f63d6ba..9ea92c300f8 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); @@ -55,7 +55,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } } - InlineAsmOperand::SymFn { anon_const } => { + InlineAsmOperand::SymFn { expr } => { if cfg!(not(feature = "inline_asm_sym")) { tcx.dcx().span_err( item.span, @@ -63,7 +63,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, ); } - let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + let ty = tcx.typeck(item_id.owner_id).expr_ty(expr); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), _ => span_bug!(op_sp, "asm sym is not a function"), diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index a4d5f8bb701..f6af889fd6e 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir_item(item_id); - if let hir::ItemKind::GlobalAsm { asm } = item.kind { + if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind { let operands: Vec<_> = asm .operands .iter() @@ -71,11 +71,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } } } - hir::InlineAsmOperand::SymFn { ref anon_const } => { - let ty = cx - .tcx() - .typeck_body(anon_const.body) - .node_type(anon_const.hir_id); + hir::InlineAsmOperand::SymFn { expr } => { + let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), _ => span_bug!(*op_sp, "asm sym is not a function"), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7cd30372783..61f64e62058 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1913,13 +1913,18 @@ pub enum BodyOwnerKind { /// Initializer of a `static` item. Static(Mutability), + + /// Fake body for a global asm to store its const-like value types. + GlobalAsm, } impl BodyOwnerKind { pub fn is_fn_or_closure(self) -> bool { match self { BodyOwnerKind::Fn | BodyOwnerKind::Closure => true, - BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false, + BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) | BodyOwnerKind::GlobalAsm => { + false + } } } } @@ -3420,7 +3425,7 @@ pub enum InlineAsmOperand<'hir> { anon_const: &'hir AnonConst, }, SymFn { - anon_const: &'hir AnonConst, + expr: &'hir Expr<'hir>, }, SymStatic { path: QPath<'hir>, @@ -3848,7 +3853,7 @@ impl<'hir> Item<'hir> { expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]), ItemKind::ForeignMod { abi, items }, (*abi, items); - expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm }, asm; + expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm; expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>), ItemKind::TyAlias(ty, generics), (ty, generics); @@ -4015,7 +4020,15 @@ pub enum ItemKind<'hir> { /// An external module, e.g. `extern { .. }`. ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). - GlobalAsm { asm: &'hir InlineAsm<'hir> }, + GlobalAsm { + asm: &'hir InlineAsm<'hir>, + /// A fake body which stores typeck results for the global asm's sym_fn + /// operands, which are represented as path expressions. This body contains + /// a single [`ExprKind::InlineAsm`] which points to the asm in the field + /// above, and which is typechecked like a inline asm expr just for the + /// typeck results. + fake_body: BodyId, + }, /// A type alias, e.g., `type Foo = Bar`. TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), /// An enum definition, e.g., `enum Foo {C, D}`. @@ -4540,6 +4553,10 @@ impl<'hir> Node<'hir> { .. }) => Some((owner_id.def_id, *body)), + Node::Item(Item { + owner_id, kind: ItemKind::GlobalAsm { asm: _, fake_body }, .. + }) => Some((owner_id.def_id, *fake_body)), + Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => { Some((*def_id, *body)) } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 5a002423a0c..89a58e947cb 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -573,9 +573,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_id(item.hir_id())); walk_list!(visitor, visit_foreign_item_ref, items); } - ItemKind::GlobalAsm { asm } => { + ItemKind::GlobalAsm { asm: _, fake_body } => { try_visit!(visitor.visit_id(item.hir_id())); - try_visit!(visitor.visit_inline_asm(asm, item.hir_id())); + // Visit the fake body, which contains the asm statement. + // Therefore we should not visit the asm statement again + // outside of the body, or some visitors won't have their + // typeck results set correctly. + try_visit!(visitor.visit_nested_body(fake_body)); } ItemKind::TyAlias(ref ty, ref generics) => { try_visit!(visitor.visit_id(item.hir_id())); @@ -1442,10 +1446,12 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>( try_visit!(visitor.visit_expr(in_expr)); visit_opt!(visitor, visit_expr, out_expr); } - InlineAsmOperand::Const { anon_const, .. } - | InlineAsmOperand::SymFn { anon_const, .. } => { + InlineAsmOperand::Const { anon_const, .. } => { try_visit!(visitor.visit_anon_const(anon_const)); } + InlineAsmOperand::SymFn { expr, .. } => { + try_visit!(visitor.visit_expr(expr)); + } InlineAsmOperand::SymStatic { path, .. } => { try_visit!(visitor.visit_qpath(path, id, *op_sp)); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 0d34b657dfc..3236e0a3644 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -15,7 +15,6 @@ use rustc_lint_defs::builtin::{ use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::span_bug; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::fold::{BottomUpFolder, fold_regions}; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; @@ -35,7 +34,6 @@ use {rustc_attr_parsing as attr, rustc_hir as hir}; use super::compare_impl_item::check_type_bounds; use super::*; -use crate::check::intrinsicck::InlineAsmCtxt; pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) { if !tcx.sess.target.is_abi_supported(abi) { @@ -895,13 +893,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } } - DefKind::GlobalAsm => { - let it = tcx.hir().expect_item(def_id); - let hir::ItemKind::GlobalAsm { asm } = it.kind else { - span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) - }; - InlineAsmCtxt::new_global_asm(tcx, def_id).check_asm(asm); - } _ => {} } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 00f2d46931f..e1727fc48a8 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; use rustc_middle::bug; -use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; +use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{Symbol, sym}; @@ -30,7 +30,11 @@ enum NonAsmTypeReason<'tcx> { } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { - pub fn new_global_asm(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, + ) -> Self { InlineAsmCtxt { tcx, typing_env: ty::TypingEnv { @@ -38,23 +42,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { param_env: ty::ParamEnv::empty(), }, target_features: tcx.asm_target_features(def_id), - expr_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), - } - } - - // FIXME(#132279): This likely causes us to incorrectly handle opaque types in their - // defining scope. - pub fn new_in_fn( - tcx: TyCtxt<'tcx>, - typing_env: ty::TypingEnv<'tcx>, - def_id: LocalDefId, - expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, - ) -> Self { - InlineAsmCtxt { - tcx, - typing_env, - target_features: tcx.asm_target_features(def_id), - expr_ty: Box::new(expr_ty), + expr_ty: Box::new(get_operand_ty), } } @@ -492,11 +480,25 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ); } // Typeck has checked that SymFn refers to a function. - hir::InlineAsmOperand::SymFn { anon_const } => { - debug_assert_matches!( - self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), - ty::Error(_) | ty::FnDef(..) - ); + hir::InlineAsmOperand::SymFn { expr } => { + let ty = self.expr_ty(expr); + match ty.kind() { + ty::FnDef(..) => {} + ty::Error(_) => {} + _ => { + self.tcx + .dcx() + .struct_span_err(op_sp, "invalid `sym` operand") + .with_span_label( + expr.span, + format!("is {} `{}`", ty.kind().article(), ty), + ) + .with_help( + "`sym` operands must refer to either a function or a static", + ) + .emit(); + } + } } // AST lowering guarantees that SymStatic points to a static. hir::InlineAsmOperand::SymStatic { .. } => {} diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index a363076b75a..2cdd9a3a934 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -189,8 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Exclude `GlobalAsm` here which cannot have generics. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) if asm.operands.iter().any(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => { + hir::InlineAsmOperand::Const { anon_const } => { anon_const.hir_id == hir_id } _ => false, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 19b78f48cfc..37c9e061091 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx let parent_node_id = tcx.parent_hir_id(hir_id); let parent_node = tcx.hir_node(parent_node_id); - let find_sym_fn = |&(op, op_sp)| match op { - hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => { - Some((anon_const, op_sp)) - } - _ => None, - }; - let find_const = |&(op, op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => { Some((anon_const, op_sp)) @@ -59,31 +52,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx // Anon consts outside the type system. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) - if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) => - { - let ty = tcx.typeck(def_id).node_type(hir_id); - - match ty.kind() { - ty::Error(_) => ty, - ty::FnDef(..) => ty, - _ => { - let guar = tcx - .dcx() - .struct_span_err(op_sp, "invalid `sym` operand") - .with_span_label( - tcx.def_span(anon_const.def_id), - format!("is {} `{}`", ty.kind().article(), ty), - ) - .with_help("`sym` operands must refer to either a function or a static") - .emit(); - - Ty::new_error(tcx, guar) - } - } - } - Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. }) if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) => { let ty = tcx.typeck(def_id).node_type(hir_id); @@ -313,12 +282,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_adt(tcx, def, args) } + ItemKind::GlobalAsm { .. } => tcx.typeck(def_id).node_type(hir_id), ItemKind::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::Macro(..) | ItemKind::Mod(..) | ItemKind::ForeignMod { .. } - | ItemKind::GlobalAsm { .. } | ItemKind::ExternCrate(..) | ItemKind::Use(..) => { span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b485b426c28..b9cdf3ddc34 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -692,7 +692,7 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::GlobalAsm { asm } => { + hir::ItemKind::GlobalAsm { asm, .. } => { self.head("global_asm!"); self.print_inline_asm(asm); self.end() @@ -1431,10 +1431,10 @@ impl<'a> State<'a> { s.space(); s.print_anon_const(anon_const); } - hir::InlineAsmOperand::SymFn { ref anon_const } => { + hir::InlineAsmOperand::SymFn { ref expr } => { s.word("sym_fn"); s.space(); - s.print_anon_const(anon_const); + s.print_expr(expr); } hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => { s.word("sym_static"); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 277396da19c..0c71ef4655c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3763,7 +3763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut diverge = asm.asm_macro.diverges(asm.options); for (op, _op_sp) in asm.operands { - match op { + match *op { hir::InlineAsmOperand::In { expr, .. } => { self.check_expr_asm_operand(expr, true); } @@ -3778,10 +3778,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_asm_operand(out_expr, false); } } + hir::InlineAsmOperand::SymFn { expr } => { + self.check_expr(expr); + } // `AnonConst`s have their own body and is type-checked separately. // As they don't flow into the type system we don't need them to // be well-formed. - hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {} + hir::InlineAsmOperand::Const { .. } => {} hir::InlineAsmOperand::SymStatic { .. } => {} hir::InlineAsmOperand::Label { block } => { let previous_diverges = self.diverges.get(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index bce9fbbd6d1..120a43576e8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -110,13 +110,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.erase_regions(ty) } }; - InlineAsmCtxt::new_in_fn( - self.tcx, - self.infcx.typing_env(self.param_env), - enclosing_id, - expr_ty, - ) - .check_asm(asm); + InlineAsmCtxt::new(self.tcx, enclosing_id, expr_ty).check_asm(asm); } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index c1ed5b0aa50..0130ad775d9 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -133,7 +133,12 @@ fn typeck_with_inspect<'tcx>( } let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id); - if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { + if let hir::Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, .. }) = node { + // Check the fake body of a global ASM. There's not much to do here except + // for visit the asm expr of the body. + let ty = fcx.check_expr(body.value); + fcx.write_ty(id, ty); + } else if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() { // In the case that we're recovering `fn() -> W<_>` or some other return // type that has an infer in it, lower the type directly so that it'll @@ -277,12 +282,9 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti Some(fcx.next_ty_var(span)) } Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. }) - | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm }, span, .. }) => { + | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm, .. }, span, .. }) => { asm.operands.iter().find_map(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } - if anon_const.hir_id == id => - { + hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => { Some(fcx.next_ty_var(span)) } _ => None, diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 8c50cc59c1d..3e9ce0e11e4 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -48,13 +48,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for param in body.params { wbcx.visit_node_id(param.pat.span, param.hir_id); } - // Type only exists for constants and statics, not functions. match self.tcx.hir_body_owner_kind(item_def_id) { - hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => { + // Visit the type of a const or static, which is used during THIR building. + hir::BodyOwnerKind::Const { .. } + | hir::BodyOwnerKind::Static(_) + | hir::BodyOwnerKind::GlobalAsm => { let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id); wbcx.visit_node_id(body.value.span, item_hir_id); } - hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (), + // For closures and consts, we already plan to visit liberated signatures. + hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => {} } wbcx.visit_body(body); wbcx.visit_min_capture_map(); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b5f09ff346a..6c5a2dcd146 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2909,7 +2909,13 @@ enum AsmLabelKind { impl<'tcx> LateLintPass<'tcx> for AsmLabels { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::Expr { - kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, options, .. }), + kind: + hir::ExprKind::InlineAsm(hir::InlineAsm { + asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm, + template_strs, + options, + .. + }), .. } = expr { diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 832f8026614..ec046d82ef6 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -305,6 +305,7 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::Static { safety: _, mutability, nested: false } => { BodyOwnerKind::Static(mutability) } + DefKind::GlobalAsm => BodyOwnerKind::GlobalAsm, dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } } @@ -327,7 +328,7 @@ impl<'tcx> TyCtxt<'tcx> { ConstContext::ConstFn } BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn, - BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None, + BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None, }; Some(ccx) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 98cc00c367c..6a2672ac02b 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -94,6 +94,7 @@ thir_with_elements! { pub enum BodyTy<'tcx> { Const(Ty<'tcx>), Fn(FnSig<'tcx>), + GlobalAsm(Ty<'tcx>), } /// Description of a type-checked function parameter. @@ -605,8 +606,7 @@ pub enum InlineAsmOperand<'tcx> { span: Span, }, SymFn { - value: mir::Const<'tcx>, - span: Span, + value: ExprId, }, SymStatic { def_id: DefId, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 13b8af55e51..e347a64e45d 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -172,7 +172,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( } Out { expr: None, reg: _, late: _ } | Const { value: _, span: _ } - | SymFn { value: _, span: _ } + | SymFn { value: _ } | SymStatic { def_id: _ } => {} Label { block } => visitor.visit_block(&visitor.thir()[*block]), } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 32a9e67f9ad..361e204fb0f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1472,7 +1472,11 @@ impl<'tcx> TyCtxt<'tcx> { self.codegen_fn_attrs(def_id) } else if matches!( def_kind, - DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst + DefKind::AnonConst + | DefKind::AssocConst + | DefKind::Const + | DefKind::InlineConst + | DefKind::GlobalAsm ) { CodegenFnAttrs::EMPTY } else { diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 65dd061003d..72443e2f60d 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -482,15 +482,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }), } } - thir::InlineAsmOperand::SymFn { value, span } => { - mir::InlineAsmOperand::SymFn { - value: Box::new(ConstOperand { - span, - user_ty: None, - const_: value, - }), - } - } + thir::InlineAsmOperand::SymFn { value } => mir::InlineAsmOperand::SymFn { + value: Box::new(this.as_constant(&this.thir[value])), + }, thir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } } @@ -518,10 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let asm_macro = match asm_macro { - AsmMacro::Asm => InlineAsmMacro::Asm, - AsmMacro::GlobalAsm => { - span_bug!(expr_span, "unexpected global_asm! in inline asm") - } + AsmMacro::Asm | AsmMacro::GlobalAsm => InlineAsmMacro::Asm, AsmMacro::NakedAsm => InlineAsmMacro::NakedAsm, }; diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 4348b7a4b4c..94955954934 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -61,7 +61,9 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { Ok((thir, expr)) => { let build_mir = |thir: &Thir<'tcx>| match thir.body_type { thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig), - thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty), + thir::BodyTy::Const(ty) | thir::BodyTy::GlobalAsm(ty) => { + construct_const(tcx, def, thir, expr, ty) + } }; // this must run before MIR dump, because @@ -576,6 +578,7 @@ fn construct_const<'a, 'tcx>( let span = tcx.def_span(def); (span, span) } + Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, span, .. }) => (*span, *span), _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), }; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index d65c2097d22..c2eafd0a74e 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::mem; use std::ops::Bound; +use rustc_ast::AsmMacro; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::DiagArgValue; use rustc_hir::def::DefKind; @@ -559,7 +560,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } ExprKind::InlineAsm(box InlineAsmExpr { - asm_macro: _, + asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm, ref operands, template: _, options: _, @@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } Out { expr: None, reg: _, late: _ } | Const { value: _, span: _ } - | SymFn { value: _, span: _ } + | SymFn { value: _ } | SymStatic { def_id: _ } => {} Label { block } => { // Label blocks are safe context. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index d0fca76fcf0..29bc1d6572d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -739,13 +739,8 @@ impl<'tcx> ThirBuildCx<'tcx> { InlineAsmOperand::Const { value, span } } - hir::InlineAsmOperand::SymFn { ref anon_const } => { - let value = - mir::Const::from_unevaluated(tcx, anon_const.def_id.to_def_id()) - .instantiate_identity(); - let span = tcx.def_span(anon_const.def_id); - - InlineAsmOperand::SymFn { value, span } + hir::InlineAsmOperand::SymFn { expr } => { + InlineAsmOperand::SymFn { value: self.mirror_expr(expr) } } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { InlineAsmOperand::SymStatic { def_id } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 7a9f6e46304..c32082c609e 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -76,23 +76,29 @@ impl<'tcx> ThirBuildCx<'tcx> { let hir = tcx.hir(); let hir_id = tcx.local_def_id_to_hir_id(def); - let body_type = if tcx.hir_body_owner_kind(def).is_fn_or_closure() { - // fetch the fully liberated fn signature (that is, all bound - // types/lifetimes replaced) - BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id]) - } else { - // Get the revealed type of this const. This is *not* the adjusted - // type of its body, which may be a subtype of this type. For - // example: - // - // fn foo(_: &()) {} - // static X: fn(&'static ()) = foo; - // - // The adjusted type of the body of X is `for<'a> fn(&'a ())` which - // is not the same as the type of X. We need the type of the return - // place to be the type of the constant because NLL typeck will - // equate them. - BodyTy::Const(typeck_results.node_type(hir_id)) + let body_type = match tcx.hir_body_owner_kind(def) { + rustc_hir::BodyOwnerKind::Fn | rustc_hir::BodyOwnerKind::Closure => { + // fetch the fully liberated fn signature (that is, all bound + // types/lifetimes replaced) + BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id]) + } + rustc_hir::BodyOwnerKind::Const { .. } | rustc_hir::BodyOwnerKind::Static(_) => { + // Get the revealed type of this const. This is *not* the adjusted + // type of its body, which may be a subtype of this type. For + // example: + // + // fn foo(_: &()) {} + // static X: fn(&'static ()) = foo; + // + // The adjusted type of the body of X is `for<'a> fn(&'a ())` which + // is not the same as the type of X. We need the type of the return + // place to be the type of the constant because NLL typeck will + // equate them. + BodyTy::Const(typeck_results.node_type(hir_id)) + } + rustc_hir::BodyOwnerKind::GlobalAsm => { + BodyTy::GlobalAsm(typeck_results.node_type(hir_id)) + } }; Self { diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 9ab87dd99ff..cd56d93afcf 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -921,10 +921,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); print_indented!(self, "}", depth_lvl + 1); } - InlineAsmOperand::SymFn { value, span } => { + InlineAsmOperand::SymFn { value } => { print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl); - print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1); - print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, "value: ", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } InlineAsmOperand::SymStatic { def_id } => { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index bf56f468179..694a4dd5b4c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -479,24 +479,23 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; let item = tcx.hir_item(item_id); - if let hir::ItemKind::GlobalAsm { asm } = item.kind { + if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind { for (op, op_sp) in asm.operands { - match op { + match *op { hir::InlineAsmOperand::Const { .. } => { // Only constants which resolve to a plain integer // are supported. Therefore the value should not // depend on any other items. } - hir::InlineAsmOperand::SymFn { anon_const } => { - let fn_ty = - tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + hir::InlineAsmOperand::SymFn { expr } => { + let fn_ty = tcx.typeck(item_id.owner_id).expr_ty(expr); visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items); } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { - let instance = Instance::mono(tcx, *def_id); + let instance = Instance::mono(tcx, def_id); if tcx.should_codegen_locally(instance) { trace!("collecting static {:?}", def_id); - used_items.push(dummy_spanned(MonoItem::Static(*def_id))); + used_items.push(dummy_spanned(MonoItem::Static(def_id))); } } hir::InlineAsmOperand::In { .. } diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs index cda99a362dc..c261fd9bd9c 100644 --- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs @@ -82,7 +82,7 @@ impl Context { } self.const_span = Some(body_span); }, - hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (), + hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::GlobalAsm => (), } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9ee30094d60..0ac675345ae 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -968,7 +968,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(out_expr); } }, - InlineAsmOperand::Const { anon_const } | InlineAsmOperand::SymFn { anon_const } => { + InlineAsmOperand::SymFn { expr } => { + self.hash_expr(expr); + } + InlineAsmOperand::Const { anon_const } => { self.hash_body(anon_const.body); }, InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path), diff --git a/tests/crashes/111709-2.rs b/tests/crashes/111709-2.rs deleted file mode 100644 index 6c4fb9f28c7..00000000000 --- a/tests/crashes/111709-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #111709 -//@ edition: 2021 - -use core::arch::asm; - -extern "C" fn test() {} - -fn uwu() { - unsafe { - asm!( - "/* {0} */", - sym test::<&mut ()> - ); - } -} diff --git a/tests/crashes/111709.rs b/tests/crashes/111709.rs deleted file mode 100644 index eef375b8924..00000000000 --- a/tests/crashes/111709.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #111709 -//@ edition:2021 - -use core::arch::asm; - -struct TrapFrame; - -unsafe extern "C" fn _rust_abi_shim1(arg: A, f: fn(A) -> R) -> R { - f(arg) -} - -unsafe extern "C" fn _start_trap() { - extern "Rust" { - fn interrupt(tf: &mut TrapFrame); - } - asm!( - " - la a1, {irq} - call {shim} - ", - shim = sym crate::_rust_abi_shim1::<&mut TrapFrame, ()>, - irq = sym interrupt, - options(noreturn) - ) -} diff --git a/tests/crashes/96304.rs b/tests/crashes/96304.rs deleted file mode 100644 index 637012f4585..00000000000 --- a/tests/crashes/96304.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #96304 - -#![feature(asm_sym)] -core::arch::global_asm!("/* {} */", sym<&'static ()>::clone); - -pub fn main() {} diff --git a/tests/ui/asm/asm-with-nested-closure.rs b/tests/ui/asm/asm-with-nested-closure.rs new file mode 100644 index 00000000000..3a5cd48d5d4 --- /dev/null +++ b/tests/ui/asm/asm-with-nested-closure.rs @@ -0,0 +1,11 @@ +//@ build-pass +//@ needs-asm-support + +fn foo() {} + +core::arch::global_asm!("/* {} */", sym foo::<{ + || {}; + 0 +}>); + +fn main() {} diff --git a/tests/ui/asm/global-asm-with-lifetimes.rs b/tests/ui/asm/global-asm-with-lifetimes.rs new file mode 100644 index 00000000000..2709ff90fe3 --- /dev/null +++ b/tests/ui/asm/global-asm-with-lifetimes.rs @@ -0,0 +1,8 @@ +//@ build-pass +//@ needs-asm-support + +fn foo() {} + +core::arch::global_asm!("/* {} */", sym foo::<&'static ()>); + +fn main() {} diff --git a/tests/ui/asm/inline-asm-with-lifetimes.bad.stderr b/tests/ui/asm/inline-asm-with-lifetimes.bad.stderr new file mode 100644 index 00000000000..f04482f9c59 --- /dev/null +++ b/tests/ui/asm/inline-asm-with-lifetimes.bad.stderr @@ -0,0 +1,17 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/inline-asm-with-lifetimes.rs:17:26 + | +LL | fn test<'a: 'a, T>() { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +LL | unsafe { +LL | asm!("/* {} */", sym dep::<'a, T> ); + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn test<'a: 'a, T: 'a>() { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/asm/inline-asm-with-lifetimes.rs b/tests/ui/asm/inline-asm-with-lifetimes.rs new file mode 100644 index 00000000000..79def03eeb2 --- /dev/null +++ b/tests/ui/asm/inline-asm-with-lifetimes.rs @@ -0,0 +1,22 @@ +//@ revisions: good bad +//@[good] build-pass +//@ needs-asm-support + +use std::arch::asm; + +// lifetime requirement, we should check it!! +#[cfg(bad)] +fn dep<'a, T: 'a>() {} + +// no lifetime requirement +#[cfg(good)] +fn dep<'a: 'a, T>() {} + +fn test<'a: 'a, T>() { + unsafe { + asm!("/* {} */", sym dep::<'a, T> ); + //[bad]~^ ERROR the parameter type `T` may not live long enough + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From c45463ec8b2675df903b2436d4baf959d801aa08 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 22 Feb 2025 13:28:12 +0800 Subject: remove invalid suggestion of into_iter for extern macro --- compiler/rustc_hir_typeck/src/method/suggest.rs | 12 +++++++----- tests/ui/proc-macro/auxiliary/quote-issue-137345.rs | 19 +++++++++++++++++++ tests/ui/proc-macro/valid-sugg-issue-137345.rs | 17 +++++++++++++++++ tests/ui/proc-macro/valid-sugg-issue-137345.stderr | 13 +++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 tests/ui/proc-macro/auxiliary/quote-issue-137345.rs create mode 100644 tests/ui/proc-macro/valid-sugg-issue-137345.rs create mode 100644 tests/ui/proc-macro/valid-sugg-issue-137345.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index c757d089478..93720a7a467 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -905,11 +905,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if self.impl_into_iterator_should_be_iterator(rcvr_ty, span, unsatisfied_predicates) { err.span_label(span, format!("`{rcvr_ty}` is not an iterator")); - err.multipart_suggestion_verbose( - "call `.into_iter()` first", - vec![(span.shrink_to_lo(), format!("into_iter()."))], - Applicability::MaybeIncorrect, - ); + if !span.in_external_macro(self.tcx.sess.source_map()) { + err.multipart_suggestion_verbose( + "call `.into_iter()` first", + vec![(span.shrink_to_lo(), format!("into_iter()."))], + Applicability::MaybeIncorrect, + ); + } return err.emit(); } else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) { // We special case the situation where we are looking for `_` in diff --git a/tests/ui/proc-macro/auxiliary/quote-issue-137345.rs b/tests/ui/proc-macro/auxiliary/quote-issue-137345.rs new file mode 100644 index 00000000000..f125a14669f --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/quote-issue-137345.rs @@ -0,0 +1,19 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +fn items() -> impl IntoIterator { + vec![1, 2, 3] +} + +#[macro_export] +macro_rules! quote { + // Rule for any other number of tokens. + ($($tt:tt)*) => {{ + fn items() -> impl IntoIterator { + vec![1, 2, 3] + } + let _s = TokenStream::new(); + let other_items = items().map(|i| i + 1); + _s + }}; +} diff --git a/tests/ui/proc-macro/valid-sugg-issue-137345.rs b/tests/ui/proc-macro/valid-sugg-issue-137345.rs new file mode 100644 index 00000000000..78674797b8d --- /dev/null +++ b/tests/ui/proc-macro/valid-sugg-issue-137345.rs @@ -0,0 +1,17 @@ +//@ aux-crate: quote=quote-issue-137345.rs + +extern crate proc_macro; +extern crate quote; + +use proc_macro::TokenStream; + +pub fn default_args_fn(_: TokenStream) -> TokenStream { + let decl_macro = TokenStream::new(); + + quote::quote! { + #(#decl_macro)* + } + .into() //~^^^ ERROR no method named `map` found for opaque type +} + +fn main() {} diff --git a/tests/ui/proc-macro/valid-sugg-issue-137345.stderr b/tests/ui/proc-macro/valid-sugg-issue-137345.stderr new file mode 100644 index 00000000000..40336803f0d --- /dev/null +++ b/tests/ui/proc-macro/valid-sugg-issue-137345.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `map` found for opaque type `impl IntoIterator` in the current scope + --> $DIR/valid-sugg-issue-137345.rs:11:5 + | +LL | / quote::quote! { +LL | | #(#decl_macro)* +LL | | } + | |_____^ `impl IntoIterator` is not an iterator + | + = note: this error originates in the macro `quote::quote` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. -- cgit 1.4.1-3-g733a5