summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter28b/src/main/java/com/seaofnodes/simple/Parser.java10
-rw-r--r--chapter28b/src/test/java/com/seaofnodes/simple/Chapter25Test.java19
2 files changed, 23 insertions, 6 deletions
diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java b/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java
index 8410bf5c..83bef882 100644
--- a/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter28b/src/main/java/com/seaofnodes/simple/Parser.java
@@ -1486,11 +1486,6 @@ public class Parser {
return TypeFunPtr.make1((byte)2, true, targs, tret, _code.fidx(clzBare,order));
}
- // A class type carries the constructor function as a required final field.
- private TypeStruct classStruct( String typeName, TypeFunPtr init, boolean open ) {
- return TypeStruct.make(addClzPrefix(typeName),open,Field.make(initFieldName(typeName),init,_code.alias(_ref._cname),true));
- }
-
private static String initFieldName( String typeName ) {
if( startsClzPrefix(typeName) )
typeName = typeName.substring(clzPrefix.length());
@@ -1702,7 +1697,10 @@ public class Parser {
private TypeMemPtr forwardRefType( String tname, TypeStruct tself ) {
TYPES.put(tname,tself);
String clzName = addClzPrefix( tname );
- TYPES.put(clzName, classStruct(tname,structInitSig(false,tself),true));
+ // Only a struct declaration publishes an instance initializer. A
+ // forward type may name a file with just <clinit>, so do not invent
+ // a constructor field (or overwrite an already parsed class).
+ TYPES.putIfAbsent(clzName,TypeStruct.make(clzName,true));
return TypeMemPtr.make(tself);
}
diff --git a/chapter28b/src/test/java/com/seaofnodes/simple/Chapter25Test.java b/chapter28b/src/test/java/com/seaofnodes/simple/Chapter25Test.java
index dbb2a5ca..f94f641b 100644
--- a/chapter28b/src/test/java/com/seaofnodes/simple/Chapter25Test.java
+++ b/chapter28b/src/test/java/com/seaofnodes/simple/Chapter25Test.java
@@ -218,6 +218,25 @@ public class Chapter25Test {
code.driver(CodeGen.Phase.TypeCheck);
}
+ @Test public void testTypeOnlyFileReference() throws IOException {
+ Path base = Path.of("build/objs");
+ Files.createDirectories(base);
+ Path root = Files.createTempDirectory(base,"type-only-");
+ Files.createDirectory(root.resolve("A"));
+ Files.writeString(root.resolve("A/B.smp"),"int x = 0;");
+ // B declares only a class initializer. Using its name as a type
+ // must not publish a nonexistent instance initializer during Opto.
+ for( String src : new String[]{
+ "B? b = null; return 0;",
+ "val readB = { B b -> 0; }; return 0;"
+ } ) {
+ Files.writeString(root.resolve("A.smp"),src);
+ CodeGen code = new CodeGen(root.toString(),root.resolve("obj").toString(),null,
+ "A",null,123,true,TypeInteger.BOT).driver(CodeGen.Phase.TypeCheck);
+ assertEquals("0",Eval2.eval(code,0));
+ }
+ }
+
@Test
public void testPostfixFieldUpdate() {