/
type-subset.t
153 lines (111 loc) · 5.69 KB
/
type-subset.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use v6.d;
use lib <t/packages/>;
use Test;
use Test::Helpers;
plan 11;
subtest "When refinement is an expression value", {
plan 3;
throws-like { my subset F where 5; my F $f = 6}, X::TypeCheck::Assignment,
"Assignment to scalar type-constrained to a subset throws when constraint is not met";
lives-ok { my subset F where 5; my F $f = 5 },
"Assignment to a scalar type-constrained to a subset lives";
throws-like { my subset F where 5; -> F $f {}(6)}, X::TypeCheck::Binding::Parameter,
"Parameter type-constrained to a subset throws when constraint is not met";
};
subtest "When refinement is a regex", {
plan 3;
throws-like { my subset F where /5/; my F $f = '6' }, X::TypeCheck::Assignment,
"Assignment to scalar type-constrained to a subset lives";
lives-ok { my subset F where /5/; my F $f = '5' },
"Assignment to a scalar type-constrained to a subset works with bare expression";
throws-like { my subset F where /5/; -> F $ {}(6)}, X::TypeCheck::Binding::Parameter,
"Parameter type-constrained to a subset throws when constraint is not met";
};
subtest "When refinement is a block", {
plan 3;
throws-like { my subset F where { $_ ~~ 5 }; my F $f = '6' }, X::TypeCheck::Assignment,
"Assignment to scalar type-constrained to a subset throws when constraint is not met";
lives-ok { my subset F where { $_ ~~ 5 }; my F $f = '5' },
"Assignment to a scalar type-constrained to a subset lives";
throws-like { my subset F where { $_ ~~ 5 }; -> F $ {}(6)}, X::TypeCheck::Binding::Parameter,
"Parameter type-constrained to a subset throws when constraint is not met";
};
subtest "When refinement has a Whatever", {
plan 3;
throws-like { my subset F where * == 5; my F $f = 6 }, X::TypeCheck::Assignment,
"Assignment to scalar type-constrained to a subset throws when constraint is not met";
lives-ok { my subset F where * == 5; my F $f = 5 },
"Assignment to a scalar type-constrained to a subset lives";
throws-like { my subset F where * == 5; -> F $f {}(6)}, X::TypeCheck::Binding::Parameter,
"Parameter type-constrained to a subset throws when constraint is not met";
};
subtest "When refinement has a Whatever with a Smartmatch", {
plan 3;
throws-like { my subset F where * ~~ 5; my F $f = '6' }, X::TypeCheck::Assignment,
"Assignment to scalar type-constrained to a subset throws when constraint is not met";
lives-ok { my subset F where * ~~ 5; my F $f = '5' },
"Assignment to a scalar type-constrained to a subset lives";
throws-like { my subset F where * ~~ 5; -> F $f {}(6)}, X::TypeCheck::Binding::Parameter,
"Parameter type-constrained to a subset throws when constraint is not met";
};
subtest "When refinee is specified", {
plan 3;
throws-like { my subset F of Int where { $_ ~~ 5 }; my F $f = '5' }, X::TypeCheck::Assignment,
"Assignment to scalar type-constrained to a subset throws when constraint is not met";
lives-ok { my subset F of Int where { $_ ~~ 5 }; my F $f = 5 },
"Assignment to a scalar type-constrained to a subset lives";
throws-like { my subset F of Int where { $_ ~~ 5 }; -> F $f {}(6)}, X::TypeCheck::Binding::Parameter,
"Parameter type-constrained to a subset throws when constraint is not met";
};
subtest "When used with smartmatch", {
plan 2;
my subset F where 5;
ok 5 ~~ F, "Smartmatch on subset that passes refinement is ok";
nok 6 ~~ F, "Smartmatch on subset that doesn't pass refinement is not ok";
}
subtest "When a subset is created with the name of a stubbed package", {
plan 2;
is-run 'class F::B {}; subset F where 5',
:exitcode(0),
"Can create subset with a name that exists as a stubbed package";
is-run 'class F::B {}; subset F where 5; die unless F::.keys.grep("B");',
:exitcode(0),
"The WHO package is stolen from the replaced stubbed package";
}
subtest "When a subset is declared within a module", {
plan 4;
is-run 'module M { my subset F where 5 }; my M::F $f = 5',
:exitcode(1), :err({ .contains: 'Malformed my' }),
"'my' scoped subset in a module is unavailable outside the module";
is-run 'module M { subset F where 5 }; my M::F $f = 5',
:exitcode(0),
"'our' scoped subset in a module is available outside the module";
is-run 'my module M { subset F where 5 }; my M::F $f = 5',
:exitcode(0),
"'our' scoped subset in a module is available outside a my-scoped module";
is-run 'my subset P::F where 5; my P::F $f = 5',
:exitcode(0),
"Subset with a stubby package in their name resolve correctly";
}
subtest "When a subset has no where block", {
plan 3;
is-run 'subset MyInt of Int; my MyInt $f = 5',
:exitcode(0),
"subset with of but no where succeeds when type constraint met";
is-run 'subset MyInt of Int; my MyInt $f = 5.0',
:exitcode(1), :err({ .contains: 'expected MyInt but got Rat' }),
"subset with of but no where fails when type constraint not met";
is-run 'my Str subset MyStr; die unless Str ~~ MyStr',
:exitcode(0),
"subset form 'my Str subset MyStr' creates essentially a type alias";
}
subtest "When a subset is a subset of a subset", {
plan 2;
is-run 'subset F of Int where * %% 2; subset G of F where * %% 3; my G $g = 6',
:exitcode(0),
"Subset works as 'of' of a subset (assignment meets criteria)";
is-run 'subset F of Int where * %% 5; subset G of F where * %% 25; my G $g = 9',
:exitcode(1), :err({ .contains: 'Type check failed in assignment ' }),
"Subset works as 'of' of a subset (asigment fails criteria)";
}
done-testing;