Skip to content

Commit be5ad64

Browse files
committed
add Specialization mdtest class
1 parent d4c005d commit be5ad64

File tree

6 files changed

+61
-5
lines changed

6 files changed

+61
-5
lines changed

crates/ty_python_semantic/src/types.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6599,6 +6599,10 @@ impl<'db> Type<'db> {
65996599
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::GenericContext],
66006600
fallback_type: Type::unknown(),
66016601
}),
6602+
KnownInstanceType::Specialization(__call__) => Err(InvalidTypeExpressionError {
6603+
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Specialization],
6604+
fallback_type: Type::unknown(),
6605+
}),
66026606
KnownInstanceType::SubscriptedProtocol(_) => Err(InvalidTypeExpressionError {
66036607
invalid_expressions: smallvec::smallvec_inline![
66046608
InvalidTypeExpression::Protocol
@@ -7860,6 +7864,10 @@ pub enum KnownInstanceType<'db> {
78607864
/// `ty_extensions.GenericContext`.
78617865
GenericContext(GenericContext<'db>),
78627866

7867+
/// A specialization, which is exposed in mdtests as an instance of
7868+
/// `ty_extensions.Specialization`.
7869+
Specialization(Specialization<'db>),
7870+
78637871
/// A single instance of `types.UnionType`, which stores the left- and
78647872
/// right-hand sides of a PEP 604 union.
78657873
UnionType(InternedTypes<'db>),
@@ -7893,7 +7901,8 @@ fn walk_known_instance_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
78937901
}
78947902
KnownInstanceType::Deprecated(_)
78957903
| KnownInstanceType::ConstraintSet(_)
7896-
| KnownInstanceType::GenericContext(_) => {
7904+
| KnownInstanceType::GenericContext(_)
7905+
| KnownInstanceType::Specialization(_) => {
78977906
// Nothing to visit
78987907
}
78997908
KnownInstanceType::Field(field) => {
@@ -7949,7 +7958,10 @@ impl<'db> KnownInstanceType<'db> {
79497958
newtype
79507959
.map_base_class_type(db, |class_type| class_type.normalized_impl(db, visitor)),
79517960
),
7952-
Self::Deprecated(_) | Self::ConstraintSet(_) | Self::GenericContext(_) => {
7961+
Self::Deprecated(_)
7962+
| Self::ConstraintSet(_)
7963+
| Self::GenericContext(_)
7964+
| Self::Specialization(_) => {
79537965
// Nothing to normalize
79547966
self
79557967
}
@@ -7971,6 +7983,7 @@ impl<'db> KnownInstanceType<'db> {
79717983
Self::Field(_) => KnownClass::Field,
79727984
Self::ConstraintSet(_) => KnownClass::ConstraintSet,
79737985
Self::GenericContext(_) => KnownClass::GenericContext,
7986+
Self::Specialization(_) => KnownClass::Specialization,
79747987
Self::UnionType(_) => KnownClass::UnionType,
79757988
Self::Literal(_) => KnownClass::GenericAlias,
79767989
Self::Annotated(_) => KnownClass::GenericAlias,
@@ -8061,6 +8074,13 @@ impl<'db> KnownInstanceType<'db> {
80618074
generic_context.display_full(self.db)
80628075
)
80638076
}
8077+
KnownInstanceType::Specialization(specialization) => {
8078+
write!(
8079+
f,
8080+
"ty_extensions.Specialization{}",
8081+
specialization.display(self.db)
8082+
)
8083+
}
80648084
KnownInstanceType::UnionType(_) => f.write_str("types.UnionType"),
80658085
KnownInstanceType::Literal(_) => f.write_str("<typing.Literal special form>"),
80668086
KnownInstanceType::Annotated(_) => {
@@ -8306,6 +8326,8 @@ enum InvalidTypeExpression<'db> {
83068326
ConstraintSet,
83078327
/// Same for `ty_extensions.GenericContext`
83088328
GenericContext,
8329+
/// Same for `ty_extensions.Specialization`
8330+
Specialization,
83098331
/// Same for `typing.TypedDict`
83108332
TypedDict,
83118333
/// Type qualifiers are always invalid in *type expressions*,
@@ -8361,6 +8383,9 @@ impl<'db> InvalidTypeExpression<'db> {
83618383
InvalidTypeExpression::GenericContext => {
83628384
f.write_str("`ty_extensions.GenericContext` is not allowed in type expressions")
83638385
}
8386+
InvalidTypeExpression::Specialization => {
8387+
f.write_str("`ty_extensions.GenericContext` is not allowed in type expressions")
8388+
}
83648389
InvalidTypeExpression::TypedDict => {
83658390
f.write_str(
83668391
"The special form `typing.TypedDict` is not allowed in type expressions. \

crates/ty_python_semantic/src/types/class.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3851,6 +3851,7 @@ pub enum KnownClass {
38513851
// ty_extensions
38523852
ConstraintSet,
38533853
GenericContext,
3854+
Specialization,
38543855
}
38553856

38563857
impl KnownClass {
@@ -3955,6 +3956,7 @@ impl KnownClass {
39553956
| Self::NamedTupleLike
39563957
| Self::ConstraintSet
39573958
| Self::GenericContext
3959+
| Self::Specialization
39583960
| Self::ProtocolMeta
39593961
| Self::TypedDictFallback => Some(Truthiness::Ambiguous),
39603962

@@ -4039,6 +4041,7 @@ impl KnownClass {
40394041
| KnownClass::NamedTupleLike
40404042
| KnownClass::ConstraintSet
40414043
| KnownClass::GenericContext
4044+
| KnownClass::Specialization
40424045
| KnownClass::TypedDictFallback
40434046
| KnownClass::BuiltinFunctionType
40444047
| KnownClass::ProtocolMeta
@@ -4123,6 +4126,7 @@ impl KnownClass {
41234126
| KnownClass::NamedTupleLike
41244127
| KnownClass::ConstraintSet
41254128
| KnownClass::GenericContext
4129+
| KnownClass::Specialization
41264130
| KnownClass::TypedDictFallback
41274131
| KnownClass::BuiltinFunctionType
41284132
| KnownClass::ProtocolMeta
@@ -4207,6 +4211,7 @@ impl KnownClass {
42074211
| KnownClass::NamedTupleFallback
42084212
| KnownClass::ConstraintSet
42094213
| KnownClass::GenericContext
4214+
| KnownClass::Specialization
42104215
| KnownClass::BuiltinFunctionType
42114216
| KnownClass::ProtocolMeta
42124217
| KnownClass::Template
@@ -4302,6 +4307,7 @@ impl KnownClass {
43024307
| Self::NamedTupleFallback
43034308
| Self::ConstraintSet
43044309
| Self::GenericContext
4310+
| Self::Specialization
43054311
| Self::TypedDictFallback
43064312
| Self::BuiltinFunctionType
43074313
| Self::ProtocolMeta
@@ -4392,6 +4398,7 @@ impl KnownClass {
43924398
| KnownClass::Path
43934399
| KnownClass::ConstraintSet
43944400
| KnownClass::GenericContext
4401+
| KnownClass::Specialization
43954402
| KnownClass::InitVar => false,
43964403
KnownClass::NamedTupleFallback | KnownClass::TypedDictFallback => true,
43974404
}
@@ -4493,6 +4500,7 @@ impl KnownClass {
44934500
Self::NamedTupleLike => "NamedTupleLike",
44944501
Self::ConstraintSet => "ConstraintSet",
44954502
Self::GenericContext => "GenericContext",
4503+
Self::Specialization => "Specialization",
44964504
Self::TypedDictFallback => "TypedDictFallback",
44974505
Self::Template => "Template",
44984506
Self::Path => "Path",
@@ -4796,9 +4804,10 @@ impl KnownClass {
47964804
| Self::OrderedDict => KnownModule::Collections,
47974805
Self::Field | Self::KwOnly | Self::InitVar => KnownModule::Dataclasses,
47984806
Self::NamedTupleFallback | Self::TypedDictFallback => KnownModule::TypeCheckerInternals,
4799-
Self::NamedTupleLike | Self::ConstraintSet | Self::GenericContext => {
4800-
KnownModule::TyExtensions
4801-
}
4807+
Self::NamedTupleLike
4808+
| Self::ConstraintSet
4809+
| Self::GenericContext
4810+
| Self::Specialization => KnownModule::TyExtensions,
48024811
Self::Template => KnownModule::Templatelib,
48034812
Self::Path => KnownModule::Pathlib,
48044813
}
@@ -4882,6 +4891,7 @@ impl KnownClass {
48824891
| Self::NamedTupleLike
48834892
| Self::ConstraintSet
48844893
| Self::GenericContext
4894+
| Self::Specialization
48854895
| Self::TypedDictFallback
48864896
| Self::BuiltinFunctionType
48874897
| Self::ProtocolMeta
@@ -4971,6 +4981,7 @@ impl KnownClass {
49714981
| Self::NamedTupleLike
49724982
| Self::ConstraintSet
49734983
| Self::GenericContext
4984+
| Self::Specialization
49744985
| Self::TypedDictFallback
49754986
| Self::BuiltinFunctionType
49764987
| Self::ProtocolMeta
@@ -5070,6 +5081,7 @@ impl KnownClass {
50705081
"NamedTupleLike" => &[Self::NamedTupleLike],
50715082
"ConstraintSet" => &[Self::ConstraintSet],
50725083
"GenericContext" => &[Self::GenericContext],
5084+
"Specialization" => &[Self::Specialization],
50735085
"TypedDictFallback" => &[Self::TypedDictFallback],
50745086
"Template" => &[Self::Template],
50755087
"Path" => &[Self::Path],
@@ -5148,6 +5160,7 @@ impl KnownClass {
51485160
| Self::NamedTupleLike
51495161
| Self::ConstraintSet
51505162
| Self::GenericContext
5163+
| Self::Specialization
51515164
| Self::Awaitable
51525165
| Self::Generator
51535166
| Self::Template

crates/ty_python_semantic/src/types/class_base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ impl<'db> ClassBase<'db> {
175175
| KnownInstanceType::Field(_)
176176
| KnownInstanceType::ConstraintSet(_)
177177
| KnownInstanceType::GenericContext(_)
178+
| KnownInstanceType::Specialization(_)
178179
| KnownInstanceType::UnionType(_)
179180
| KnownInstanceType::Literal(_)
180181
// A class inheriting from a newtype would make intuitive sense, but newtype

crates/ty_python_semantic/src/types/generics.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,12 @@ impl std::fmt::Display for LegacyGenericBase {
659659
///
660660
/// TODO: Handle nested specializations better, with actual parent links to the specialization of
661661
/// the lexically containing context.
662+
///
663+
/// # Ordering
664+
/// Ordering is based on the context's salsa-assigned id and not on its values.
665+
/// The id may change between runs, or when the context was garbage collected and recreated.
662666
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
667+
#[derive(PartialOrd, Ord)]
663668
pub struct Specialization<'db> {
664669
pub(crate) generic_context: GenericContext<'db>,
665670
#[returns(deref)]

crates/ty_python_semantic/src/types/infer/builder/type_expression.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,15 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
777777
}
778778
Type::unknown()
779779
}
780+
KnownInstanceType::Specialization(_) => {
781+
self.infer_type_expression(slice);
782+
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
783+
builder.into_diagnostic(format_args!(
784+
"`ty_extensions.Specialization` is not allowed in type expressions",
785+
));
786+
}
787+
Type::unknown()
788+
}
780789
KnownInstanceType::TypeVar(_) => {
781790
self.infer_type_expression(slice);
782791
todo_type!("TypeVar annotations")

crates/ty_vendored/ty_extensions/ty_extensions.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ class GenericContext:
9797
alias.
9898
"""
9999

100+
class Specialization:
101+
"""A mapping of typevars to specific types"""
102+
100103
# Predicates on types
101104
#
102105
# Ideally, these would be annotated using `TypeForm`, but that has not been

0 commit comments

Comments
 (0)