Repository: veryl-lang/veryl (Rust)

Issue:
Invalid filelist order
Veryl generates a filelist with incorrect order for the sample project below.

* a.veryl
  ```systemverilog
  proto package a_proto_pkg {
      const A: u32;
  }
  package a_pkg::<V: u32> for a_proto_pkg {
      const A: u32 = V;
  }
  ```
* b.veryl
  ```systemverilog
  module b_module::<A_PKG: a_proto_pkg> {
      const B: u32 = c_pkg::<A_PKG>::C;
  }
  alias package a = a_pkg::<32>;
  alias module  b = b_module::<a>;
  ```
* c.veryl
  ```systemverilog
  package c_pkg::<A_PKG: a_proto_pkg> {
      const C: u32 = A_PKG::A;
  }
  ```

`c.veryl` is depend on `a.veryl` because `a_proto_pkg` is used in `c.veryl`.
Therefore, generated filelist should be:

```
a.veryl
c.veryl
b.veryl
```

But actual generated filelist is:

```
/home/taichi/workspace/temp/veryl/26/c.sv
/home/taichi/workspace/temp/veryl/26/a.sv
/home/taichi/workspace/temp/veryl/26/b.sv
```



Discussion:

Patch:
diff --git a/crates/analyzer/src/handlers/create_symbol_table.rs b/crates/analyzer/src/handlers/create_symbol_table.rs
index 99a437120..65009262a 100644
--- a/crates/analyzer/src/handlers/create_symbol_table.rs
+++ b/crates/analyzer/src/handlers/create_symbol_table.rs
@@ -611,6 +611,7 @@ impl CreateSymbolTable {
             let cand = TypeDagCandidate::Symbol {
                 id: symbol.0,
                 context: symbol.1,
+                project_namespace: self.project_namespace.clone(),
                 parent: None,
                 import,
             };
diff --git a/crates/analyzer/src/type_dag.rs b/crates/analyzer/src/type_dag.rs
index 7d4abcc93..69b73a923 100644
--- a/crates/analyzer/src/type_dag.rs
+++ b/crates/analyzer/src/type_dag.rs
@@ -23,6 +23,7 @@ pub enum TypeDagCandidate {
     Symbol {
         id: SymbolId,
         context: Context,
+        project_namespace: Namespace,
         parent: Option<(SymbolId, Context)>,
         import: Vec<GenericSymbolPathNamesapce>,
     },
@@ -130,6 +131,7 @@ impl TypeDag {
             if let TypeDagCandidate::Symbol {
                 id,
                 context,
+                project_namespace,
                 parent,
                 import,
             } = cand
@@ -143,6 +145,18 @@ impl TypeDag {
                         self.insert_dag_edge(child, import, *context);
                     }
                 }
+
+                for map in symbol.generic_maps() {
+                    for arg_path in map.map.values() {
+                        // insert edge between given generic arg and base symbol
+                        self.insert_path(
+                            arg_path,
+                            &symbol.namespace,
+                            project_namespace,
+                            &Some((*id, *context)),
+                        );
+                    }
+                }
             }
         }
 
@@ -226,17 +240,6 @@ impl TypeDag {
                     self.insert_dag_edge(parent, base, parent_context);
                 }
             }
-
-            for arg in path.paths[i]
-                .arguments
-                .iter()
-                .filter_map(|x| Self::resolve_symbol_path(&x.generic_path(), namespace))
-            {
-                let Some(arg) = self.insert_symbol(&arg) else {
-                    continue;
-                };
-                self.insert_dag_edge(base, arg, Context::GenericInstance);
-            }
         }
     }
 


Test patch:
diff --git a/crates/analyzer/src/tests.rs b/crates/analyzer/src/tests.rs
index 37dbcd006..e98533bad 100644
--- a/crates/analyzer/src/tests.rs
+++ b/crates/analyzer/src/tests.rs
@@ -6704,16 +6704,21 @@ fn unresolvable_generic_argument() {
         struct Bar {
             bar: Baz
         }
-        function Func::<baz: Baz> {}
     }
     package PkgB {
         import PkgA::*;
         const FOO: Bar = Bar'{ bar: Baz'{ baz: 1 } };
     }
+    package PkgC {
+        import PkgA::*;
+        function Func::<baz: Baz> -> logic {
+            return baz.baz;
+        }
+    }
     module ModuleA {
         import PkgB::*;
         always_comb {
-            PkgA::Func::<PkgB::FOO.bar>();
+            PkgC::Func::<PkgB::FOO.bar>();
         }
     }
     "#;
diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs
index b572eec1b..f64166f45 100644
--- a/crates/tests/src/lib.rs
+++ b/crates/tests/src/lib.rs
@@ -444,6 +444,9 @@ mod filelist {
             "11_package_h.veryl",
             "12_alias_i.veryl",
             "13_embed.veryl",
+            "14_package_j.veryl",
+            "15_module_k.veryl",
+            "16_package_l.veryl",
             "ram.veryl",
             "axi_pkg.veryl",
         ];
@@ -458,5 +461,7 @@ mod filelist {
         check_order(&paths, "10_package_g.veryl", "11_package_h.veryl");
         check_order(&paths, "axi_pkg.veryl", "12_alias_i.veryl");
         check_order(&paths, "axi_pkg.veryl", "13_embed.veryl");
+        check_order(&paths, "14_package_j.veryl", "16_package_l.veryl");
+        check_order(&paths, "16_package_l.veryl", "15_module_k.veryl");
     }
 }
diff --git a/testcases/filelist/src/14_package_j.veryl b/testcases/filelist/src/14_package_j.veryl
new file mode 100644
index 000000000..1c2a80f35
--- /dev/null
+++ b/testcases/filelist/src/14_package_j.veryl
@@ -0,0 +1,7 @@
+proto package ProtoPackageJ {
+  const J: u32;
+}
+
+package PackageJ::<V: u32> for ProtoPackageJ {
+  const J: u32 = V;
+}
diff --git a/testcases/filelist/src/15_module_k.veryl b/testcases/filelist/src/15_module_k.veryl
new file mode 100644
index 000000000..462895cba
--- /dev/null
+++ b/testcases/filelist/src/15_module_k.veryl
@@ -0,0 +1,6 @@
+module ModuleK::<PKG: ProtoPackageJ> {
+  const K: u32 = PackageL::<PKG>::L;
+}
+
+alias package J = PackageJ::<32>;
+alias module K = ModuleK::<J>;
diff --git a/testcases/filelist/src/16_package_l.veryl b/testcases/filelist/src/16_package_l.veryl
new file mode 100644
index 000000000..bc5c6b4fa
--- /dev/null
+++ b/testcases/filelist/src/16_package_l.veryl
@@ -0,0 +1,3 @@
+package PackageL::<PKG: ProtoPackageJ> {
+  const L: u32 = PKG::J;
+}