Skip to content

Fix lambda contextual typing with keyword-only callables - #11609

Open
Kirill (vetrovk) wants to merge 2 commits into
microsoft:mainfrom
vetrovk:fix/lambda-context-keyword-only
Open

Fix lambda contextual typing with keyword-only callables#11609
Kirill (vetrovk) wants to merge 2 commits into
microsoft:mainfrom
vetrovk:fix/lambda-context-keyword-only

Conversation

@vetrovk

Copy link
Copy Markdown

Fixes #11603.

When a lambda was contextually typed from a union of callable candidates, a keyword-only parameter from one candidate could incorrectly provide the type for a positional lambda parameter. This caused the wrong candidate to influence inference instead of being rejected.

Treat a keyword-only contextual parameter as compatible only with a lambda parameter that follows * or *args. Otherwise, skip that candidate and continue with the remaining contextual signatures.

Tests cover the reported case, generic and callback-protocol variants, ordinary callable unions, positional callable objects, and the incompatible keyword-only case.

Validation:

  • Lambda4: 1/1 passed
  • lambda subset: 16/16 passed
  • typeEvaluator1.test.ts: 159/159 passed
  • npm run build:cli:dev
  • Prettier
  • ESLint
  • git diff --check

@StellaHuang95

Stella Huang (StellaHuang95) commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

🔒 Automated review in progress — Stella Huang (@StellaHuang95) is auto-reviewing this PR.

positional_callable_union: Callable[[PositionalCallable], PositionalCallable] | PositionalCallable = lambda x: x

# This should generate an error.
keyword_only_callback: KeywordOnlyCallback = lambda x: x

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Warning · Non-blocking recommendation

Add a positive regression case for the enabled branch: a lambda with *args followed by a keyword-only parameter contextually typed against a keyword-only callable. The new guard's rejection behavior is well covered, but this ensures valid keyword-only lambda parameters still receive their expected type.

[verified]

if (
expectedParam.param.category === param.d.category &&
!param.d.name === !expectedParam.param.name
!param.d.name === !expectedParam.param.name &&

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Warning · Non-blocking recommendation

This guard also prevents contextual typing for a compatible single callable such as Callable[*, value: int] assigned from lambda value: value: that lambda accepts the required value= keyword, but its parameter now falls back to Unknown. Please preserve contextual typing when the lambda parameter name matches the keyword-only expected parameter, or add coverage showing why this case must be rejected.

[verified]

@StellaHuang95

Copy link
Copy Markdown
Collaborator

Please mirror the keyword-only lambda-parameter compatibility guard in packages/pylance-internal/src/analyzer/typeEvaluator.ts; the current diff updates only the Pyright evaluator, so async Pylance users retain the bug.

@StellaHuang95 Stella Huang (StellaHuang95) added the review-auto:changes-requested Automated review: posted blocking findings to address. label Aug 10, 2026
isPrivateName(param.d.name.d.value));
const isCompatibleKeywordParam =
expectedParam.kind !== ParamKind.Keyword ||
sawLambdaArgsParam ||

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Info · Optional note

isPositionOnlyParam reads paramsArePositionOnly, which is mutated later in this loop. It is correct today, but that coupling makes the matching behavior sensitive to loop ordering. Consider deriving this status up front from node.d.params, alongside positionOnlySeparatorIndex, so future refactoring cannot silently change contextual-typing behavior.

[verified]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@StellaHuang95 Stella Huang (StellaHuang95) added review-auto:approved Automated review: no blocking findings (approval posted). and removed review-auto:changes-requested Automated review: posted blocking findings to address. labels Aug 10, 2026

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

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

Labels

review-auto:approved Automated review: no blocking findings (approval posted).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inference of identity lambda into union of keyword-only function and its identity

3 participants