summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Berndt <matthias_berndt@gmx.de>2016-09-21 00:05:35 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2016-09-21 18:43:24 +0200
commit6054e9d6c68bd1696ceec44ffbc5ba7c3b5f2088 (patch)
tree43bcb67ddfbdbc9a18e80e9c3c40c88ea5e20020
parent5c9b22e779122c2ce5598e0e11b6a9a34325910d (diff)
downloadvala-wip/bug615830.tar.gz
Fix type checking when using generics in combination with subtypingwip/bug615830
https://bugzilla.gnome.org/show_bug.cgi?id=615830
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/objects/bug615830-1.test11
-rw-r--r--tests/objects/bug615830-2.test12
-rw-r--r--tests/objects/generics.vala7
-rw-r--r--vala/valadatatype.vala19
-rw-r--r--vala/valasemanticanalyzer.vala13
6 files changed, 48 insertions, 17 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b2caa7767..4a29806be 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -128,6 +128,7 @@ TESTS = \
delegates/bug703804.vala \
objects/chainup.vala \
objects/classes.vala \
+ objects/generics.vala \
objects/fields.vala \
objects/interfaces.vala \
objects/methods.vala \
@@ -171,6 +172,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
index 000000000..0283ce4b8
--- /dev/null
+++ b/tests/objects/bug615830-1.test
@@ -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
index 000000000..88b2493b2
--- /dev/null
+++ b/tests/objects/bug615830-2.test
@@ -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
index 000000000..8b39db945
--- /dev/null
+++ b/tests/objects/generics.vala
@@ -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;
+}
diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala
index 02b4cf13f..2e799b3b1 100644
--- a/vala/valadatatype.vala
+++ b/vala/valadatatype.vala
@@ -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;
}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index cb1a575f5..cf04458be 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -721,11 +721,14 @@ 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);
+ instance_base_type = null;
+ assert(false);
}
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 +738,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) {
+ public 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) {