Repository: veryl-lang/veryl (Rust)

Issue:
Can't use struct type referenced via proto package for struct literal
Veryl compiler reports `unknown_member` error for a struct literal typed by a struct type referenced via a proto package.

```systemverilog
package FooPkg {
    struct Foo {
        foo: logic,
    }
}

proto package BarProtoPkg {
    type Foo = FooPkg::Foo;
}

package BarPkg for BarProtoPkg {
    type Foo = FooPkg::Foo;
}

module ModuleA::<PKG: BarProtoPkg> {
    let _foo: PKG::Foo = PKG::Foo'{ foo: 0 };
}

module ModuleB {
    inst u: ModuleA::<BarPkg>;
}
```

```
]8;;https://doc.veryl-lang.org/book/07_appendix/02_semantic_error.html#unknown_member\unknown_member (link)]8;;\

  💥 "Foo" doesn't have member "foo"
    ╭─[:16:37]
 15 │ module ModuleA::<PKG: BarProtoPkg> {
 16 │     let _foo: PKG::Foo = PKG::Foo'{ foo: 0 };
    ·                                     ─┬─
    ·                                      ╰── Error location
 17 │ }
    ╰────
  help: 
```


Discussion:
Veryl compiler reports the error for struct type referenced via typedef.

```systemverilog
package FooPkg {
    struct Foo {
        foo: logic,
    }
}

package BarPkg {
    type Foo = FooPkg::Foo;
}

module ModuleA {
    let _foo: BarPkg::Foo = BarPkg::Foo'{ foo: 0 };
}
```

```
]8;;https://doc.veryl-lang.org/book/07_appendix/02_semantic_error.html#unknown_member\unknown_member (link)]8;;\

  💥 "Foo" doesn't have member "foo"
    ╭─[:12:43]
 11 │ module ModuleA {
 12 │     let _foo: BarPkg::Foo = BarPkg::Foo'{ foo: 0 };
    ·                                           ─┬─
    ·                                            ╰── Error location
 13 │ }
    ╰────
  help: 
```



Patch:
diff --git a/crates/analyzer/src/reference_table.rs b/crates/analyzer/src/reference_table.rs
index d0719b703..3086e1cfd 100644
--- a/crates/analyzer/src/reference_table.rs
+++ b/crates/analyzer/src/reference_table.rs
@@ -462,7 +462,7 @@ impl ReferenceTable {
                 }
                 ReferenceCandidate::StructConstructorItem { arg, r#type } => {
                     if let Ok(symbol) = symbol_table::resolve(r#type) {
-                        let namespace = symbol.found.inner_namespace();
+                        let namespace = Self::get_struct_namespace(&symbol.found);
                         let symbol_path: SymbolPath = arg.identifier.as_ref().into();
 
                         match symbol_table::resolve((&symbol_path, &namespace)) {
@@ -512,6 +512,25 @@ impl ReferenceTable {
 
         self.errors.drain(0..).collect()
     }
+
+    fn get_struct_namespace(symbol: &Symbol) -> Namespace {
+        match &symbol.kind {
+            SymbolKind::TypeDef(x) => {
+                if let Some((_, Some(symbol))) = x.r#type.trace_user_defined(&symbol.namespace) {
+                    return Self::get_struct_namespace(&symbol);
+                }
+            }
+            SymbolKind::ProtoTypeDef(x) => {
+                if let Some(r#type) = &x.r#type {
+                    if let Some((_, Some(symbol))) = r#type.trace_user_defined(&symbol.namespace) {
+                        return Self::get_struct_namespace(&symbol);
+                    }
+                }
+            }
+            _ => {}
+        }
+        symbol.inner_namespace()
+    }
 }
 
 thread_local!(static REFERENCE_TABLE: RefCell<ReferenceTable> = RefCell::new(ReferenceTable::new()));
diff --git a/crates/analyzer/src/symbol.rs b/crates/analyzer/src/symbol.rs
index c8bba8261..761d2ae42 100644
--- a/crates/analyzer/src/symbol.rs
+++ b/crates/analyzer/src/symbol.rs
@@ -1176,6 +1176,13 @@ impl Type {
                 SymbolKind::TypeDef(x) => {
                     return x.r#type.trace_user_defined(&symbol.found.namespace);
                 }
+                SymbolKind::ProtoTypeDef(ref x) => {
+                    if let Some(r#type) = &x.r#type {
+                        return r#type.trace_user_defined(&symbol.found.namespace);
+                    } else {
+                        return Some((self.clone(), Some(symbol.found)));
+                    }
+                }
                 SymbolKind::Module(_)
                 | SymbolKind::ProtoModule(_)
                 | SymbolKind::Interface(_)


Test patch:
diff --git a/crates/analyzer/src/tests.rs b/crates/analyzer/src/tests.rs
index 2648c6a4e..7ef78df49 100644
--- a/crates/analyzer/src/tests.rs
+++ b/crates/analyzer/src/tests.rs
@@ -4281,6 +4281,40 @@ fn unknown_member() {
 
     let errors = analyze(code);
     assert!(errors.is_empty());
+
+    let code = r#"
+    package FooPkg {
+        struct Foo {
+            foo: logic,
+        }
+    }
+    package BarPkg {
+        type Foo = FooPkg::Foo;
+    }
+    module ModuleA {
+        let _foo: BarPkg::Foo = BarPkg::Foo'{ foo: 0 };
+    }
+    "#;
+
+    let errors = analyze(code);
+    assert!(errors.is_empty());
+
+    let code = r#"
+    package FooPkg {
+        struct Foo {
+            foo: logic,
+        }
+    }
+    proto package BarProtoPkg {
+        type Foo = FooPkg::Foo;
+    }
+    module ModuleA::<PKG: BarProtoPkg> {
+        let _foo: PKG::Foo = PKG::Foo'{ foo: 0 };
+    }
+    "#;
+
+    let errors = analyze(code);
+    assert!(errors.is_empty());
 }
 
 #[test]