Skip to content

Conversation

@asukaminato0721
Copy link
Contributor

@asukaminato0721 asukaminato0721 commented Nov 4, 2025

fix #1138

Preserved literal instantiations for quantified type variables, so generic calls now keep Literal[...] precision. Let quantified variables keep their precise literal answer only until a later constraint rejects it, then automatically widen to the promoted class type so multi-argument inference succeeds without regressing literal-preserving cases

stores the literal answer first, only promoting to the base type when the literal fails its bound, and continues to record specialization errors if both literal and promoted forms violate the bound.

After TypedDict construction, promote inferred type arguments from literals to their general class types so C(x=0) now infers C[int] instead of C[Literal[0]]

@meta-cla meta-cla bot added the cla signed label Nov 4, 2025
@asukaminato0721 asukaminato0721 changed the title fix fix preserve Literal through generic function calls Nov 4, 2025
@asukaminato0721 asukaminato0721 marked this pull request as ready for review November 4, 2025 16:25
@stroxler stroxler requested a review from samwgoldman November 5, 2025 02:35
drop(v2_ref);
drop(variables);
self.is_subset_eq(t1, &t2)
match self.is_subset_eq(t1, &t2) {
Copy link
Contributor

Choose a reason for hiding this comment

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

(same thing here - I don't think we would ever want to change an answer after it has been decided already)

drop(v1_ref);
drop(variables);
self.is_subset_eq(&t1, t2)
match self.is_subset_eq(&t1, t2) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This section looks unsafe to me, I don't see how it could be okay to change an Answer after it's already been decided.

Do you remember why this was needed? It may be a hint that propagating literals isn't going to work well at least at this time.

@stroxler
Copy link
Contributor

stroxler commented Nov 5, 2025

The core part of the change in Type::Quantified looks about right to me in the sense that it does what the issue says it wants done.

But that issue is controversial, I'm not convinced this is a good idea for two reasons:

  • First, issue preserve Literal through generic function calls #1138 is marked as needs-discussion because we intentionally decided to promote in generic function calls, partly inspired by what Pyright and mypy do. I think any change needs to be made intentionally
  • Second, it worries me that this implementation relied on changing Answers after the fact. I'm fairly certain we cannot do that safely at all; if that was necessary to make this work, then I think it may be a clear indication that we should just continue promoting literals at least for now.

I believe the discussion of #1138 also suggested that we might also have to promote sometimes depending on variance to make this work well because, for example if f[T](x: T) -> list[T]: return [x] then we would really want f(1) to have type list[int] rather than list[Literal[1]] to avoid lots of noise do to invariance.

I'm curious what @samwgoldman thinks, I'd also be curious to hear more about why the lines rewriting Variable::Answer seemed necessary.

@asukaminato0721 asukaminato0721 marked this pull request as draft November 5, 2025 07:19
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.

preserve Literal through generic function calls

2 participants