From b90687377c0519b477af52aa6b2d08944122612f Mon Sep 17 00:00:00 2001 From: cijiugechu Date: Wed, 22 Apr 2026 10:22:14 +0800 Subject: [PATCH] Add constness & asyncness --- .../rustc_public/src/compiler_interface.rs | 26 +++++- compiler/rustc_public/src/ty.rs | 34 +++++++ .../src/unstable/convert/internal.rs | 34 ++++++- .../src/unstable/convert/stable/mod.rs | 20 ++++ .../rustc_public_bridge/src/context/impls.rs | 10 ++ .../rustc_public/check_fn_attrs.rs | 93 +++++++++++++++++++ 6 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 tests/ui-fulldeps/rustc_public/check_fn_attrs.rs diff --git a/compiler/rustc_public/src/compiler_interface.rs b/compiler/rustc_public/src/compiler_interface.rs index 30fbc5c5233d..c2f36bea81ca 100644 --- a/compiler/rustc_public/src/compiler_interface.rs +++ b/compiler/rustc_public/src/compiler_interface.rs @@ -17,11 +17,11 @@ use crate::mir::{BinOp, Body, Place, UnOp}; use crate::target::{MachineInfo, MachineSize}; use crate::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, - ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, - Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, - TraitDecl, TraitDef, TraitRef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, - VtblEntry, + AdtDef, AdtKind, Allocation, Asyncness, ClosureDef, ClosureKind, Constness, CoroutineDef, + Discr, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, + GenericArgs, GenericPredicates, Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, + PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, TraitRef, Ty, TyConst, TyConstId, TyKind, + UintTy, VariantDef, VariantIdx, VtblEntry, }; use crate::unstable::{RustcInternal, Stable, new_item_kind}; use crate::{ @@ -388,6 +388,22 @@ pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { cx.fn_sig(def_id, args_ref).stable(&mut *tables, cx) } + /// Retrieve the constness for the given function definition. + pub(crate) fn constness(&self, def: FnDef) -> Constness { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + cx.constness(def_id).stable(&mut *tables, cx) + } + + /// Retrieve the asyncness for the given function definition. + pub(crate) fn asyncness(&self, def: FnDef) -> Asyncness { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + cx.asyncness(def_id).stable(&mut *tables, cx) + } + /// Retrieve the intrinsic definition if the item corresponds one. pub(crate) fn intrinsic(&self, item: DefId) -> Option { let mut tables = self.tables.borrow_mut(); diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index 7ec8b688402a..9b79c92ac2b9 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -710,6 +710,16 @@ pub fn is_intrinsic(&self) -> bool { self.as_intrinsic().is_some() } + /// Get the constness of this function definition. + pub fn constness(&self) -> Constness { + with(|cx| cx.constness(*self)) + } + + /// Get the asyncness of this function definition. + pub fn asyncness(&self) -> Asyncness { + with(|cx| cx.asyncness(*self)) + } + /// Get the function signature for this function definition. pub fn fn_sig(&self) -> PolyFnSig { let kind = self.ty().kind(); @@ -1103,6 +1113,30 @@ pub fn inputs(&self) -> &[Ty] { } } +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] +pub enum Constness { + Const, + NotConst, +} + +impl Constness { + pub fn is_const(self) -> bool { + matches!(self, Constness::Const) + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] +pub enum Asyncness { + Async, + NotAsync, +} + +impl Asyncness { + pub fn is_async(self) -> bool { + matches!(self, Asyncness::Async) + } +} + #[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub enum Abi { Rust, diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 4f3e9f94c599..ddecfd3c73f4 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -14,8 +14,8 @@ use crate::mir::mono::{Instance, MonoItem, StaticDef}; use crate::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp}; use crate::ty::{ - Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, - ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, + Abi, AdtDef, Asyncness, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, + Constness, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx, }; @@ -637,6 +637,36 @@ fn internal<'tcx>( } } } + +impl RustcInternal for Constness { + type T<'tcx> = rustc_hir::Constness; + + fn internal<'tcx>( + &self, + _tables: &mut Tables<'_, BridgeTys>, + _tcx: impl InternalCx<'tcx>, + ) -> Self::T<'tcx> { + match self { + Constness::Const => rustc_hir::Constness::Const, + Constness::NotConst => rustc_hir::Constness::NotConst, + } + } +} + +impl RustcInternal for Asyncness { + type T<'tcx> = rustc_ty::Asyncness; + + fn internal<'tcx>( + &self, + _tables: &mut Tables<'_, BridgeTys>, + _tcx: impl InternalCx<'tcx>, + ) -> Self::T<'tcx> { + match self { + Asyncness::Async => rustc_ty::Asyncness::Yes, + Asyncness::NotAsync => rustc_ty::Asyncness::No, + } + } +} impl RustcInternal for Span { type T<'tcx> = rustc_span::Span; diff --git a/compiler/rustc_public/src/unstable/convert/stable/mod.rs b/compiler/rustc_public/src/unstable/convert/stable/mod.rs index 4d550487525f..ce55e898b2ac 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mod.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mod.rs @@ -21,6 +21,26 @@ fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) } } +impl<'tcx> Stable<'tcx> for rustc_hir::Constness { + type T = crate::ty::Constness; + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { + match self { + rustc_hir::Constness::Const => crate::ty::Constness::Const, + rustc_hir::Constness::NotConst => crate::ty::Constness::NotConst, + } + } +} + +impl<'tcx> Stable<'tcx> for rustc_middle::ty::Asyncness { + type T = crate::ty::Asyncness; + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { + match self { + rustc_middle::ty::Asyncness::Yes => crate::ty::Asyncness::Async, + rustc_middle::ty::Asyncness::No => crate::ty::Asyncness::NotAsync, + } + } +} + impl<'tcx> Stable<'tcx> for FieldIdx { type T = usize; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { diff --git a/compiler/rustc_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index 1df2b1fa6428..bb504bd0017a 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs @@ -383,6 +383,16 @@ pub fn fn_sig( sig } + /// Retrieve the constness for the given function definition. + pub fn constness(&self, def_id: DefId) -> rustc_hir::Constness { + self.tcx.constness(def_id) + } + + /// Retrieve the asyncness for the given function definition. + pub fn asyncness(&self, def_id: DefId) -> ty::Asyncness { + self.tcx.asyncness(def_id) + } + /// Retrieve the intrinsic definition if the item corresponds one. pub fn intrinsic(&self, def_id: DefId) -> Option { let intrinsic = self.tcx.intrinsic_raw(def_id); diff --git a/tests/ui-fulldeps/rustc_public/check_fn_attrs.rs b/tests/ui-fulldeps/rustc_public/check_fn_attrs.rs new file mode 100644 index 000000000000..552e8cbec376 --- /dev/null +++ b/tests/ui-fulldeps/rustc_public/check_fn_attrs.rs @@ -0,0 +1,93 @@ +//@ run-pass +//! Test that users are able to query function-level constness and asyncness. + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ edition: 2021 + +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_public; + +use rustc_public::crate_def::CrateDef; +use rustc_public::ty::{Asyncness, Constness, FnDef}; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +fn test_stable_mir() -> ControlFlow<()> { + let fns = rustc_public::local_crate().fn_defs(); + + check_fn(&fns, "input::const_sync", Constness::Const, Asyncness::NotAsync); + check_fn(&fns, "input::async_fn", Constness::NotConst, Asyncness::Async); + check_fn(&fns, "input::plain", Constness::NotConst, Asyncness::NotAsync); + check_fn(&fns, "input::Widget::assoc_const", Constness::Const, Asyncness::NotAsync); + check_fn(&fns, "input::Widget::assoc_async", Constness::NotConst, Asyncness::Async); + check_fn(&fns, "input::Widget::assoc_plain", Constness::NotConst, Asyncness::NotAsync); + + ControlFlow::Continue(()) +} + +fn check_fn(fns: &[FnDef], name: &str, constness: Constness, asyncness: Asyncness) { + let fn_def = + fns.iter().find(|def| def.name() == name).unwrap_or_else(|| panic!("missing {name}")); + assert_eq!(fn_def.constness(), constness, "wrong constness for {}", fn_def.name()); + assert_eq!(fn_def.asyncness(), asyncness, "wrong asyncness for {}", fn_def.name()); +} + +fn main() { + let path = "fn_attrs_input.rs"; + generate_input(&path).unwrap(); + let args = &[ + "rustc".to_string(), + "--edition=2021".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, test_stable_mir).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub const fn const_sync() -> u32 {{ + 1 + }} + + pub async fn async_fn() -> u32 {{ + 2 + }} + + pub fn plain() -> u32 {{ + 3 + }} + + pub struct Widget; + + impl Widget {{ + pub const fn assoc_const() -> u32 {{ + 4 + }} + + pub async fn assoc_async() -> u32 {{ + 5 + }} + + pub fn assoc_plain() -> u32 {{ + 6 + }} + }} + "# + )?; + Ok(()) +}