Skip to content

Commit

Permalink
Compilation: use System.Object from target corlib
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
abock committed Jun 1, 2016
1 parent 3fa5910 commit 9b206e6
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,20 @@ private static void CalculateReturnType(
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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,33 @@ static void Main() { }
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()
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/Core/Portable/Compilation/Compilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
End Namespace
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 9b206e6

Please sign in to comment.