Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -2794,4 +2794,15 @@ int M(R v)
""",
LanguageVersion = LanguageVersion.CSharp14,
}.RunAsync();

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/81714")]
public Task TestNullableBool()
=> new VerifyCS.Test
{
TestCode = """
[||]if ((bool?)null == false) { }
""",
LanguageVersion = LanguageVersion.CSharp14,
TestState = { OutputKind = OutputKind.ConsoleApplication }
}.RunAsync();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.PooledObjects;
Expand Down Expand Up @@ -255,8 +256,8 @@ private ConstantResult DetermineConstant(IBinaryOperation op)
{
return (op.LeftOperand, op.RightOperand) switch
{
var (e, v) when IsConstant(v) && CheckTargetExpression(e) && CheckConstantType(v) => ConstantResult.Right,
var (v, e) when IsConstant(v) && CheckTargetExpression(e) && CheckConstantType(v) => ConstantResult.Left,
var (e, v) when IsConstant(v) && CheckTargetExpression(e, out var switchTargetType) && CheckConstantType(v, switchTargetType) => ConstantResult.Right,
var (v, e) when IsConstant(v) && CheckTargetExpression(e, out var switchTargetType) && CheckConstantType(v, switchTargetType) => ConstantResult.Left,
_ => ConstantResult.None,
};
}
Expand Down Expand Up @@ -330,11 +331,11 @@ when Supports(Feature.AndPattern | Feature.CaseGuard):
}

case IIsTypeOperation op
when Supports(Feature.IsTypePattern) && CheckTargetExpression(op.ValueOperand) && op.Syntax is TIsExpressionSyntax node:
when Supports(Feature.IsTypePattern) && CheckTargetExpression(op.ValueOperand, out _) && op.Syntax is TIsExpressionSyntax node:
return new AnalyzedPattern.Type(node);

case IIsPatternOperation op
when Supports(Feature.SourcePattern) && CheckTargetExpression(op.Value) && op.Pattern.Syntax is TPatternSyntax pattern:
when Supports(Feature.SourcePattern) && CheckTargetExpression(op.Value, out _) && op.Pattern.Syntax is TPatternSyntax pattern:
return new AnalyzedPattern.Source(pattern);

case IParenthesizedOperation op:
Expand Down Expand Up @@ -390,7 +391,7 @@ when CheckTargetExpression(low.Expression, high.Expression) => (low.Value.Syntax
};

bool CheckTargetExpression(IOperation left, IOperation right)
=> _syntaxFacts.AreEquivalent(left.Syntax, right.Syntax) && this.CheckTargetExpression(left);
=> _syntaxFacts.AreEquivalent(left.Syntax, right.Syntax) && this.CheckTargetExpression(left, out _);
}

private static (BoundKind Kind, IOperation Expression, IOperation Value) GetRangeBound(IBinaryOperation op)
Expand Down Expand Up @@ -447,33 +448,34 @@ private static bool IsConstant(IOperation operation)
: operation.ConstantValue.HasValue;
}

private bool CheckTargetExpression(IOperation operation)
private bool CheckTargetExpression(IOperation operation, [NotNullWhen(true)] out ITypeSymbol? switchTargetType)
{
operation = operation.WalkDownConversion();

if (operation.Syntax is not TExpressionSyntax expression)
{
switchTargetType = null;
return false;
}

// If we have not figured the switch expression yet,
// we will assume that the first expression is the one.
// If we have not figured the switch expression yet, we will assume that the first expression is the one.
if (_switchTargetExpression is null)
{
RoslynDebug.Assert(_switchTargetType is null);

_switchTargetExpression = expression;
_switchTargetType = operation.Type;
return true;
}

return _syntaxFacts.AreEquivalent(expression, _switchTargetExpression);
switchTargetType = _switchTargetType;
return switchTargetType != null && _syntaxFacts.AreEquivalent(expression, _switchTargetExpression);
}

private bool CheckConstantType(IOperation operation)
private bool CheckConstantType(IOperation operation, ITypeSymbol switchTargetType)
{
RoslynDebug.AssertNotNull(operation.SemanticModel);
RoslynDebug.AssertNotNull(_switchTargetType);

return CanImplicitlyConvert(operation.SemanticModel, operation.Syntax, _switchTargetType);
return CanImplicitlyConvert(operation.SemanticModel, operation.Syntax, switchTargetType);
}
}

Expand Down
Loading