Skip to content

Commit 9a697f6

Browse files
committed
Temp: Generics issue
1 parent 63531ea commit 9a697f6

File tree

5 files changed

+50
-4
lines changed

5 files changed

+50
-4
lines changed

crates/ty_python_semantic/resources/mdtest/annotations/self.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,27 @@ class MyMetaclass(type):
231231
def __new__(cls) -> Self:
232232
return super().__new__(cls)
233233
```
234+
235+
## Custom
236+
237+
TODO: Just a random test I added for debugging.
238+
239+
```toml
240+
[environment]
241+
python-version = "3.11"
242+
```
243+
244+
```py
245+
from typing import Generic, TypeVar
246+
247+
T = TypeVar("T")
248+
249+
class C(Generic[T]):
250+
def __init__(self, x: T) -> None: ...
251+
252+
# in the __init__ method self has type of C[Literal["five"]]
253+
C("five")
254+
```
255+
256+
The argument self has type C[T] and then it is specialized to C\[Literal["five"]\]. But then the
257+
argument type is C[str]. One way they are assignable but not the other way around.

crates/ty_python_semantic/src/types.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4949,9 +4949,15 @@ impl<'db> Type<'db> {
49494949
],
49504950
});
49514951
};
4952-
let instance = Type::ClassLiteral(class)
4953-
.to_instance(db)
4954-
.expect("enclosing_class_symbol must return type that can be instantiated");
4952+
let instance = match class.generic_context(db) {
4953+
Some(generic_context) => {
4954+
let specialization = generic_context.identity_specialization(db);
4955+
Type::GenericAlias(GenericAlias::new(db, class, specialization))
4956+
}
4957+
_ => Type::ClassLiteral(class).to_instance(db).expect(
4958+
"enclosing_class_symbol must return type that can be instantiated",
4959+
),
4960+
};
49554961
Ok(Type::TypeVar(TypeVarInstance::new(
49564962
db,
49574963
ast::name::Name::new("Self"),

crates/ty_python_semantic/src/types/call/bind.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,7 @@ impl<'db> Binding<'db> {
14091409
});
14101410
}
14111411
}
1412+
// dbg!(signature.generic_context);
14121413
self.specialization = signature.generic_context.map(|gc| builder.build(gc));
14131414
self.inherited_specialization = signature.inherited_generic_context.map(|gc| {
14141415
// The inherited generic context is used when inferring the specialization of a
@@ -1432,6 +1433,9 @@ impl<'db> Binding<'db> {
14321433
};
14331434
let parameter = &parameters[parameter_index];
14341435
if let Some(mut expected_ty) = parameter.annotated_type() {
1436+
if parameter.name().is_some_and(|f| f == "self") {
1437+
dbg!(parameter);
1438+
}
14351439
if let Some(specialization) = self.specialization {
14361440
argument_type = argument_type.apply_specialization(db, specialization);
14371441
expected_ty = expected_ty.apply_specialization(db, specialization);
@@ -1444,6 +1448,7 @@ impl<'db> Binding<'db> {
14441448
if !argument_type.is_assignable_to(db, expected_ty) {
14451449
let positional = matches!(argument, Argument::Positional | Argument::Synthetic)
14461450
&& !parameter.is_variadic();
1451+
dbg!("problem", argument_type, expected_ty);
14471452
self.errors.push(BindingError::InvalidArgumentType {
14481453
parameter: ParameterContext::new(parameter, parameter_index, positional),
14491454
argument_index: get_argument_index(argument_index, num_synthetic_args),

crates/ty_python_semantic/src/types/class.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,8 @@ impl<'db> ClassType<'db> {
402402
ClassBase::Class(base) => match (base, other) {
403403
(ClassType::NonGeneric(base), ClassType::NonGeneric(other)) => base == other,
404404
(ClassType::Generic(base), ClassType::Generic(other)) => {
405+
// Here base has specialization Literal
406+
// dbg!(base);
405407
base.origin(db) == other.origin(db)
406408
&& base
407409
.specialization(db)

crates/ty_python_semantic/src/types/generics.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::types::class_base::ClassBase;
99
use crate::types::instance::{NominalInstanceType, Protocol, ProtocolInstanceType};
1010
use crate::types::signatures::{Parameter, Parameters, Signature};
1111
use crate::types::{
12-
KnownInstanceType, Type, TypeMapping, TypeVarBoundOrConstraints, TypeVarInstance,
12+
KnownClass, KnownInstanceType, Type, TypeMapping, TypeVarBoundOrConstraints, TypeVarInstance,
1313
TypeVarVariance, UnionType, declaration_type, todo_type,
1414
};
1515
use crate::{Db, FxOrderSet};
@@ -448,6 +448,14 @@ impl<'db> Specialization<'db> {
448448
// - bivariant: skip, can't make assignability false
449449
let compatible = match typevar.variance(db) {
450450
TypeVarVariance::Invariant => {
451+
match self_type {
452+
Type::StringLiteral(_) => {
453+
dbg!(self_type, other_type);
454+
dbg!(self_type.is_assignable_to(db, *other_type));
455+
dbg!(other_type.is_assignable_to(db, *self_type));
456+
}
457+
_ => (),
458+
};
451459
self_type.is_assignable_to(db, *other_type)
452460
&& other_type.is_assignable_to(db, *self_type)
453461
}
@@ -561,6 +569,7 @@ impl<'db> SpecializationBuilder<'db> {
561569
}
562570
}
563571

572+
// Here we produce literal
564573
pub(crate) fn build(&mut self, generic_context: GenericContext<'db>) -> Specialization<'db> {
565574
let types: Box<[_]> = generic_context
566575
.variables(self.db)

0 commit comments

Comments
 (0)