@@ -38,7 +38,6 @@ use crate::ty::{InferConst, ParamConst};
3838use crate :: ty:: GenericParamDefKind ;
3939use crate :: ty:: layout:: { LayoutDetails , TargetDataLayout , VariantIdx } ;
4040use crate :: ty:: query;
41- use crate :: ty:: steal:: Steal ;
4241use crate :: ty:: subst:: { UserSubsts , GenericArgKind } ;
4342use crate :: ty:: { BoundVar , BindingMode } ;
4443use crate :: ty:: CanonicalPolyFnSig ;
@@ -49,12 +48,13 @@ use crate::util::nodemap::{FxHashMap, FxHashSet};
4948use errors:: DiagnosticBuilder ;
5049use arena:: SyncDroplessArena ;
5150use smallvec:: SmallVec ;
51+ use rustc_index:: vec:: { Idx , IndexVec } ;
5252use rustc_data_structures:: stable_hasher:: {
5353 HashStable , StableHasher , StableVec , hash_stable_hashmap,
5454} ;
55- use rustc_index:: vec:: { Idx , IndexVec } ;
5655use rustc_data_structures:: sharded:: ShardedHashMap ;
5756use rustc_data_structures:: sync:: { Lrc , Lock , WorkerLocal } ;
57+ use rustc_data_structures:: steal:: Steal ;
5858use std:: any:: Any ;
5959use std:: borrow:: Borrow ;
6060use std:: cmp:: Ordering ;
@@ -2859,6 +2859,44 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
28592859 t as * const ( ) == u as * const ( )
28602860}
28612861
2862+ /// In interpreter mode, locates the `DefId` of the user fn (a closure marked by an attribute named
2863+ /// `rustc_interp_user_fn`) by visiting the local crate's HIR.
2864+ fn find_interp_user_fn ( tcx : TyCtxt < ' _ > ) -> DefId {
2865+ use hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
2866+
2867+ struct InterpUserFnVisitor < ' tcx > {
2868+ tcx : TyCtxt < ' tcx > ,
2869+ def_id : Option < DefId > ,
2870+ }
2871+
2872+ impl < ' tcx > Visitor < ' tcx > for InterpUserFnVisitor < ' tcx > {
2873+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
2874+ NestedVisitorMap :: OnlyBodies ( & self . tcx . hir ( ) )
2875+ }
2876+
2877+ fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr ) {
2878+ if syntax:: attr:: contains_name ( & ex. attrs , sym:: rustc_interp_user_fn) {
2879+ self . def_id = Some ( self . tcx . hir ( ) . local_def_id ( ex. hir_id ) ) ;
2880+ return ;
2881+ }
2882+
2883+ intravisit:: walk_expr ( self , ex) ;
2884+ }
2885+ }
2886+
2887+ let mut visitor = InterpUserFnVisitor {
2888+ tcx,
2889+ def_id : None ,
2890+ } ;
2891+ tcx. hir ( ) . krate ( ) . visit_all_item_likes ( & mut visitor. as_deep_visitor ( ) ) ;
2892+ visitor. def_id
2893+ . unwrap_or_else ( || tcx. sess . fatal ( & format ! (
2894+ "could not find interpreter user fn in HIR; it should be a closure expression \
2895+ marked with the `#[{}]` attribute",
2896+ sym:: rustc_interp_user_fn
2897+ ) ) )
2898+ }
2899+
28622900pub fn provide ( providers : & mut ty:: query:: Providers < ' _ > ) {
28632901 providers. in_scope_traits_map = |tcx, id| tcx. gcx . trait_map . get ( & id) ;
28642902 providers. module_exports = |tcx, id| tcx. gcx . export_map . get ( & id) . map ( |v| & v[ ..] ) ;
@@ -2936,4 +2974,8 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
29362974 assert_eq ! ( cnum, LOCAL_CRATE ) ;
29372975 attr:: contains_name ( tcx. hir ( ) . krate_attrs ( ) , sym:: compiler_builtins)
29382976 } ;
2977+ providers. interp_user_fn = |tcx, cnum| {
2978+ assert_eq ! ( cnum, LOCAL_CRATE ) ;
2979+ find_interp_user_fn ( tcx)
2980+ } ;
29392981}
0 commit comments