Skip to content

Show the actual type of RHS on type error when LHS is a pattern with a type annotation#19284

Open
travv0 wants to merge 3 commits intodotnet:mainfrom
travv0:wrong-type-reported-when-annotation-doesnt-match-pattern
Open

Show the actual type of RHS on type error when LHS is a pattern with a type annotation#19284
travv0 wants to merge 3 commits intodotnet:mainfrom
travv0:wrong-type-reported-when-annotation-doesnt-match-pattern

Conversation

@travv0
Copy link
Contributor

@travv0 travv0 commented Feb 12, 2026

Description

Previously, when a pattern on the LHS had a type annotation that didn't match the binding's type, a type error would report the annotation type as the type of the RHS. This PR separates it into two steps, so the binding type is checked against the annotation type, and then the RHS's type is checked against the binding's type. (Hopefully I worded this okay, I'm new to typechecking stuff.)

Fixes #18849

Checklist

  • Test cases added

  • Release notes entry updated:

    Please make sure to add an entry with short succinct description of the change as well as link to this pull request to the respective release notes file, if applicable.

    Release notes files:

    • If anything under src/Compiler has been changed, please make sure to make an entry in docs/release-notes/.FSharp.Compiler.Service/<version>.md, where <version> is usually "highest" one, e.g. 42.8.200
    • If language feature was added (i.e. LanguageFeatures.fsi was changed), please add it to docs/release-notes/.Language/preview.md
    • If a change to FSharp.Core was made, please make sure to edit docs/release-notes/.FSharp.Core/<version>.md where version is "highest" one, e.g. 8.0.200.

    Information about the release notes entries format can be found in the documentation.
    Example:

    If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

@github-actions
Copy link
Contributor

❗ Release notes required

@travv0,

Caution

No release notes found for the changed paths (see table below).

Please make sure to add an entry with an informative description of the change as well as link to this pull request, issue and language suggestion if applicable. Release notes for this repository are based on Keep A Changelog format.

The following format is recommended for this repository:

* <Informative description>. ([PR #XXXXX](https://github.com/dotnet/fsharp/pull/XXXXX))

See examples in the files, listed in the table below or in th full documentation at https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html.

If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

You can open this PR in browser to add release notes: open in github.dev

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/10.0.300.md No release notes found or release notes format is not correct

Comment on lines +11160 to +11165
| Some (SynBindingReturnInfo(typeName = retInfoTy; range = mRetTy)), SynExpr.Typed(innerExpr, _, _) when spatsL.IsEmpty ->
let retTy, _ = TcTypeAndRecover cenv NewTyparsOK CheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes envinner tpenv retInfoTy
try UnifyTypes cenv envinner pat.Range retTy overallExprTy
with RecoverableException exn -> errorRecovery exn mRetTy
innerExpr
| _ ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider

let a: T = b

If I understand it correctly, during the analysis the compiler rewrites it to

let a = (b: T)

T may be a partially annotated type, e.g. _ list in the source, and then it can be inferred to something like int list after the type checking of the b expression. Can we propagate this inferred type here instead of type checking T from scratch? Would there be downsides?

Copy link
Contributor Author

@travv0 travv0 Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if I'm misunderstanding what you're saying here, but the problem this addresses is that when it's rewritten to let a = (b: T), if a is a pattern and b doesn't typecheck, it reports the annotated type of a as the type of b instead of the actual type of b (in the specific scenario where the type annotation doesn't fit the pattern).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

A wrong type is reported in a type mismatch error

2 participants