1--TEST--
2Scalar type strict mode
3--SKIPIF--
4<?php if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only"); ?>
5--FILE--
6<?php
7declare(strict_types=1);
8
9$functions = [
10    'int' => function (int $i) { return $i; },
11    'float' => function (float $f) { return $f; },
12    'string' => function (string $s) { return $s; },
13    'bool' => function (bool $b) { return $b; }
14];
15
16class Stringable {
17    public function __toString() {
18        return "foobar";
19    }
20}
21
22$values = [
23    1,
24    "1",
25    1.0,
26    1.5,
27    "1a",
28    "a",
29    "",
30    PHP_INT_MAX,
31    NAN,
32    TRUE,
33    FALSE,
34    NULL,
35    [],
36    new StdClass,
37    new Stringable,
38    fopen("data:text/plain,foobar", "r")
39];
40
41foreach ($functions as $type => $function) {
42    echo PHP_EOL, "Testing '$type' type:", PHP_EOL;
43    foreach ($values as $value) {
44        echo PHP_EOL . "*** Trying ";
45        var_dump($value);
46        try {
47            var_dump($function($value));
48        } catch (TypeError $e) {
49            echo "*** Caught " . $e->getMessage() . PHP_EOL;
50        }
51    }
52}
53
54echo PHP_EOL . "Done";
55?>
56--EXPECTF--
57Testing 'int' type:
58
59*** Trying int(1)
60int(1)
61
62*** Trying string(1) "1"
63*** Caught Argument 1 passed to {closure}() must be of the type int, string given, called in %s on line %d
64
65*** Trying float(1)
66*** Caught Argument 1 passed to {closure}() must be of the type int, float given, called in %s on line %d
67
68*** Trying float(1.5)
69*** Caught Argument 1 passed to {closure}() must be of the type int, float given, called in %s on line %d
70
71*** Trying string(2) "1a"
72*** Caught Argument 1 passed to {closure}() must be of the type int, string given, called in %s on line %d
73
74*** Trying string(1) "a"
75*** Caught Argument 1 passed to {closure}() must be of the type int, string given, called in %s on line %d
76
77*** Trying string(0) ""
78*** Caught Argument 1 passed to {closure}() must be of the type int, string given, called in %s on line %d
79
80*** Trying int(9223372036854775807)
81int(9223372036854775807)
82
83*** Trying float(NAN)
84*** Caught Argument 1 passed to {closure}() must be of the type int, float given, called in %s on line %d
85
86*** Trying bool(true)
87*** Caught Argument 1 passed to {closure}() must be of the type int, bool given, called in %s on line %d
88
89*** Trying bool(false)
90*** Caught Argument 1 passed to {closure}() must be of the type int, bool given, called in %s on line %d
91
92*** Trying NULL
93*** Caught Argument 1 passed to {closure}() must be of the type int, null given, called in %s on line %d
94
95*** Trying array(0) {
96}
97*** Caught Argument 1 passed to {closure}() must be of the type int, array given, called in %s on line %d
98
99*** Trying object(stdClass)#5 (0) {
100}
101*** Caught Argument 1 passed to {closure}() must be of the type int, object given, called in %s on line %d
102
103*** Trying object(Stringable)#6 (0) {
104}
105*** Caught Argument 1 passed to {closure}() must be of the type int, object given, called in %s on line %d
106
107*** Trying resource(5) of type (stream)
108*** Caught Argument 1 passed to {closure}() must be of the type int, resource given, called in %s on line %d
109
110Testing 'float' type:
111
112*** Trying int(1)
113float(1)
114
115*** Trying string(1) "1"
116*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d
117
118*** Trying float(1)
119float(1)
120
121*** Trying float(1.5)
122float(1.5)
123
124*** Trying string(2) "1a"
125*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d
126
127*** Trying string(1) "a"
128*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d
129
130*** Trying string(0) ""
131*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d
132
133*** Trying int(9223372036854775807)
134float(9.2233720368548E+18)
135
136*** Trying float(NAN)
137float(NAN)
138
139*** Trying bool(true)
140*** Caught Argument 1 passed to {closure}() must be of the type float, bool given, called in %s on line %d
141
142*** Trying bool(false)
143*** Caught Argument 1 passed to {closure}() must be of the type float, bool given, called in %s on line %d
144
145*** Trying NULL
146*** Caught Argument 1 passed to {closure}() must be of the type float, null given, called in %s on line %d
147
148*** Trying array(0) {
149}
150*** Caught Argument 1 passed to {closure}() must be of the type float, array given, called in %s on line %d
151
152*** Trying object(stdClass)#5 (0) {
153}
154*** Caught Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d
155
156*** Trying object(Stringable)#6 (0) {
157}
158*** Caught Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d
159
160*** Trying resource(5) of type (stream)
161*** Caught Argument 1 passed to {closure}() must be of the type float, resource given, called in %s on line %d
162
163Testing 'string' type:
164
165*** Trying int(1)
166*** Caught Argument 1 passed to {closure}() must be of the type string, int given, called in %s on line %d
167
168*** Trying string(1) "1"
169string(1) "1"
170
171*** Trying float(1)
172*** Caught Argument 1 passed to {closure}() must be of the type string, float given, called in %s on line %d
173
174*** Trying float(1.5)
175*** Caught Argument 1 passed to {closure}() must be of the type string, float given, called in %s on line %d
176
177*** Trying string(2) "1a"
178string(2) "1a"
179
180*** Trying string(1) "a"
181string(1) "a"
182
183*** Trying string(0) ""
184string(0) ""
185
186*** Trying int(9223372036854775807)
187*** Caught Argument 1 passed to {closure}() must be of the type string, int given, called in %s on line %d
188
189*** Trying float(NAN)
190*** Caught Argument 1 passed to {closure}() must be of the type string, float given, called in %s on line %d
191
192*** Trying bool(true)
193*** Caught Argument 1 passed to {closure}() must be of the type string, bool given, called in %s on line %d
194
195*** Trying bool(false)
196*** Caught Argument 1 passed to {closure}() must be of the type string, bool given, called in %s on line %d
197
198*** Trying NULL
199*** Caught Argument 1 passed to {closure}() must be of the type string, null given, called in %s on line %d
200
201*** Trying array(0) {
202}
203*** Caught Argument 1 passed to {closure}() must be of the type string, array given, called in %s on line %d
204
205*** Trying object(stdClass)#5 (0) {
206}
207*** Caught Argument 1 passed to {closure}() must be of the type string, object given, called in %s on line %d
208
209*** Trying object(Stringable)#6 (0) {
210}
211*** Caught Argument 1 passed to {closure}() must be of the type string, object given, called in %s on line %d
212
213*** Trying resource(5) of type (stream)
214*** Caught Argument 1 passed to {closure}() must be of the type string, resource given, called in %s on line %d
215
216Testing 'bool' type:
217
218*** Trying int(1)
219*** Caught Argument 1 passed to {closure}() must be of the type bool, int given, called in %s on line %d
220
221*** Trying string(1) "1"
222*** Caught Argument 1 passed to {closure}() must be of the type bool, string given, called in %s on line %d
223
224*** Trying float(1)
225*** Caught Argument 1 passed to {closure}() must be of the type bool, float given, called in %s on line %d
226
227*** Trying float(1.5)
228*** Caught Argument 1 passed to {closure}() must be of the type bool, float given, called in %s on line %d
229
230*** Trying string(2) "1a"
231*** Caught Argument 1 passed to {closure}() must be of the type bool, string given, called in %s on line %d
232
233*** Trying string(1) "a"
234*** Caught Argument 1 passed to {closure}() must be of the type bool, string given, called in %s on line %d
235
236*** Trying string(0) ""
237*** Caught Argument 1 passed to {closure}() must be of the type bool, string given, called in %s on line %d
238
239*** Trying int(9223372036854775807)
240*** Caught Argument 1 passed to {closure}() must be of the type bool, int given, called in %s on line %d
241
242*** Trying float(NAN)
243*** Caught Argument 1 passed to {closure}() must be of the type bool, float given, called in %s on line %d
244
245*** Trying bool(true)
246bool(true)
247
248*** Trying bool(false)
249bool(false)
250
251*** Trying NULL
252*** Caught Argument 1 passed to {closure}() must be of the type bool, null given, called in %s on line %d
253
254*** Trying array(0) {
255}
256*** Caught Argument 1 passed to {closure}() must be of the type bool, array given, called in %s on line %d
257
258*** Trying object(stdClass)#5 (0) {
259}
260*** Caught Argument 1 passed to {closure}() must be of the type bool, object given, called in %s on line %d
261
262*** Trying object(Stringable)#6 (0) {
263}
264*** Caught Argument 1 passed to {closure}() must be of the type bool, object given, called in %s on line %d
265
266*** Trying resource(5) of type (stream)
267*** Caught Argument 1 passed to {closure}() must be of the type bool, resource given, called in %s on line %d
268
269Done
270