Skip to content

Commit 57c66cd

Browse files
authored
[spec/expression] Improve EqualExpression docs for classes (#4218)
Fixes #4217. Add summary with correct info for class references. Add subheading for structs. Tweak `is` docs for comparing class reference to null. Add `operatoroverloading.dd` link to struct equality best practices.
1 parent 2e691c0 commit 57c66cd

File tree

2 files changed

+27
-28
lines changed

2 files changed

+27
-28
lines changed

spec/expression.dd

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -662,17 +662,37 @@ $(GNAME EqualExpression):
662662

663663
$(H4 $(LNAME2 class_struct_equality, Class & Struct Equality))
664664

665+
$(P For class references, `a == b` is rewritten to `.object.opEquals(a, b)`,
666+
which handles `null`.
667+
This is intended to compare the contents of two objects, however an
668+
appropriate $(D opEquals) method override must be defined for this to work.
669+
The default $(D opEquals) provided by the root $(D Object) class is
670+
equivalent to the $(RELATIVE_LINK2 identity_expressions, $(D is) operator).)
671+
672+
$(P For struct objects, the expression $(D (a == b))
673+
is rewritten as $(D a.opEquals(b)), or failing that, $(D b.opEquals(a)).)
674+
675+
$(P For both class references and struct objects, $(D (a != b)) is rewritten as
676+
$(D !(a == b)).)
677+
678+
$(P See $(DDSUBLINK spec/operatoroverloading, equals, `opEquals`) for details.)
679+
680+
$(H5 $(LNAME2 struct_equality, Struct Equality))
681+
665682
$(P For struct objects, equality means the result of the
666683
$(LINK2 https://dlang.org/spec/operatoroverloading.html#equals, `opEquals()` member function).
667684
If an `opEquals()` is not provided, equality is defined as
668685
the logical product of all equality
669686
results of the corresponding object fields.
670687
)
671688

672-
$(IMPLEMENTATION_DEFINED The contents of any alignment gaps in the struct object.)
689+
$(IMPLEMENTATION_DEFINED The contents of any $(DDSUBLINK spec/struct, struct_layout,
690+
alignment gaps) in the struct object.)
691+
692+
$(P If there are overlapping fields, which happens with unions, the default
693+
equality will compare each of the overlapping fields.)
673694

674-
$(BEST_PRACTICE If there are overlapping fields, which happens with unions, the default
675-
equality will compare each of the overlapping fields.
695+
$(BEST_PRACTICE
676696
An `opEquals()` can account for which of the overlapping fields contains valid data.
677697
An `opEquals()` can override the default behavior of floating point NaN values
678698
always comparing as unequal.
@@ -684,29 +704,6 @@ $(GNAME EqualExpression):
684704
$(LI there are any floating point fields that may contain NaN or `-0` values)
685705
)
686706

687-
$(P For class and struct objects, the expression $(D (a == b))
688-
is rewritten as
689-
$(D a.opEquals(b)), and $(D (a != b)) is rewritten as
690-
$(D !a.opEquals(b)).
691-
)
692-
693-
$(P For class objects, the $(D ==) and $(D !=)
694-
operators are intended to compare the contents of the objects,
695-
however an appropriate $(D opEquals) override must be defined for this to work.
696-
The default $(D opEquals) provided by the root $(D Object) class is
697-
equivalent to the $(D is) operator (see below).
698-
Comparing against $(D null) is invalid, as $(D null) has no contents.
699-
Use the $(D is) and $(D !is) operators instead.)
700-
701-
---
702-
class C;
703-
C c;
704-
if (c == null) // error
705-
...
706-
if (c is null) // ok
707-
...
708-
---
709-
710707
$(H3 $(LNAME2 identity_expressions, Identity Expressions))
711708

712709
$(GRAMMAR
@@ -723,7 +720,7 @@ $(GNAME IdentityExpression):
723720
)
724721

725722
$(P For class / interface objects, identity is defined as the object references being identical.
726-
Null class objects can be compared with `is`.
723+
Class references can be efficiently compared against `null` using `is`.
727724
Note that interface objects need not have the same reference of the class they were cast from.
728725
To test whether an `interface` shares a class instance with another `interface` / `class` value, cast both operands to `Object` before comparing with `is`.
729726
)

spec/operatoroverloading.dd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ $(OL
411411
---
412412
.object.opEquals(a, b)
413413
---
414-
$(P and that function is implemented as:)
414+
$(P and that function is similar to:)
415415
---
416416
bool opEquals(Object a, Object b)
417417
{
@@ -464,6 +464,8 @@ $(OL
464464
bool opEquals()(auto ref const S s) const { ... }
465465
}
466466
---
467+
$(NOTE See $(DDSUBLINK spec/expression, struct_equality, Struct Equality)
468+
for best practices on implementing `opEquals` for structs.)
467469

468470

469471
$(H3 $(LNAME2 compare, Overloading $(D <), $(D <)$(D =), $(D >), and $(D >)$(D =)))

0 commit comments

Comments
 (0)