Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinRansom committed Dec 14, 2023
1 parent b846403 commit 9d9993b
Show file tree
Hide file tree
Showing 21 changed files with 141 additions and 10 deletions.
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/8.0.200.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* Miscellaneous fixes to parentheses analysis. ([PR #16262](https://github.com/dotnet/fsharp/pull/16262), [PR #16391](https://github.com/dotnet/fsharp/pull/16391), [PR #16370](https://github.com/dotnet/fsharp/pull/16370), [PR #16395](https://github.com/dotnet/fsharp/pull/16395))
* Correctly handle assembly imports with public key token of 0 length. ([Issue #16359](https://github.com/dotnet/fsharp/issues/16359), [PR #16363](https://github.com/dotnet/fsharp/pull/16363))
* Fix #16398 - The dotnet framework has a limit of ~64K methods in a single class. Introduce a compile-time error if any class has over approx 64K methods in generated IL

### Added
* Raise a new error when interfaces with auto properties are implemented on constructor-less types. ([PR #16352](https://github.com/dotnet/fsharp/pull/16352))
Expand Down
20 changes: 17 additions & 3 deletions src/Compiler/AbstractIL/ilwrite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ let emitBytesViaBuffer f = use bb = ByteBuffer.Create EmitBytesViaBufferCapacity
/// Alignment and padding
let align alignment n = ((n + alignment - 1) / alignment) * alignment


/// Maximum number of methods in a dotnet type
/// This differs from the spec and file formats slightly which suggests 0xfffe is the maximum
/// this value was identified empirically.
[<Literal>]
let maximumMethodsPerDotNetType = 0xfff0

//---------------------------------------------------------------------
// Concrete token representations etc. used in PE files
//---------------------------------------------------------------------
Expand Down Expand Up @@ -672,8 +679,14 @@ let GetTypeNameAsElemPair cenv n =
//=====================================================================

let rec GenTypeDefPass1 enc cenv (tdef: ILTypeDef) =
ignore (cenv.typeDefs.AddUniqueEntry "type index" (fun (TdKey (_, n)) -> n) (TdKey (enc, tdef.Name)))
GenTypeDefsPass1 (enc@[tdef.Name]) cenv (tdef.NestedTypes.AsList())
ignore (cenv.typeDefs.AddUniqueEntry "type index" (fun (TdKey (_, n)) -> n) (TdKey (enc, tdef.Name)))

// Verify that the typedef contains fewer than maximumMethodsPerDotNetType
let count = tdef.Methods.AsArray().Length
if count > maximumMethodsPerDotNetType then
errorR(Error(FSComp.SR.tooManyMethodsInDotNetTypeWritingAssembly (tdef.Name, count, maximumMethodsPerDotNetType), rangeStartup))

GenTypeDefsPass1 (enc@[tdef.Name]) cenv (tdef.NestedTypes.AsList())

and GenTypeDefsPass1 enc cenv tdefs = List.iter (GenTypeDefPass1 enc cenv) tdefs

Expand All @@ -682,7 +695,8 @@ and GenTypeDefsPass1 enc cenv tdefs = List.iter (GenTypeDefPass1 enc cenv) tdefs
//=====================================================================

let rec GetIdxForTypeDef cenv key =
try cenv.typeDefs.GetTableEntry key
try
cenv.typeDefs.GetTableEntry key
with
:? KeyNotFoundException ->
let (TdKey (enc, n) ) = key
Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1738,4 +1738,5 @@ featureReuseSameFieldsInStructUnions,"Share underlying fields in a [<Struct>] di
3860,chkStaticMembersOnObjectExpressions,"Object expressions cannot implement interfaces with static abstract members or declare static members."
3861,chkTailCallAttrOnNonRec,"The TailCall attribute should only be applied to recursive functions."
3862,parsStaticMemberImcompleteSyntax,"Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration."
3863,parsExpectingField,"Expecting record field"
3863,parsExpectingField,"Expecting record field"
3864,tooManyMethodsInDotNetTypeWritingAssembly,"The type '%s' has too many methods. Found: '%d', maximum: '%d'"
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions tests/FSharp.Compiler.ComponentTests/EmittedIL/VeryLargeClasses.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace EmittedIL

open Microsoft.FSharp.Core
open Xunit
open FSharp.Test.Compiler

module VeryLargeClasses =

let classWithManyMethods n =
let methods =
let mutable source = ""
for i = 0 to n - 1 do
source <- source + $"""
static member Method%05x{i}() = () """
source

FSharp
$"""
namespace VeryLargeClassesTestcases

type Type1 ={methods}
"""

[<Fact>]
let ``More than 64K Methods -- should fail`` () =
classWithManyMethods (1024 * 64 + 1)
|> compile
|> shouldFail
|> withDiagnostics [
(Error 3864, Line 1, Col 1, Line 1, Col 1, "The type 'VeryLargeClassesTestcases.Type1' has too many methods. Found: '65537', maximum: '65520'")
]

[<Fact>]
let ``Exactly (0xfff0) Methods -- should succeed`` () =
FSharp
"""
module MyMain
open System
open System.Reflection
do printfn $"location: {typeof<VeryLargeClassesTestcases.Type1>.Assembly.Location}"
let asm = Assembly.LoadFrom(typeof<VeryLargeClassesTestcases.Type1>.Assembly.Location)
printfn $"asm: {asm}"
let types = asm.GetTypes()
printfn "length: {types.Length}"
"""
|> withReferences [ classWithManyMethods 0xfff0 |> asLibrary ]
|> asExe
|> compileAndRun
|> shouldSucceed

Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
<Compile Include="Conformance\UnitsOfMeasure\Parsing.fs" />
<Compile Include="Conformance\UnitsOfMeasure\TypeChecker.fs" />
<Compile Include="EmittedIL\CompilerGeneratedAttributeOnAccessors.fs" />
<Compile Include="EmittedIL\VeryLargeClasses.fs" />
<Compile Include="EmittedIL\EmptyArray.fs" />
<Compile Include="EmittedIL\Enums.fs" />
<Compile Include="EmittedIL\Literals.fs" />
Expand Down
2 changes: 1 addition & 1 deletion tests/FSharp.Test.Utilities/CompilerAssert.fs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ module rec CompilerAssertHelpers =
let name =
match nameOpt with
| Some name -> name
| _ -> tryCreateTemporaryFileName()
| _ -> tryCreateTemporaryFileNameInDirectory(outputDirectory)

let outputFilePath = Path.ChangeExtension (Path.Combine(outputDirectory.FullName, name), if isExe then ".exe" else ".dll")
disposals.Add(disposeFile outputFilePath)
Expand Down
5 changes: 2 additions & 3 deletions tests/FSharp.Test.Utilities/TestFramework.fs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ let tryCreateTemporaryFileName () =
filePath

// Create a temporaryFileName -- newGuid is random --- there is no point validating the file alread exists because: threading and Path.ChangeExtension() is commonly used after this API
let tryCreateTemporaryFileNameInDirectory (directory) =
let tryCreateTemporaryFileNameInDirectory (directory: DirectoryInfo) =
let fileName = ("Temp-" + Guid.NewGuid().ToString() + ".tmp").Replace('-', '_')
let filePath = Path.Combine(directory, fileName)
let filePath = Path.Combine(directory.FullName, fileName)
filePath


[<RequireQualifiedAccess>]
module Commands =

Expand Down
4 changes: 2 additions & 2 deletions tests/service/ScriptOptionsTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ let ``can generate options for different frameworks regardless of execution envi
[<TestCase([| "--targetprofile:netstandard" |])>]
[<Test>]
let ``can resolve nuget packages to right target framework for different frameworks regardless of execution environment``(flags) =
let path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
let path = DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location))
let file = tryCreateTemporaryFileNameInDirectory(path) + ".fsx"
let scriptFullPath = Path.Combine(path, file)
let scriptFullPath = Path.Combine(path.FullName, file)
let scriptSource = """
#r "nuget: FSharp.Data, 3.3.3"
open System
Expand Down

0 comments on commit 9d9993b

Please sign in to comment.