]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Fix type checking when using generics in combination with subtyping
authorMatthias Berndt <matthias_berndt@gmx.de>
Mon, 8 Aug 2016 17:41:33 +0000 (19:41 +0200)
committerJürg Billeter <j@bitron.ch>
Wed, 28 Sep 2016 07:15:13 +0000 (09:15 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=615830

tests/Makefile.am
tests/objects/bug615830-1.test [new file with mode: 0644]
tests/objects/bug615830-2.test [new file with mode: 0644]
tests/objects/generics.vala [new file with mode: 0644]
vala/valadatatype.vala
vala/valasemanticanalyzer.vala

index 4e684a75d265154590ba1bf73be8778c304cc0d9..0fd49d9fa02b4b71889a8bb292ecb9ea9a209c02 100644 (file)
@@ -130,6 +130,7 @@ TESTS = \
        delegates/bug703804.vala \
        objects/chainup.vala \
        objects/classes.vala \
+       objects/generics.vala \
        objects/fields.vala \
        objects/interfaces.vala \
        objects/methods.vala \
@@ -173,6 +174,8 @@ TESTS = \
        objects/bug751338.vala \
        objects/bug767092.test \
        objects/bug768823.test \
+       objects/bug615830-1.test \
+       objects/bug615830-2.test \
        errors/errors.vala \
        errors/bug567181.vala \
        errors/bug579101.vala \
diff --git a/tests/objects/bug615830-1.test b/tests/objects/bug615830-1.test
new file mode 100644 (file)
index 0000000..0283ce4
--- /dev/null
@@ -0,0 +1,11 @@
+Invalid Code
+
+class Foo<T> {
+}
+
+class Bar<T> : Foo<T> {
+}
+
+void main (string[] args) {
+       Foo<int> f = new Bar<string> ();
+}
diff --git a/tests/objects/bug615830-2.test b/tests/objects/bug615830-2.test
new file mode 100644 (file)
index 0000000..88b2493
--- /dev/null
@@ -0,0 +1,12 @@
+Invalid Code
+
+struct Foo<T> {
+       int x;
+}
+
+struct Bar<T> : Foo<T> {
+}
+
+void main (string[] args) {
+       Foo<int> f = Bar<string> ();
+}
diff --git a/tests/objects/generics.vala b/tests/objects/generics.vala
new file mode 100644 (file)
index 0000000..8b39db9
--- /dev/null
@@ -0,0 +1,7 @@
+void main() {
+       // Support generic types without type arguments for non-generic
+       // functions that are agnostic with regard to the actual type arguments.
+
+       GLib.HashTable<int, string> h = (GLib.HashTable) null;
+       (void) h;
+}
index 2277224facab577892bf57b7b326f9d289be44d3..5fe8c7b7928e7204405049c43a6a4fe7d16c42d6 100644 (file)
@@ -303,20 +303,19 @@ public abstract class Vala.DataType : CodeNode {
                        return true;
                }
 
-               if (data_type == target_type.data_type) {
+               if (data_type != null && target_type.data_type != null && data_type.is_subtype_of (target_type.data_type)) {
+                       var base_type = SemanticAnalyzer.get_instance_base_type_for_member(this, target_type.data_type, this);
                        // check compatibility of generic type arguments
-                       if (type_argument_list != null
-                           && type_argument_list.size > 0
-                           && type_argument_list.size == target_type.get_type_arguments ().size) {
-                               for (int i = 0; i < type_argument_list.size; i++) {
-                                       var type_arg = type_argument_list[i];
-                                       var target_type_arg = target_type.get_type_arguments ()[i];
+                       var base_type_args = base_type.get_type_arguments();
+                       var target_type_args = target_type.get_type_arguments();
+                       if (base_type_args.size == target_type_args.size) {
+                               for (int i = 0; i < base_type_args.size; i++) {
                                        // mutable generic types require type argument equality,
                                        // not just one way compatibility
                                        // as we do not currently have immutable generic container types,
                                        // the additional check would be very inconvenient, so we
                                        // skip the additional check for now
-                                       if (!type_arg.compatible (target_type_arg)) {
+                                       if (!base_type_args[i].compatible (target_type_args[i])) {
                                                return false;
                                        }
                                }
@@ -341,10 +340,6 @@ public abstract class Vala.DataType : CodeNode {
                        }
                }
 
-               if (data_type != null && target_type.data_type != null && data_type.is_subtype_of (target_type.data_type)) {
-                       return true;
-               }
-
                return false;
        }
 
index 5a83c9b993ec3dc07b04e8b256f623e6f867fbd8..ef023e10192483d5c57e3ff36fea524e5682a220 100644 (file)
@@ -721,11 +721,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
        private static DataType? get_instance_base_type (DataType instance_type, DataType base_type, CodeNode node_reference) {
                // construct a new type reference for the base type with correctly linked type arguments
-               ReferenceType instance_base_type;
-               if (base_type.data_type is Class) {
-                       instance_base_type = new ObjectType ((Class) base_type.data_type);
+               DataType instance_base_type;
+               if (base_type.data_type is ObjectTypeSymbol) {
+                       instance_base_type = new ObjectType ((ObjectTypeSymbol) base_type.data_type);
+               } else if (base_type.data_type is Struct) {
+                       instance_base_type = new StructValueType ((Struct) base_type.data_type);
                } else {
-                       instance_base_type = new ObjectType ((Interface) base_type.data_type);
+                       assert_not_reached ();
                }
                foreach (DataType type_arg in base_type.get_type_arguments ()) {
                        // resolve type argument specified in base type (possibly recursively for nested generic types)
@@ -735,7 +737,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                return instance_base_type;
        }
 
-       static DataType? get_instance_base_type_for_member (DataType derived_instance_type, TypeSymbol type_symbol, CodeNode node_reference) {
+       internal static DataType? get_instance_base_type_for_member (DataType derived_instance_type, TypeSymbol type_symbol, CodeNode node_reference) {
                DataType instance_type = derived_instance_type;
 
                while (instance_type is PointerType) {