Sitelet https://github.com/php/doc-en/pull/5916
Skip to content

settype(): document that it always returns true and can throw TypeError - #5916

Merged
lacatoire merged 2 commits into
php:masterfrom
angeliszotis:doc/settype-return-and-typeerror
Oct 7, 2026
Merged

lacatoire merged 2 commits into
php:masterfrom
angeliszotis:doc/settype-return-and-typeerror

Conversation

@angeliszotis

Copy link
Copy Markdown
Contributor

Fixes #2677

I checked both points from the report on PHP 8.4.26.

It cannot return false

The return values section used &return.success;, which renders as "Returns true on success or false on failure". I tried to make it return false:

var_dump(settype($v, "nonexistent_type"));  // ValueError
var_dump(settype($arr, "integer"));         // bool(true)
var_dump(settype($obj, "integer"));         // bool(true)  + Warning
var_dump(settype($res, "integer"));         // bool(true)

Every path either returns true or throws. Switched to &return.true.always;, which is already used by openlog(), closelog() and syslog() for the same situation.

TypeError was not documented

The errors section only had the ValueError for an invalid type name. There is also a TypeError:

declare(strict_types=1);
class Foo { public int $value = 123; }
$foo = new Foo;
$ref = &$foo->value;
settype($ref, "string");
TypeError: Cannot assign string to reference held by property Foo::$value of type int

I wrote it as "cannot be assigned to the declared type under the active typing mode" rather than listing the cases, because widening still works with strict typing:

declare(strict_types=1);
class A { public float $f = 1.5; }
$a = new A; $r = &$a->f;
var_dump(settype($r, "integer"));  // bool(true)
var_dump($a->f);                   // float(1)     int to float is allowed

class B { public int $i = 7; }
$b = new B; $r2 = &$b->i;
settype($r2, "float");             // TypeError    float to int is not

The case from the report

The original report was about this looking like a bug:

class Foo { public int $value = 123; }
$foo = new Foo;
$ref = &$foo->value;
var_dump(settype($ref, "string"));  // bool(true)
var_dump($foo->value);              // int(123)

With coercive typing the converted value is assigned back and coerced to the declared type, so the property keeps its type and the call still returns true. I added a note for that, since the page gave no hint why the conversion appears to do nothing.

Changes

  • returnvalues: &return.success; to &return.true.always;
  • errors: added the TypeError paragraph
  • notes: added the note about assigning the converted value back

Both linkend targets I used, language.oop5.properties and language.types.declarations.strict, already exist and are used by other pages.

The return values section used return.success, which says the function
returns false on failure. It cannot return false. I tried an invalid type
name, an array, an object and a resource, and a reference to a typed
property, and it either returned true or threw.

Switched to return.true.always, the entity already used by openlog(),
closelog() and syslog() for the same situation.

The errors section only documented the ValueError for an invalid type
name. A TypeError is also thrown when var is a reference to a typed
property and the converted value cannot be assigned back to the declared
type. Tested on PHP 8.4.26:

  declare(strict_types=1);
  class Foo { public int $value = 123; }
  $foo = new Foo;
  $ref = &$foo->value;
  settype($ref, "string");
  // TypeError: Cannot assign string to reference held by property
  //            Foo::$value of type int

I wrote it as "cannot be assigned under the active typing mode" instead
of listing the cases, because widening still works in strict mode. With
strict_types a float property set to "integer" returns true and ends up
as float(1), while an int property set to "float" throws.

Added a note for the coercive case, where the converted value is assigned
back and gets coerced to the declared type, so the property keeps its
type and the call still returns true. That is the behaviour reported in
the issue that looked like a bug.

Fixes php#2677
Comment thread reference/var/functions/settype.xml Outdated
Comment on lines +167 to +169
converted value is coerced back to the declared type of the property. The
type of the property therefore does not change, and
<function>settype</function> still returns &true;.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
converted value is coerced back to the declared type of the property. The
type of the property therefore does not change, and
<function>settype</function> still returns &true;.
converted value is coerced back to the declared type of the property when
possible, so the type of the property does not change and
<function>settype</function> returns &true;. Otherwise a
<exceptionname>TypeError</exceptionname> is thrown.

@lacatoire

Copy link
Copy Markdown
Member

Thanks @angeliszotis a small nits, and ci ones but LGTM

Apply @lacatoire's wording suggestion for the note and switch the three
inline-only para blocks to simpara, which the DocBook style check flagged.
@angeliszotis

Copy link
Copy Markdown
Contributor Author

Thanks @lacatoire! Applied your wording for the note and changed the three inline-only para blocks to simpara, which should clear the DocBook style check too.

@lacatoire
lacatoire merged commit dafe552 into php:master Oct 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Clarifications on settype() behaviour wrt coercion and failure

2 participants