Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace EmittedIL

open Xunit
open FSharp.Test
open FSharp.Test.Compiler
open FSharp.Test.Utilities

module CodeGenRegressions_Observations =
// https://github.com/dotnet/fsharp/issues/13100
[<Fact>]
let ``Issue_13100_PlatformCharacteristic`` () =
let source = """
module PlatformTest

[<EntryPoint>]
let main _ = 0
"""
FSharp source
|> asExe
|> withPlatform ExecutionPlatform.X64
|> compile
|> shouldSucceed
|> withPeReader (fun rdr ->
let characteristics = rdr.PEHeaders.CoffHeader.Characteristics
if not (characteristics.HasFlag(System.Reflection.PortableExecutable.Characteristics.LargeAddressAware)) then
failwith $"x64 binary should have LargeAddressAware flag. Found: {characteristics}"
if characteristics.HasFlag(System.Reflection.PortableExecutable.Characteristics.Bit32Machine) then
failwith $"x64 binary should NOT have Bit32Machine flag. Found: {characteristics}")
|> ignore


// https://github.com/dotnet/fsharp/issues/11935
[<Fact>]
let ``Issue_11935_UnmanagedConstraintInterop`` () =
let source = """
module Test

let test<'T when 'T : unmanaged> (x: 'T) = x
"""
FSharp source
|> asLibrary
|> withLangVersion10
|> compile
|> shouldSucceed
|> verifyILContains [
".method public static !!T test<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>(!!T x) cil managed"
]
|> shouldSucceed


[<Fact>]
let ``Issue_11935_UnmanagedConstraintInterop_ClassType`` () =
let source = """
module Test

type Container<'T when 'T : unmanaged>() =
member _.GetDefault() : 'T = Unchecked.defaultof<'T>
"""
FSharp source
|> asLibrary
|> withLangVersion10
|> compile
|> shouldSucceed
|> verifyILContains [
"Container`1<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>"
]
|> shouldSucceed


[<Fact>]
let ``Issue_11935_UnmanagedConstraintInterop_StructType`` () =
let source = """
module Test

[<Struct>]
type StructContainer<'T when 'T : unmanaged> =
val Value : 'T
new(v) = { Value = v }
"""
FSharp source
|> asLibrary
|> withLangVersion10
|> compile
|> shouldSucceed
|> verifyILContains [
"StructContainer`1<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>"
]
|> shouldSucceed


[<Fact>]
let ``Issue_11935_UnmanagedConstraintInterop_InstanceMethod`` () =
let source = """
module Test

type Processor() =
member _.Process<'T when 'T : unmanaged>(x: 'T) = x
"""
FSharp source
|> asLibrary
|> withLangVersion10
|> compile
|> shouldSucceed
|> verifyILContains [
".method public hidebysig instance !!T Process<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T>(!!T x) cil managed"
]
|> shouldSucceed


[<Fact>]
let ``Issue_11935_UnmanagedConstraintInterop_MultipleTypeParams`` () =
let source = """
module Test

let combine<'T, 'U when 'T : unmanaged and 'U : unmanaged> (x: 'T) (y: 'U) = struct(x, y)
"""
FSharp source
|> asLibrary
|> withLangVersion10
|> compile
|> shouldSucceed
|> verifyILContains [
"combine<valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) T,valuetype (class [runtime]System.ValueType modreq([runtime]System.Runtime.InteropServices.UnmanagedType)) U>(!!T x, !!U y) cil managed"
]
|> shouldSucceed


// https://github.com/dotnet/fsharp/issues/7861
[<Fact>]
let ``Issue_7861_AttributeTypeReference`` () =
let source = """
module Test

open System

type TypedAttribute(t: Type) =
inherit Attribute()
member _.TargetType = t

[<Typed(typeof<System.Xml.XmlDocument>)>]
type MyClass() = class end
"""
FSharp source
|> asLibrary
|> compile
|> shouldSucceed
|> verifyAssemblyReference "System.Xml"
|> ignore


[<Fact>]
let ``Issue_7861_NamedAttributeArgument`` () =
let source = """
module Test

open System

type TypePropertyAttribute() =
inherit Attribute()
member val TargetType : Type = null with get, set

[<TypeProperty(TargetType = typeof<System.Xml.XmlDocument>)>]
type MyClass() = class end
"""
FSharp source
|> asLibrary
|> compile
|> shouldSucceed
|> verifyAssemblyReference "System.Xml"
|> ignore


[<Fact>]
let ``Issue_7861_AttributeOnMethod`` () =
let source = """
module Test

open System

type TypedAttribute(t: Type) =
inherit Attribute()
member _.TargetType = t

type MyClass() =
[<Typed(typeof<System.Xml.XmlDocument>)>]
member _.MyMethod() = ()
"""
FSharp source
|> asLibrary
|> compile
|> shouldSucceed
|> verifyAssemblyReference "System.Xml"
|> ignore
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
<Compile Include="EmittedIL\TryCatch\TryCatch.fs" />
<Compile Include="EmittedIL\Nullness\NullnessMetadata.fs" />
<Compile Include="EmittedIL\FixedBindings\FixedBindings.fs" />
<Compile Include="EmittedIL\CodeGenRegressions\CodeGenRegressions_Observations.fs" />
<Compile Include="ErrorMessages\TypedInterpolatedStringsTests.fs" />
<!--<Compile Include="EmittedIL\StructDefensiveCopy\StructDefensiveCopy.fs" />-->
<Compile Include="ErrorMessages\UnsupportedAttributes.fs" />
Expand Down
22 changes: 22 additions & 0 deletions tests/FSharp.Test.Utilities/Compiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,28 @@ Actual:

let verifyILNotPresent = doILCheck ILChecker.checkILNotPresent

/// Verifies that the compiled assembly contains an assembly reference whose name starts with the given prefix.
let verifyAssemblyReference (prefix: string) (result: CompilationResult) : CompilationResult =
match result with
| CompilationResult.Success s ->
match s.OutputPath with
| None -> failwith "Operation didn't produce any output!"
| Some p ->
let bytes = File.ReadAllBytes(p)
use peReader = new PEReader(bytes.ToImmutableArray())
let mdReader = peReader.GetMetadataReader()
let refs =
[ for h in mdReader.AssemblyReferences do
mdReader.GetString(mdReader.GetAssemblyReference(h).Name) ]
if refs |> List.exists (fun name -> name.StartsWith(prefix, StringComparison.Ordinal)) then
result
else
failwith $"Expected assembly reference starting with '{prefix}'. Found: %A{refs}"
| CompilationResult.Failure f ->
printfn "Failure:"
printfn $"{f}"
failwith "Result should be \"Success\" in order to verify assembly references."

let verifyILBinary (il: string list) (dll: string)= ILChecker.checkIL dll il

let private verifyFSILBaseline (baseline: Baseline) (result: CompilationOutput) : unit =
Expand Down
Loading