Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 52a2397

Browse files
author
Mikhail Arkhipov
authored
Prevent unions with itself (#1997)
* Remove stale reference * Don't suppress LHS diagnostics on augmented assign * Revert "Don't suppress LHS diagnostics on augmented assign" This reverts commit 6109ac7. * Escape [ and ] * PR feedback * Prevent unions with itself * Add special Union comparison + test
1 parent 94ae060 commit 52a2397

File tree

2 files changed

+48
-5
lines changed

2 files changed

+48
-5
lines changed

src/Analysis/Ast/Impl/Types/PythonUnionType.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,19 @@ internal sealed class PythonUnionType : LocatedMember, IPythonUnionType {
2828

2929
public PythonUnionType(IEnumerable<IPythonType> types, IPythonModule declaringModule)
3030
: base(declaringModule.Interpreter.ModuleResolution.GetSpecializedModule("typing")) {
31-
_types.UnionWith(types);
31+
_types.UnionWith(types.Where(t => !this.Equals(t)));
3232
}
3333

3434
private PythonUnionType(IPythonType x, IPythonType y)
3535
: base(x.DeclaringModule.Interpreter.ModuleResolution.GetSpecializedModule("typing")) {
3636
Check.Argument(nameof(x), () => !(x is IPythonUnionType));
3737
Check.Argument(nameof(y), () => !(y is IPythonUnionType));
38-
_types.Add(x);
39-
_types.Add(y);
38+
if (!this.Equals(x)) {
39+
_types.Add(x);
40+
}
41+
if (!this.Equals(y)) {
42+
_types.Add(y);
43+
}
4044
}
4145

4246
public override PythonMemberType MemberType => PythonMemberType.Union;
@@ -91,7 +95,7 @@ public IMember Index(IPythonInstance instance, IArgumentSet args) {
9195
// Check if any types support indexing
9296
var result = types
9397
.Select(t => t.Index(instance, args))
94-
.FirstOrDefault(r => !r.IsUnknown() && r.GetPythonType() != this);
98+
.FirstOrDefault(r => !r.IsUnknown() && !r.GetPythonType().Equals(this));
9599
return result ?? DeclaringModule.Interpreter.UnknownType;
96100
}
97101

@@ -112,7 +116,7 @@ public IPythonUnionType Add(IPythonType t) {
112116

113117
public IPythonUnionType Add(IPythonUnionType types) {
114118
lock (_lock) {
115-
_types.UnionWith(types);
119+
_types.UnionWith(types.Where(t => !this.Equals(t)));
116120
return this;
117121
}
118122
}
@@ -158,5 +162,16 @@ public static IPythonType Combine(IPythonType x, IPythonType y) {
158162

159163
return utx == null ? uty.Add(x) : utx.Add(uty);
160164
}
165+
166+
public override bool Equals(object obj) {
167+
if (obj is PythonUnionType u) {
168+
lock (_lock) {
169+
return _types.SetEquals(u._types);
170+
}
171+
}
172+
return false;
173+
}
174+
175+
public override int GetHashCode() => 0;
161176
}
162177
}

src/Analysis/Ast/Test/TypingTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,34 @@ public void AnnotationParsing() {
386386
AssertTransform("Dict['Int, Str']", "NameOp:Dict", "StartListOp", "NameOp:Int", "NameOp:Str", "MakeGenericOp");
387387
}
388388

389+
[TestMethod, Priority(0)]
390+
public async Task UnionsCompare() {
391+
var analysis = await GetAnalysisAsync("from typing import Union", PythonVersions.LatestAvailable3X);
392+
var i = analysis.Document.Interpreter.GetBuiltinType(BuiltinTypeId.Int);
393+
var b = analysis.Document.Interpreter.GetBuiltinType(BuiltinTypeId.Bool);
394+
395+
var expected = new[] {i, b};
396+
var u1 = new PythonUnionType(expected, analysis.Document);
397+
var u2 = new PythonUnionType(expected, analysis.Document);
398+
399+
u2.Equals(u1).Should().BeTrue();
400+
u1.Add(u2);
401+
var actual = u1.ToArray();
402+
actual.Should().Equal(expected);
403+
404+
u1.Add(u1);
405+
actual = u1.ToArray();
406+
actual.Should().Equal(expected);
407+
408+
u2.Add(u1);
409+
actual = u2.ToArray();
410+
actual.Should().Equal(expected);
411+
412+
u2.Add(u2);
413+
actual = u1.ToArray();
414+
actual.Should().Equal(expected);
415+
}
416+
389417
[TestMethod, Priority(0)]
390418
public void AnnotationConversion() {
391419
AssertConvert("List");

0 commit comments

Comments
 (0)