Skip to content

Commit

Permalink
Merge pull request #48250 from dotnet/merges/master-to-master-vs-deps
Browse files Browse the repository at this point in the history
Merge master to master-vs-deps
  • Loading branch information
msftbot[bot] committed Oct 2, 2020
2 parents f280daa + 0bd72a7 commit 3d33a9e
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public CSharpUseIsNullCheckForReferenceEqualsDiagnosticAnalyzer()
protected override bool IsLanguageVersionSupported(ParseOptions options)
=> ((CSharpParseOptions)options).LanguageVersion >= LanguageVersion.CSharp7;

protected override bool IsUnconstrainedGenericSupported(ParseOptions options)
=> ((CSharpParseOptions)options).LanguageVersion >= LanguageVersion.CSharp8;

protected override ISyntaxFacts GetSyntaxFacts()
=> CSharpSyntaxFacts.Instance;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public UseIsNullCheckForReferenceEqualsTests(ITestOutputHelper logger)
}

private static readonly ParseOptions CSharp7 = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7);
private static readonly ParseOptions CSharp8 = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8);
private static readonly ParseOptions CSharp9 = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9);

internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
Expand Down Expand Up @@ -261,7 +262,7 @@ void M(string s1, string s2)

[WorkItem(23581, "https://github.com/dotnet/roslyn/issues/23581")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseIsNullCheck)]
public async Task TestValueParameterTypeIsUnconstrainedGeneric()
public async Task TestValueParameterTypeIsUnconstrainedGeneric_CSharp7()
{
await TestInRegularAndScript1Async(
@"
Expand All @@ -286,7 +287,38 @@ public static void NotNull<T>(T value)
}
}
}
");
", new TestParameters(parseOptions: CSharp7));
}

[WorkItem(23581, "https://github.com/dotnet/roslyn/issues/47972")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseIsNullCheck)]
public async Task TestValueParameterTypeIsUnconstrainedGeneric_CSharp8()
{
await TestInRegularAndScript1Async(
@"using System;
class C
{
public static void NotNull<T>(T value)
{
if ({|FixAllInDocument:ReferenceEquals|}(value, null))
{
return;
}
}
}",
@"using System;
class C
{
public static void NotNull<T>(T value)
{
if (value is null)
{
return;
}
}
}", new TestParameters(parseOptions: CSharp8));
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseIsNullCheck)]
Expand Down Expand Up @@ -500,5 +532,36 @@ void M(string s2)
}
}");
}

[WorkItem(23581, "https://github.com/dotnet/roslyn/issues/47972")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseIsNullCheck)]
public async Task TestValueParameterTypeIsBaseTypeConstraintGeneric()
{
await TestInRegularAndScript1Async(
@"using System;
class C
{
public static void NotNull<T>(T value) where T:C
{
if ({|FixAllInDocument:ReferenceEquals|}(value, null))
{
return;
}
}
}",
@"using System;
class C
{
public static void NotNull<T>(T value) where T:C
{
if (value is null)
{
return;
}
}
}", new TestParameters(parseOptions: CSharp7));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ protected override void InitializeWorker(AnalysisContext context)
});

protected abstract bool IsLanguageVersionSupported(ParseOptions options);
protected abstract bool IsUnconstrainedGenericSupported(ParseOptions options);
protected abstract ISyntaxFacts GetSyntaxFacts();

private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, IMethodSymbol referenceEqualsMethod)
Expand Down Expand Up @@ -112,19 +113,21 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, IMethodSymbol refe
var genericParameterSymbol = GetGenericParameterSymbol(syntaxFacts, semanticModel, arguments[0], arguments[1], cancellationToken);
if (genericParameterSymbol != null)
{
if (genericParameterSymbol.HasValueTypeConstraint)
if (genericParameterSymbol.IsValueType)
{
// 'is null' would generate error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
// '== null' would generate error CS0019: Operator '==' cannot be applied to operands of type 'T' and '<null>'
// 'Is Nothing' would generate error BC30020: 'Is' operator does not accept operands of type 'T'. Operands must be reference or nullable types.
return;
}

if (!genericParameterSymbol.HasReferenceTypeConstraint)
// HasReferenceTypeConstraint returns false for base type constraint.
// IsReferenceType returns true.

if (!genericParameterSymbol.IsReferenceType && !IsUnconstrainedGenericSupported(syntaxTree.Options))
{
// Needs special casing for C# as long as
// https://github.com/dotnet/csharplang/issues/1284
// is not implemented.
// 'is null' over unconstrained generic is implemented in C# 8.
properties = properties.Add(UseIsNullConstants.UnconstrainedGeneric, "");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseIsNullCheck
Return True
End Function

Protected Overrides Function IsUnconstrainedGenericSupported(options As ParseOptions) As Boolean
Return True
End Function

Protected Overrides Function GetSyntaxFacts() As ISyntaxFacts
Return VisualBasicSyntaxFacts.Instance
End Function
Expand Down
74 changes: 72 additions & 2 deletions src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7243,8 +7243,6 @@ .maxstack 1
conversions(sourceType: "nint", destType: "int", expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4"));
conversions(sourceType: "nint", destType: "uint", expectedImplicitIL: null, expectedExplicitIL: conv("conv.u4"), expectedCheckedIL: conv("conv.ovf.u4"));
conversions(sourceType: "nint", destType: "long", expectedImplicitIL: conv("conv.i8"), expectedExplicitIL: conv("conv.i8"));
// https://github.com/dotnet/roslyn/issues/42457: Investigate why this conversion (and other conversions from nint to ulong and from nuint to long)
// use differently signed opcodes for unchecked and checked conversions. (Why conv.i8 but conv.ovf.u8 here for instance?)
conversions(sourceType: "nint", destType: "ulong", expectedImplicitIL: null, expectedExplicitIL: conv("conv.i8"), expectedCheckedIL: conv("conv.ovf.u8"));
conversions(sourceType: "nint", destType: "float", expectedImplicitIL: conv("conv.r4"), expectedExplicitIL: conv("conv.r4"));
conversions(sourceType: "nint", destType: "double", expectedImplicitIL: conv("conv.r8"), expectedExplicitIL: conv("conv.r8"));
Expand Down Expand Up @@ -12530,6 +12528,78 @@ .method public virtual native int[] modopt(int32) F4()
Assert.Equal("System.IntPtr[] modopt(System.Int32) B.F4()", type.GetMember("F4").ToTestDisplayString());
}

[WorkItem(42457, "https://github.com/dotnet/roslyn/issues/42457")]
[Fact]
public void Int64Conversions()
{
convert(fromType: "nint", toType: "ulong", "int.MinValue", "18446744071562067968", "conv.i8", "System.OverflowException", "conv.ovf.u8");
convert(fromType: "nint", toType: "ulong", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.ovf.u8");
convert(fromType: "nint", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", "conv.u", "System.OverflowException", "conv.ovf.u");
convert(fromType: "nint", toType: "nuint", "int.MaxValue", "2147483647", "conv.u", "2147483647", "conv.ovf.u");

convert(fromType: "nuint", toType: "long", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.ovf.i8.un");
convert(fromType: "nuint", toType: "nint", "uint.MaxValue", IntPtr.Size == 4 ? "-1" : "4294967295", "conv.i", IntPtr.Size == 4 ? "System.OverflowException" : "4294967295", "conv.ovf.i.un");

string nintMinValue = IntPtr.Size == 4 ? int.MinValue.ToString() : long.MinValue.ToString();
string nintMaxValue = IntPtr.Size == 4 ? int.MaxValue.ToString() : long.MaxValue.ToString();
string nuintMaxValue = IntPtr.Size == 4 ? uint.MaxValue.ToString() : ulong.MaxValue.ToString();

convert(fromType: "nint", toType: "ulong", nintMinValue, IntPtr.Size == 4 ? "18446744071562067968" : "9223372036854775808", "conv.i8", "System.OverflowException", "conv.ovf.u8");
convert(fromType: "nint", toType: "ulong", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.i8", IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u8");
convert(fromType: "nint", toType: "nuint", nintMinValue, IntPtr.Size == 4 ? "2147483648" : "9223372036854775808", "conv.u", "System.OverflowException", "conv.ovf.u");
convert(fromType: "nint", toType: "nuint", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.u", IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u");

convert(fromType: "nuint", toType: "long", nuintMaxValue, IntPtr.Size == 4 ? "4294967295" : "-1", "conv.u8", IntPtr.Size == 4 ? "4294967295" : "System.OverflowException", "conv.ovf.i8.un");
convert(fromType: "nuint", toType: "nint", nuintMaxValue, "-1", "conv.i", "System.OverflowException", "conv.ovf.i.un");

void convert(string fromType, string toType, string fromValue, string toValueUnchecked, string toConvUnchecked, string toValueChecked, string toConvChecked)
{
string source =
$@"using System;
class Program
{{
static {toType} Convert({fromType} value) => ({toType})(value);
static {toType} ConvertChecked({fromType} value) => checked(({toType})(value));
static object Execute(Func<object> f)
{{
try
{{
return f();
}}
catch (Exception e)
{{
return e.GetType().FullName;
}}
}}
static void Main()
{{
{fromType} value = ({fromType})({fromValue});
Console.WriteLine(Execute(() => Convert(value)));
Console.WriteLine(Execute(() => ConvertChecked(value)));
}}
}}";
var verifier = CompileAndVerify(source, parseOptions: TestOptions.Regular9, expectedOutput:
$@"{toValueUnchecked}
{toValueChecked}");
verifier.VerifyIL("Program.Convert",
$@"{{
// Code size 3 (0x3)
.maxstack 1
IL_0000: ldarg.0
IL_0001: {toConvUnchecked}
IL_0002: ret
}}");
verifier.VerifyIL("Program.ConvertChecked",
$@"{{
// Code size 3 (0x3)
.maxstack 1
IL_0000: ldarg.0
IL_0001: {toConvChecked}
IL_0002: ret
}}");
}
}

[WorkItem(44810, "https://github.com/dotnet/roslyn/issues/44810")]
[Theory]
[InlineData("void*")]
Expand Down

0 comments on commit 3d33a9e

Please sign in to comment.