Getting colder with our second freeze... it's 3.31.91 release day and string freeze, upload a tarball and lock those strings 🏂

Commit 03f8e291 authored by Matthias Berndt's avatar Matthias Berndt Committed by Jürg Billeter

Fix type checking when using generics in combination with subtyping

https://bugzilla.gnome.org/show_bug.cgi?id=615830
parent 52406608
......@@ -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 \
......
Invalid Code
class Foo<T> {
}
class Bar<T> : Foo<T> {
}
void main (string[] args) {
Foo<int> f = new Bar<string> ();
}
Invalid Code
struct Foo<T> {
int x;
}
struct Bar<T> : Foo<T> {
}
void main (string[] args) {
Foo<int> f = Bar<string> ();
}
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;
}
......@@ -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;
}
......
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment