1--TEST--
2Return scalar type basics
3--SKIPIF--
4<?php if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only"); ?>
5--FILE--
6<?php
7
8$errnames = [
9    E_NOTICE => 'E_NOTICE',
10    E_WARNING => 'E_WARNING',
11];
12set_error_handler(function (int $errno, string $errmsg, string $file, int $line) use ($errnames) {
13    echo "$errnames[$errno]: $errmsg on line $line\n";
14    return true;
15});
16
17$functions = [
18    'int' => function ($i): int { return $i; },
19    'float' => function ($f): float { return $f; },
20    'string' => function ($s): string { return $s; },
21    'bool' => function ($b): bool { return $b; }
22];
23
24class Stringable {
25    public function __toString() {
26        return "foobar";
27    }
28}
29
30$values = [
31    1,
32    "1",
33    1.0,
34    1.5,
35    "1a",
36    "a",
37    "",
38    PHP_INT_MAX,
39    NAN,
40    TRUE,
41    FALSE,
42    NULL,
43    [],
44    new StdClass,
45    new Stringable,
46    fopen("data:text/plain,foobar", "r")
47];
48
49foreach ($functions as $type => $function) {
50    echo PHP_EOL, "Testing '$type' type:", PHP_EOL;
51    foreach ($values as $value) {
52        echo "*** Trying ";
53        var_dump($value);
54        try {
55            var_dump($function($value));
56        } catch (TypeError $e) {
57            echo "*** Caught ", $e->getMessage(), " in ", $e->getFile(), " on line ", $e->getLine(), PHP_EOL;
58        }
59    }
60}
61
62echo PHP_EOL . "Done";
63?>
64--EXPECTF--
65Testing 'int' type:
66*** Trying int(1)
67int(1)
68*** Trying string(1) "1"
69int(1)
70*** Trying float(1)
71int(1)
72*** Trying float(1.5)
73int(1)
74*** Trying string(2) "1a"
75E_NOTICE: A non well formed numeric value encountered on line %d
76int(1)
77*** Trying string(1) "a"
78*** Caught Return value of {closure}() must be of the type int, string returned in %s on line %d
79*** Trying string(0) ""
80*** Caught Return value of {closure}() must be of the type int, string returned in %s on line %d
81*** Trying int(9223372036854775807)
82int(9223372036854775807)
83*** Trying float(NAN)
84*** Caught Return value of {closure}() must be of the type int, float returned in %s on line %d
85*** Trying bool(true)
86int(1)
87*** Trying bool(false)
88int(0)
89*** Trying NULL
90*** Caught Return value of {closure}() must be of the type int, null returned in %s on line %d
91*** Trying array(0) {
92}
93*** Caught Return value of {closure}() must be of the type int, array returned in %s on line %d
94*** Trying object(stdClass)#6 (0) {
95}
96*** Caught Return value of {closure}() must be of the type int, object returned in %s on line %d
97*** Trying object(Stringable)#7 (0) {
98}
99*** Caught Return value of {closure}() must be of the type int, object returned in %s on line %d
100*** Trying resource(5) of type (stream)
101*** Caught Return value of {closure}() must be of the type int, resource returned in %s on line %d
102
103Testing 'float' type:
104*** Trying int(1)
105float(1)
106*** Trying string(1) "1"
107float(1)
108*** Trying float(1)
109float(1)
110*** Trying float(1.5)
111float(1.5)
112*** Trying string(2) "1a"
113E_NOTICE: A non well formed numeric value encountered on line %d
114float(1)
115*** Trying string(1) "a"
116*** Caught Return value of {closure}() must be of the type float, string returned in %s on line %d
117*** Trying string(0) ""
118*** Caught Return value of {closure}() must be of the type float, string returned in %s on line %d
119*** Trying int(9223372036854775807)
120float(9.2233720368548E+18)
121*** Trying float(NAN)
122float(NAN)
123*** Trying bool(true)
124float(1)
125*** Trying bool(false)
126float(0)
127*** Trying NULL
128*** Caught Return value of {closure}() must be of the type float, null returned in %s on line %d
129*** Trying array(0) {
130}
131*** Caught Return value of {closure}() must be of the type float, array returned in %s on line %d
132*** Trying object(stdClass)#6 (0) {
133}
134*** Caught Return value of {closure}() must be of the type float, object returned in %s on line %d
135*** Trying object(Stringable)#7 (0) {
136}
137*** Caught Return value of {closure}() must be of the type float, object returned in %s on line %d
138*** Trying resource(5) of type (stream)
139*** Caught Return value of {closure}() must be of the type float, resource returned in %s on line %d
140
141Testing 'string' type:
142*** Trying int(1)
143string(1) "1"
144*** Trying string(1) "1"
145string(1) "1"
146*** Trying float(1)
147string(1) "1"
148*** Trying float(1.5)
149string(3) "1.5"
150*** Trying string(2) "1a"
151string(2) "1a"
152*** Trying string(1) "a"
153string(1) "a"
154*** Trying string(0) ""
155string(0) ""
156*** Trying int(9223372036854775807)
157string(19) "9223372036854775807"
158*** Trying float(NAN)
159string(3) "NAN"
160*** Trying bool(true)
161string(1) "1"
162*** Trying bool(false)
163string(0) ""
164*** Trying NULL
165*** Caught Return value of {closure}() must be of the type string, null returned in %s on line %d
166*** Trying array(0) {
167}
168*** Caught Return value of {closure}() must be of the type string, array returned in %s on line %d
169*** Trying object(stdClass)#6 (0) {
170}
171*** Caught Return value of {closure}() must be of the type string, object returned in %s on line %d
172*** Trying object(Stringable)#7 (0) {
173}
174string(6) "foobar"
175*** Trying resource(5) of type (stream)
176*** Caught Return value of {closure}() must be of the type string, resource returned in %s on line %d
177
178Testing 'bool' type:
179*** Trying int(1)
180bool(true)
181*** Trying string(1) "1"
182bool(true)
183*** Trying float(1)
184bool(true)
185*** Trying float(1.5)
186bool(true)
187*** Trying string(2) "1a"
188bool(true)
189*** Trying string(1) "a"
190bool(true)
191*** Trying string(0) ""
192bool(false)
193*** Trying int(9223372036854775807)
194bool(true)
195*** Trying float(NAN)
196bool(true)
197*** Trying bool(true)
198bool(true)
199*** Trying bool(false)
200bool(false)
201*** Trying NULL
202*** Caught Return value of {closure}() must be of the type bool, null returned in %s on line %d
203*** Trying array(0) {
204}
205*** Caught Return value of {closure}() must be of the type bool, array returned in %s on line %d
206*** Trying object(stdClass)#6 (0) {
207}
208*** Caught Return value of {closure}() must be of the type bool, object returned in %s on line %d
209*** Trying object(Stringable)#7 (0) {
210}
211*** Caught Return value of {closure}() must be of the type bool, object returned in %s on line %d
212*** Trying resource(5) of type (stream)
213*** Caught Return value of {closure}() must be of the type bool, resource returned in %s on line %d
214
215Done
216