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