From fad637a79db03df201c8193165b49889777e656d Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Sat, 14 Dec 2024 10:13:16 -0800 Subject: [PATCH 1/2] Capture some of the invariants around InputType/NarrowedType in patterns --- .../Portable/BoundTree/BoundBinaryPattern.cs | 28 +++++++++++++ .../BoundTree/BoundConstantPattern.cs | 17 ++++++++ .../BoundTree/BoundDeclarationPattern.cs | 18 +++++++++ .../Portable/BoundTree/BoundDiscardPattern.cs | 17 ++++++++ .../Portable/BoundTree/BoundITuplePattern.cs | 17 ++++++++ .../Portable/BoundTree/BoundListPattern.cs | 2 + .../Portable/BoundTree/BoundNegatedPattern.cs | 17 ++++++++ .../CSharp/Portable/BoundTree/BoundNodes.xml | 40 ++++++++++++++----- .../BoundTree/BoundRecursivePattern.cs | 19 +++++++++ .../Portable/BoundTree/BoundSlicePattern.cs | 1 + .../Generated/BoundNodes.xml.Generated.cs | 36 +++++++++++++++++ .../Generated/BoundRelationalPattern.cs | 17 ++++++++ .../Portable/Generated/BoundTypePattern.cs | 16 ++++++++ 13 files changed, 236 insertions(+), 9 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/BoundTree/BoundBinaryPattern.cs create mode 100644 src/Compilers/CSharp/Portable/BoundTree/BoundConstantPattern.cs create mode 100644 src/Compilers/CSharp/Portable/BoundTree/BoundDeclarationPattern.cs create mode 100644 src/Compilers/CSharp/Portable/BoundTree/BoundDiscardPattern.cs create mode 100644 src/Compilers/CSharp/Portable/BoundTree/BoundITuplePattern.cs create mode 100644 src/Compilers/CSharp/Portable/BoundTree/BoundNegatedPattern.cs create mode 100644 src/Compilers/CSharp/Portable/BoundTree/BoundRecursivePattern.cs create mode 100644 src/Compilers/CSharp/Portable/Generated/BoundRelationalPattern.cs create mode 100644 src/Compilers/CSharp/Portable/Generated/BoundTypePattern.cs 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/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/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; } diff --git a/src/Compilers/CSharp/Portable/Generated/BoundRelationalPattern.cs b/src/Compilers/CSharp/Portable/Generated/BoundRelationalPattern.cs new file mode 100644 index 0000000000000..955782d1edbe9 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Generated/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/Generated/BoundTypePattern.cs b/src/Compilers/CSharp/Portable/Generated/BoundTypePattern.cs new file mode 100644 index 0000000000000..349a82f28047c --- /dev/null +++ b/src/Compilers/CSharp/Portable/Generated/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)); + } + } +} From ba868a3d4450dcf78fc12c13beec95076cd08231 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Sat, 14 Dec 2024 10:17:47 -0800 Subject: [PATCH 2/2] Move files to the right place --- .../Portable/{Generated => BoundTree}/BoundRelationalPattern.cs | 0 .../CSharp/Portable/{Generated => BoundTree}/BoundTypePattern.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/Compilers/CSharp/Portable/{Generated => BoundTree}/BoundRelationalPattern.cs (100%) rename src/Compilers/CSharp/Portable/{Generated => BoundTree}/BoundTypePattern.cs (100%) diff --git a/src/Compilers/CSharp/Portable/Generated/BoundRelationalPattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundRelationalPattern.cs similarity index 100% rename from src/Compilers/CSharp/Portable/Generated/BoundRelationalPattern.cs rename to src/Compilers/CSharp/Portable/BoundTree/BoundRelationalPattern.cs diff --git a/src/Compilers/CSharp/Portable/Generated/BoundTypePattern.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundTypePattern.cs similarity index 100% rename from src/Compilers/CSharp/Portable/Generated/BoundTypePattern.cs rename to src/Compilers/CSharp/Portable/BoundTree/BoundTypePattern.cs