Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture some of the invariants around InputType/NarrowedType in patterns #76434

Merged
merged 2 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
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
28 changes: 28 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundBinaryPattern.cs
Original file line number Diff line number Diff line change
@@ -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?
Comment on lines +18 to +19
Copy link
Member

Choose a reason for hiding this comment

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

Feels like would be potentially a lot of walking in debug mode.

}
else
{
Debug.Assert(Right.InputType.Equals(Left.NarrowedType, TypeCompareKind.AllIgnoreOptions));
Debug.Assert(NarrowedType.Equals(Right.NarrowedType, TypeCompareKind.AllIgnoreOptions));
}
}
}
}
17 changes: 17 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundConstantPattern.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
17 changes: 17 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundDiscardPattern.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}

17 changes: 17 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundITuplePattern.cs
Original file line number Diff line number Diff line change
@@ -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");
}
}
}
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundListPattern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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));
}
}
}
17 changes: 17 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNegatedPattern.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
40 changes: 31 additions & 9 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2389,12 +2389,14 @@
<Field Name="NarrowedType" Type="TypeSymbol" Null="disallow"/>
</AbstractNode>

<Node Name="BoundConstantPattern" Base="BoundPattern">
<!-- NarrowedType is either the InputType, or the Value.Type -->
<Node Name="BoundConstantPattern" Base="BoundPattern" HasValidate="true">
<Field Name="Value" Type="BoundExpression"/>
<Field Name="ConstantValue" Type="ConstantValue" Null="disallow"/>
</Node>

<Node Name="BoundDiscardPattern" Base="BoundPattern">
<!-- NarrowedType is always the InputType -->
<Node Name="BoundDiscardPattern" Base="BoundPattern" HasValidate="true">
</Node>

<AbstractNode Name="BoundObjectPattern" Base="BoundPattern">
Expand All @@ -2411,19 +2413,22 @@
<Field Name="VariableAccess" Type="BoundExpression?"/>
</AbstractNode>

<Node Name="BoundDeclarationPattern" Base="BoundObjectPattern">
<!-- NarrowedType is the DeclaredType if given, or an InputType -->
<Node Name="BoundDeclarationPattern" Base="BoundObjectPattern" HasValidate="true">
<Field Name="DeclaredType" Type="BoundTypeExpression" Null="disallow"/>
<Field Name="IsVar" Type="bool"/>
</Node>

<Node Name="BoundRecursivePattern" Base="BoundObjectPattern">
<!-- NarrowedType is the DeclaredType if given, or an InputType, or its underlying type when the InputType is a Nullable of T -->
<Node Name="BoundRecursivePattern" Base="BoundObjectPattern" HasValidate="true">
<Field Name="DeclaredType" Type="BoundTypeExpression?"/>
<Field Name="DeconstructMethod" Type="MethodSymbol?"/>
<Field Name="Deconstruction" Type="ImmutableArray&lt;BoundPositionalSubpattern&gt;" Null="allow"/>
<Field Name="Properties" Type="ImmutableArray&lt;BoundPropertySubpattern&gt;" Null="allow"/>
<Field Name="IsExplicitNotNullTest" Type="bool"/>
</Node>

<!-- NarrowedType is always an InputType, or its underlying type when the InputType is a Nullable of T -->
<Node Name="BoundListPattern" Base="BoundObjectPattern" HasValidate="true">
<Field Name="Subpatterns" Type="ImmutableArray&lt;BoundPattern&gt;" Null="disallow"/>
<Field Name="HasSlice" Type="bool"/>
Expand All @@ -2442,6 +2447,7 @@
<Field Name="ArgumentPlaceholder" Type="BoundListPatternIndexPlaceholder?" SkipInVisitor="true"/>
</Node>

<!-- NarrowedType is always the InputType -->
<Node Name="BoundSlicePattern" Base="BoundPattern" HasValidate="true">
<Field Name="Pattern" Type="BoundPattern?"/>

Expand All @@ -2458,7 +2464,8 @@
<Field Name="ArgumentPlaceholder" Type="BoundSlicePatternRangePlaceholder?" SkipInVisitor="true"/>
</Node>

<Node Name="BoundITuplePattern" Base="BoundPattern">
<!-- Narrowed type is always System.Runtime.CompilerServices.ITuple -->
<Node Name="BoundITuplePattern" Base="BoundPattern" HasValidate="true">
<Field Name="GetLengthMethod" Type="MethodSymbol" Null="disallow"/>
<Field Name="GetItemMethod" Type="MethodSymbol" Null="disallow"/>
<Field Name="Subpatterns" Type="ImmutableArray&lt;BoundPositionalSubpattern&gt;" Null="disallow"/>
Expand All @@ -2482,22 +2489,37 @@
<Field Name="Type" Type="TypeSymbol"/>
</Node>

<Node Name="BoundTypePattern" Base="BoundPattern">
<!-- NarrowedType is always the DeclaredType -->
<Node Name="BoundTypePattern" Base="BoundPattern" HasValidate="true">
<Field Name="DeclaredType" Type="BoundTypeExpression"/>
<Field Name="IsExplicitNotNullTest" Type="bool"/>
</Node>

<Node Name="BoundBinaryPattern" Base="BoundPattern">
<!--
For Disjunction
NarrowedType is the least specific NarrowedType type across all leafs of constituent disjunctions, or
the InputType if one cannot be determined
Left.InputType is the InputType
Right.InputType is the InputType

For Conjunction
NarrowedType is the Right.NarrowedType
Left.InputType is the InputType
Right.InputType is the Left.NarrowedType
-->
<Node Name="BoundBinaryPattern" Base="BoundPattern" HasValidate="true">
<Field Name="Disjunction" Type="bool"/>
<Field Name="Left" Type="BoundPattern"/>
<Field Name="Right" Type="BoundPattern"/>
</Node>

<Node Name="BoundNegatedPattern" Base="BoundPattern">
<!-- NarrowedType is always the InputType -->
<Node Name="BoundNegatedPattern" Base="BoundPattern" HasValidate="true">
<Field Name="Negated" Type="BoundPattern"/>
</Node>

<Node Name="BoundRelationalPattern" Base="BoundPattern">
<!-- NarrowedType is either the InputType, or the Value.Type -->
<Node Name="BoundRelationalPattern" Base="BoundPattern" HasValidate="true">
<Field Name="Relation" Type="BinaryOperatorKind"/>
<Field Name="Value" Type="BoundExpression"/>
<Field Name="ConstantValue" Type="ConstantValue" Null="disallow"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
}
16 changes: 16 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundTypePattern.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
Loading