From 661e776c01667eddbe8f9be80ea5869f1d7630b4 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Wed, 10 Aug 2016 14:03:31 -0700 Subject: [PATCH] Handle pointer and error types in NormalizeTaskTypes --- .../Portable/Symbols/TypeSymbolExtensions.cs | 20 ++++ .../Semantics/OverloadResolutionTests.cs | 107 ++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index bce6baa2273..55b636f7448 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -1354,6 +1354,7 @@ private static bool NormalizeTaskTypesInType(CSharpCompilation compilation, ref switch (type.Kind) { case SymbolKind.NamedType: + case SymbolKind.ErrorType: { var namedType = (NamedTypeSymbol)type; var changed = type.IsTupleType ? @@ -1369,6 +1370,13 @@ private static bool NormalizeTaskTypesInType(CSharpCompilation compilation, ref type = arrayType; return changed; } + case SymbolKind.PointerType: + { + var pointerType = (PointerTypeSymbol)type; + var changed = NormalizeTaskTypesInPointer(compilation, ref pointerType); + type = pointerType; + return changed; + } } return false; } @@ -1456,6 +1464,18 @@ private static bool NormalizeTaskTypesInArray(CSharpCompilation compilation, ref return true; } + private static bool NormalizeTaskTypesInPointer(CSharpCompilation compilation, ref PointerTypeSymbol pointerType) + { + var pointedAtType = pointerType.PointedAtType; + if (!NormalizeTaskTypesInType(compilation, ref pointedAtType)) + { + return false; + } + // Preserve custom modifiers but without normalizing those types. + pointerType = new PointerTypeSymbol(pointedAtType, pointerType.CustomModifiers); + return true; + } + internal static Cci.TypeReferenceWithAttributes GetTypeRefWithAttributes( this TypeSymbol type, CSharpCompilation declaringCompilation, diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs index 7321fbd1fba..d0b7eef02ac 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs @@ -744,6 +744,113 @@ public void NormalizeTaskTypes_TypeArgumentCustomModifiers() Assert.Equal("System.Threading.Tasks.Task)>", normalized.ToTestDisplayString()); } + [Fact] + public void NormalizeTaskTypes_Pointers() + { + string source = +@"unsafe class C +{ +#pragma warning disable CS0169 + static C>* F0; +#pragma warning restore CS0169 +} +struct MyTask +{ + public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); +} +struct MyTaskMethodBuilder +{ +}"; + var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.UnsafeDebugDll); + compilation.VerifyDiagnostics( + // (4,12): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C>') + // static C>* F0; + Diagnostic(ErrorCode.ERR_ManagedAddr, "C>*").WithArguments("C>").WithLocation(4, 12)); + + var type = compilation.GetMember("C.F0").Type; + var normalized = type.NormalizeTaskTypes(compilation); + Assert.Equal("C>*", type.ToTestDisplayString()); + Assert.Equal("C>*", normalized.ToTestDisplayString()); + } + + [Fact] + public void NormalizeTaskTypes_PointersCustomModifiers() + { + var ilSource = +@".class public C +{ + .field public static class MyTask modopt(class MyTask) *[] F0 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public MyTask +{ + .method public hidebysig static class MyTaskMethodBuilder CreateAsyncMethodBuilder() cil managed { ldnull ret } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public MyTaskMethodBuilder +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +"; + var source = +@""; + var reference = CompileIL(ilSource); + var compilation = CreateCompilationWithMscorlib45(source, references: new[] { reference }); + compilation.VerifyDiagnostics(); + + var type = compilation.GetMember("C.F0").Type; + var normalized = type.NormalizeTaskTypes(compilation); + Assert.Equal("MyTask modopt(MyTask) *[]", type.ToTestDisplayString()); + Assert.Equal("System.Threading.Tasks.Task modopt(MyTask) *[]", normalized.ToTestDisplayString()); + } + + [Fact] + public void NormalizeTaskTypes_Errors() + { + string source = +@"class C +{ +#pragma warning disable CS0169 + static A F0; + static MyTask F1; +#pragma warning restore CS0169 +} +struct MyTask +{ + public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); +} +struct MyTask +{ + public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); +} +struct MyTaskMethodBuilder +{ +} +struct MyTaskMethodBuilder +{ +}"; + var compilation = CreateCompilationWithMscorlib45(source); + compilation.VerifyDiagnostics( + // (5,19): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?) + // static MyTask F1; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(5, 19), + // (4,12): error CS0246: The type or namespace name 'A<,>' could not be found (are you missing a using directive or an assembly reference?) + // static A F0; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "A").WithArguments("A<,>").WithLocation(4, 12)); + + var type = compilation.GetMember("C.F0").Type; + Assert.Equal(TypeKind.Error, type.TypeKind); + var normalized = type.NormalizeTaskTypes(compilation); + Assert.Equal("A", type.ToTestDisplayString()); + Assert.Equal("A", normalized.ToTestDisplayString()); + + type = compilation.GetMember("C.F1").Type; + Assert.Equal(TypeKind.Error, ((NamedTypeSymbol)type).TypeArguments[0].TypeKind); + normalized = type.NormalizeTaskTypes(compilation); + Assert.Equal("MyTask", type.ToTestDisplayString()); + Assert.Equal("System.Threading.Tasks.Task", normalized.ToTestDisplayString()); + } + [Fact] public void NormalizeTaskTypes_Inner() { -- GitLab