Hi
Thank you for your RFC. It is really well-written and nicely explains
the various (edge) cases. I've only read through the `#[\NoSerialize]`
one, since it is the topic of this RFC discussion. I agree with Ilija on
all points.
Am 2025-10-29 15:35, schrieb Dmytro Kulyk:
#[NoSerialize], on the other hand, would apply to wrappers,
containers, or domain objects where serialization of the rest of the
structure should continue even if one field or nested object cannot be
meaningfully serialized.
But even for wrappers you can't guarantee that the wrapper is stored in
a nullable property. When applying the attribute to a field, omitting
the field makes sense, since the author of the property is the same
person who is capable of adding the attribute and thus is in full
control. This is different for classes where the author of the class
doesn't know how and where the class is being used. I thus agree with
Ilija that this should throw to clearly indicate that the user of the
class is doing something incorrect and to not silently corrupt data. If
an author of a class needs more fine-grained control, they can either
add the attribute to individual properties themselves - or implement
`__serialize()`.
> Class-level #[NoSerialize] is inherited by child classes unless explicitly
overridden.
Can you clarify how this would work? How can you override this
attribute by omission?
#[NoSerialize]
class Foo {}
/* What do I add here to remove #[NoSerialize]? */
class Bar extends Foo {}
Class-level #[NoSerialize] is transparently inherited by child classes.
There’s currently no way to override or cancel this behavior in
descendants; the attribute remains effective throughout the
inheritance chain.
Indeed, however the “unless explicitly overridden” bit in the RFC text
implies that this is possible.
As an alternative, #[NotSerializable] could be extended to
#[NotSerializable(bool $soft = false)], which would provide the same
behavior while keeping it in a separate, more consistent attribute —
avoiding the double semantics currently implied by #[NoSerialize].
I don't think that sub classes should be able to make a non-serializable
parent class serializable, since they clearly won't be able to correctly
restore the state of the parent class. In fact I would consider this an
improvement over the existing serialization hooks where the child class
can simply skip calling the parent's serializer and thus create a
situation that the parent class does not expect to occur.
Initially, the idea was to make all of these cases emit warnings, but
I didn’t figure out how to implement that consistently within the
attribute validators.
At this point, I don’t see any practical reason to allow the attribute
on unsupported targets, so all such cases will be changed to
compile-time errors instead of warnings.
Yes, every clear error that is detectable at compile-time should be a
hard error to make it easy for users to detect the mistake.
Best regards
Tim Düsterhus