Skip to content

Pass only narrow terminal-identifier range from name resolution#19818

Open
T-Gro wants to merge 2 commits into
mainfrom
narrow-range-only
Open

Pass only narrow terminal-identifier range from name resolution#19818
T-Gro wants to merge 2 commits into
mainfrom
narrow-range-only

Conversation

@T-Gro
Copy link
Copy Markdown
Member

@T-Gro T-Gro commented May 26, 2026

Follow-up to #19505 per review feedback.

Removes the wide module-qualified range from resolved-item returns. Only the narrow terminal-identifier range flows through the type-checking pipeline.

What changes for users: Error/warning squiggles now point at the member name rather than the full qualified path. Example:

let rt1 = Task.Run(fun () -> task)
//        ~~~~~~~~~~~~~~~~~~~~~~~~  Before: FS0041 on entire expression
//             ~~~                  After:  FS0041 on just `Run`

A unique overload for method 'Run' could not be determined based on type information prior to this program point.

What doesn't change: IDE hover, go-to-definition, find-all-references — these use ranges from NameResolution sinks which still receive the wide range internally. No impact on IL emission or binary compatibility (all changed APIs are internal).


Baseline impact

74 ranges changed across 26 test files

  • All strictly narrower — start column shifts right, end column unchanged
  • All point to terminal identifier — no overshoot into whitespace or arguments
  • Dropped prefix categories:
    • Module: 33
      • Operators., NativePtr., Seq., M., Option., …
    • Type: 14
      • Color., Class., ILookup., NullableClass., ITest., …
    • Namespace.Type: 16
      • System.Int32., System.String., NativeInterop.NativePtr., …
    • Variable/instance: 8
      • raio., r1., c., a., bc., …
    • Other: 3
      • this.: 1
      • _. (dot-lambda): 1
      • (new Foo()).: 1
  • Affected features:
    • Diagnostics (errors/warnings): 72
      • All standard compiler error/warning baselines
    • PDB sequence points: 1
      • Debugger highlights CurrentDirectory instead of Environment.CurrentDirectory
    • Quotation DebugRange: 1
      • Informational metadata — consumers use line numbers, not columns

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 26, 2026

⚠️ Release notes required, but author opted out

Warning

Author opted out of release notes, check is disabled for this pull request.
cc @dotnet/fsharp-team-msft

@github-actions github-actions Bot added the AI-Tooling-Check-Bypassed Tooling check: non-fork PR, not diff-analyzed label May 26, 2026
@T-Gro T-Gro force-pushed the narrow-range-only branch from 45a6bcf to 37c3c9e Compare May 27, 2026 10:24
@T-Gro T-Gro requested a review from abonie May 27, 2026 13:28
@T-Gro T-Gro force-pushed the narrow-range-only branch 2 times, most recently from 45a6bcf to 4f5da6f Compare May 28, 2026 08:45
@T-Gro T-Gro requested a review from auduchinok May 28, 2026 12:44
@T-Gro T-Gro added the NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes label May 28, 2026
@T-Gro
Copy link
Copy Markdown
Member Author

T-Gro commented May 28, 2026

(this adds on a recent PR, release notes were part of it already)

let resolvesAsExpr =
match nameResolutionResult with
| Result (tinstEnclosing, item, mItem, mItemIdent, rest, afterRes)
| Result (tinstEnclosing, item, mItem, rest, afterRes)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this be reverted to pre-#19505, so we don't reconstruct res argument below?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yes 👍

let ad = env.eAccessRights
let typeNameResInfo = GetLongIdentTypeNameInfo delayed
let (tinstEnclosing, item, mItem, mItemIdent, rest, afterResolution) =
let (tinstEnclosing, item, mItem, rest, afterResolution) =
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this be reverted to pre-#19505?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yes 👍

Comment on lines 10500 to 10505
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we remove this error post-processing?

match ResolveExprLongIdent sink ncenv wholem ad nenv typeNameResInfo lid maybeAppliedArgExpr with
| Exception e -> Exception e
| Result (tinstEnclosing, item1, rest) ->
let itemRange, itemIdentRange = ComputeItemRange wholem lid rest
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can ComputeItemRange return the single range, as in pre-#19505?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

They are both needed - the other goes into sink(s) for IDE functions.

@auduchinok
Copy link
Copy Markdown
Member

auduchinok commented May 28, 2026

PDB sequence points: 1
Debugger highlights CurrentDirectory instead of Environment.CurrentDirectory

This is unexpected change and adds inconsistency with the breakpoints that tooling uses. We should try to keep the debugger info as is here. I think sequence points should use the whole expression ranges? Or do they rely on typed tree ranges that are now narrowed down?

Simplifies the type-checking pipeline by removing the wide (module-qualified)
range from resolved-item returns. Only the narrow terminal-identifier range
flows through TcItemThen and downstream functions.

Affected features: error/warning squiggles now point at the member name
(e.g. 'Member') rather than the full qualified path ('Module.Member').
IDE hover, go-to-definition, and find-all-references use the narrow range
from NameResolution sinks (unchanged). No impact on IL emission or
binary compatibility — all changed APIs are internal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@T-Gro T-Gro force-pushed the narrow-range-only branch from 4f5da6f to e779dee Compare May 28, 2026 13:22
@T-Gro
Copy link
Copy Markdown
Member Author

T-Gro commented May 28, 2026

@auduchinok : It comes from the range on Expr node in TypedTree.
And then it makes its way into EmitDebugPoint from it.

When stepping, why do you think it's wrong to highlight only the narrow item? Or is there another concern?

@auduchinok
Copy link
Copy Markdown
Member

When stepping, why do you think it's wrong to highlight only the narrow item? Or is there another concern?

The debugger sequence points normally cover the whole "statements" that include complete calls, arguments, and so on. Narrowing it here would create inconsistency in debugger experience. It would also be inconsistent with breakpoint ranges we provide in the tooling.

@auduchinok : It comes from the range on Expr node in TypedTree.

A guess: could it be because mItem was used somewhere instead of mWhole when creating Expr? Previously these range two could be the same and now mItem is narrower.

@T-Gro
Copy link
Copy Markdown
Member Author

T-Gro commented May 28, 2026

The narrowing only strips module/namespace/type prefixes from the sequence point:

  • System.Environment.CurrentDirectory → debug highlight on just CurrentDirectory
  • Option.None → just None
  • MyModule.myValue → just myValue

But System.Console.WriteLine("hello") still gets a sequence point covering the entire call including "hello", because mWholeExpr unions the method range with the argument ranges.

So I think OK?

Revert to pre-#19505 patterns: use '_ as res' in TcNameOfExpr and
pass-through binding in TcLongIdentThen instead of destructuring
and reconstructing the 5-tuple.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@auduchinok
Copy link
Copy Markdown
Member

auduchinok commented May 28, 2026

I really think we should not change sequence point ranges. I think we have to stay consistent with the rest of the language and C# and other languages debugging experience. Unfortunately, it seems we have to pass the two ranges to places like TcItemThen to use them in the typed tree expressions, after all.

@auduchinok
Copy link
Copy Markdown
Member

I also think we should keep the typed tree ranges closer to the syntax tree, so if some IDE feature work with this tree, they could also rely on these ranges. And we've been working hard on making syntax tree ranges correct 🙂

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

Labels

AI-Tooling-Check-Bypassed Tooling check: non-fork PR, not diff-analyzed NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

2 participants