Skip to content

Commit 7d5f12d

Browse files
author
dotnet-automerge-bot
authored
Merge pull request #7187 from dotnet/merges/master-to-release/dev16.3
Merge master to release/dev16.3
2 parents c807da6 + 4f99eeb commit 7d5f12d

11 files changed

Lines changed: 3936 additions & 278 deletions

File tree

eng/Version.Details.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
<ProductDependencies>
44
</ProductDependencies>
55
<ToolsetDependencies>
6-
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19359.1">
6+
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19359.6">
77
<Uri>https://github.com/dotnet/arcade</Uri>
8-
<Sha>ef3834feb8615429a58808cdcf9ad9284d767654</Sha>
8+
<Sha>0f5dd7680174620f31c9a00cdb2ac0b0e70e631f</Sha>
99
</Dependency>
1010
</ToolsetDependencies>
1111
</Dependencies>

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
}
1111
},
1212
"msbuild-sdks": {
13-
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19359.1",
13+
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19359.6",
1414
"Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2"
1515
}
1616
}

src/fsharp/IlxGen.fs

Lines changed: 119 additions & 69 deletions
Large diffs are not rendered by default.

src/fsharp/lib.fs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,3 +536,14 @@ module UnmanagedProcessExecutionOptions =
536536
"HeapSetInformation() returned FALSE; LastError = 0x" +
537537
GetLastError().ToString("X").PadLeft(8, '0') + "."))
538538

539+
[<RequireQualifiedAccess>]
540+
module StackGuard =
541+
542+
open System.Runtime.CompilerServices
543+
544+
[<Literal>]
545+
let private MaxUncheckedRecursionDepth = 20
546+
547+
let EnsureSufficientExecutionStack recursionDepth =
548+
if recursionDepth > MaxUncheckedRecursionDepth then
549+
RuntimeHelpers.EnsureSufficientExecutionStack ()

tests/fsharp/Compiler/CompilerAssert.fs

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ open FSharp.Compiler.SourceCodeServices
1111
open FSharp.Compiler.Interactive.Shell
1212

1313
open NUnit.Framework
14+
open System.Reflection.Emit
15+
16+
[<Sealed>]
17+
type ILVerifier (dllFilePath: string) =
18+
19+
member this.VerifyIL (qualifiedItemName: string, expectedIL: string) =
20+
ILChecker.checkILItem qualifiedItemName dllFilePath [ expectedIL ]
21+
22+
member this.VerifyIL (expectedIL: string list) =
23+
ILChecker.checkIL dllFilePath expectedIL
24+
25+
member this.VerifyILWithLineNumbers (qualifiedItemName: string, expectedIL: string) =
26+
ILChecker.checkILItemWithLineNumbers qualifiedItemName dllFilePath [ expectedIL ]
1427

1528
[<RequireQualifiedAccess>]
1629
module CompilerAssert =
@@ -48,10 +61,45 @@ module CompilerAssert =
4861
Stamp = None
4962
}
5063

51-
let lockObj = obj ()
64+
let private gate = obj ()
65+
66+
let private compile isExe source f =
67+
lock gate <| fun () ->
68+
let inputFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".fs")
69+
let outputFilePath = Path.ChangeExtension (Path.GetTempFileName(), if isExe then ".exe" else ".dll")
70+
let runtimeConfigFilePath = Path.ChangeExtension (outputFilePath, ".runtimeconfig.json")
71+
let fsCoreDllPath = config.FSCOREDLLPATH
72+
let tmpFsCoreFilePath = Path.Combine (Path.GetDirectoryName(outputFilePath), Path.GetFileName(fsCoreDllPath))
73+
try
74+
File.Copy (fsCoreDllPath , tmpFsCoreFilePath, true)
75+
File.WriteAllText (inputFilePath, source)
76+
File.WriteAllText (runtimeConfigFilePath, """
77+
{
78+
"runtimeOptions": {
79+
"tfm": "netcoreapp2.1",
80+
"framework": {
81+
"name": "Microsoft.NETCore.App",
82+
"version": "2.1.0"
83+
}
84+
}
85+
}
86+
""")
87+
88+
let args =
89+
defaultProjectOptions.OtherOptions
90+
|> Array.append [| "fsc.exe"; inputFilePath; "-o:" + outputFilePath; (if isExe then "--target:exe" else "--target:library"); "--nowin32manifest" |]
91+
let errors, _ = checker.Compile args |> Async.RunSynchronously
92+
93+
f (errors, outputFilePath)
94+
95+
finally
96+
try File.Delete inputFilePath with | _ -> ()
97+
try File.Delete outputFilePath with | _ -> ()
98+
try File.Delete runtimeConfigFilePath with | _ -> ()
99+
try File.Delete tmpFsCoreFilePath with | _ -> ()
52100

53101
let Pass (source: string) =
54-
lock lockObj <| fun () ->
102+
lock gate <| fun () ->
55103
let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously
56104

57105
Assert.IsEmpty(parseResults.Errors, sprintf "Parse errors: %A" parseResults.Errors)
@@ -64,7 +112,7 @@ module CompilerAssert =
64112

65113

66114
let TypeCheckSingleError (source: string) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) =
67-
lock lockObj <| fun () ->
115+
lock gate <| fun () ->
68116
let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously
69117

70118
Assert.IsEmpty(parseResults.Errors, sprintf "Parse errors: %A" parseResults.Errors)
@@ -82,8 +130,46 @@ module CompilerAssert =
82130
Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg")
83131
)
84132

133+
let CompileExe (source: string) =
134+
compile true source (fun (errors, _) ->
135+
if errors.Length > 0 then
136+
Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors))
137+
138+
let CompileExeAndRun (source: string) =
139+
compile true source (fun (errors, outputExe) ->
140+
141+
if errors.Length > 0 then
142+
Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors)
143+
144+
let pInfo = ProcessStartInfo ()
145+
#if NETCOREAPP
146+
pInfo.FileName <- config.DotNetExe
147+
pInfo.Arguments <- outputExe
148+
#else
149+
pInfo.FileName <- outputExe
150+
#endif
151+
152+
pInfo.RedirectStandardError <- true
153+
pInfo.UseShellExecute <- false
154+
155+
let p = Process.Start(pInfo)
156+
157+
p.WaitForExit()
158+
let errors = p.StandardError.ReadToEnd ()
159+
if not (String.IsNullOrWhiteSpace errors) then
160+
Assert.Fail errors
161+
)
162+
163+
let CompileLibraryAndVerifyIL (source: string) (f: ILVerifier -> unit) =
164+
compile false source (fun (errors, outputFilePath) ->
165+
if errors.Length > 0 then
166+
Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors)
167+
168+
f (ILVerifier outputFilePath)
169+
)
170+
85171
let RunScript (source: string) (expectedErrorMessages: string list) =
86-
lock lockObj <| fun () ->
172+
lock gate <| fun () ->
87173
// Intialize output and input streams
88174
use inStream = new StringReader("")
89175
use outStream = new StringWriter()

tests/fsharp/Compiler/ILChecker.fs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
namespace FSharp.Compiler.UnitTests
4+
5+
open System
6+
open System.IO
7+
open System.Diagnostics
8+
9+
open NUnit.Framework
10+
open TestFramework
11+
12+
[<RequireQualifiedAccess>]
13+
module ILChecker =
14+
15+
let config = initializeSuite ()
16+
17+
let private exec exe args =
18+
let startInfo = ProcessStartInfo(exe, String.concat " " args)
19+
startInfo.RedirectStandardError <- true
20+
startInfo.UseShellExecute <- false
21+
use p = Process.Start(startInfo)
22+
p.WaitForExit()
23+
p.StandardError.ReadToEnd(), p.ExitCode
24+
25+
/// Filters i.e ['The system type \'System.ReadOnlySpan`1\' was required but no referenced system DLL contained this type']
26+
let private filterSpecialComment (text: string) =
27+
let pattern = @"(\[\'(.*?)\'\])"
28+
System.Text.RegularExpressions.Regex.Replace(text, pattern,
29+
(fun me -> String.Empty)
30+
)
31+
32+
let private checkILAux ildasmArgs dllFilePath expectedIL =
33+
let ilFilePath = Path.ChangeExtension(dllFilePath, ".il")
34+
35+
let mutable errorMsgOpt = None
36+
try
37+
let ildasmPath = config.ILDASM
38+
39+
exec ildasmPath (ildasmArgs @ [ sprintf "%s /out=%s" dllFilePath ilFilePath ]) |> ignore
40+
41+
let text = File.ReadAllText(ilFilePath)
42+
let blockComments = @"/\*(.*?)\*/"
43+
let lineComments = @"//(.*?)\r?\n"
44+
let strings = @"""((\\[^\n]|[^""\n])*)"""
45+
let verbatimStrings = @"@(""[^""]*"")+"
46+
let textNoComments =
47+
System.Text.RegularExpressions.Regex.Replace(text,
48+
blockComments + "|" + lineComments + "|" + strings + "|" + verbatimStrings,
49+
(fun me ->
50+
if (me.Value.StartsWith("/*") || me.Value.StartsWith("//")) then
51+
if me.Value.StartsWith("//") then Environment.NewLine else String.Empty
52+
else
53+
me.Value), System.Text.RegularExpressions.RegexOptions.Singleline)
54+
|> filterSpecialComment
55+
56+
expectedIL
57+
|> List.iter (fun (ilCode: string) ->
58+
let expectedLines = ilCode.Split('\n')
59+
let startIndex = textNoComments.IndexOf(expectedLines.[0])
60+
if startIndex = -1 || textNoComments.Length < startIndex + ilCode.Length then
61+
errorMsgOpt <- Some("==EXPECTED CONTAINS==\n" + ilCode + "\n")
62+
else
63+
let errors = ResizeArray()
64+
let actualLines = textNoComments.Substring(startIndex, textNoComments.Length - startIndex).Split('\n')
65+
for i = 0 to expectedLines.Length - 1 do
66+
let expected = expectedLines.[i].Trim()
67+
let actual = actualLines.[i].Trim()
68+
if expected <> actual then
69+
errors.Add(sprintf "\n==\nName: %s\n\nExpected:\t %s\nActual:\t\t %s\n==" actualLines.[0] expected actual)
70+
71+
if errors.Count > 0 then
72+
let msg = String.concat "\n" errors + "\n\n\n==EXPECTED==\n" + ilCode + "\n"
73+
errorMsgOpt <- Some(msg + "\n\n\n==ACTUAL==\n" + String.Join("\n", actualLines, 0, expectedLines.Length))
74+
)
75+
76+
if expectedIL.Length = 0 then
77+
errorMsgOpt <- Some ("No Expected IL")
78+
79+
match errorMsgOpt with
80+
| Some(msg) -> errorMsgOpt <- Some(msg + "\n\n\n==ENTIRE ACTUAL==\n" + textNoComments)
81+
| _ -> ()
82+
finally
83+
try File.Delete(ilFilePath) with | _ -> ()
84+
85+
match errorMsgOpt with
86+
| Some(errorMsg) ->
87+
Assert.Fail(errorMsg)
88+
| _ -> ()
89+
90+
let checkILItem item dllFilePath expectedIL =
91+
checkILAux [ sprintf "/item:%s" item ] dllFilePath expectedIL
92+
93+
let checkILItemWithLineNumbers item dllFilePath expectedIL =
94+
checkILAux [ sprintf "/item:\"%s\"" item; "/linenum" ] dllFilePath expectedIL
95+
96+
let checkIL dllFilePath expectedIL =
97+
checkILAux [] dllFilePath expectedIL

0 commit comments

Comments
 (0)