diff --git a/S14-roles/parameterized-type.t b/S14-roles/parameterized-type.t index d64e32d1d7..d72e56fa25 100644 --- a/S14-roles/parameterized-type.t +++ b/S14-roles/parameterized-type.t @@ -2,7 +2,7 @@ use v6; use Test; -plan 32; +plan 11; =begin pod @@ -13,55 +13,59 @@ Tests for using parameterized roles as types, plus the of keyword. # L # L -role R1[::T] { method x { T } } -class C1 does R1[Int] { } -class C2 does R1[Str] { } -lives-ok { my R1 of Int $x = C1.new }, 'using of as type constraint on variable works (class does role)'; -dies-ok { my R1 of Int $x = C2.new }, 'using of as type constraint on variable works (class does role)'; -lives-ok { my R1 of Int $x = R1[Int].new }, 'using of as type constraint on variable works (role instantiation)'; -dies-ok { my R1 of Int $x = R1[Str].new }, 'using of as type constraint on variable works (role instantiation)'; - -sub param_test(R1 of Int $x) { $x.x } -isa-ok param_test(C1.new), Int, 'using of as type constraint on parameter works (class does role)'; -dies-ok { param_test(C2.new) }, 'using of as type constraint on parameter works (class does role)'; -isa-ok param_test(R1[Int].new), Int, 'using of as type constraint on parameter works (role instantiation)'; -dies-ok { param_test(R1[Str].new) }, 'using of as type constraint on parameter works (role instantiation)'; - -role R2[::T] { - method x { "ok" } - method call_test { self.call_test_helper(T.new) } - method call_test_helper(T $x) { "ok" } #OK not used - method call_fail { self.call_test_helper(4.5) } +subtest "Parameterization as constraint" => { + my role R1[::T] { method x { T } } + my class C1 does R1[Int] { } + my class C2 does R1[Str] { } + lives-ok { my R1 of Int $x = C1.new }, 'using of as type constraint on variable works (class does role)'; + dies-ok { my R1 of Int $x = C2.new }, 'using of as type constraint on variable works (class does role)'; + lives-ok { my R1 of Int $x = R1[Int].new }, 'using of as type constraint on variable works (role instantiation)'; + dies-ok { my R1 of Int $x = R1[Str].new }, 'using of as type constraint on variable works (role instantiation)'; + + sub param_test(R1 of Int $x) { $x.x } + isa-ok param_test(C1.new), Int, 'using of as type constraint on parameter works (class does role)'; + dies-ok { param_test(C2.new) }, 'using of as type constraint on parameter works (class does role)'; + isa-ok param_test(R1[Int].new), Int, 'using of as type constraint on parameter works (role instantiation)'; + dies-ok { param_test(R1[Str].new) }, 'using of as type constraint on parameter works (role instantiation)'; +} + +subtest "Recursive-ish parameterization" => { + my role R2[::T] { + method x { "ok" } + method call_test { self.call_test_helper(T.new) } + method call_test_helper(T $x) { "ok" } #OK not used + method call_fail { self.call_test_helper(4.5) } + } + my class C3 does R2[R2[Int]] { } + my class C4 does R2[R2[Str]] { } + + lives-ok { my R2 of R2 of Int $x = C3.new }, 'roles parameterized with themselves as type constraints'; + dies-ok { my R2 of R2 of Int $x = C4.new }, 'roles parameterized with themselves as type constraints'; + lives-ok { my R2 of R2 of Int $x = R2[R2[Int]].new }, 'roles parameterized with themselves as type constraints'; + dies-ok { my R2 of R2 of Int $x = R2[R2[Str]].new }, 'roles parameterized with themselves as type constraints'; + + sub param_test_r(R2 of R2 of Int $x) { $x.x } + is param_test_r(C3.new), 'ok', 'roles parameterized with themselves as type constraints'; + dies-ok { param_test_r(C4.new) }, 'roles parameterized with themselves as type constraints'; + is param_test_r(R2[R2[Int]].new), 'ok', 'roles parameterized with themselves as type constraints'; + dies-ok { param_test_r(R2[R2[Str]].new) }, 'roles parameterized with themselves as type constraints'; + + is R2[Int].new.call_test, 'ok', 'types being used as type constraints inside roles work'; + dies-ok { R2[Int].new.call_fail }, 'types being used as type constraints inside roles work'; + is C3.new.call_test, 'ok', 'roles being used as type constraints inside roles work'; + dies-ok { C3.new.call_fail }, 'roles being used as type constraints inside roles work'; + is C4.new.call_test, 'ok', 'roles being used as type constraints inside roles work'; + dies-ok { C4.new.call_fail }, 'roles being used as type constraints inside roles work'; + is R2[C3].new.call_test, 'ok', 'classes being used as type constraints inside roles work'; + dies-ok { R2[C3].new.call_fail }, 'classes being used as type constraints inside roles work'; } -class C3 does R2[R2[Int]] { } -class C4 does R2[R2[Str]] { } - -lives-ok { my R2 of R2 of Int $x = C3.new }, 'roles parameterized with themselves as type constraints'; -dies-ok { my R2 of R2 of Int $x = C4.new }, 'roles parameterized with themselves as type constraints'; -lives-ok { my R2 of R2 of Int $x = R2[R2[Int]].new }, 'roles parameterized with themselves as type constraints'; -dies-ok { my R2 of R2 of Int $x = R2[R2[Str]].new }, 'roles parameterized with themselves as type constraints'; - -sub param_test_r(R2 of R2 of Int $x) { $x.x } -is param_test_r(C3.new), 'ok', 'roles parameterized with themselves as type constraints'; -dies-ok { param_test_r(C4.new) }, 'roles parameterized with themselves as type constraints'; -is param_test_r(R2[R2[Int]].new), 'ok', 'roles parameterized with themselves as type constraints'; -dies-ok { param_test_r(R2[R2[Str]].new) }, 'roles parameterized with themselves as type constraints'; - -is R2[Int].new.call_test, 'ok', 'types being used as type constraints inside roles work'; -dies-ok { R2[Int].new.call_fail }, 'types being used as type constraints inside roles work'; -is C3.new.call_test, 'ok', 'roles being used as type constraints inside roles work'; -dies-ok { C3.new.call_fail }, 'roles being used as type constraints inside roles work'; -is C4.new.call_test, 'ok', 'roles being used as type constraints inside roles work'; -dies-ok { C4.new.call_fail }, 'roles being used as type constraints inside roles work'; -is R2[C3].new.call_test, 'ok', 'classes being used as type constraints inside roles work'; -dies-ok { R2[C3].new.call_fail }, 'classes being used as type constraints inside roles work'; # https://github.com/Raku/old-issue-tracker/issues/1491 throws-like 'role ABCD[EFGH] { }', X::Parameter::InvalidType, 'role with undefined type as parameter dies'; # https://github.com/Raku/old-issue-tracker/issues/1193 { - role TreeNode[::T] does Positional { + my role TreeNode[::T] does Positional { has TreeNode[T] @!children handles ; has T $.data is rw; }; @@ -77,7 +81,7 @@ throws-like 'role ABCD[EFGH] { }', X::Parameter::InvalidType, 'role with undefin # https://github.com/Raku/old-issue-tracker/issues/1192 { - role P[$x] { } + my role P[$x] { } # ::T only makes sense in a signature here, not in # an argument list. dies-ok { EVAL 'class MyClass does P[::T] { }' }, @@ -121,4 +125,11 @@ throws-like 'role ABCD[EFGH] { }', X::Parameter::InvalidType, 'role with undefin lives-ok { EVAL 'my role A [ :$bs where { True } = 512] { }; class B does A { }' }, 'role with where clause and default in parametric signature works out OK'; +{ + my role A[::T] { + method a { A[T] } + } + isa-ok A[Int].a, A[Int], "role is correctly paramterized in a role's method body"; +} + # vim: expandtab shiftwidth=4