diff options
| author | Matthias Berndt <matthias_berndt@gmx.de> | 2016-08-08 17:41:33 (GMT) |
|---|---|---|
| committer | Jürg Billeter <j@bitron.ch> | 2016-09-28 07:15:13 (GMT) |
| commit | 03f8e291755297ae3c39520cd08d0df9684a9e66 (patch) | |
| tree | 75a9a625edd0ff934179c4a4418a63c8758eb94b | |
| parent | 52406608968d7056adc6cefaab2a834d8b4c1636 (diff) | |
| download | vala-03f8e291755297ae3c39520cd08d0df9684a9e66.zip vala-03f8e291755297ae3c39520cd08d0df9684a9e66.tar.xz | |
Fix type checking when using generics in combination with subtyping
https://bugzilla.gnome.org/show_bug.cgi?id=615830
| -rw-r--r-- | tests/Makefile.am | 3 | ||||
| -rw-r--r-- | tests/objects/bug615830-1.test | 11 | ||||
| -rw-r--r-- | tests/objects/bug615830-2.test | 12 | ||||
| -rw-r--r-- | tests/objects/generics.vala | 7 | ||||
| -rw-r--r-- | vala/valadatatype.vala | 19 | ||||
| -rw-r--r-- | vala/valasemanticanalyzer.vala | 12 |
6 files changed, 47 insertions, 17 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 4e684a7..0fd49d9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 0000000..0283ce4 --- /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 0000000..88b2493 --- /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 0000000..8b39db9 --- /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 2277224..5fe8c7b 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 5a83c9b..ef023e1 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -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) { |
