From 93420adcf421875db866b6d90ecf07c4da163771 Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Mon, 23 May 2022 15:01:55 -0300 Subject: [PATCH 1/4] Specify behaviour of generics + return types in signatures - In general, a generic on the RHS can accept anything on the LHS... - ...but a non-generic type on the RHS cannot accept a generic on the LHS... - ...buf if either carry a type signature, we should take advantage of it... - ...mapping type capture to type capture until we find any non-generic type (or Mu). - A return type must not exist on the LHS if one does not exist on the RHS, otherwise it should defer to ACCEPTS as with parameters. --- S03-smartmatch/signature-signature.t | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/S03-smartmatch/signature-signature.t b/S03-smartmatch/signature-signature.t index ad2d5de35a..9260c4cab2 100644 --- a/S03-smartmatch/signature-signature.t +++ b/S03-smartmatch/signature-signature.t @@ -1,6 +1,6 @@ use v6; use Test; -plan 38; +plan 49; #L { @@ -35,14 +35,23 @@ plan 38; :(*%), :(:$ ($, $)), True, :(|), :(:$ ($, $)), True, :(:$b ($, $)), :(:$a ($, $)), False, + :(Any ::T, T), :(Cool ::T, T), True, + :(Any ::T, T), :(Cool ::T, Mu), False, + :(::T, Cool), :(Cool ::T, T), True, + :(::T, T), :(::T, ::U), True, + :(::A, A ::AA, AA ::OW ::HOT, HOT ::AAAA), :(Mu, Any, Cool, Str), True, + :(Mu, Mu, Mu), :(::BI, BI ::DI, ::BABIDI), True, + :(--> Mu), :(--> Any), True, + :(), :(--> Mu), False, + :(Cool --> Cool), :(Str ::T --> T), True, + :(--> 1), :(--> 1), True, + :(--> 1), :(--> 0), False, ); for @tests -> $s1, $s2, $res { is(($s2 ~~ $s1), $res, "{$s2.raku} ~~ {$s1.raku}"); } - #?rakudo skip "Parametric types" - # Can't deal with parameters. ok (:(::T $x, T $y) R~~ :(Str $y, Str $z)), "Parametric types"; ok (:(&foo:(Str --> Bool)) ~~ :(&bar:(Str --> Bool))), From ced4b3103615a9fb90dbe702a84fb16418d0348f Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Wed, 11 May 2022 05:36:26 -0300 Subject: [PATCH 2/4] Reintroduce S14-roles/generic-subtyping.t Unlike before: - Spare any unnecessary &EVAL nonsense. - Ensure that generic doees, parents, and a complicated blend of the two can typecheck. - Ensure we can access the doees list before composition (as typechecks may depend on it). --- S14-roles/generic-subtyping.t | 46 +++++++++++++++++++++++++---------- spectest.data | 1 + 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/S14-roles/generic-subtyping.t b/S14-roles/generic-subtyping.t index ea451d9222..d5036aa25a 100644 --- a/S14-roles/generic-subtyping.t +++ b/S14-roles/generic-subtyping.t @@ -2,23 +2,43 @@ use v6; use Test; -plan 5; - -lives-ok({ EVAL(Q:to/ROLES/) }, 'can do subtyped generic roles'); role R1[Any ::T] { } -role R2[Cool ::T] does R1[T] { } -ROLES -EVAL(Q:to/TESTS/); -ok(R2[Cool] ~~ R1[Any], 'subtyped generic roles'); -ok(R2[Cool] ~~ R2[Cool], 'subtyped generic roles'); -ok(R2[Int] ~~ R2[Cool], 'subtyped generic roles'); -TESTS +role R2[Cool ::T] is R1[T] { } + +role R3[Stringy ::T] does R2[T] { } + +role R4[Str ::T] does R2[T] is R3[T] { } + +only infix:(Mu $a is raw, Mu $b is raw) is test-assertion { + ok $a ~~ $b, "$a.raku() ~~ $b.raku()"; + nok $b ~~ $a, "$b.raku() !~~ $a.raku()"; +} + +plan 2; + +subtest 'subtyped generic roles can typecheck', { + plan 14 * 2; -lives-ok({ EVAL(Q:to/ROLE/) }, 'can lookup roles of subtyped generic roles done by roles before they get composed'); -multi sub trait_mod:(Mu:U \T, :ok($)!) { T.^roles[0].^roles } + R2[Str] checks R2; + R2[Str] checks R1; + R2[Str] checks R1[Any]; + R2[Str] checks R2[Cool]; + R3[Str] checks R1; + R3[Str] checks R1[Any]; + R3[Str] checks R3[Stringy]; + R4[Allomorph] checks R3; + R4[Allomorph] checks R2; + R4[Allomorph] checks R1; + R4[Allomorph] checks R1[Any]; + R4[Allomorph] checks R2[Cool]; + R4[Allomorph] checks R3[Stringy]; + R4[Allomorph] checks R4[Str]; +}; -role R2[Int ::T] does R1[T] is ok { } +lives-ok({ EVAL Q:to/ROLE/ }, 'can lookup generic doees of a role before they get composed'); +multi trait_mod:(Mu:U \T, :roled($)!) { T.^roles[0].^roles } +role R5[Int ::T] does R2[T] is roled { } ROLE # vim: expandtab shiftwidth=4 diff --git a/spectest.data b/spectest.data index 73285d9503..d85f16e30b 100644 --- a/spectest.data +++ b/spectest.data @@ -763,6 +763,7 @@ S14-roles/parameter-subtyping.t S14-roles/parameterized-basic.t S14-roles/parameterized-mixin.t S14-roles/parameterized-type.t +S14-roles/generic-subtyping.t S14-roles/rw.t S14-roles/stubs.t S14-roles/submethods-6e.t From 9384deb6ce7a5c44cfea6b29f9ced9e8e41ad404 Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Wed, 11 May 2022 05:43:46 -0300 Subject: [PATCH 3/4] Un-TODO a bunch of native array typechecking tests --- S09-typed-arrays/native-shape1-int.t | 3 --- S09-typed-arrays/native-shape1-num.t | 3 --- S09-typed-arrays/native-shape1-str.t | 3 --- 3 files changed, 9 deletions(-) diff --git a/S09-typed-arrays/native-shape1-int.t b/S09-typed-arrays/native-shape1-int.t index ed61d79b8c..39e50308a4 100644 --- a/S09-typed-arrays/native-shape1-int.t +++ b/S09-typed-arrays/native-shape1-int.t @@ -16,17 +16,14 @@ for flat @int,@uint -> $T { diag "Testing $t array"; ok array[$T].new(:shape(5)) ~~ Positional, "$t array is Positional"; - #?rakudo todo 'apparently it is not a typed Positional' ok array[$T].new(:shape(5)) ~~ Positional[$T], "$t array is Positional[$t]"; ok array[$T].new(:shape(5)).of === $T, "$t array .of is $t"; my @a := EVAL "my $t @[5]"; ok @a ~~ Positional, "$t array is Positional"; - #?rakudo todo 'apparently it is not a typed Positional' ok @a ~~ Positional[$T], "$t array is Positional[$t]"; ok @a.of === $T, "$t array .of is $t"; ok @a.new ~~ Positional, ".new from $t array is Positional"; - #?rakudo todo 'apparently it is not a typed Positional' ok @a.new ~~ Positional[$T], ".new from $t array Positional[$t]"; ok @a.new.of === $T, ".new from $t array .of is $t"; diff --git a/S09-typed-arrays/native-shape1-num.t b/S09-typed-arrays/native-shape1-num.t index 62f17ad585..30964e2cbe 100644 --- a/S09-typed-arrays/native-shape1-num.t +++ b/S09-typed-arrays/native-shape1-num.t @@ -14,17 +14,14 @@ for @num -> $T { diag "Testing $t array"; ok array[$T].new(:shape(5)) ~~ Positional, "$t array is Positional"; - #?rakudo todo 'apparently it is not a typed Positional' ok array[$T].new(:shape(5)) ~~ Positional[$T], "$t array is Positional[$t]"; ok array[$T].new(:shape(5)).of === $T, "$t array .of is $t"; my @a := EVAL "my $t @[5]"; ok @a ~~ Positional, "$t array is Positional"; - #?rakudo todo 'apparently it is not a typed Positional' ok @a ~~ Positional[$T], "$t array is Positional[$t]"; ok @a.of === $T, "$t array .of is $t"; ok @a.new ~~ Positional, ".new from $t array is Positional"; - #?rakudo todo 'apparently it is not a typed Positional' ok @a.new ~~ Positional[$T], ".new from $t array Positional[$t]"; ok @a.new.of === $T, ".new from $t array .of is $t"; diff --git a/S09-typed-arrays/native-shape1-str.t b/S09-typed-arrays/native-shape1-str.t index 387bf69447..42f548a3e5 100644 --- a/S09-typed-arrays/native-shape1-str.t +++ b/S09-typed-arrays/native-shape1-str.t @@ -9,17 +9,14 @@ my $t = $T.^name; diag "Testing $t array"; ok array[$T].new(:shape(5)) ~~ Positional, "$t array is Positional"; -#?rakudo todo 'apparently it is not a typed Positional' ok array[$T].new(:shape(5)) ~~ Positional[$T], "$t array is Positional[$t]"; ok array[$T].new(:shape(5)).of === $T, "$t array .of is $t"; my @a := EVAL "my $t @[5]"; ok @a ~~ Positional, "$t array is Positional"; -#?rakudo todo 'apparently it is not a typed Positional' ok @a ~~ Positional[$T], "$t array is Positional[$t]"; ok @a.of === $T, "$t array .of is $t"; ok @a.new ~~ Positional, ".new from $t array is Positional"; -#?rakudo todo 'apparently it is not a typed Positional' ok @a.new ~~ Positional[$T], ".new from $t array Positional[$t]"; ok @a.new.of === $T, ".new from $t array .of is $t"; From 9bcc38d8e298e73f6ccf19f03a84afa76284279c Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Fri, 10 Jun 2022 19:31:37 -0300 Subject: [PATCH 4/4] ^parents(:tree) isa List:D Because the cons of picking Array for type objects (need to decont for `=:=`. not a normal array otherwise) outweigh the pros of mutability here. --- S12-introspection/parents.t | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/S12-introspection/parents.t b/S12-introspection/parents.t index 78ecfc0230..4395708ca6 100644 --- a/S12-introspection/parents.t +++ b/S12-introspection/parents.t @@ -83,9 +83,9 @@ ok @parents[0].WHAT =:= B, 'first parent is B'; ok @parents[1].WHAT =:= C, 'second parent is C'; @parents = D.^parents(:tree); -is +@parents, 2, 'with :tree, D has two immediate parents (on proto)'; -ok @parents[0] ~~ Array, ':tree gives back nested arrays for each parent (on proto)'; -ok @parents[1] ~~ Array, ':tree gives back nested arrays for each parent (on proto)'; +is +@parents, 2, 'with :tree, D has two immediate parents (on proto)'; +ok @parents[0] ~~ List:D, ':tree gives back nested arrays for each parent (on proto)'; +ok @parents[1] ~~ List:D, ':tree gives back nested arrays for each parent (on proto)'; sub walk(Mu $a) { $a ~~ Positional ?? '(' ~ $a.map(&walk).join(', ') ~ ')' @@ -95,9 +95,9 @@ is walk(@parents), walk( [[B, [A, [Any, [Mu]]]], [C, [A, [Any, [Mu]]]]]), ':tree gives back the expected data structure (on proto)'; @parents = D.new.^parents(:tree); -is +@parents, 2, 'with :tree, D has two immediate parents (on instance)'; -ok @parents[0] ~~ Array, ':tree gives back nested arrays for each parent (on instance)'; -ok @parents[1] ~~ Array, ':tree gives back nested arrays for each parent (on instance)'; +is +@parents, 2, 'with :tree, D has two immediate parents (on instance)'; +ok @parents[0] ~~ List:D, ':tree gives back nested arrays for each parent (on instance)'; +ok @parents[1] ~~ List:D, ':tree gives back nested arrays for each parent (on instance)'; is walk(@parents), walk([[B, [A, [Any, [Mu]]]], [C, [A, [Any, [Mu]]]]]), ':tree gives back the expected data structure (on instance)';