changeset 11467:43eab069ca9b

Truffle-DSL: improved error recovery of type systems and improved error testability infrastructure.
author Christian Humer <christian.humer@gmail.com>
date Thu, 29 Aug 2013 19:19:00 +0200
parents 4830676526e3
children 79d4c4b2d6db
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java
diffstat 17 files changed, 181 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java	Thu Aug 29 19:19:00 2013 +0200
@@ -38,7 +38,7 @@
 
     }
 
-    @ExpectError("Nodes containing the @Specialization annotation cannot be private.")
+    @ExpectError("Classes containing a @Specialization annotation must not be private.")
     private abstract static class Visiblity02 extends ValueNode {
 
         @Specialization
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java	Thu Aug 29 19:19:00 2013 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+
+public class TypeSystemErrorsTest {
+
+    @TypeSystem({int.class, boolean.class})
+    static class Types0 {
+
+    }
+
+    @ExpectError("Invalid type order. The type(s) [java.lang.String] are inherited from a earlier defined type java.lang.CharSequence.")
+    @TypeSystem({CharSequence.class, String.class})
+    static class Types1 {
+
+    }
+
+    @TypeSystem({int.class, boolean.class})
+    static class Types2 {
+
+        @TypeCast
+        @ExpectError("The provided return type \"String\" does not match expected return type \"int\".%")
+        String asInteger(Object value) {
+            return (String) value;
+        }
+
+    }
+
+    @TypeSystem({int.class, boolean.class})
+    static class Types3 {
+
+        @TypeCast
+        @ExpectError("The provided return type \"boolean\" does not match expected return type \"int\".%")
+        boolean asInteger(Object value) {
+            return (boolean) value;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Thu Aug 29 19:19:00 2013 +0200
@@ -423,6 +423,8 @@
                 return getSimpleName(mirror);
             case ERROR:
                 throw new CompileErrorException("Type error " + mirror);
+            case EXECUTABLE:
+                return ((ExecutableType) mirror).toString();
             case NONE:
                 return "$none";
             default:
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public CreateCastData create(TemplateMethod method) {
+    public CreateCastData create(TemplateMethod method, boolean invalid) {
         AnnotationMirror mirror = method.getMarkerAnnotation();
         List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
         CreateCastData cast = new CreateCastData(method, childNames);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -83,7 +83,7 @@
     }
 
     @Override
-    public ExecutableTypeData create(TemplateMethod method) {
+    public ExecutableTypeData create(TemplateMethod method, boolean invalid) {
         TypeData resolvedType = method.getReturnType().getTypeSystemType();
         return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType);
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public SpecializationData create(TemplateMethod method) {
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
         SpecializationData data = new SpecializationData(method, true, false, false);
         return data;
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -30,8 +30,6 @@
 import javax.lang.model.util.*;
 import javax.tools.Diagnostic.Kind;
 
-import org.omg.CORBA.*;
-
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
@@ -202,7 +200,7 @@
 
         for (NodeData splittedNode : nodes) {
             if (templateType.getModifiers().contains(Modifier.PRIVATE) && splittedNode.getSpecializations().size() > 0) {
-                splittedNode.addError("Nodes containing the @%s annotation cannot be private.", Specialization.class.getSimpleName());
+                splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
             }
 
             finalizeSpecializations(elements, splittedNode);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -58,7 +58,7 @@
     }
 
     @Override
-    public ShortCircuitData create(TemplateMethod method) {
+    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
         String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
 
         if (!shortCircuitValues.contains(shortCircuitValue)) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public SpecializationListenerData create(TemplateMethod method) {
+    public SpecializationListenerData create(TemplateMethod method, boolean invalid) {
         return new SpecializationListenerData(method);
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public SpecializationData create(TemplateMethod method) {
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
         return parseSpecialization(method);
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Thu Aug 29 19:19:00 2013 +0200
@@ -52,25 +52,17 @@
     public abstract Element getMessageElement();
 
     public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) {
-        emitMessagesImpl(context, baseElement, log, new HashSet<MessageContainer>());
+        emitMessagesImpl(context, baseElement, log, new HashSet<MessageContainer>(), null);
     }
 
-    private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks) {
-        TypeElement expectError = context.getTruffleTypes().getExpectError();
-        if (expectError != null) {
-            Element element = getMessageElement();
-            AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
-            if (mirror != null) {
-                List<String> values = Utils.getAnnotationValueList(String.class, mirror, "value");
-                if (values == null) {
-                    values = Collections.emptyList();
-                }
-                List<Message> msgs = getMessages();
-                if (values.size() != msgs.size()) {
-                    log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
-                }
-            }
+    private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
+        List<Message> childMessages;
+        if (verifiedMessages == null) {
+            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
+        } else {
+            childMessages = verifiedMessages;
         }
+        verifyExpectedMessages(context, log, childMessages);
 
         for (Message message : getMessages()) {
             emitDefault(context, baseElement, log, message);
@@ -82,7 +74,44 @@
             }
 
             visitedSinks.add(sink);
-            sink.emitMessagesImpl(context, baseElement, log, visitedSinks);
+            if (sink.getMessageElement() == this.getMessageElement()) {
+                sink.emitMessagesImpl(context, baseElement, log, visitedSinks, childMessages);
+            } else {
+                sink.emitMessagesImpl(context, baseElement, log, visitedSinks, null);
+            }
+        }
+    }
+
+    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
+        if (visitedSinks.contains(this)) {
+            return Collections.emptyList();
+        }
+        visitedSinks.add(this);
+
+        List<Message> foundMessages = new ArrayList<>();
+        if (Utils.typeEquals(getMessageElement().asType(), e.asType())) {
+            foundMessages.addAll(getMessages());
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
+        }
+        return foundMessages;
+    }
+
+    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            Element element = getMessageElement();
+            AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
+            if (mirror != null) {
+                List<String> values = Utils.getAnnotationValueList(String.class, mirror, "value");
+                if (values == null) {
+                    values = Collections.emptyList();
+                }
+                if (values.size() != msgs.size()) {
+                    log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
+                }
+            }
         }
     }
 
@@ -99,7 +128,8 @@
         String text = message.getText();
 
         TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement());
-        if (rootEnclosing == null || !Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) || this != message.getOriginalContainer()) {
+        TypeElement baseEnclosing = Utils.findRootEnclosingType(baseType);
+        if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType()) || this != message.getOriginalContainer()) {
             // redirect message
             MessageContainer original = message.getOriginalContainer();
             messageElement = baseType;
@@ -113,11 +143,22 @@
             AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError);
             if (mirror != null) {
                 List<String> expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value");
-                if (!expectedTexts.contains(text)) {
-                    log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Message expected one of '%s' but was '%s'.", expectedTexts, text));
+                boolean found = false;
+                for (String expectedText : expectedTexts) {
+                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
+                        found = true;
+                        break;
+                    } else if (text.equals(expectedText)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
                 } else {
                     return;
                 }
+
             }
         }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -76,7 +76,7 @@
 
     public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
 
-    public abstract E create(TemplateMethod method);
+    public abstract E create(TemplateMethod method, boolean invalid);
 
     public abstract boolean isParsable(ExecutableElement method);
 
@@ -143,7 +143,7 @@
         ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false);
         if (returnTypeMirror == null) {
             if (emitErrors) {
-                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
+                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
                 String expectedReturnType = returnTypeSpec.toSignatureString(true);
                 String actualReturnType = Utils.getSimpleName(method.getReturnType());
 
@@ -164,7 +164,7 @@
         List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes);
         if (parameters == null) {
             if (isEmitErrors()) {
-                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
+                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
                 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
                                 methodSpecification.toSignatureString(method.getSimpleName().toString()));
                 invalidMethod.addError(message);
@@ -174,7 +174,7 @@
             }
         }
 
-        return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters));
+        return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
     }
 
     private static String createActualSignature(MethodSpec spec, ExecutableElement method) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -79,7 +79,7 @@
     }
 
     @Override
-    public GuardData create(TemplateMethod method) {
+    public GuardData create(TemplateMethod method, boolean invalid) {
         GuardData guard = new GuardData(method, specialization, negated);
         /*
          * Update parameters in way that parameter specifications match again the node field names
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -48,10 +48,25 @@
     }
 
     @Override
-    public TypeCastData create(TemplateMethod method) {
+    public TypeCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new TypeCastData(method, null, null);
+        }
+
         TypeData targetType = findTypeByMethodName(method, "as");
         ActualParameter parameter = method.findParameter("valueValue");
-        return new TypeCastData(method, parameter.getTypeSystemType(), targetType);
+
+        TypeData sourceType = null;
+        if (parameter != null) {
+            sourceType = getTypeSystem().findTypeData(parameter.getType());
+        }
+        TypeCastData cast = new TypeCastData(method, sourceType, targetType);
+
+        if (targetType != method.getReturnType().getTypeSystemType()) {
+            cast.addError("Cast type %s does not match to the returned type %s.", Utils.getSimpleName(targetType.getPrimitiveType()),
+                            method.getReturnType() != null ? Utils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null);
+        }
+        return cast;
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public TypeCheckData create(TemplateMethod method) {
+    public TypeCheckData create(TemplateMethod method, boolean invalid) {
         TypeData checkedType = findTypeByMethodName(method, "is");
         assert checkedType != null;
         ActualParameter parameter = method.findParameter("valueValue");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java	Thu Aug 29 19:19:00 2013 +0200
@@ -36,6 +36,9 @@
     private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
     private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
 
+    private List<TypeCastData> casts;
+    private List<TypeCheckData> checks;
+
     private TypeMirror genericType;
     private TypeData voidType;
 
@@ -58,6 +61,14 @@
         }
     }
 
+    public void setCasts(List<TypeCastData> casts) {
+        this.casts = casts;
+    }
+
+    public void setChecks(List<TypeCheckData> checks) {
+        this.checks = checks;
+    }
+
     void setGenericType(TypeMirror genericType) {
         this.genericType = genericType;
     }
@@ -72,6 +83,12 @@
         if (types != null) {
             sinks.addAll(types);
         }
+        if (checks != null) {
+            sinks.addAll(checks);
+        }
+        if (casts != null) {
+            sinks.addAll(casts);
+        }
         return sinks;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Thu Aug 29 17:39:55 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Thu Aug 29 19:19:00 2013 +0200
@@ -84,11 +84,17 @@
         verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
 
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-
+        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
         List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
         List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
 
-        if (casts == null || checks == null) {
+        if (casts == null || checks == null || implicitCasts == null) {
+            return typeSystem;
+        }
+        typeSystem.setCasts(casts);
+        typeSystem.setChecks(checks);
+
+        if (typeSystem.hasErrors()) {
             return typeSystem;
         }