diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundBinaryPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundBinaryPattern.cs
new file mode 100644
index 0000000000000..8a54803dc2d11
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundBinaryPattern.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundBinaryPattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(Left.InputType.Equals(InputType, TypeCompareKind.AllIgnoreOptions));
+
+ if (Disjunction)
+ {
+ Debug.Assert(Right.InputType.Equals(InputType, TypeCompareKind.AllIgnoreOptions));
+ // Is it worth asserting that NarrowedType is either the InputType, or or the NarrowedType
+ // of one of the leaves in the Disjunction hierarchy?
+ }
+ else
+ {
+ Debug.Assert(Right.InputType.Equals(Left.NarrowedType, TypeCompareKind.AllIgnoreOptions));
+ Debug.Assert(NarrowedType.Equals(Right.NarrowedType, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundConstantPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundConstantPattern.cs
new file mode 100644
index 0000000000000..df9ee648e1101
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundConstantPattern.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundConstantPattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(NarrowedType.Equals(InputType, TypeCompareKind.AllIgnoreOptions) ||
+ NarrowedType.Equals(Value.Type, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundDeclarationPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundDeclarationPattern.cs
new file mode 100644
index 0000000000000..6d06293512d1b
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundDeclarationPattern.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundDeclarationPattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(DeclaredType is null ?
+ NarrowedType.Equals(InputType, TypeCompareKind.AllIgnoreOptions) :
+ NarrowedType.Equals(DeclaredType.Type, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundDiscardPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundDiscardPattern.cs
new file mode 100644
index 0000000000000..3c517185d7f48
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundDiscardPattern.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundDiscardPattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(NarrowedType.Equals(InputType, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+}
+
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundITuplePattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundITuplePattern.cs
new file mode 100644
index 0000000000000..94393db773bca
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundITuplePattern.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundITuplePattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(NarrowedType.IsCompilerServicesTopLevelType() && NarrowedType.Name == "ITuple");
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundListPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundListPattern.cs
index 7522e92dcf8ff..6835e60a7c5f5 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundListPattern.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundListPattern.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
namespace Microsoft.CodeAnalysis.CSharp
{
@@ -13,6 +14,7 @@ private partial void Validate()
Debug.Assert(LengthAccess is null or BoundPropertyAccess or BoundBadExpression);
Debug.Assert(IndexerAccess is null or BoundIndexerAccess or BoundImplicitIndexerAccess or BoundArrayAccess or BoundBadExpression or BoundDynamicIndexerAccess);
Debug.Assert(Binder.GetIndexerOrImplicitIndexerSymbol(IndexerAccess) is var _);
+ Debug.Assert(NarrowedType.Equals(InputType.StrippedType(), TypeCompareKind.AllIgnoreOptions));
}
}
}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNegatedPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundNegatedPattern.cs
new file mode 100644
index 0000000000000..412e783539c5c
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNegatedPattern.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundNegatedPattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(NarrowedType.Equals(InputType, TypeCompareKind.AllIgnoreOptions));
+ Debug.Assert(Negated.InputType.Equals(InputType, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
index 61e25923823f0..5a227e6297a93 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
@@ -2389,12 +2389,14 @@
-
+
+
-
+
+
@@ -2411,12 +2413,14 @@
-
+
+
-
+
+
@@ -2424,6 +2428,7 @@
+
@@ -2442,6 +2447,7 @@
+
@@ -2458,7 +2464,8 @@
-
+
+
@@ -2482,22 +2489,37 @@
-
+
+
-
+
+
-
+
+
-
+
+
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundRecursivePattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundRecursivePattern.cs
new file mode 100644
index 0000000000000..dfc478df4d92e
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundRecursivePattern.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundRecursivePattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(DeclaredType is null ?
+ NarrowedType.Equals(InputType.StrippedType(), TypeCompareKind.AllIgnoreOptions) :
+ NarrowedType.Equals(DeclaredType.Type, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundRelationalPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundRelationalPattern.cs
new file mode 100644
index 0000000000000..955782d1edbe9
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundRelationalPattern.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundRelationalPattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(NarrowedType.Equals(InputType, TypeCompareKind.AllIgnoreOptions) ||
+ NarrowedType.Equals(Value.Type, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundSlicePattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundSlicePattern.cs
index c1434c854ca58..a26c3928daaa7 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundSlicePattern.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundSlicePattern.cs
@@ -12,6 +12,7 @@ private partial void Validate()
{
Debug.Assert(IndexerAccess is null or BoundIndexerAccess or BoundImplicitIndexerAccess or BoundArrayAccess or BoundBadExpression or BoundDynamicIndexerAccess);
Debug.Assert(Binder.GetIndexerOrImplicitIndexerSymbol(IndexerAccess) is var _);
+ Debug.Assert(NarrowedType.Equals(InputType, TypeCompareKind.AllIgnoreOptions));
}
}
}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundTypePattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundTypePattern.cs
new file mode 100644
index 0000000000000..349a82f28047c
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundTypePattern.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class BoundTypePattern
+ {
+ private partial void Validate()
+ {
+ Debug.Assert(NarrowedType.Equals(DeclaredType.Type, TypeCompareKind.AllIgnoreOptions));
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
index 595e5105ae73c..228ce05213251 100644
--- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
@@ -8026,8 +8026,12 @@ public BoundConstantPattern(SyntaxNode syntax, BoundExpression value, ConstantVa
this.Value = value;
this.ConstantValue = constantValue;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public BoundExpression Value { get; }
public ConstantValue ConstantValue { get; }
@@ -8055,8 +8059,12 @@ public BoundDiscardPattern(SyntaxNode syntax, TypeSymbol inputType, TypeSymbol n
RoslynDebug.Assert(inputType is object, "Field 'inputType' cannot be null (make the type nullable in BoundNodes.xml to remove this check)");
RoslynDebug.Assert(narrowedType is object, "Field 'narrowedType' cannot be null (make the type nullable in BoundNodes.xml to remove this check)");
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public BoundDiscardPattern(SyntaxNode syntax, TypeSymbol inputType, TypeSymbol narrowedType)
: base(BoundKind.DiscardPattern, syntax, inputType, narrowedType)
{
@@ -8111,8 +8119,12 @@ public BoundDeclarationPattern(SyntaxNode syntax, BoundTypeExpression declaredTy
this.DeclaredType = declaredType;
this.IsVar = isVar;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public BoundTypeExpression DeclaredType { get; }
public bool IsVar { get; }
@@ -8145,8 +8157,12 @@ public BoundRecursivePattern(SyntaxNode syntax, BoundTypeExpression? declaredTyp
this.Deconstruction = deconstruction;
this.Properties = properties;
this.IsExplicitNotNullTest = isExplicitNotNullTest;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public BoundTypeExpression? DeclaredType { get; }
public MethodSymbol? DeconstructMethod { get; }
public ImmutableArray Deconstruction { get; }
@@ -8266,8 +8282,12 @@ public BoundITuplePattern(SyntaxNode syntax, MethodSymbol getLengthMethod, Metho
this.GetLengthMethod = getLengthMethod;
this.GetItemMethod = getItemMethod;
this.Subpatterns = subpatterns;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public MethodSymbol GetLengthMethod { get; }
public MethodSymbol GetItemMethod { get; }
public ImmutableArray Subpatterns { get; }
@@ -8403,8 +8423,12 @@ public BoundTypePattern(SyntaxNode syntax, BoundTypeExpression declaredType, boo
this.DeclaredType = declaredType;
this.IsExplicitNotNullTest = isExplicitNotNullTest;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public BoundTypeExpression DeclaredType { get; }
public bool IsExplicitNotNullTest { get; }
@@ -8437,8 +8461,12 @@ public BoundBinaryPattern(SyntaxNode syntax, bool disjunction, BoundPattern left
this.Disjunction = disjunction;
this.Left = left;
this.Right = right;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public bool Disjunction { get; }
public BoundPattern Left { get; }
public BoundPattern Right { get; }
@@ -8469,8 +8497,12 @@ public BoundNegatedPattern(SyntaxNode syntax, BoundPattern negated, TypeSymbol i
RoslynDebug.Assert(narrowedType is object, "Field 'narrowedType' cannot be null (make the type nullable in BoundNodes.xml to remove this check)");
this.Negated = negated;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public BoundPattern Negated { get; }
[DebuggerStepThrough]
@@ -8502,8 +8534,12 @@ public BoundRelationalPattern(SyntaxNode syntax, BinaryOperatorKind relation, Bo
this.Relation = relation;
this.Value = value;
this.ConstantValue = constantValue;
+ Validate();
}
+ [Conditional("DEBUG")]
+ private partial void Validate();
+
public BinaryOperatorKind Relation { get; }
public BoundExpression Value { get; }
public ConstantValue ConstantValue { get; }