Open
Conversation
Contributor
✅ No release notes required |
103245e to
6a5aab8
Compare
…nature Filter out compiler-generated vals with '@' in their LogicalName from inferred signature printing. In 'module rec' contexts, 'do ()' bindings are compiled as TMDefRec with vals named like 'doval@3' that leaked into generated signatures. Fixes #13832 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When generating signatures, attribute arguments that reference [<Literal>]
values now preserve the literal identifier name instead of showing the
evaluated constant value. For example, [<Category(A)>] is preserved
instead of being reduced to [<Category("A")>].
The fix works by recovering literal val references from the syntax tree
during attribute checking: TcVal inlines literals to Expr.Const, but we
now look up the original identifier in the name resolution environment
and store Expr.Val as the source expression in AttribExpr. The Expr.Val
case is then handled in layoutAttribArg in NicePrint.fs to display the
literal name.
Fixes #13810
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When generating signatures for struct types whose fields prevent comparison/equality augmentation (e.g., fields of type obj), the generated signature now includes [<NoComparison>] and [<NoEquality>] attributes. Without these, the signature fails to compile with FS0293. The fix detects when a struct type is a candidate for comparison/equality augmentation but augmentation was not generated (GeneratedCompareToValues or GeneratedHashAndEqualsValues is None), and injects synthetic attributes into the signature output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Change single-backtick checks to double-backtick checks so identifiers containing backticks in their names get properly escaped with `` `` `` delimiters during signature generation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tures (#15560) Move layoutAccessibility call after layoutTyparDecls so that 'private' is placed before the entire ''a P' construct rather than between the type parameter and name (producing 'type 'a private P' instead of the correct 'type private 'a P'). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…le constructors When generating signatures for class types whose constructors are not visible (e.g., private constructors), the [<Class>] attribute was not emitted. This caused the generated signatures to fail compilation with error FS0938 because the compiler cannot infer that the type is a class from the signature alone. The fix: 1. Always set start=Some "class" for class types regardless of printVerboseSignatures setting (was gated behind it before) 2. Suppress [<Class>] when allDecls is empty since the repr layout already produces 'class end' for empty classes 3. Remove commented-out conditions that were never active Fixes #16531 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Test multiple literal args in tuple attribute position (names recovered) - Test qualified literal reference limitation (shows constant value) - Add CompilerCompat test: type with literal-based attribute arg exercises Expr.Val in AttribExpr.source pickling across compiler versions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Struct with explicit [<NoComparison>] does not get duplicate attribute - Struct with [<CustomComparison>] does not get [<NoComparison>] injected - Empty class with private constructor uses 'class end' repr - AbstractClass with private constructor roundtrips correctly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Only replace Expr.Const with Expr.Val in AttribExpr.source when the literal val reference is local (VRefLocal). Cross-assembly literals (VRefNonLocal from 'open ExternalLib') keep Expr.Const to avoid creating unresolvable transitive assembly dependencies in pickled metadata — consumers of the DLL may not reference the external assembly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The literal name recovery stores Expr.Val in AttribExpr.source as an in-memory optimization for signature generation display. However, this must NOT change the pickle format: - Old compilers reading Expr.Val in AttribExpr.source would display '(* unsupported attribute argument *)' instead of the constant value in tooltips and signatures — a cross-version display regression. - Old compilers' CheckDeclarations.fs pattern-matches on the source field and would miss the AssemblyVersion format warning. By normalizing Expr.Val(literal_vref) back to Expr.Const(literal_value) before pickling, the on-disk format is identical to before this PR. The literal name display only works during the current compilation (the signature generation use case), which is the correct scope. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two fixes from adversarial cross-model review:
1. Add SynExpr.App traversal to literal ident collector so named
attribute arguments like [<Attr(Name = MyLiteral)>] also get
literal name recovery. Previously only positional args worked.
2. Replace IsCompilerGeneratedName (any '@' in name) with targeted
StartsWithOrdinal("doval@") in filterVal. The broad '@' check
would incorrectly drop backtick-escaped user identifiers containing
'@' from module rec signatures. The doval@ prefix is the only
compiler-generated name pattern that leaks through TMDefRec bindings,
matching the same pattern used in SignatureHash.fs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The PR unconditionally set start=Some "class" for class types, causing [<Class>] to appear in FSI output. Gate on denv.showAttributes instead of the removed printVerboseSignatures check: - FSI (showAttributes=false): no [<Class>] emitted (matches old behavior) - GenerateSignature (showAttributes=true): [<Class>] emitted when needed - --sig flag (showAttributes=true): [<Class>] emitted when needed Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes 6 signature generation bugs in
FSharpCheckFileResults.GenerateSignature. All fixes ensure generated signatures roundtrip-compile with their implementations.Fixes
dobinding leaking compiler-generated val in signature[<NoComparison>]/[<NoEquality>]attributesprivatekeyword misplaced in prefix-style type abbreviation signatures[<Class>]attribute for types without visible constructorsDesign notes
Literal attribute arg recovery:
TcValinlines literal vals toExpr.Const, losing the original identifier. The fix recovers literalValReffrom the syntax tree via range matching and stores it asExpr.ValinAttribExpr.sourcefor display. This is an in-memory-only optimization —p_attrib_exprnormalizes back toExpr.Constbefore pickling, so the on-disk format is unchanged.Struct NoComparison/NoEquality: When a struct type's fields prevent comparison/equality augmentation, synthetic attributes are injected in the display layer (NicePrint) only.
[] emission: The
printVerboseSignaturesgate was removed; class kind is now always tracked. TheneedsStartEndheuristic determines whether[<Class>]orclass...endis needed based on visible constructors, fields, and members.Binary compatibility
Zero cross-version regression. The pickle normalization in
p_attrib_exprensures that DLLs compiled with this change produce identical metadata to before. Old compilers reading new DLLs seeExpr.Constin all positions — no behavioral change.