Skip to content

[TSP] Return contextual expected type from getExpectedType#3672

Closed
rchiodo wants to merge 2 commits into
facebook:mainfrom
rchiodo:rchiodo/typeDictsTsp
Closed

[TSP] Return contextual expected type from getExpectedType#3672
rchiodo wants to merge 2 commits into
facebook:mainfrom
rchiodo:rchiodo/typeDictsTsp

Conversation

@rchiodo
Copy link
Copy Markdown
Contributor

@rchiodo rchiodo commented Jun 3, 2026

Summary

typeServer/getExpectedType was returning the inferred (computed) type at the cursor instead of the contextually expected type that the position imposes. For example, in x: int | str = 4, querying on 4 returned int rather than int | str.

This change makes get_expected_type_at_position walk the covering AST nodes innermost-first and, when the cursor lies in a context that supplies an expected type, look up that contextual type. Recognized contexts:

  • Call argument (positional or keyword) — uses the parameter type declared by the callee, via Transaction::expected_call_argument_type (now pub(crate) so the non-WASM server can call it).
  • return <expr> — uses the enclosing function's return annotation (resolved via get_type_trace over the annotation's full range so unions like int | str are preserved instead of collapsing to the leading identifier).
  • Parameter default def f(x: T = <expr>) — uses the parameter's annotation T.
  • Annotated assignment RHS x: T = <expr> — uses the LHS declared type T.

Other contexts (yield expressions, container-literal elements under an annotation, etc.) still fall back to the inferred type at the cursor; tests document that behavior so future fixes can flip the expectations.

Fixes microsoft/pylance-release#8060

Test Plan

Added 8 new tests in pyrefly/lib/test/tsp/tsp_interaction/get_type_queries.rs covering each newly supported context plus the documented fallbacks:

  • test_get_expected_type_call_positional_argument
  • test_get_expected_type_call_keyword_argument
  • test_get_expected_type_return_statement_value
  • test_get_expected_type_default_parameter_value
  • test_get_expected_type_yield_falls_back_to_value_type
  • test_get_expected_type_list_element_falls_back_to_container_type
  • test_get_expected_type_dict_value_falls_back_to_container_type

All 14 test_get_expected_type* tests pass:

cargo test -p pyrefly --lib test_get_expected_type
test result: ok. 14 passed; 0 failed; 0 ignored; 0 measured

Also ran python3 test.py --no-test --no-conformance --no-jsonschema — formatting and linting clean. cargo clippy --all-targets --all-features produces no new warnings (only 2 pre-existing unused-import warnings in pyrefly_lsp_interaction_tests, unrelated to this branch).

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@kinto0 kinto0 self-assigned this Jun 4, 2026
// 1111111
// 0123456789012345678
let source = "x: int | str = 42\n";
let (mut tsp, file_uri, snapshot) = setup_project(source);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: we probably don't need an integration test for these. we can probably just use a normal unit test

@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync Bot commented Jun 4, 2026

@kinto0 has imported this pull request. If you are a Meta employee, you can view this in D107524019.

@kinto0
Copy link
Copy Markdown
Contributor

kinto0 commented Jun 4, 2026

discussed offline. closing

@kinto0 kinto0 closed this Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TSP] Expected type for TSP is returning the computed type

2 participants