@@ -11,13 +11,14 @@ use std::collections::HashMap;
1111use std:: rc:: Rc ;
1212
1313use rustc_hir:: lang_items:: LangItem ;
14+ use rustc_index:: IndexVec ;
1415use rustc_middle:: mir:: { self , BasicBlock , Local } ;
1516use rustc_middle:: ty:: { self as mir_ty, TyCtxt } ;
1617use rustc_span:: def_id:: { DefId , LocalDefId } ;
1718
1819use crate :: chc;
1920use crate :: pretty:: PrettyDisplayExt as _;
20- use crate :: refine:: { self , BasicBlockType } ;
21+ use crate :: refine:: { self , BasicBlockType , TypeBuilder } ;
2122use crate :: rty;
2223
2324mod annot;
@@ -103,6 +104,17 @@ impl<'tcx> ReplacePlacesVisitor<'tcx> {
103104 }
104105}
105106
107+ #[ derive( Debug , Clone ) ]
108+ struct DeferredDefTy < ' tcx > {
109+ cache : Rc < RefCell < HashMap < Vec < mir_ty:: Ty < ' tcx > > , rty:: RefinedType > > > ,
110+ }
111+
112+ #[ derive( Debug , Clone ) ]
113+ enum DefTy < ' tcx > {
114+ Concrete ( rty:: RefinedType ) ,
115+ Deferred ( DeferredDefTy < ' tcx > ) ,
116+ }
117+
106118#[ derive( Clone ) ]
107119pub struct Analyzer < ' tcx > {
108120 tcx : TyCtxt < ' tcx > ,
@@ -112,7 +124,7 @@ pub struct Analyzer<'tcx> {
112124 /// currently contains only local-def templates,
113125 /// but will be extended to contain externally known def's refinement types
114126 /// (at least for every defs referenced by local def bodies)
115- defs : HashMap < DefId , rty :: RefinedType > ,
127+ defs : HashMap < DefId , DefTy < ' tcx > > ,
116128
117129 /// Resulting CHC system.
118130 system : Rc < RefCell < chc:: System > > ,
@@ -207,11 +219,72 @@ impl<'tcx> Analyzer<'tcx> {
207219
208220 pub fn register_def ( & mut self , def_id : DefId , rty : rty:: RefinedType ) {
209221 tracing:: info!( def_id = ?def_id, rty = %rty. display( ) , "register_def" ) ;
210- self . defs . insert ( def_id, rty) ;
222+ self . defs . insert ( def_id, DefTy :: Concrete ( rty) ) ;
223+ }
224+
225+ pub fn register_deferred_def ( & mut self , def_id : DefId ) {
226+ tracing:: info!( def_id = ?def_id, "register_deferred_def" ) ;
227+ self . defs . insert (
228+ def_id,
229+ DefTy :: Deferred ( DeferredDefTy {
230+ cache : Rc :: new ( RefCell :: new ( HashMap :: new ( ) ) ) ,
231+ } ) ,
232+ ) ;
233+ }
234+
235+ pub fn concrete_def_ty ( & self , def_id : DefId ) -> Option < & rty:: RefinedType > {
236+ self . defs . get ( & def_id) . and_then ( |def_ty| match def_ty {
237+ DefTy :: Concrete ( rty) => Some ( rty) ,
238+ DefTy :: Deferred ( _) => None ,
239+ } )
211240 }
212241
213- pub fn def_ty ( & self , def_id : DefId ) -> Option < & rty:: RefinedType > {
214- self . defs . get ( & def_id)
242+ pub fn def_ty_with_args (
243+ & mut self ,
244+ def_id : DefId ,
245+ args : mir_ty:: GenericArgsRef < ' tcx > ,
246+ ) -> Option < rty:: RefinedType > {
247+ let type_builder = TypeBuilder :: new ( self . tcx , def_id) ;
248+ let rty_args: IndexVec < _ , _ > = args. types ( ) . map ( |ty| type_builder. build ( ty) ) . collect ( ) ;
249+
250+ let deferred_ty = match self . defs . get ( & def_id) ? {
251+ DefTy :: Concrete ( rty) => {
252+ let mut def_ty = rty. clone ( ) ;
253+ def_ty. instantiate_ty_params (
254+ rty_args
255+ . clone ( )
256+ . into_iter ( )
257+ . map ( rty:: RefinedType :: unrefined)
258+ . collect ( ) ,
259+ ) ;
260+ return Some ( def_ty) ;
261+ }
262+ DefTy :: Deferred ( deferred) => deferred,
263+ } ;
264+
265+ let ty_args: Vec < _ > = args. types ( ) . collect ( ) ;
266+ let deferred_ty_cache = Rc :: clone ( & deferred_ty. cache ) ; // to cut reference to allow &mut self
267+ if let Some ( rty) = deferred_ty_cache. borrow ( ) . get ( & ty_args) {
268+ return Some ( rty. clone ( ) ) ;
269+ }
270+ let local_def_id = def_id. as_local ( ) ?;
271+
272+ let sig = self
273+ . tcx
274+ . fn_sig ( def_id)
275+ . instantiate ( self . tcx , args)
276+ . skip_binder ( ) ;
277+ let expected = self
278+ . crate_analyzer ( )
279+ . fn_def_ty_with_sig ( local_def_id. to_def_id ( ) , sig)
280+ . unwrap ( ) ;
281+ self . local_def_analyzer ( local_def_id)
282+ . type_builder ( type_builder. with_param_mapper ( move |ty| rty_args[ ty. idx ] . clone ( ) ) )
283+ . run ( & expected) ;
284+ deferred_ty_cache
285+ . borrow_mut ( )
286+ . insert ( ty_args, expected. clone ( ) ) ;
287+ Some ( expected)
215288 }
216289
217290 pub fn register_basic_block_ty (
0 commit comments