From: Rico Tzschichholz Date: Sat, 13 Feb 2021 18:34:12 +0000 (+0100) Subject: vala: Include type-checks in preconditions of methods for type narrowing X-Git-Tag: 0.51.2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e199f5621175c47a1b3c22a5c8c6337412df6fb9;p=thirdparty%2Fvala.git vala: Include type-checks in preconditions of methods for type narrowing See https://gitlab.gnome.org/GNOME/vala/issues/894 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 16820e66d..e7e7e9ced 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..5c6f42974 --- /dev/null +++ b/tests/objects/type-narrowing-by-precondition.vala @@ -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 (); +} diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala index 06cf64ce4..735f1b79e 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -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 (); 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; + } + } + } } }