Uh oh!
There was an error while loading. Please reload this page.
Fix for #83 (improve constraint error message) - #16304
Conversation
This includes - An addition of field "source" to TraitConstraintInfo / TTrait in TypedTree.fs/fsi - Code in CompilerImports.fs which, after import, adds the sources to all constraints - New error messages, including the constraint source, in ConstraintSolver.fs - The error messages in FSComp.txt - A new test in MemberConstraints.fs - 29 adaptations b.o. the new field in TTrait in 9 files
Martin521
commented
Nov 19, 2023
/run xlf |
Co-authored-by: Martin521 <29605222+Martin521@users.noreply.github.com>
psfinaki
commented
Nov 20, 2023
Hey @Martin521 - thanks for taking this long-standing issue! :) I know there is a discussion in the related ticket - my opinion is that whatever we do will be better than the current situation. That said, for me even having I see that the message in FSComp is generic for types and operators so for now I would appreciate just adding a few more test cases that are expected to produce the same error, so that we can see a bigger picture. |
Martin521
commented
Nov 20, 2023
@psfinaki - thanks for your feedback!
I will do that. I will also respond (tomorrow) to your other remarks, but in the ticket. |
smoothdeveloper
commented
Nov 20, 2023
AFAIU, this would require infrastructure for API authors, and adjusting FSharp.Core to use it; the infrastructure would allow to give customized error message on members with constraints, given predicate on the passed / infered type arguments, to deliver a custom message. IMO, this is out of scope in just trying to improve the constraint not matching error, which should, unless the infrastructure & special condition that it would detect in API, always be displayed, in order to give the full picture. |
vzarytovskii
commented
Nov 20, 2023
I personally disagree with that. It doesn't have to be either/or. It should be both - a simple message as well as bunch of details. We don't need to simplify messages in sake of simplifying them. But rather extend them. @DedSec256 and @auduchinok may have some opinions here. |
psfinaki
commented
Nov 20, 2023
No yeah for sure we shouldn't overhaul the compiler just in order to make this usecase clear.
... is definitely a valid approach. |
Martin521
commented
Nov 21, 2023
Thanks @psfinaki for asking for more examples and the broader picture. This made me realize that the picture is broader indeed. I will continue with implementation (including test cases) once the discussion on the ticket is converging. |
since the second error it is introducing is not related to methods on enums and is difficult to verify.
Martin521
commented
Dec 12, 2023
This is ready. Also note that the extended error message only appears when the constraint source (the operator or method or function that has the constraint typar) is imported. Doing the same while that source is in your own project is more difficult, but also deemed to be not needed, because both the language guide and the spec say that creating member constraints is "not intended for common use". |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Martin521
commented
Dec 18, 2023
/azp run |
|
Commenter does not have sufficient privileges for PR 16304 in repo dotnet/fsharp |
T-Gro
commented
Dec 19, 2023
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
vzarytovskii
commented
Dec 20, 2023
Thanks, let's see how it looks in IDEs, and get feedback from people. |
`addConstraintSources` (added in dotnet#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 <noreply@anthropic.com>
…sources (#20090) * 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.
This fix for #83 includes