Skip to content

Commit d0b68f9

Browse files
committed
use CycleHeads to remove Divergent types
1 parent 682a2e8 commit d0b68f9

File tree

8 files changed

+65
-26
lines changed

8 files changed

+65
-26
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ regex-automata = { version = "0.4.9" }
146146
rustc-hash = { version = "2.0.0" }
147147
rustc-stable-hash = { version = "0.1.2" }
148148
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
149-
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "05a9af7f554b64b8aadc2eeb6f2caf73d0408d09", default-features = false, features = [
149+
salsa = { git = "https://github.com/mtshiba/salsa.git", rev = "11f2ec8629e46b391c41aef5d770de92760a4f01", default-features = false, features = [
150150
"compact_str",
151151
"macros",
152152
"salsa_unstable",

crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ from typing_extensions import Generic, TypeVar
734734

735735
T = TypeVar("T")
736736

737+
# TODO: no error
738+
# error: [unsupported-base] "Unsupported class base with type `<class 'list[Derived[T@Derived]]'> | <class 'list[@Todo(specialized non-generic class)]'>`"
737739
class Derived(list[Derived[T]], Generic[T]): ...
738740
```
739741

crates/ty_python_semantic/src/place.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ fn place_cycle_initial<'db>(
710710
fn place_cycle_recover<'db>(
711711
db: &'db dyn Db,
712712
id: salsa::Id,
713+
cycle_heads: &salsa::CycleHeads,
713714
previous_place: &PlaceAndQualifiers<'db>,
714715
place: PlaceAndQualifiers<'db>,
715716
_count: u32,
@@ -720,7 +721,13 @@ fn place_cycle_recover<'db>(
720721
) -> PlaceAndQualifiers<'db> {
721722
let div = Type::divergent(id);
722723
PlaceAndQualifiers {
723-
place: join_with_previous_cycle_place(db, &previous_place.place, &place.place, div),
724+
place: join_with_previous_cycle_place(
725+
db,
726+
&previous_place.place,
727+
&place.place,
728+
div,
729+
cycle_heads,
730+
),
724731
qualifiers: place.qualifiers,
725732
}
726733
}

crates/ty_python_semantic/src/types.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ fn member_lookup_cycle_initial<'db>(
416416
fn member_lookup_cycle_recover<'db>(
417417
db: &'db dyn Db,
418418
id: salsa::Id,
419+
cycle_heads: &salsa::CycleHeads,
419420
previous_member: &PlaceAndQualifiers<'db>,
420421
member: PlaceAndQualifiers<'db>,
421422
_count: u32,
@@ -424,7 +425,8 @@ fn member_lookup_cycle_recover<'db>(
424425
_policy: MemberLookupPolicy,
425426
) -> PlaceAndQualifiers<'db> {
426427
let div = Type::divergent(id);
427-
let place = join_with_previous_cycle_place(db, &previous_member.place, &member.place, div);
428+
let place =
429+
join_with_previous_cycle_place(db, &previous_member.place, &member.place, div, cycle_heads);
428430
PlaceAndQualifiers {
429431
place,
430432
qualifiers: member.qualifiers,
@@ -446,12 +448,13 @@ pub(crate) fn join_with_previous_cycle_place<'db>(
446448
previous_place: &Place<'db>,
447449
place: &Place<'db>,
448450
div: Type<'db>,
451+
cycle_heads: &salsa::CycleHeads,
449452
) -> Place<'db> {
450453
match (previous_place, place) {
451454
// In fixed-point iteration of type inference, the member type must be monotonically widened and not "oscillate".
452455
// Here, monotonicity is guaranteed by pre-unioning the type of the previous iteration into the current result.
453456
(Place::Defined(prev_ty, _, _), Place::Defined(ty, origin, definedness)) => Place::Defined(
454-
ty.cycle_normalized(db, *prev_ty, div),
457+
ty.cycle_normalized(db, *prev_ty, div, cycle_heads),
455458
*origin,
456459
*definedness,
457460
),
@@ -466,6 +469,7 @@ pub(crate) fn join_with_previous_cycle_place<'db>(
466469
fn class_lookup_cycle_recover<'db>(
467470
db: &'db dyn Db,
468471
id: salsa::Id,
472+
cycle_heads: &salsa::CycleHeads,
469473
previous_member: &PlaceAndQualifiers<'db>,
470474
member: PlaceAndQualifiers<'db>,
471475
_count: u32,
@@ -474,7 +478,8 @@ fn class_lookup_cycle_recover<'db>(
474478
_policy: MemberLookupPolicy,
475479
) -> PlaceAndQualifiers<'db> {
476480
let div = Type::divergent(id);
477-
let place = join_with_previous_cycle_place(db, &previous_member.place, &member.place, div);
481+
let place =
482+
join_with_previous_cycle_place(db, &previous_member.place, &member.place, div, cycle_heads);
478483
PlaceAndQualifiers {
479484
place,
480485
qualifiers: member.qualifiers,
@@ -920,9 +925,18 @@ impl<'db> Type<'db> {
920925
matches!(self, Type::Callable(..))
921926
}
922927

923-
pub(crate) fn cycle_normalized(self, db: &'db dyn Db, previous: Self, div: Self) -> Self {
924-
UnionType::from_elements_cycle_recovery(db, [self, previous])
925-
.recursive_type_normalized(db, div)
928+
pub(crate) fn cycle_normalized(
929+
self,
930+
db: &'db dyn Db,
931+
previous: Self,
932+
div: Self,
933+
cycle_heads: &salsa::CycleHeads,
934+
) -> Self {
935+
let normalized = UnionType::from_elements_cycle_recovery(db, [self, previous])
936+
.recursive_type_normalized(db, div);
937+
cycle_heads.ids().fold(normalized, |ty, id| {
938+
ty.recursive_type_normalized(db, Type::divergent(id))
939+
})
926940
}
927941

928942
fn is_none(&self, db: &'db dyn Db) -> bool {
@@ -7692,17 +7706,19 @@ fn is_redundant_with_cycle_initial<'db>(
76927706
true
76937707
}
76947708

7709+
#[allow(clippy::too_many_arguments)]
76957710
fn apply_specialization_cycle_recover<'db>(
76967711
db: &'db dyn Db,
76977712
id: salsa::Id,
7713+
cycle_heads: &salsa::CycleHeads,
76987714
previous_value: &Type<'db>,
76997715
value: Type<'db>,
77007716
_count: u32,
77017717
_self: Type<'db>,
77027718
_specialization: Specialization<'db>,
77037719
) -> Type<'db> {
77047720
let div = Type::divergent(id);
7705-
value.cycle_normalized(db, *previous_value, div)
7721+
value.cycle_normalized(db, *previous_value, div, cycle_heads)
77067722
}
77077723

77087724
fn apply_specialization_cycle_initial<'db>(
@@ -8909,14 +8925,15 @@ fn lazy_bound_or_constraints_cycle_initial<'db>(
89098925
fn lazy_default_cycle_recover<'db>(
89108926
db: &'db dyn Db,
89118927
id: salsa::Id,
8928+
cycle_heads: &salsa::CycleHeads,
89128929
previous_default: &Option<Type<'db>>,
89138930
default: Option<Type<'db>>,
89148931
_count: u32,
89158932
_typevar: TypeVarInstance<'db>,
89168933
) -> Option<Type<'db>> {
89178934
let div = Type::divergent(id);
89188935
match (previous_default, default) {
8919-
(Some(prev), Some(default)) => Some(default.cycle_normalized(db, *prev, div)),
8936+
(Some(prev), Some(default)) => Some(default.cycle_normalized(db, *prev, div, cycle_heads)),
89208937
(None, Some(default)) => Some(default.recursive_type_normalized(db, div)),
89218938
(_, None) => None,
89228939
}

crates/ty_python_semantic/src/types/class.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ fn implicit_attribute_initial<'db>(
120120
fn implicit_attribute_cycle_recover<'db>(
121121
db: &'db dyn Db,
122122
id: salsa::Id,
123+
cycle_heads: &salsa::CycleHeads,
123124
previous_member: &Member<'db>,
124125
member: Member<'db>,
125126
_count: u32,
@@ -128,8 +129,13 @@ fn implicit_attribute_cycle_recover<'db>(
128129
_target_method_decorator: MethodDecorator,
129130
) -> Member<'db> {
130131
let div = Type::divergent(id);
131-
let place =
132-
join_with_previous_cycle_place(db, &previous_member.inner.place, &member.inner.place, div);
132+
let place = join_with_previous_cycle_place(
133+
db,
134+
&previous_member.inner.place,
135+
&member.inner.place,
136+
div,
137+
cycle_heads,
138+
);
133139
Member {
134140
inner: PlaceAndQualifiers {
135141
place,

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub(crate) fn infer_scope_types<'db>(db: &'db dyn Db, scope: ScopeId<'db>) -> Sc
8585
fn scope_cycle_recover<'db>(
8686
db: &'db dyn Db,
8787
id: salsa::Id,
88+
cycle_heads: &salsa::CycleHeads,
8889
previous_inference: &ScopeInference<'db>,
8990
mut inference: ScopeInference<'db>,
9091
_count: u32,
@@ -93,7 +94,7 @@ fn scope_cycle_recover<'db>(
9394
let div = Type::divergent(id);
9495
for (expr, ty) in &mut inference.expressions {
9596
let previous_ty = previous_inference.expression_type(*expr);
96-
*ty = ty.cycle_normalized(db, previous_ty, div);
97+
*ty = ty.cycle_normalized(db, previous_ty, div, cycle_heads);
9798
}
9899

99100
inference
@@ -134,32 +135,34 @@ pub(crate) fn infer_definition_types<'db>(
134135
fn definition_cycle_recover<'db>(
135136
db: &'db dyn Db,
136137
id: salsa::Id,
138+
cycle_heads: &salsa::CycleHeads,
137139
previous_inference: &DefinitionInference<'db>,
138140
inference: DefinitionInference<'db>,
139141
_count: u32,
140142
_definition: Definition<'db>,
141143
) -> DefinitionInference<'db> {
142-
definition_cycle_recover_inner(db, id, previous_inference, inference)
144+
definition_cycle_recover_inner(db, id, cycle_heads, previous_inference, inference)
143145
}
144146

145147
fn definition_cycle_recover_inner<'db>(
146148
db: &'db dyn Db,
147149
id: salsa::Id,
150+
cycle_heads: &salsa::CycleHeads,
148151
previous_inference: &DefinitionInference<'db>,
149152
mut inference: DefinitionInference<'db>,
150153
) -> DefinitionInference<'db> {
151154
let div = Type::divergent(id);
152155
for (expr, ty) in &mut inference.expressions {
153156
let previous_ty = previous_inference.expression_type(*expr);
154-
*ty = ty.cycle_normalized(db, previous_ty, div);
157+
*ty = ty.cycle_normalized(db, previous_ty, div, cycle_heads);
155158
}
156159
for (binding, binding_ty) in &mut inference.bindings {
157160
if let Some((_, previous_binding)) = previous_inference
158161
.bindings
159162
.iter()
160163
.find(|(previous_binding, _)| previous_binding == binding)
161164
{
162-
*binding_ty = binding_ty.cycle_normalized(db, *previous_binding, div);
165+
*binding_ty = binding_ty.cycle_normalized(db, *previous_binding, div, cycle_heads);
163166
} else {
164167
*binding_ty = binding_ty.recursive_type_normalized(db, div);
165168
}
@@ -171,7 +174,7 @@ fn definition_cycle_recover_inner<'db>(
171174
.find(|(previous_declaration, _)| previous_declaration == declaration)
172175
{
173176
*declaration_ty = declaration_ty.map_type(|decl_ty| {
174-
decl_ty.cycle_normalized(db, previous_declaration.inner_type(), div)
177+
decl_ty.cycle_normalized(db, previous_declaration.inner_type(), div, cycle_heads)
175178
});
176179
} else {
177180
*declaration_ty =
@@ -218,12 +221,13 @@ pub(crate) fn infer_deferred_types<'db>(
218221
fn deferred_cycle_recovery<'db>(
219222
db: &'db dyn Db,
220223
id: salsa::Id,
224+
cycle_heads: &salsa::CycleHeads,
221225
previous_inference: &DefinitionInference<'db>,
222226
inference: DefinitionInference<'db>,
223227
_count: u32,
224228
_definition: Definition<'db>,
225229
) -> DefinitionInference<'db> {
226-
definition_cycle_recover_inner(db, id, previous_inference, inference)
230+
definition_cycle_recover_inner(db, id, cycle_heads, previous_inference, inference)
227231
}
228232

229233
fn deferred_cycle_initial<'db>(
@@ -298,6 +302,7 @@ pub(crate) fn infer_isolated_expression<'db>(
298302
fn expression_cycle_recover<'db>(
299303
db: &'db dyn Db,
300304
id: salsa::Id,
305+
cycle_heads: &salsa::CycleHeads,
301306
previous_inference: &ExpressionInference<'db>,
302307
mut inference: ExpressionInference<'db>,
303308
_count: u32,
@@ -314,7 +319,7 @@ fn expression_cycle_recover<'db>(
314319
.find(|(previous_binding, _)| previous_binding == binding)
315320
})
316321
{
317-
*binding_ty = binding_ty.cycle_normalized(db, *previous_binding, div);
322+
*binding_ty = binding_ty.cycle_normalized(db, *previous_binding, div, cycle_heads);
318323
} else {
319324
*binding_ty = binding_ty.recursive_type_normalized(db, div);
320325
}
@@ -323,7 +328,7 @@ fn expression_cycle_recover<'db>(
323328

324329
for (expr, ty) in &mut inference.expressions {
325330
let previous_ty = previous_inference.expression_type(*expr);
326-
*ty = ty.cycle_normalized(db, previous_ty, div);
331+
*ty = ty.cycle_normalized(db, previous_ty, div, cycle_heads);
327332
}
328333

329334
inference
@@ -382,13 +387,14 @@ fn infer_expression_type_impl<'db>(db: &'db dyn Db, input: InferExpression<'db>)
382387
fn single_expression_cycle_recover<'db>(
383388
db: &'db dyn Db,
384389
id: salsa::Id,
390+
cycle_heads: &salsa::CycleHeads,
385391
previous_cycle_value: &Type<'db>,
386392
result: Type<'db>,
387393
_count: u32,
388394
_input: InferExpression<'db>,
389395
) -> Type<'db> {
390396
let div = Type::divergent(id);
391-
result.cycle_normalized(db, *previous_cycle_value, div)
397+
result.cycle_normalized(db, *previous_cycle_value, div, cycle_heads)
392398
}
393399

394400
fn single_expression_cycle_initial<'db>(
@@ -540,6 +546,7 @@ fn unpack_cycle_initial<'db>(
540546
fn unpack_cycle_recover<'db>(
541547
db: &'db dyn Db,
542548
id: salsa::Id,
549+
cycle_heads: &salsa::CycleHeads,
543550
previous_cycle_result: &UnpackResult<'db>,
544551
mut result: UnpackResult<'db>,
545552
_count: u32,
@@ -548,7 +555,7 @@ fn unpack_cycle_recover<'db>(
548555
let div = Type::divergent(id);
549556
for (expr, ty) in &mut result.targets {
550557
let previous_ty = previous_cycle_result.expression_type(*expr);
551-
*ty = ty.cycle_normalized(db, previous_ty, div);
558+
*ty = ty.cycle_normalized(db, previous_ty, div, cycle_heads);
552559
}
553560

554561
result

fuzz/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ty_python_semantic = { path = "../crates/ty_python_semantic" }
3030
ty_vendored = { path = "../crates/ty_vendored" }
3131

3232
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer", default-features = false }
33-
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "05a9af7f554b64b8aadc2eeb6f2caf73d0408d09", default-features = false, features = [
33+
salsa = { git = "https://github.com/mtshiba/salsa.git", rev = "11f2ec8629e46b391c41aef5d770de92760a4f01", default-features = false, features = [
3434
"compact_str",
3535
"macros",
3636
"salsa_unstable",

0 commit comments

Comments
 (0)