From e991f3a00a8c24754bfadae7465dce80790af4d3 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 28 Jul 2026 17:04:56 +0200 Subject: [PATCH] Don't walk non-F# assemblies when labelling trait constraint sources `addConstraintSources` (added in #16304, so that a failed member constraint names the member it came from) is applied to every imported assembly, and recurses through `e.ModuleOrNamespaceType` for every module and namespace entity it finds. For an assembly imported from IL there is nothing to find: the walk only reads `AllValsAndMembers`, and `ImportILTypeDefs` gives every namespace and type entity an empty val list; only an F# trait constraint produces a `TyparConstraint.MayResolveMember` to label in the first place. Meanwhile the recursion forces each namespace entity's `ModuleOrNamespaceType`, which imports that namespace - so referencing an assembly ends up importing every namespace in it, and reading every type definition, whether or not the code touches it. Skip the CCUs that aren't F#. FSharp.Core and F# references are still walked, so the error messages are unchanged. Measured with FSharpChecker.ParseAndCheckProject, keeping the results alive so the imported assembly structures stay on the heap (averages of 3 runs, one per process): a 486-reference F# project retains 1319.2 -> 952.1 MB (-27.8%), and a 168-reference console project 77.7 -> 69.8 MB (-10.2%). Checking FSharp.Compiler.Service itself (124 references, 397 sources) goes 2301.7 -> 2298.0 MB, i.e. within the noise at that size - what the imports cost there is dwarfed by the trees of the project's own code. Co-Authored-By: Claude Opus 5 --- src/Compiler/Driver/CompilerImports.fs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs index f0868919ad0..46a3b83b604 100644 --- a/src/Compiler/Driver/CompilerImports.fs +++ b/src/Compiler/Driver/CompilerImports.fs @@ -2341,6 +2341,12 @@ and [] TcImports let! ccuinfos = phase2s |> runMethod if importsBase.IsSome then + let addConstraintSources (ia: ImportedAssembly) = + // Only an F# assembly can carry a trait constraint to label. + // Prevent force-reading of the whole assembly namespace tree for other assemblies. + if ia.FSharpViewOfMetadata.IsFSharp then + addConstraintSources ia + importsBase.Value.CcuTable.Values |> Seq.iter addConstraintSources ccuTable.Values |> Seq.iter addConstraintSources