From 2b806a974aa30ff8ae79bab4aa9bd44528126e51 Mon Sep 17 00:00:00 2001 From: Matthew Mckee Date: Tue, 3 Jun 2025 17:02:14 +0100 Subject: [PATCH 1/2] Add generic inference for dataclasses --- .../mdtest/generics/legacy/classes.md | 18 ++++++++++++++++++ .../mdtest/generics/pep695/classes.md | 15 +++++++++++++++ .../resources/mdtest/named_tuple.md | 4 +--- crates/ty_python_semantic/src/types/class.rs | 3 ++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md b/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md index ad1fe65958a2a5..ab6f8f2004f0ed 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md @@ -379,6 +379,24 @@ C[None](b"bytes") # error: [no-matching-overload] C[None](12) ``` +### Synthesized methods with dataclasses + +```py +from dataclasses import dataclass +from typing import Generic, TypeVar + +T = TypeVar("T") + +@dataclass +class A(Generic[T]): + x: T + +class B(A[T], Generic[T]): ... + +reveal_type(A(x=1)) # revealed: A[int] +reveal_type(B(x=1)) # revealed: B[int] +``` + ## Generic subclass When a generic subclass fills its superclass's type parameter with one of its own, the actual types diff --git a/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md b/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md index 1d3fee229bace0..796f861f39bf33 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md @@ -354,6 +354,21 @@ C[None](b"bytes") # error: [no-matching-overload] C[None](12) ``` +### Synthesized methods with dataclasses + +```py +from dataclasses import dataclass + +@dataclass +class A[T]: + x: T + +class B[T](A[T]): ... + +reveal_type(A(x=1)) # revealed: A[int] +reveal_type(B(x=1)) # revealed: B[int] +``` + ## Generic subclass When a generic subclass fills its superclass's type parameter with one of its own, the actual types diff --git a/crates/ty_python_semantic/resources/mdtest/named_tuple.md b/crates/ty_python_semantic/resources/mdtest/named_tuple.md index 8c5a79d62f9095..dfc81a73f0e77f 100644 --- a/crates/ty_python_semantic/resources/mdtest/named_tuple.md +++ b/crates/ty_python_semantic/resources/mdtest/named_tuple.md @@ -134,9 +134,7 @@ class Property[T](NamedTuple): name: str value: T -# TODO: this should be supported (no error, revealed type of `Property[float]`) -# error: [invalid-argument-type] -reveal_type(Property("height", 3.4)) # revealed: Property[Unknown] +reveal_type(Property("height", 3.4)) # revealed: Property[float] ``` ## Attributes on `NamedTuple` diff --git a/crates/ty_python_semantic/src/types/class.rs b/crates/ty_python_semantic/src/types/class.rs index 94158e653cd489..8056b9ef784cac 100644 --- a/crates/ty_python_semantic/src/types/class.rs +++ b/crates/ty_python_semantic/src/types/class.rs @@ -1372,7 +1372,8 @@ impl<'db> ClassLiteral<'db> { parameters.push(parameter); } - let signature = Signature::new(Parameters::new(parameters), Some(Type::none(db))); + let mut signature = Signature::new(Parameters::new(parameters), Some(Type::none(db))); + signature.inherited_generic_context = self.generic_context(db); Some(CallableType::function_like(db, signature)) }; From e1c0eca7b43b25381f95d9b986b975675764b061 Mon Sep 17 00:00:00 2001 From: Matthew Mckee Date: Tue, 3 Jun 2025 17:32:20 +0100 Subject: [PATCH 2/2] Remove unsupporeted tests --- .../resources/mdtest/generics/legacy/classes.md | 3 --- .../resources/mdtest/generics/pep695/classes.md | 3 --- 2 files changed, 6 deletions(-) diff --git a/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md b/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md index ab6f8f2004f0ed..5e8858bf7b716d 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md @@ -391,10 +391,7 @@ T = TypeVar("T") class A(Generic[T]): x: T -class B(A[T], Generic[T]): ... - reveal_type(A(x=1)) # revealed: A[int] -reveal_type(B(x=1)) # revealed: B[int] ``` ## Generic subclass diff --git a/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md b/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md index 796f861f39bf33..9726dbae542250 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md @@ -363,10 +363,7 @@ from dataclasses import dataclass class A[T]: x: T -class B[T](A[T]): ... - reveal_type(A(x=1)) # revealed: A[int] -reveal_type(B(x=1)) # revealed: B[int] ``` ## Generic subclass