]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Include type-checks in preconditions of methods for type narrowing
authorRico Tzschichholz <ricotz@ubuntu.com>
Sat, 13 Feb 2021 18:34:12 +0000 (19:34 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Sat, 13 Feb 2021 18:34:12 +0000 (19:34 +0100)
See https://gitlab.gnome.org/GNOME/vala/issues/894

tests/Makefile.am
tests/objects/type-narrowing-by-precondition.vala [new file with mode: 0644]
vala/valamemberaccess.vala

index 16820e66dd6ee285bc36b02eff3d0956900c0966..e7e7e9cedc8dcf5d2aceb80dbac615f6b9b298be 100644 (file)
@@ -497,6 +497,7 @@ TESTS = \
        objects/simple-generics-chainup.vala \
        objects/singleton.vala \
        objects/type-narrowing.vala \
+       objects/type-narrowing-by-precondition.vala \
        objects/type-narrowing-fallback.vala \
        objects/test-025.vala \
        objects/test-026.vala \
diff --git a/tests/objects/type-narrowing-by-precondition.vala b/tests/objects/type-narrowing-by-precondition.vala
new file mode 100644 (file)
index 0000000..5c6f429
--- /dev/null
@@ -0,0 +1,19 @@
+class Foo {
+       public void minim () requires (this is Bar) {
+               assert (this.i == 42);
+       }
+}
+
+class Bar : Foo {
+       public int i = 42;
+}
+
+void manam (Foo foo) requires (foo is Bar) {
+       assert (foo.i == 42);
+}
+
+void main () {
+       var bar = new Bar ();
+       manam (bar);
+       bar.minim ();
+}
index 06cf64ce4a430e0eb8909e9eb45d93ca46f9362b..735f1b79e78f77642a513f865a5766b7608fe304 100644 (file)
@@ -1130,6 +1130,7 @@ public class Vala.MemberAccess : Expression {
                bool is_negation = false;
                unowned CodeNode? parent = parent_node;
                unowned IfStatement? if_statement = null;
+               var scope_type_checks = new ArrayList<unowned TypeCheck> ();
                while (parent != null && !(parent is Method)) {
                        if (parent is TypeCheck) {
                                parent = null;
@@ -1140,6 +1141,14 @@ public class Vala.MemberAccess : Expression {
                                is_negation = if_statement.false_statement == parent;
                                break;
                        }
+                       if (parent.parent_node is Method) {
+                               foreach (Expression expr in ((Method) parent.parent_node).get_preconditions ()) {
+                                       if (expr is TypeCheck) {
+                                               scope_type_checks.add ((TypeCheck) expr);
+                                       }
+                               }
+                               break;
+                       }
                        parent = parent.parent_node;
                }
 
@@ -1160,5 +1169,16 @@ public class Vala.MemberAccess : Expression {
                                }
                        }
                }
+               if (value_type.context_symbol == null) {
+                       foreach (TypeCheck type_check in scope_type_checks) {
+                               unowned TypeSymbol? narrowed_symnol = type_check.type_reference.type_symbol;
+                               if (variable == type_check.expression.symbol_reference) {
+                                       if (narrowed_symnol != value_type.type_symbol) {
+                                               value_type.context_symbol = narrowed_symnol;
+                                       }
+                                       value_type.nullable = false;
+                               }
+                       }
+               }
        }
 }