diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs
index 5ae3468323ad8c96f9fce58395e73b5dc40b9488..ba473a5e763b7aad0f6edf80e0a32fd8b75a2026 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInteractiveInitializerMethod.cs
@@ -236,14 +236,20 @@ internal TypeSymbol ResultType
out TypeSymbol resultType,
out TypeSymbol returnType)
{
- var submissionReturnType = compilation.SubmissionReturnType ?? typeof(object);
+ var submissionReturnTypeOpt = compilation.ScriptCompilationInfo?.ReturnTypeOpt;
var taskT = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T);
var useSiteDiagnostic = taskT.GetUseSiteDiagnostic();
if (useSiteDiagnostic != null)
{
diagnostics.Add(useSiteDiagnostic, NoLocation.Singleton);
}
- resultType = compilation.GetTypeByReflectionType(submissionReturnType, diagnostics);
+ // If no explicit return type is set on ScriptCompilationInfo, default to
+ // System.Object from the target corlib. This allows cross compiling scripts
+ // to run on a target corlib that may differ from the host compiler's corlib.
+ // cf. https://github.com/dotnet/roslyn/issues/8506
+ resultType = (object)submissionReturnTypeOpt == null
+ ? compilation.GetSpecialType(SpecialType.System_Object)
+ : compilation.GetTypeByReflectionType(submissionReturnTypeOpt, diagnostics);
returnType = taskT.Construct(resultType);
}
}
diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs
index 90fa3f80d163f1059b6f583f1e1a7a23b340750e..001dabf6c0284906d22ca1437a193aedcfd1372f 100644
--- a/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs
@@ -1484,6 +1484,33 @@ class A
Assert.Equal("ModuleAssemblyName", compilation.Assembly.Identity.Name);
}
+ [WorkItem(8506, "https://github.com/dotnet/roslyn/issues/8506")]
+ [Fact]
+ public void CrossCorlibSystemObjectReturnType_Script()
+ {
+ // MinAsyncCorlibRef corlib is used since it provides just enough corlib type definitions
+ // and Task APIs necessary for script hosting are provided by MinAsyncRef. This ensures that
+ // `System.Object, mscorlib, Version=4.0.0.0` will not be provided (since it's unversioned).
+ //
+ // In the original bug, Xamarin iOS, Android, and Mac Mobile profile corlibs were
+ // realistic cross-compilation targets.
+ var compilation = CSharpCompilation.CreateScriptCompilation(
+ "submission-assembly",
+ references: new [] { MinAsyncCorlibRef },
+ syntaxTree: Parse("true", options: TestOptions.Script)
+ ).VerifyDiagnostics();
+
+ Assert.True(compilation.IsSubmission);
+
+ var taskOfT = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T);
+ var taskOfObject = taskOfT.Construct(compilation.ObjectType);
+ var entryPoint = compilation.GetEntryPoint(default(CancellationToken));
+
+ Assert.Same(compilation.ObjectType.ContainingAssembly, taskOfT.ContainingAssembly);
+ Assert.Same(compilation.ObjectType.ContainingAssembly, taskOfObject.ContainingAssembly);
+ Assert.Equal(taskOfObject, entryPoint.ReturnType);
+ }
+
[WorkItem(3719, "https://github.com/dotnet/roslyn/issues/3719")]
[Fact]
public void GetEntryPoint_Script()
diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs
index e6e1e8bac0a9640e9a1d4a58110bd19f382244b5..154c14b85bef297ef3ed0f91fd6917dfd3169660 100644
--- a/src/Compilers/Core/Portable/Compilation/Compilation.cs
+++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs
@@ -330,7 +330,7 @@ internal int GetSubmissionSlotIndex()
///
/// The type object that represents the type of submission result the host requested.
///
- internal Type SubmissionReturnType => ScriptCompilationInfo?.ReturnType;
+ internal Type SubmissionReturnType => ScriptCompilationInfo?.ReturnTypeOpt;
internal static bool IsValidSubmissionReturnType(Type type)
{
diff --git a/src/Compilers/Core/Portable/Compilation/ScriptCompilationInfo.cs b/src/Compilers/Core/Portable/Compilation/ScriptCompilationInfo.cs
index 927a52c7670829a661611a77eaa8f3d0f2eeb867..8f45663b1ec55df84e027902fda98af51945d7f2 100644
--- a/src/Compilers/Core/Portable/Compilation/ScriptCompilationInfo.cs
+++ b/src/Compilers/Core/Portable/Compilation/ScriptCompilationInfo.cs
@@ -6,12 +6,13 @@ namespace Microsoft.CodeAnalysis
{
public abstract class ScriptCompilationInfo
{
- public Type ReturnType { get; }
+ internal Type ReturnTypeOpt { get; }
+ public Type ReturnType => ReturnTypeOpt ?? typeof(object);
public Type GlobalsType { get; }
internal ScriptCompilationInfo(Type returnType, Type globalsType)
{
- ReturnType = returnType ?? typeof(object);
+ ReturnTypeOpt = returnType;
GlobalsType = globalsType;
}
diff --git a/src/Compilers/Test/Resources/Core/CompilerTestResources.csproj b/src/Compilers/Test/Resources/Core/CompilerTestResources.csproj
index 4bb2c2ab0bb96a1080740c7d143e42fe4561c5cf..de418166daa10084d5cf0f97fca3633b9d28dae7 100644
--- a/src/Compilers/Test/Resources/Core/CompilerTestResources.csproj
+++ b/src/Compilers/Test/Resources/Core/CompilerTestResources.csproj
@@ -136,6 +136,7 @@
+
diff --git a/src/Compilers/Test/Resources/Core/NetFX/Minimal/build.cmd b/src/Compilers/Test/Resources/Core/NetFX/Minimal/build.cmd
index ba14a626bc9eaa157c7626f82075898c79728880..c465afaf1dd816d13251730ef4e450e0b969e726 100644
--- a/src/Compilers/Test/Resources/Core/NetFX/Minimal/build.cmd
+++ b/src/Compilers/Test/Resources/Core/NetFX/Minimal/build.cmd
@@ -2,3 +2,4 @@
csc /target:library /nostdlib /noconfig /keyfile:Key.snk /out:mincorlib.dll mincorlib.cs
csc /target:library /nostdlib /noconfig /keyfile:Key.snk /r:mincorlib.dll /out:minasync.dll minasync.cs
+csc /target:library /nostdlib /noconfig /keyfile:Key.snk /out:minasynccorlib.dll mincorlib.cs minasync.cs
diff --git a/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.cs b/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.cs
index d31e1f78056f88d3b0b75fcff1aaefaa3b65db7d..fc97264291b88dbeada90b23d7a63827ff84a439 100644
--- a/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.cs
+++ b/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.cs
@@ -14,9 +14,9 @@ public class Task : IAsyncResult, IDisposable
public Awaiter GetAwaiter() => null;
}
- public class Task : IAsyncResult, IDisposable
+ public class Task : Task, IAsyncResult, IDisposable
{
- public Awaiter GetAwaiter() => null;
+ public new Awaiter GetAwaiter() => null;
}
public class Awaiter : INotifyCompletion
diff --git a/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.dll b/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.dll
index f9e08aaab65303d142554546ea9d000b165702eb..979309bb0ef25bf7bffdeadb9113ca5915e6600d 100644
Binary files a/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.dll and b/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasync.dll differ
diff --git a/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasynccorlib.dll b/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasynccorlib.dll
new file mode 100644
index 0000000000000000000000000000000000000000..79bee6784a7d3c91b38a33dbb549c17a65aaa5e9
Binary files /dev/null and b/src/Compilers/Test/Resources/Core/NetFX/Minimal/minasynccorlib.dll differ
diff --git a/src/Compilers/Test/Resources/Core/TestResources.cs b/src/Compilers/Test/Resources/Core/TestResources.cs
index 3fc5d83bcc36f29ff2aa538f780ad3cf6a6efa51..13961b2741d78741c5535e304c3991633ca10b1a 100644
--- a/src/Compilers/Test/Resources/Core/TestResources.cs
+++ b/src/Compilers/Test/Resources/Core/TestResources.cs
@@ -165,6 +165,9 @@ public static class Minimal
private static byte[] s_minasync;
public static byte[] minasync => ResourceLoader.GetOrCreateResource(ref s_minasync, "NetFX.Minimal.minasync.dll");
+
+ private static byte [] s_minasynccorlib;
+ public static byte [] minasynccorlib => ResourceLoader.GetOrCreateResource(ref s_minasynccorlib, "NetFX.Minimal.minasynccorlib.dll");
}
public static class ValueTuple
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SynthesizedInteractiveInitializerMethod.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SynthesizedInteractiveInitializerMethod.vb
index 3f6aad78210ea80573b195361f763187915d6591..d9e88c538a8cbc69b0945d98a70fbd977c8edeaf 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SynthesizedInteractiveInitializerMethod.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SynthesizedInteractiveInitializerMethod.vb
@@ -149,16 +149,28 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
ByRef resultType As TypeSymbol,
ByRef returnType As TypeSymbol)
- Dim submissionReturnType = If(compilation.SubmissionReturnType, GetType(Object))
+ Dim submissionReturnType As Type = Nothing
+ If compilation.ScriptCompilationInfo IsNot Nothing Then
+ submissionReturnType = compilation.ScriptCompilationInfo.ReturnTypeOpt
+ End If
+
Dim taskT = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T)
Dim useSiteDiagnostic = taskT.GetUseSiteErrorInfo()
If useSiteDiagnostic IsNot Nothing Then
diagnostics.Add(useSiteDiagnostic, NoLocation.Singleton)
End If
- resultType = compilation.GetTypeByReflectionType(submissionReturnType, diagnostics)
+ ' If no explicit return type is set on ScriptCompilationInfo, default to
+ ' System.Object from the target corlib. This allows cross compiling scripts
+ ' to run on a target corlib that may differ from the host compiler's corlib.
+ ' cf. https://github.com/dotnet/roslyn/issues/8506
+ If submissionReturnType Is Nothing Then
+ resultType = compilation.GetSpecialType(SpecialType.System_Object)
+ Else
+ resultType = compilation.GetTypeByReflectionType(submissionReturnType, diagnostics)
+ End If
returnType = taskT.Construct(resultType)
End Sub
End Class
-End Namespace
\ No newline at end of file
+End Namespace
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb
index 93a83ce98969615b09233814004332ea499f7417..0355b7bb8a352329e8e373ea756e02caaf383192 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/CompilationAPITests.vb
@@ -1311,6 +1311,32 @@ End Class
Assert.Equal("ModuleAssemblyName", c.Assembly.Identity.Name)
End Sub
+
+
+ Public Sub CrossCorlibSystemObjectReturnType_Script()
+ ' MinAsyncCorlibRef corlib Is used since it provides just enough corlib type definitions
+ ' And Task APIs necessary for script hosting are provided by MinAsyncRef. This ensures that
+ ' `System.Object, mscorlib, Version=4.0.0.0` will Not be provided (since it's unversioned).
+ '
+ ' In the original bug, Xamarin iOS, Android, And Mac Mobile profile corlibs were
+ ' realistic cross-compilation targets.
+ Dim compilation = VisualBasicCompilation.CreateScriptCompilation(
+ "submission-assembly",
+ references:={MinAsyncCorlibRef},
+ syntaxTree:=Parse("? True", options:=TestOptions.Script)
+ ).VerifyDiagnostics()
+
+ Assert.True(compilation.IsSubmission)
+
+ Dim taskOfT = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T)
+ Dim taskOfObject = taskOfT.Construct(compilation.ObjectType)
+ Dim entryPoint = compilation.GetEntryPoint(Nothing)
+
+ Assert.Same(compilation.ObjectType.ContainingAssembly, taskOfT.ContainingAssembly)
+ Assert.Same(compilation.ObjectType.ContainingAssembly, taskOfObject.ContainingAssembly)
+ Assert.Equal(taskOfObject, entryPoint.ReturnType)
+ End Sub
+
Public Sub GetEntryPoint_Script()
diff --git a/src/Test/Utilities/Shared/Mocks/TestReferences.cs b/src/Test/Utilities/Shared/Mocks/TestReferences.cs
index 51436e8191f9948b91af2afe32c261f6701e28cc..09be1347e672ffb0b28c086efb035782e15150f5 100644
--- a/src/Test/Utilities/Shared/Mocks/TestReferences.cs
+++ b/src/Test/Utilities/Shared/Mocks/TestReferences.cs
@@ -170,6 +170,20 @@ public static PortableExecutableReference minasync
return s_minasync;
}
}
+
+ private static PortableExecutableReference s_minasynccorlib;
+ public static PortableExecutableReference minasynccorlib
+ {
+ get
+ {
+ if (s_minasynccorlib == null)
+ {
+ s_minasynccorlib = AssemblyMetadata.CreateFromImage(TestResources.NetFX.Minimal.minasynccorlib).GetReference(display: "minasynccorlib.dll");
+ }
+
+ return s_minasynccorlib;
+ }
+ }
}
public static class ValueTuple
diff --git a/src/Test/Utilities/Shared/TestBase.cs b/src/Test/Utilities/Shared/TestBase.cs
index 6f9375eef9a2ff412c411e976e6fc6c49da1cf88..445a43529b2fc75041ab2b64bc125895bd51957f 100644
--- a/src/Test/Utilities/Shared/TestBase.cs
+++ b/src/Test/Utilities/Shared/TestBase.cs
@@ -325,6 +325,8 @@ public static MetadataReference MscorlibRefSilverlight
public static MetadataReference MinCorlibRef => TestReferences.NetFx.Minimal.mincorlib;
+ public static MetadataReference MinAsyncCorlibRef => TestReferences.NetFx.Minimal.minasynccorlib;
+
public static MetadataReference ValueTupleRef => TestReferences.NetFx.ValueTuple.tuplelib;
private static MetadataReference s_msvbRef;