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 May 9, 2016
1 parent 0cce20b commit f2a44b3
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,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 @@ -1407,6 +1407,26 @@ static void Main() { }
Assert.Equal("ModuleAssemblyName", compilation.Assembly.Identity.Name);
}

[WorkItem(8506, "https://github.com/dotnet/roslyn/issues/8506")]
[Fact]
public void CrossCorlibSystemObjectReturnType_Script()
{
// The ScriptMinCorlibRef corlib is used since it provides just enough corlib type
// definitions, including the Task APIs necessary for script hosting, yet can't provide
// provide `System.Object, mscorlib, Version=4.0.0.0` (since it's unversioned).
//
// In the original bug, Xamarin iOS, Android, and Mac Mobile profile corlibs were
// realistic cross-compilation targets.
var compilation = CreateCompilation("true",
references: new [] { ScriptMinCorlibRef },
options: TestOptions.ReleaseExe,
parseOptions: TestOptions.Script
).VerifyDiagnostics();

var entryPoint = compilation.GetEntryPoint(default(CancellationToken));
Assert.Same(compilation.ObjectType, entryPoint.ReturnType);
}

[WorkItem(3719, "https://github.com/dotnet/roslyn/issues/3719")]
[Fact]
public void GetEntryPoint_Script()
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 @@ -1296,6 +1296,25 @@ 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()
' The ScriptMinCorlibRef corlib is used since it provides just enough corlib type
' definitions, including the Task APIs necessary for script hosting, yet can't provide
' provide `System.Object, mscorlib, Version=4.0.0.0` (since it's unversioned).
'
' In the original bug, Xamarin iOS, Android, and Mac Mobile profile corlibs were
' realistic cross-compilation targets.
Dim source = "? True"
Dim compilation = VisualBasicCompilation.CreateScriptCompilation(
"sub",
references:={ScriptMinCorlibRef},
syntaxTree:=Parse(source, options:=TestOptions.Script))
compilation.VerifyDiagnostics()
Dim entryPoint = compilation.GetEntryPoint(Nothing)
Assert.Same(compilation.ObjectType, entryPoint.ReturnType)
End Sub

<WorkItem(3719, "https://github.com/dotnet/roslyn/issues/3719")>
<Fact()>
Public Sub GetEntryPoint_Script()
Expand Down

0 comments on commit f2a44b3

Please sign in to comment.