Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing a few issues that were primarily impacting F# #1049

Merged
merged 1 commit into from
Dec 16, 2016

Conversation

fabiocav
Copy link
Member

@fabiocav fabiocav commented Dec 14, 2016

1 - Ensuring that package resolver does not return duplicate references
2 - Ensuring that the MetadataResolver handles duplicates when adding default references
3 - Fixing F# compilation service to get the script references and removing dependency on C# compilation
4 - Fixing issue preventing the load context from being initialized for F#, which would trigger dependency resolution failures.

Resolves #1044
Resolves #1027
Resolves #985
Mitigates #178 (this addresses the most common scenarios)


public CSharpCompilationService(IFunctionMetadataResolver metadataResolver, OptimizationLevel optimizationLevel)
{
_metadataResolver = metadataResolver;
_optimizationLevel = optimizationLevel;
}

public string Language
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some cleanup and small optimizations here since I was working in this area.

@@ -258,15 +258,16 @@ private object[] ProcessInputParameters(object[] parameters)
using (_metricsLogger.LatencyEvent(eventName))
{
ICompilation compilation = _compilationService.GetFunctionCompilation(Metadata);

Assembly assembly = compilation.EmitAndLoad(cancellationToken);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this change, we now emit before validation. This does remove an optimization in the case of C# where we can perform code analysis for the small check we run below, but it's not significant in this code path (this is not triggered as part of diagnostics compilations) and the complexity to handle both scenarios (where emit is required and when it isn't) is probably not justified at this point.

// However F# has its own view on default options. For scripts these should include the
// following framework facade references.

otherFlags.Add("-r:System.Linq.dll"); // System.Linq.Expressions.Expression<T>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sylvanc were these really necessary? After switching so to get the script references, these references were causing issues and compilation, execution and tests succeed without them. We did add System.Runtime to the default references as we have been planning to do that for a while.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, I did try using types that (as defined here) would depend on those references and didn't seem to run into issues. I think it would probably be a good idea to have some tests covering those for validation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those don't appear to be necessary, no. Good catch. As far as I can tell, git claims those were introduced before the work @dsyme and I did, which means I should have noticed them, sorry about that!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NP! Glad to have confirmation that those are not needed.

@@ -77,7 +69,6 @@ public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
var resolverSource = resolverSourceBuilder.ToString();

Script<object> script = CodeAnalysis.CSharp.Scripting.CSharpScript.Create(resolverSource, options: _metadataResolver.CreateScriptOptions(), assemblyLoader: AssemblyLoader.Value);
Compilation compilation = script.GetCompilation();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dependency has been removed. We get all the references from the script and run them directly against the metadata resolver. This call was not cheap, so I'm happy to get rid of it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic

@@ -196,13 +172,17 @@ public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
var assembly = Assembly.Load(assemblyBytes, pdbBytes);
assemblyOption = FSharpOption<Assembly>.Some(assembly);
}
else
{
_traceWriter.Verbose($"F# Compilation failed with arguments: { string.Join(" ", otherFlags) }");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of failures, we now log the arguments, which will help us identify issues like the duplicate references we ran into.

Copy link
Member

@mathewc mathewc Dec 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: lower case Compilation to match new trace below. Also, should this be logged at Error level? Our default log level is Info I thought - does this even make it out? Or is the error already logged elsewhere and this is just verbose details?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual compilation/diagnostics errors are already logged and reported back. This gives us some additional details in verbose mode to show the entire set of arguments passed to the compiler.

@fabiocav
Copy link
Member Author

@sylvanc could take a quick look at this changes (particularly on the comment I tagged you on)?

@@ -60,7 +61,7 @@ public ICompilationService CreateService(ScriptType scriptType, IFunctionMetadat
case ScriptType.CSharp:
return new CSharpCompilationService(metadataResolver, OptimizationLevel);
case ScriptType.FSharp:
return new FSharpCompiler(metadataResolver, OptimizationLevel);
return new FSharpCompiler(metadataResolver, OptimizationLevel, _traceWriter);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay :)

@sylvanc
Copy link
Contributor

sylvanc commented Dec 16, 2016

This looks great, thanks so much @fabiocav . Can't wait to try this out live :)

Copy link
Member

@brettsam brettsam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert here, but it mostly looks good. The only thing that jumps out at me is the lack of tests that would have caught this. Or tests that prove the tracing happens as you expect now.

@mathewc
Copy link
Member

mathewc commented Dec 16, 2016

I agree with Brett that for the number of bugs being resolved with these changes, I would expect us to have some new regression tests.

@fabiocav
Copy link
Member Author

@brettsam and @mathewc agree with the comments on the tests. Will add some tests to make sure the scenarios we're fixing are covered.

1 - Ensuring that package resolver does not return duplicate references
2 - Ensuring that the MetadataResolver handles duplicates when adding default references
3 - Fixing F# compilation service to get the script references and removing dependency on C# compilation
4 - Fixing issue preventing the load context from being initialized for F#, which would trigger dependency resolution failures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants