fix: cyclic loop detection in cross-module def-use relation checking (#396)

This commit is contained in:
Myriad-Dreamin 2024-07-10 12:01:22 +08:00 committed by GitHub
parent 1e424eca8a
commit 653789c1e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 10 deletions

View file

@ -123,7 +123,7 @@ impl DefUseInfo {
} }
pub(super) fn get_def_use_inner( pub(super) fn get_def_use_inner(
ctx: &mut AnalysisContext, ctx: &mut SearchCtx,
source: Source, source: Source,
e: EcoVec<LexicalHierarchy>, e: EcoVec<LexicalHierarchy>,
import: Arc<ImportInfo>, import: Arc<ImportInfo>,
@ -154,8 +154,8 @@ pub(super) fn get_def_use_inner(
Some(Arc::new(collector.info)) Some(Arc::new(collector.info))
} }
struct DefUseCollector<'a, 'w> { struct DefUseCollector<'a, 'b, 'w> {
ctx: &'a mut AnalysisContext<'w>, ctx: &'a mut SearchCtx<'b, 'w>,
info: DefUseInfo, info: DefUseInfo,
label_scope: SnapshotMap<String, DefId>, label_scope: SnapshotMap<String, DefId>,
id_scope: SnapshotMap<String, DefId>, id_scope: SnapshotMap<String, DefId>,
@ -165,7 +165,7 @@ struct DefUseCollector<'a, 'w> {
ext_src: Option<Source>, ext_src: Option<Source>,
} }
impl<'a, 'w> DefUseCollector<'a, 'w> { impl<'a, 'b, 'w> DefUseCollector<'a, 'b, 'w> {
fn enter<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { fn enter<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
let id_snap = self.id_scope.snapshot(); let id_snap = self.id_scope.snapshot();
let res = f(self); let res = f(self);
@ -186,7 +186,8 @@ impl<'a, 'w> DefUseCollector<'a, 'w> {
let source = self.ext_src.as_ref()?; let source = self.ext_src.as_ref()?;
log::debug!("import for def use: {:?}, name: {name}", source.id()); log::debug!("import for def use: {:?}, name: {name}", source.id());
let (_, external_info) = Some(source.id()).zip(self.ctx.def_use(source.clone()))?; let (_, external_info) =
Some(source.id()).zip(AnalysisContext::def_use_(self.ctx, source.clone()))?;
let ext_id = external_info.exports_defs.get(name)?; let ext_id = external_info.exports_defs.get(name)?;
self.import_from(&external_info, *ext_id); self.import_from(&external_info, *ext_id);
@ -252,8 +253,8 @@ impl<'a, 'w> DefUseCollector<'a, 'w> {
LexicalKind::Mod(LexicalModKind::Star) => { LexicalKind::Mod(LexicalModKind::Star) => {
if let Some(source) = &self.ext_src { if let Some(source) = &self.ext_src {
log::debug!("diving source for def use: {:?}", source.id()); log::debug!("diving source for def use: {:?}", source.id());
let (_, external_info) = let (_, external_info) = Some(source.id())
Some(source.id()).zip(self.ctx.def_use(source.clone()))?; .zip(AnalysisContext::def_use_(self.ctx, source.clone()))?;
for ext_id in &external_info.exports_refs { for ext_id in &external_info.exports_refs {
self.import_from(&external_info, *ext_id); self.import_from(&external_info, *ext_id);

View file

@ -527,20 +527,20 @@ impl<'w> AnalysisContext<'w> {
let l = def_use_lexical_hierarchy(source.clone())?; let l = def_use_lexical_hierarchy(source.clone())?;
let m = ctx.ctx.import_info(source.clone())?; let m = ctx.ctx.import_info(source.clone())?;
let dep_hash = m let deps = m
.imports .imports
.iter() .iter()
.flat_map(|e| e.1) .flat_map(|e| e.1)
.map(|e| Self::def_use_(ctx, e.clone())) .map(|e| Self::def_use_(ctx, e.clone()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let key = (&source, &l, &m, dep_hash); let key = (&source, &l, &m, deps);
let h = hash128(&key); let h = hash128(&key);
let res = if let Some(res) = ctx.ctx.analysis.caches.def_use.get(&h) { let res = if let Some(res) = ctx.ctx.analysis.caches.def_use.get(&h) {
res.1.clone() res.1.clone()
} else { } else {
let res = crate::analysis::get_def_use_inner(ctx.ctx, source, l, m); let res = crate::analysis::get_def_use_inner(ctx, source, l, m);
ctx.ctx ctx.ctx
.analysis .analysis
.caches .caches