提交 c0738262 编写于 作者: A Aaron Bockover 提交者: Tomáš Matoušek

Compilation: use System.Object from target corlib (#8507)

* Tests: fix minasync Task<T> to derive from Task

* Tests: provide MinAsyncCorlibRef

This combines the async features of minasync with mincorlib to produce
a minimum unversioned corlib with async stubs.

* Compilation: use System.Object from target corlib

When creating a script compilation without an explicit return type,
System.Object was being resolved via reflection from the host.

This resulted in an implicit dependency of a script compilation on the
host corlib, even if a different corlib was specified as a reference
for the compilation (e.g. Xamarin.iOS).

Fix this by using System.Object as defined in the corlib resovled
for the compilation.
上级 dd42f4c6
......@@ -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);
}
}
......
......@@ -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()
......
......@@ -330,7 +330,7 @@ internal int GetSubmissionSlotIndex()
/// <summary>
/// The type object that represents the type of submission result the host requested.
/// </summary>
internal Type SubmissionReturnType => ScriptCompilationInfo?.ReturnType;
internal Type SubmissionReturnType => ScriptCompilationInfo?.ReturnTypeOpt;
internal static bool IsValidSubmissionReturnType(Type type)
{
......
......@@ -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;
}
......
......@@ -136,6 +136,7 @@
<Content Include="NetFX\Minimal\build.cmd" />
<Content Include="NetFX\Minimal\Key.snk" />
<Content Include="NetFX\Minimal\minasync.cs" />
<EmbeddedResource Include="NetFX\Minimal\minasynccorlib.dll" />
<Content Include="NetFX\Minimal\mincorlib.cs" />
<EmbeddedResource Include="NetFX\ValueTuple\System.ValueTuple.dll" />
<EmbeddedResource Include="SymbolsTests\Metadata\public-and-private.dll" />
......
......@@ -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
......@@ -14,9 +14,9 @@ public class Task : IAsyncResult, IDisposable
public Awaiter GetAwaiter() => null;
}
public class Task<T> : IAsyncResult, IDisposable
public class Task<T> : Task, IAsyncResult, IDisposable
{
public Awaiter<T> GetAwaiter() => null;
public new Awaiter<T> GetAwaiter() => null;
}
public class Awaiter : INotifyCompletion
......
......@@ -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
......
......@@ -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
......@@ -1311,6 +1311,32 @@ End Class
Assert.Equal("ModuleAssemblyName", c.Assembly.Identity.Name)
End Sub
<WorkItem(8506, "https://github.com/dotnet/roslyn/issues/8506")>
<Fact()>
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
<WorkItem(3719, "https://github.com/dotnet/roslyn/issues/3719")>
<Fact()>
Public Sub GetEntryPoint_Script()
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册