-
Notifications
You must be signed in to change notification settings - Fork 134
/
parameterized-type.t
135 lines (112 loc) · 5.67 KB
/
parameterized-type.t
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use v6;
use Test;
plan 11;
=begin pod
Tests for using parameterized roles as types, plus the of keyword.
=end pod
# L<S14/Parametric Roles>
# L<S14/Relationship Between of And Types>
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';
}
# 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
{
my role TreeNode[::T] does Positional {
has TreeNode[T] @!children handles <AT-POS ASSIGN-POS BIND-POS>;
has T $.data is rw;
};
my $tree = TreeNode[Int].new;
$tree.data = 3;
$tree[0] = TreeNode[Int].new;
$tree[1] = TreeNode[Int].new;
$tree[0].data = 1;
$tree[1].data = 4;
is ($tree.data, $tree[0,1]>>.data).flat.join(','), '3,1,4',
'parameterized role doing non-parameterized role';
}
# https://github.com/Raku/old-issue-tracker/issues/1192
{
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] { }' },
'can not use ::T in role application';
}
# https://github.com/Raku/old-issue-tracker/issues/2515
{
my role R[::T = my role Q[::S = role { method baz { "OH HAI" } }] { method bar { S.baz } }] { method foo { T.bar } };
is R.new.foo, 'OH HAI', 'can use a parameterized role as a default value of a parameterized role';
}
# https://github.com/Raku/old-issue-tracker/issues/2902
{
my module A {
role B[$x] is export {
method payload { $x }
}
}
import A;
is B['blubb'].payload, 'blubb', 'can export and import parameterized roles';
}
# https://github.com/Raku/old-issue-tracker/issues/2374
{
my role R[::T] { multi method foo(T $t) { T.gist } };
my class A does R[Str] does R[Int] { };
is A.new.foo(5), 5.WHAT.gist, 'correct multi selected from multiple parametric roles';
}
# https://github.com/Raku/old-issue-tracker/issues/2767
{
throws-like 'sub f(Int @x) {}; f( [] )',
X::TypeCheck::Binding,
message => /Positional\[Int\]/,
'error message mentions expected type when a typed array in a signature fails to bind';
}
# https://github.com/Raku/old-issue-tracker/issues/3648
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