Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions src/fsharp/AugmentWithHashCompare.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1071,23 +1071,28 @@ let MakeBindingsForEqualsAugmentation (g: TcGlobals) (tycon: Tycon) =
elif tycon.IsRecordTycon || tycon.IsStructOrEnumTycon then mkEquals mkRecdEquality
else []

let rec TypeDefinitelyHasEquality g ty =
if isAppTy g ty && HasFSharpAttribute g g.attrib_NoEqualityAttribute (tcrefOfAppTy g ty).Attribs then
let rec TypeDefinitelyHasEquality g ty =
let appTy = tryAppTy g ty
match appTy with
| ValueSome(tcref,_) when HasFSharpAttribute g g.attrib_NoEqualityAttribute tcref.Attribs ->
false
elif isTyparTy g ty &&
(destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsEquality _ -> true | _ -> false) then
true
else
match ty with
| SpecialEquatableHeadType g tinst ->
tinst |> List.forall (TypeDefinitelyHasEquality g)
| SpecialNotEquatableHeadType g _ ->
false
| _ ->
// The type is equatable because it has Object.Equals(...)
isAppTy g ty &&
let tcref, tinst = destAppTy g ty
// Give a good error for structural types excluded from the equality relation because of their fields
not (TyconIsCandidateForAugmentationWithEquals g tcref.Deref && Option.isNone tcref.GeneratedHashAndEqualsWithComparerValues) &&
// Check the (possibly inferred) structural dependencies
(tinst, tcref.TyparsNoRange) ||> List.lengthsEqAndForall2 (fun ty tp -> not tp.EqualityConditionalOn || TypeDefinitelyHasEquality g ty)
| _ ->
if isTyparTy g ty &&
(destTyparTy g ty).Constraints |> List.exists (function TyparConstraint.SupportsEquality _ -> true | _ -> false) then
true
else
match ty with
| SpecialEquatableHeadType g tinst ->
tinst |> List.forall (TypeDefinitelyHasEquality g)
| SpecialNotEquatableHeadType g _ ->
false
| _ ->
// The type is equatable because it has Object.Equals(...)
match appTy with
| ValueSome(tcref,tinst) ->
// Give a good error for structural types excluded from the equality relation because of their fields
not (TyconIsCandidateForAugmentationWithEquals g tcref.Deref && Option.isNone tcref.GeneratedHashAndEqualsWithComparerValues) &&
// Check the (possibly inferred) structural dependencies
(tinst, tcref.TyparsNoRange)
||> List.lengthsEqAndForall2 (fun ty tp -> not tp.EqualityConditionalOn || TypeDefinitelyHasEquality g ty)
| _ -> false
Copy link
Contributor

@cartermp cartermp Jan 20, 2020

Choose a reason for hiding this comment

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

Nit: the _ case (as mentioned in another PR) feels less appropriate since ValueNone is the only other case here. The above usage is fine though since the ValueSome case prior also has a when clause.