Bug 10771 – std.typecons.Nullable throws an exception on comparision of null values

Status
RESOLVED
Resolution
DUPLICATE
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-08-07T10:58:00Z
Last change time
2017-05-02T07:29:47Z
Assigned to
nobody
Creator
qaston
See also
https://issues.dlang.org/show_bug.cgi?id=14804

Comments

Comment #0 by qaston — 2013-08-07T10:58:50Z
The following code should work and assert should pass. On dmd 2.063.2 assert "Called `get' on null Nullable!Test" occurs instead --- import std.typecons; void main() { struct Test{ int a; } Nullable!Test a; Nullable!Test b; assert(a==b); } --- So, IMO Nullable!T needs opEquals implemented.
Comment #1 by monarchdodra — 2013-08-08T10:31:03Z
(In reply to comment #0) > The following code should work and assert should pass. > On dmd 2.063.2 assert "Called `get' on null Nullable!Test" occurs instead > --- > import std.typecons; > void main() > { > struct Test{ > int a; > } > Nullable!Test a; > Nullable!Test b; > assert(a==b); > } > --- > > So, IMO Nullable!T needs opEquals implemented. I'm not sure it should. It would blend the notion of *what* the comparison compares. For example, in the opposite case: Nullable!Test a; Nullable!Test b = 5; if (a == b) ... //Legal ? Arguably, this is a mistake, as a null was used in a comparison. But it now simply returns false. And I don't think it's OK to assert when *one* of both are null, yet not both, so I'm not entirely sure about the proposed enhancement.
Comment #2 by qaston — 2013-08-08T11:16:05Z
(In reply to comment #1) > I'm not sure it should. It would blend the notion of *what* the comparison > compares. For example, in the opposite case: > > Nullable!Test a; > Nullable!Test b = 5; > > if (a == b) ... //Legal ? > > Arguably, this is a mistake, as a null was used in a comparison. But it now > simply returns false. > > And I don't think it's OK to assert when *one* of both are null, yet not both, > so I'm not entirely sure about the proposed enhancement. I forgot to say that I'd expect the case you posted as legal as well. I thought that this was a simple analogy to how null works in the language, but apparently at the time of posting I forgot that null is never compared with opEquals, it uses [is] operator instead. Phobos doc state that Nullable: "Defines a value paired with a distinctive "null" state that denotes the absence of a value." I was paying more attention to the "distinctive state" than to the "absence of a value". Now I see that it makes no sense to compare absences. In my case it was useful however, so maybe this may be a candidate for a separate type or template flag. Anyways comparision semantics should be mentioned in the doc imo.
Comment #3 by monarchdodra — 2013-08-09T05:38:51Z
(In reply to comment #2) > (In reply to comment #1) > > I'm not sure it should. It would blend the notion of *what* the comparison > > compares. For example, in the opposite case: > > > > Nullable!Test a; > > Nullable!Test b = 5; > > > > if (a == b) ... //Legal ? > > > > Arguably, this is a mistake, as a null was used in a comparison. But it now > > simply returns false. > > > > And I don't think it's OK to assert when *one* of both are null, yet not both, > > so I'm not entirely sure about the proposed enhancement. > > I forgot to say that I'd expect the case you posted as legal as well. > > I thought that this was a simple analogy to how null works in the language, but > apparently at the time of posting I forgot that null is never compared with > opEquals, it uses [is] operator instead. > > Phobos doc state that Nullable: "Defines a value paired with a distinctive > "null" state that denotes the absence of a value." I was paying more attention > to the "distinctive state" than to the "absence of a value". Now I see that it > makes no sense to compare absences. Well, this is up to debate of course. I'd agree with you if Nullable was a reference type, in which case, "==" would compare the references, and "a.get == b.get" or "a == 5" would be actual value comparisons. Unfortunatly, Nullable is a value type, so I think it is safer to consider a "null Nullable" as simply something you can't use or even compare to anything. That's what I think anyways. > In my case it was useful however, so maybe this may be a candidate for a > separate type or template flag. Anyways comparision semantics should be > mentioned in the doc imo. RefCounted, (which uses reference semantics) may do what you need? If you don't care for reference counting, then... raw pointers?
Comment #4 by qaston — 2014-01-19T05:29:32Z
(In reply to comment #3) > (In reply to comment #2) > > (In reply to comment #1) > > > I'm not sure it should. It would blend the notion of *what* the comparison > > > compares. For example, in the opposite case: > > > > > > Nullable!Test a; > > > Nullable!Test b = 5; > > > > > > if (a == b) ... //Legal ? > > > > > > Arguably, this is a mistake, as a null was used in a comparison. But it now > > > simply returns false. > > > > > > And I don't think it's OK to assert when *one* of both are null, yet not both, > > > so I'm not entirely sure about the proposed enhancement. > > > > I forgot to say that I'd expect the case you posted as legal as well. > > > > I thought that this was a simple analogy to how null works in the language, but > > apparently at the time of posting I forgot that null is never compared with > > opEquals, it uses [is] operator instead. > > > > Phobos doc state that Nullable: "Defines a value paired with a distinctive > > "null" state that denotes the absence of a value." I was paying more attention > > to the "distinctive state" than to the "absence of a value". Now I see that it > > makes no sense to compare absences. > > Well, this is up to debate of course. I'd agree with you if Nullable was a > reference type, in which case, "==" would compare the references, and "a.get == > b.get" or "a == 5" would be actual value comparisons. > > Unfortunatly, Nullable is a value type, so I think it is safer to consider a > "null Nullable" as simply something you can't use or even compare to anything. > > That's what I think anyways. > > > In my case it was useful however, so maybe this may be a candidate for a > > separate type or template flag. Anyways comparision semantics should be > > mentioned in the doc imo. > > RefCounted, (which uses reference semantics) may do what you need? > > If you don't care for reference counting, then... raw pointers? I want something like Optional(T), which compares null and non-null uniformly instead of having a distinction like it is now for classes with is and opEquals. Nullable is intended to emulate behavior of null for classes so current implementation is ok and this bug can be closed.
Comment #5 by kroeplin.d — 2014-01-21T14:47:47Z
For Objects we no longer have to think about (lhs is rhs || lhs !is null && rhs !is null && lhs == rhs): bool opEquals(Object lhs, Object rhs) { // If aliased to the same object or both null => equal if (lhs is rhs) return true; // If either is null => non-equal if (lhs is null || rhs is null) return false; // If same exact type => one call to method opEquals if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs))) return lhs.opEquals(rhs); // General case => symmetric calls to method opEquals return lhs.opEquals(rhs) && rhs.opEquals(lhs); } (null == null) is true, and that's what it's supposed to be with Nullable!T - a T or null.
Comment #6 by kroeplin.d — 2017-05-02T07:29:47Z
*** This issue has been marked as a duplicate of issue 13017 ***