diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs index 6a0485bf6..41ae471b3 100644 --- a/kclvm/sema/src/core/symbol.rs +++ b/kclvm/sema/src/core/symbol.rs @@ -959,7 +959,7 @@ impl SymbolData { .insert(r#ref); } SymbolKind::Rule => { - self.attributes + self.rules .get_mut(def.get_id()) .unwrap() .r#ref diff --git a/kclvm/sema/src/resolver/global.rs b/kclvm/sema/src/resolver/global.rs index d4ad2a76b..df470c144 100644 --- a/kclvm/sema/src/resolver/global.rs +++ b/kclvm/sema/src/resolver/global.rs @@ -765,7 +765,7 @@ impl<'ctx> Resolver<'ctx> { self.ctx .ty_ctx .add_dependencies(&schema_runtime_ty, &parent_schema_runtime_ty); - if self.ctx.ty_ctx.is_cyclic() { + if self.ctx.ty_ctx.is_cyclic_from_node(&schema_runtime_ty) { self.handler.add_compile_error( &format!( "There is a circular reference between schema {} and {}", @@ -877,7 +877,7 @@ impl<'ctx> Resolver<'ctx> { self.ctx .ty_ctx .add_dependencies(&schema_runtime_ty, &parent_schema_runtime_ty); - if self.ctx.ty_ctx.is_cyclic() { + if self.ctx.ty_ctx.is_cyclic_from_node(&schema_runtime_ty) { self.handler.add_compile_error( &format!( "There is a circular reference between rule {} and {}", diff --git a/kclvm/sema/src/resolver/import.rs b/kclvm/sema/src/resolver/import.rs index 96a0d0df4..2664f3b68 100644 --- a/kclvm/sema/src/resolver/import.rs +++ b/kclvm/sema/src/resolver/import.rs @@ -7,7 +7,7 @@ use crate::{ ty::{Type, TypeKind}, }; use indexmap::{IndexMap, IndexSet}; -use kclvm_ast::ast; +use kclvm_ast::{ast, MAIN_PKG}; use kclvm_error::*; use std::rc::Rc; use std::sync::Arc; @@ -235,11 +235,16 @@ impl<'ctx> Resolver<'ctx> { self.ctx .ty_ctx .add_dependencies(&self.ctx.pkgpath, &import_stmt.path.node); - if self.ctx.ty_ctx.is_cyclic() { + if self.ctx.ty_ctx.is_cyclic_from_node(&self.ctx.pkgpath) { + let pkg_path = if self.ctx.pkgpath == MAIN_PKG { + self.ctx.filename.clone() + } else { + self.ctx.pkgpath.clone() + }; self.handler.add_compile_error( &format!( "There is a circular import reference between module {} and {}", - self.ctx.pkgpath, import_stmt.path.node, + pkg_path, import_stmt.path.node, ), stmt.get_span_pos(), ); diff --git a/kclvm/sema/src/resolver/tests.rs b/kclvm/sema/src/resolver/tests.rs index b967885d8..dc676c101 100644 --- a/kclvm/sema/src/resolver/tests.rs +++ b/kclvm/sema/src/resolver/tests.rs @@ -238,9 +238,9 @@ fn test_resolve_program_cycle_reference_fail() { let scope = resolve_program(&mut program); let err_messages = [ "There is a circular import reference between module file1 and file2", - "There is a circular reference between schema SchemaBase and SchemaSub", + // "There is a circular reference between schema SchemaBase and SchemaSub", "There is a circular reference between schema SchemaSub and SchemaBase", - "There is a circular reference between rule RuleBase and RuleSub", + // "There is a circular reference between rule RuleBase and RuleSub", "There is a circular reference between rule RuleSub and RuleBase", "Module 'file2' imported but unused", "Module 'file1' imported but unused", diff --git a/kclvm/sema/src/ty/context.rs b/kclvm/sema/src/ty/context.rs index 5cfce1514..bea447e71 100644 --- a/kclvm/sema/src/ty/context.rs +++ b/kclvm/sema/src/ty/context.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use super::{sup, DictType, Type, TypeFlags, TypeKind, TypeRef}; use petgraph::algo::is_cyclic_directed; use petgraph::graph::{DiGraph, NodeIndex}; +use petgraph::visit::{depth_first_search, DfsEvent}; /// TypeContext responsible for type generation, calculation, /// and equality and subtype judgment between types. @@ -49,10 +50,18 @@ impl TypeContext { } } - /// Return true if the dep graph contains a cycle. + /// Return true if the dep graph contains a cycle from node. #[inline] - pub fn is_cyclic(&self) -> bool { - is_cyclic_directed(&self.dep_graph) + pub fn is_cyclic_from_node(&self, node: &String) -> bool { + let idx = match self.node_index_map.get(node) { + Some(idx) => idx, + None => return false, + }; + depth_first_search(&self.dep_graph, vec![idx.clone()], |event| match event { + DfsEvent::BackEdge(_, _) => Err(()), + _ => Ok(()), + }) + .is_err() } /// Add dependencies between "from" and "to".