-
Notifications
You must be signed in to change notification settings - Fork 442
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
Conversation
90eb340
to
3121f34
Compare
|
||
public CSharpCompilationService(IFunctionMetadataResolver metadataResolver, OptimizationLevel optimizationLevel) | ||
{ | ||
_metadataResolver = metadataResolver; | ||
_optimizationLevel = optimizationLevel; | ||
} | ||
|
||
public string Language |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) }"); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
3121f34
to
5255116
Compare
@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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay :)
This looks great, thanks so much @fabiocav . Can't wait to try this out live :) |
There was a problem hiding this 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.
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. |
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.
818d4c4
to
0080db7
Compare
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)