From edbb0257db1635cb00224af2465e6542161faa54 Mon Sep 17 00:00:00 2001 From: hermanventer Date: Wed, 4 Dec 2024 17:21:25 -0800 Subject: [PATCH] Cleanup visit_function_reference calls --- binaries/summary_store.tar | Bin 3527168 -> 3527168 bytes checker/src/block_visitor.rs | 57 +++++++++++++++------------------ checker/src/constant_domain.rs | 13 ++++++++ checker/src/summaries.rs | 7 ++-- checker/src/type_visitor.rs | 18 +++++------ 5 files changed, 53 insertions(+), 42 deletions(-) diff --git a/binaries/summary_store.tar b/binaries/summary_store.tar index 07b27d0b5e70b45d8b891c4f48606b6c5ae59cff..de0521e1991f10c4a633c1d46cc17b9c5776e247 100644 GIT binary patch delta 1740 zcma)-3s4kw9LI0(_T=t7;JiB&fji+I>^-=>-M!npLsFb1Ut?m8%#@f=Vos*{81cbG zK57m#QHX5KoT(<0fo4!7{YGWVm?BD{q0Q zr|}|jdh~_fq)bJWi6Y1e3Ia_~5=Ids$|;kI(yq`*0|R#k$g#1uDAKGVs0kXvXo8jy zNr)mu6Lf?z1U?I-W zyJDY9Ls?+YH{hKv`&I>-cG@q^M3NkvvV+I2tmIk) ze(xL9*gr}>6@#)2W>9lI`H}(IJDB%ESm0rTV#v4)M-j`sANm; z?_Q;uu9WtkW@bdpJ5!i3xM(K}m1)_)&zkNECDIz0J#tlPx$K~(yHbgkv&@HbweI80 z)vCUTRwXw7z?{=X3A0|PRrTrjDBmoS$;?t+uH#93(#mASkaDjS@OL#UhTtW87aVQ01xB|cZB4?4L^VM6y>*9{Ja39dpT z7JuW)wjgzht2P?1wY%DUXf1aY8PVZ$-{WxnnyX3+%PM!Ph|CG@y+(ZdwcE?%w>)>6 z7BzR>_c>7I?xRK&O->=28y)Ubqfz&INvk_JtTgmpM z)5$rSa%sk4cBaI2vGItjX62NWu5(?*-9zlVG@TVo&BG3`%P1+~5PKDuYuUFH^ah&M zVc}6WL-9~M=_IS9(9z2tQ%L06g01~*wY>aX1Iy4Yw08pBSFU#pEyOZA5&xq1i2QF=osXY{syuI;g?9bAY782~-nM_x zY{02)-dS7Jg_qBF%KK>YXWZ;(u1AK=T-eNq%|h7h3!D8%%wqAr;i%_>K|U}XnV?RH sLkUbKj==lEr;0RR}{d7tOI;n0C!jOeDqRtcPJz z-4vV3Fez@2*Aq~OFBgO|7>~z|GPt3P$OwX>k$^}@8trAk&^(_jB+N0-$ zaN?PMD+wQ5($|V$y~A)v0sX(}KZ^zNJVUb;Mwtu~BcNcjL8gQ^#u)Y`!0!hQW1Z0I zGwi~lxZS`gVdZ|qY9S>2VaOc~mNvs=AtY1ASxTtBWq3;n7cz|7Q(&#t_=yl|%8VsS zC>d+a62KAO*pUfy*BNKva9?HOm5{X4xKRiT7MP+Ou&&#E;e4OucMEnwGt0??~{+nUSXVrul&q*hS`@DT@8)FO-Te;Jz?oSxHe& zPKn3O=N&R<@MC6?r80f##SHO96cnQ%fBI9il|OONtlhEPE#{nE9M{7r#uddp&3D~yKo|pztM>={`l2NJM=mInoM0RSRx`W?N#CpI# zU)E*FC^wW>jf{>+|Q-cp{~#wufsET3w+SJ z$=UsKrM8w{11(#eli!cj+)ykO1S5VH!M#57ExAua`!tMC1#7`_ AnE(I) diff --git a/checker/src/block_visitor.rs b/checker/src/block_visitor.rs index b49d19bb..ce3f62b2 100644 --- a/checker/src/block_visitor.rs +++ b/checker/src/block_visitor.rs @@ -514,7 +514,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com &actual_argument_types, ); let fun_ty = tcx.type_of(destructor.did).skip_binder(); - // todo: perhaps use the type of the struct (ty) instead of fun_ty + // since ty is specialized, fun_ty and args should be specialized as well. let func_const = self .visit_function_reference(destructor.did, fun_ty, Some(args)) .clone(); @@ -1047,9 +1047,11 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com if let TyKind::Closure(def_id, args) | TyKind::FnDef(def_id, args) = specialized_closure_ty.kind() { + let fun_ty = self.bv.tcx.type_of(def_id).skip_binder(); + // since specialized_closure_ty is specialized, fun_ty and args should be specialized as well. return extract_func_ref(self.visit_function_reference( *def_id, - specialized_closure_ty, + fun_ty, Some(args), )); } @@ -2661,12 +2663,15 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com mir::AggregateKind::Closure(def_id, args) | mir::AggregateKind::Coroutine(def_id, args) | mir::AggregateKind::CoroutineClosure(def_id, args) => { - // todo: perhaps this should be - // let ty = self - // .type_visitor() - // .get_path_rustc_type(&path, self.bv.current_span); let ty = self.bv.tcx.type_of(*def_id).skip_binder(); - let func_const = self.visit_function_reference(*def_id, ty, Some(args)); + let specialized_ty = self + .type_visitor() + .specialize_type(ty, &self.type_visitor().generic_argument_map); + let specialized_args = self + .type_visitor() + .specialize_generic_args(args, &self.type_visitor().generic_argument_map); + let func_const = + self.visit_function_reference(*def_id, specialized_ty, Some(specialized_args)); let func_val = Rc::new(func_const.clone().into()); self.bv.update_value_at(path.clone(), func_val); for (i, operand) in operands.iter().enumerate() { @@ -3601,7 +3606,7 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com bytes_left_deserialize } // todo: bytes is the serialization of the captured state of a closure/generator - // deserialize that and return an heap block that represents the closure state + func ptr + // deserialize that and return a heap block that represents the closure state + func ptr TyKind::Closure(def_id, args) | TyKind::FnDef(def_id, args) | TyKind::Coroutine(def_id, args, ..) @@ -3609,14 +3614,10 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com rustc_middle::ty::Opaque, rustc_middle::ty::AliasTy { def_id, args, .. }, ) => { - let specialized_ty = self - .type_visitor() - .specialize_type(ty, &self.type_visitor().generic_argument_map); - let specialized_args = self - .type_visitor() - .specialize_generic_args(args, &self.type_visitor().generic_argument_map); + let fun_ty = self.bv.tcx.type_of(def_id).skip_binder(); + // since ty is specialized, fun_ty and args should be specialized as well. let func_val = Rc::new( - self.visit_function_reference(*def_id, specialized_ty, Some(specialized_args)) + self.visit_function_reference(*def_id, fun_ty, Some(args)) .clone() .into(), ); @@ -3931,7 +3932,8 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com } TyKind::FnDef(def_id, args) => { debug_assert!(size == 0 && data == 0); - // todo: this seems the right approach. Make other calls sites conform. + // guard against the possibility that ty is not specialized with respect the actual + // type arguments of the current function. let specialized_ty = self .type_visitor() .specialize_type(ty, &self.type_visitor().generic_argument_map); @@ -4109,29 +4111,22 @@ impl<'block, 'analysis, 'compilation, 'tcx> BlockVisitor<'block, 'analysis, 'com rustc_middle::ty::Opaque, rustc_middle::ty::AliasTy { def_id, .. }, ) => { - let ty = self.bv.tcx.type_of(*def_id).skip_binder(); - let specialized_ty = self - .type_visitor() - .specialize_type(ty, &self.type_visitor().generic_argument_map); + let aliased_ty = self.bv.tcx.type_of(*def_id).skip_binder(); + // since ty is specialized, aliased_ty should be specialized as well. if let TyKind::Closure(def_id, generic_args) - | TyKind::Coroutine(def_id, generic_args) = specialized_ty.kind() + | TyKind::Coroutine(def_id, generic_args) = aliased_ty.kind() { - let func_const = self.visit_function_reference( - *def_id, - specialized_ty, - Some(generic_args), - ); + let fun_ty = self.bv.tcx.type_of(*def_id).skip_binder(); + // since aliased_ty is specialized, fun_ty and generic_args should be specialized as well. + let func_const = + self.visit_function_reference(*def_id, fun_ty, Some(generic_args)); let func_val = Rc::new(func_const.clone().into()); self.bv .update_value_at(Path::new_function(base_path.clone()), func_val); } } TyKind::FnDef(def_id, generic_args) => { - let func_const = self.visit_function_reference( - *def_id, - ty, - Some(generic_args.as_closure().args), - ); + let func_const = self.visit_function_reference(*def_id, ty, Some(generic_args)); let func_val = Rc::new(func_const.clone().into()); self.bv .update_value_at(Path::new_function(base_path.clone()), func_val); diff --git a/checker/src/constant_domain.rs b/checker/src/constant_domain.rs index d15dc570..3f80c8d3 100644 --- a/checker/src/constant_domain.rs +++ b/checker/src/constant_domain.rs @@ -1596,14 +1596,27 @@ impl<'tcx> ConstantValueCache<'tcx> { /// corresponds to the function identified by that DefId. pub fn get_function_constant_for( &mut self, + // The identifier of the function definition. def_id: DefId, + // The type of the function instance ty: Ty<'tcx>, + // The generic arguments used to obtain the function instance generic_args: Option>, + // The rustc type context that knows about def_id tcx: TyCtxt<'tcx>, + // A cache of known names to updated with this function if its name is known. known_names_cache: &mut KnownNamesCache, + // A cache of function summaries. It is not provided with a summary for def_id + // at this point, but it does provide a place to cache the key string that is used + // to cache the summary when it is created. We do this so that we can use DefIds + // for lookups while also making the summary cache persistable. summary_cache: &mut PersistentSummaryCache<'tcx>, ) -> &ConstantDomain { let function_id = self.function_cache.len(); + // Distinct instances of def_id will have distinct ty values, but + // since ty is anonymous we combine it with the def_id to get a unique key. + // The combination is aliased function_id to provide a more efficient key for + // other caches. self.function_cache.entry((def_id, ty)).or_insert_with(|| { ConstantDomain::for_function( function_id, diff --git a/checker/src/summaries.rs b/checker/src/summaries.rs index 419bad94..fd931906 100644 --- a/checker/src/summaries.rs +++ b/checker/src/summaries.rs @@ -388,10 +388,13 @@ impl Hash for CallSiteKey<'_> { /// Summary. The latter is cleared after every outer fixed point loop iteration. /// Also tracks which definitions depend on (use) any particular Summary. pub struct PersistentSummaryCache<'tcx> { - // The sled database that stores the summaries. Can be persisted between runs. + /// The sled database that stores the summaries. Can be persisted between runs. db: Db, - // Functions that are not generic are uniquely identified by their def_id and are cached here. + /// Functions that are not generic instances are uniquely identified by their def_id and their + /// summaries are cached here. def_id_cache: HashMap, + /// Functions that are generic instances are identified by their function_id and their summaries + /// are cached here. typed_cache: HashMap, typed_cache_table: HashMap, HashMap>, reference_cache: HashMap, Summary>, diff --git a/checker/src/type_visitor.rs b/checker/src/type_visitor.rs index cfe7e24c..85834138 100644 --- a/checker/src/type_visitor.rs +++ b/checker/src/type_visitor.rs @@ -1055,12 +1055,12 @@ impl<'tcx> TypeVisitor<'tcx> { #[logfn_inputs(TRACE)] pub fn specialize_type( &self, - gen_arg_type: Ty<'tcx>, + ty: Ty<'tcx>, map: &Option>>, ) -> Ty<'tcx> { // The projection of an associated type. For example, // `>::N`. - if let TyKind::Alias(rustc_middle::ty::Projection, projection) = gen_arg_type.kind() { + if let TyKind::Alias(rustc_middle::ty::Projection, projection) = ty.kind() { let specialized_substs = self.specialize_generic_args(projection.args, map); let item_def_id = projection.def_id; return if utils::are_concrete(specialized_substs) { @@ -1080,7 +1080,7 @@ impl<'tcx> TypeVisitor<'tcx> { let item_type = self.tcx.type_of(instance_item_def_id).skip_binder(); let map = self.get_generic_arguments_map(instance_item_def_id, instance.args, &[]); - if item_type == gen_arg_type && map.is_none() { + if item_type == ty && map.is_none() { // Can happen if the projection just adds a life time item_type } else { @@ -1100,16 +1100,16 @@ impl<'tcx> TypeVisitor<'tcx> { } } debug!("could not resolve an associated type with concrete type arguments"); - gen_arg_type + ty } } else { Ty::new_projection(self.tcx, projection.def_id, specialized_substs) }; } if map.is_none() { - return gen_arg_type; + return ty; } - match gen_arg_type.kind() { + match ty.kind() { TyKind::Adt(def, args) => { Ty::new_adt(self.tcx, *def, self.specialize_generic_args(args, map)) } @@ -1213,7 +1213,7 @@ impl<'tcx> TypeVisitor<'tcx> { let closures_being_specialized = borrowed_closures_being_specialized.deref_mut(); if !closures_being_specialized.insert(*def_id) { - return gen_arg_type; + return ty; } } let specialized_closure = @@ -1245,9 +1245,9 @@ impl<'tcx> TypeVisitor<'tcx> { return gen_arg.expect_ty(); } } - gen_arg_type + ty } - _ => gen_arg_type, + _ => ty, } }