Skip to content

Commit c47755f

Browse files
authored
Correctly set type args binding for derived generic classes, fixes #871 (#1100)
1 parent f4e4dd1 commit c47755f

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,7 +1742,7 @@ private void checkParams(Element where, String preMsg, List<Expr> args, List<Wur
17421742
// if (expected instanceof AstElementWithTypeArgs)
17431743
if (!actual.isSubtypeOf(expected, where)) {
17441744
args.get(i).addError(
1745-
preMsg + "Expected " + expected + " as parameter " + (i + 1) + " but found " + actual);
1745+
preMsg + "Expected " + expected + " as parameter " + (i + 1) + " but found " + actual);
17461746
}
17471747
}
17481748
}
@@ -2363,22 +2363,30 @@ private void checkConstructor(ConstructorDef d) {
23632363
WurstTypeClass ct = c.attrTypC();
23642364
WurstTypeClass extendedClass = ct.extendedClass();
23652365
if (extendedClass != null) {
2366-
// check if super constructor is called correctly...
2367-
// TODO check constr: get it from ct so that it has the correct type binding
2366+
// Use the *bound* super-constructor signature
23682367
ConstructorDef sc = d.attrSuperConstructor();
23692368
if (sc == null) {
23702369
d.addError("No super constructor found.");
23712370
} else {
2372-
List<WurstType> paramTypes = Lists.newArrayList();
2371+
// Build expected param types in the subclass binding context
2372+
List<WurstType> expected = Lists.newArrayList();
2373+
2374+
// The binding that maps the superclass type params to the subclass type args
2375+
VariableBinding binding = extendedClass.getTypeArgBinding();
2376+
23732377
for (WParameter p : sc.getParameters()) {
2374-
paramTypes.add(p.attrTyp());
2378+
WurstType t = p.attrTyp();
2379+
t = t.setTypeArgs(binding);
2380+
2381+
expected.add(t);
23752382
}
2383+
23762384
if (d.getSuperConstructorCall() instanceof NoSuperConstructorCall
2377-
&& paramTypes.size() > 0) {
2385+
&& !expected.isEmpty()) {
23782386
c.addError("The extended class <" + extendedClass.getName() + "> does not expose a no-arg constructor. " +
2379-
"You must define a constructor that calls super(..) appropriately, in this class.");
2387+
"You must define a constructor that calls super(..) appropriately, in this class.");
23802388
} else {
2381-
checkParams(d, "Incorrect call to super constructor: ", superArgs(d), paramTypes);
2389+
checkParams(d, "Incorrect call to super constructor: ", superArgs(d), expected);
23822390
}
23832391
}
23842392
}
@@ -2390,6 +2398,7 @@ private void checkConstructor(ConstructorDef d) {
23902398
}
23912399

23922400

2401+
23932402
private void checkArrayAccess(ExprVarArrayAccess ea) {
23942403
checkNameRefDeprecated(ea, ea.tryGetNameDef());
23952404
for (Expr index : ea.getIndexes()) {

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,5 +1472,41 @@ public void callingDestroyThisInConstructor() {
14721472
" testSuccess()",
14731473
"endpackage");
14741474
}
1475+
@Test
1476+
public void derivedGenericClassConstructor() {
1477+
testAssertOkLinesWithStdLib(true,
1478+
"package test",
1479+
"import LinkedList",
1480+
"public class ListIterator<T> extends LLIterator<T>",
1481+
" construct(LinkedList<T> parent)",
1482+
" super(parent)",
1483+
"init",
1484+
" let b = new ListIterator<int>(new LinkedList<int>())",
1485+
" if b != null",
1486+
" testSuccess()",
1487+
"endpackage");
1488+
}
1489+
1490+
@Test
1491+
public void derivedGenericClassConstructorNewGenerics() {
1492+
testAssertOkLines(true,
1493+
"package test",
1494+
"native testSuccess()",
1495+
"class A<T:>",
1496+
" T value",
1497+
"class B<X:>",
1498+
" A<X> a",
1499+
" construct(A<X> a)",
1500+
" this.a = a",
1501+
"public class C<T:> extends B<T>",
1502+
" construct(A<T> parent)",
1503+
" super(parent)",
1504+
"init",
1505+
" let b = new C<int>(new A<int>())",
1506+
" if b != null",
1507+
" testSuccess()",
1508+
"endpackage");
1509+
}
1510+
14751511

14761512
}

0 commit comments

Comments
 (0)