Skip to content

Commit a72b60b

Browse files
committed
revert unnecessary changes for the purpose of this PR
1 parent 6419669 commit a72b60b

File tree

12 files changed

+237
-466
lines changed

12 files changed

+237
-466
lines changed

crates/ty_python_semantic/resources/corpus/divergent.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ def unwrap(value):
5757
else:
5858
raise TypeError()
5959

60+
# TODO: If this is commented out, that is, if `infer_scope_types` is called before `infer_return_type`, it will panic.
61+
reveal_type(unwrap(Foo()))
62+
6063
def descent(x: int, y: int):
6164
if x > y:
6265
y, x = descent(y, x)
@@ -67,3 +70,6 @@ def descent(x: int, y: int):
6770
return (0, 1)
6871
else:
6972
return descent(x-1, y-1)
73+
74+
# TODO: If this is commented out, that is, if `infer_scope_types` is called before `infer_return_type`, it will panic.
75+
reveal_type(descent(5, 3))

crates/ty_python_semantic/resources/mdtest/attributes.md

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,24 +2281,6 @@ class B:
22812281

22822282
reveal_type(B().x) # revealed: Unknown | Literal[1]
22832283
reveal_type(A().x) # revealed: Unknown | Literal[1]
2284-
2285-
class Base:
2286-
def flip(self) -> "Sub":
2287-
return Sub()
2288-
2289-
class Sub(Base):
2290-
# TODO invalid override error
2291-
def flip(self) -> "Base":
2292-
return Base()
2293-
2294-
class C2:
2295-
def __init__(self, x: Sub):
2296-
self.x = x
2297-
2298-
def replace_with(self, other: "C2"):
2299-
self.x = other.x.flip()
2300-
2301-
reveal_type(C2(Sub()).x) # revealed: Unknown | Base
23022284
```
23032285

23042286
This case additionally tests our union/intersection simplification logic:

crates/ty_python_semantic/resources/mdtest/cycle.md

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,3 @@ p = Point()
3131
reveal_type(p.x) # revealed: Unknown | int
3232
reveal_type(p.y) # revealed: Unknown | int
3333
```
34-
35-
## Self-referential bare type alias
36-
37-
```py
38-
A = list["A" | None]
39-
40-
def f(x: A):
41-
# TODO: should be `list[A | None]`?
42-
reveal_type(x) # revealed: list[Divergent]
43-
# TODO: should be `A | None`?
44-
reveal_type(x[0]) # revealed: Divergent
45-
```
46-
47-
## Self-referential type variables
48-
49-
```py
50-
from typing import Generic, TypeVar
51-
52-
B = TypeVar("B", bound="Base")
53-
54-
# TODO: no error
55-
# error: [invalid-argument-type] "`typing.TypeVar | typing.TypeVar` is not a valid argument to `Generic`"
56-
class Base(Generic[B]):
57-
pass
58-
```

crates/ty_python_semantic/src/types.rs

Lines changed: 33 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ use crate::semantic_index::scope::ScopeId;
3939
use crate::semantic_index::{imported_modules, place_table, semantic_index};
4040
use crate::suppression::check_suppressions;
4141
use crate::types::call::{Binding, Bindings, CallArguments, CallableBinding};
42-
use crate::types::class::MethodDecorator;
4342
pub(crate) use crate::types::class_base::ClassBase;
4443
use crate::types::constraints::{
4544
ConstraintSet, IteratorConstraintsExtension, OptionConstraintsExtension,
@@ -62,15 +61,14 @@ pub use crate::types::ide_support::{
6261
definitions_for_keyword_argument, definitions_for_name, find_active_signature_from_details,
6362
inlay_hint_function_argument_details,
6463
};
65-
use crate::types::infer::InferExpression;
6664
use crate::types::mro::{Mro, MroError, MroIterator};
6765
pub(crate) use crate::types::narrow::infer_narrowing_constraint;
6866
pub(crate) use crate::types::signatures::{Parameter, Parameters};
6967
use crate::types::signatures::{ParameterForm, walk_signature};
7068
use crate::types::tuple::TupleSpec;
7169
pub(crate) use crate::types::typed_dict::{TypedDictParams, TypedDictType, walk_typed_dict_type};
7270
use crate::types::variance::{TypeVarVariance, VarianceInferable};
73-
use crate::unpack::{EvaluationMode, Unpack};
71+
use crate::unpack::EvaluationMode;
7472
pub use crate::util::diagnostics::add_inferred_python_version_hint_to_diagnostic;
7573
use crate::{Db, FxOrderSet, Module, Program};
7674
pub(crate) use class::{ClassLiteral, ClassType, GenericAlias, KnownClass};
@@ -121,16 +119,13 @@ fn return_type_cycle_recover<'db>(
121119
}
122120

123121
fn return_type_cycle_initial<'db>(db: &'db dyn Db, method: BoundMethodType<'db>) -> Type<'db> {
124-
Type::divergent(DivergentType::new(
125-
db,
126-
DivergenceKind::InferReturnType(
127-
method
128-
.function(db)
129-
.literal(db)
130-
.last_definition(db)
131-
.body_scope(db),
132-
),
133-
))
122+
Type::divergent(
123+
method
124+
.function(db)
125+
.literal(db)
126+
.last_definition(db)
127+
.body_scope(db),
128+
)
134129
}
135130

136131
pub fn check_types(db: &dyn Db, file: File) -> Vec<Diagnostic> {
@@ -287,7 +282,11 @@ pub(crate) struct RecursiveTypeNormalizedVisitor<'db> {
287282

288283
impl<'db> RecursiveTypeNormalizedVisitor<'db> {
289284
fn new(div: Type<'db>) -> Self {
290-
debug_assert!(matches!(div, Type::Dynamic(DynamicType::Divergent(_))));
285+
// TODO: Divergent only
286+
debug_assert!(matches!(
287+
div,
288+
Type::Never | Type::Dynamic(DynamicType::Divergent(_))
289+
));
291290
Self {
292291
transformer: NormalizedVisitor::default(),
293292
div,
@@ -446,22 +445,13 @@ fn member_lookup_cycle_recover<'db>(
446445
salsa::CycleRecoveryAction::Iterate
447446
}
448447

449-
#[allow(clippy::needless_pass_by_value)]
450448
fn member_lookup_cycle_initial<'db>(
451-
db: &'db dyn Db,
452-
self_type: Type<'db>,
453-
name: Name,
454-
policy: MemberLookupPolicy,
449+
_db: &'db dyn Db,
450+
_self: Type<'db>,
451+
_name: Name,
452+
_policy: MemberLookupPolicy,
455453
) -> PlaceAndQualifiers<'db> {
456-
Place::bound(Type::divergent(DivergentType::new(
457-
db,
458-
DivergenceKind::MemberLookupWithPolicy {
459-
self_type,
460-
name,
461-
policy,
462-
},
463-
)))
464-
.into()
454+
Place::bound(Type::Never).into()
465455
}
466456

467457
fn class_lookup_cycle_recover<'db>(
@@ -475,22 +465,13 @@ fn class_lookup_cycle_recover<'db>(
475465
salsa::CycleRecoveryAction::Iterate
476466
}
477467

478-
#[allow(clippy::needless_pass_by_value)]
479468
fn class_lookup_cycle_initial<'db>(
480-
db: &'db dyn Db,
481-
self_type: Type<'db>,
482-
name: Name,
483-
policy: MemberLookupPolicy,
469+
_db: &'db dyn Db,
470+
_self: Type<'db>,
471+
_name: Name,
472+
_policy: MemberLookupPolicy,
484473
) -> PlaceAndQualifiers<'db> {
485-
Place::bound(Type::divergent(DivergentType::new(
486-
db,
487-
DivergenceKind::ClassLookupWithPolicy {
488-
self_type,
489-
name,
490-
policy,
491-
},
492-
)))
493-
.into()
474+
Place::bound(Type::Never).into()
494475
}
495476

496477
#[allow(clippy::trivially_copy_pass_by_ref)]
@@ -909,8 +890,8 @@ impl<'db> Type<'db> {
909890
Self::Dynamic(DynamicType::Unknown)
910891
}
911892

912-
pub(crate) fn divergent(divergent: DivergentType<'db>) -> Self {
913-
Self::Dynamic(DynamicType::Divergent(divergent))
893+
pub(crate) fn divergent(scope: ScopeId<'db>) -> Self {
894+
Self::Dynamic(DynamicType::Divergent(DivergentType { scope }))
914895
}
915896

916897
pub const fn is_unknown(&self) -> bool {
@@ -3169,7 +3150,7 @@ impl<'db> Type<'db> {
31693150
policy: MemberLookupPolicy,
31703151
) -> PlaceAndQualifiers<'db> {
31713152
tracing::trace!("class_member: {}.{}", self.display(db), name);
3172-
let result = match self {
3153+
match self {
31733154
Type::Union(union) => union.map_with_boundness_and_qualifiers(db, |elem| {
31743155
elem.class_member_with_policy(db, name.clone(), policy)
31753156
}),
@@ -3187,30 +3168,7 @@ impl<'db> Type<'db> {
31873168
.expect(
31883169
"`Type::find_name_in_mro()` should return `Some()` when called on a meta-type",
31893170
),
3190-
};
3191-
result.map_type(|ty| {
3192-
// In fixed-point iteration of type inference, the member type must be monotonically widened and not "oscillate".
3193-
// Here, monotonicity is guaranteed by pre-unioning the type of the previous iteration into the current result.
3194-
let previous_cycle_value = self.class_member_with_policy(db, name.clone(), policy);
3195-
3196-
let ty = if let Some(previous_ty) = previous_cycle_value.place.ignore_possibly_unbound()
3197-
{
3198-
UnionType::from_elements(db, [ty, previous_ty])
3199-
} else {
3200-
ty
3201-
};
3202-
3203-
let div = Type::divergent(DivergentType::new(
3204-
db,
3205-
DivergenceKind::ClassLookupWithPolicy {
3206-
self_type: self,
3207-
name,
3208-
policy,
3209-
},
3210-
));
3211-
let visitor = RecursiveTypeNormalizedVisitor::new(div);
3212-
ty.recursive_type_normalized(db, &visitor)
3213-
})
3171+
}
32143172
}
32153173

32163174
/// This function roughly corresponds to looking up an attribute in the `__dict__` of an object.
@@ -3664,7 +3622,7 @@ impl<'db> Type<'db> {
36643622

36653623
let name_str = name.as_str();
36663624

3667-
let result = match self {
3625+
match self {
36683626
Type::Union(union) => union.map_with_boundness_and_qualifiers(db, |elem| {
36693627
elem.member_lookup_with_policy(db, name_str.into(), policy)
36703628
}),
@@ -4003,30 +3961,7 @@ impl<'db> Type<'db> {
40033961
.try_call_dunder_get_on_attribute(db, owner_attr.clone())
40043962
.unwrap_or(owner_attr)
40053963
}
4006-
};
4007-
result.map_type(|ty| {
4008-
// In fixed-point iteration of type inference, the member type must be monotonically widened and not "oscillate".
4009-
// Here, monotonicity is guaranteed by pre-unioning the type of the previous iteration into the current result.
4010-
let previous_cycle_value = self.member_lookup_with_policy(db, name.clone(), policy);
4011-
4012-
let ty = if let Some(previous_ty) = previous_cycle_value.place.ignore_possibly_unbound()
4013-
{
4014-
UnionType::from_elements(db, [ty, previous_ty])
4015-
} else {
4016-
ty
4017-
};
4018-
4019-
let div = Type::divergent(DivergentType::new(
4020-
db,
4021-
DivergenceKind::MemberLookupWithPolicy {
4022-
self_type: self,
4023-
name,
4024-
policy,
4025-
},
4026-
));
4027-
let visotor = RecursiveTypeNormalizedVisitor::new(div);
4028-
ty.recursive_type_normalized(db, &visotor)
4029-
})
3964+
}
40303965
}
40313966

40323967
/// Resolves the boolean value of the type and falls back to [`Truthiness::Ambiguous`] if the type doesn't implement `__bool__` correctly.
@@ -7485,59 +7420,17 @@ impl<'db> KnownInstanceType<'db> {
74857420
}
74867421
}
74877422

7488-
#[allow(private_interfaces)]
7489-
#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update, get_size2::GetSize)]
7490-
pub enum DivergenceKind<'db> {
7491-
/// Divergence from `{FunctionLiteral, BoundMethodType}::infer_return_type`.
7492-
InferReturnType(ScopeId<'db>),
7493-
/// Divergence from `ClassLiteral::implicit_attribute_inner`.
7494-
ImplicitAttribute {
7495-
class_body_scope: ScopeId<'db>,
7496-
name: String,
7497-
target_method_decorator: MethodDecorator,
7498-
},
7499-
/// Divergence from `Type::member_lookup_with_policy`.
7500-
MemberLookupWithPolicy {
7501-
self_type: Type<'db>,
7502-
name: Name,
7503-
policy: MemberLookupPolicy,
7504-
},
7505-
/// Divergence from `Type::class_lookup_with_policy`.
7506-
ClassLookupWithPolicy {
7507-
self_type: Type<'db>,
7508-
name: Name,
7509-
policy: MemberLookupPolicy,
7510-
},
7511-
/// Divergence from `infer_expression_type_impl`.
7512-
InferExpression(InferExpression<'db>),
7513-
/// Divergence from `infer_expression_types_impl`.
7514-
InferExpressionTypes(InferExpression<'db>),
7515-
/// Divergence from `infer_definition_types`.
7516-
InferDefinitionTypes(Definition<'db>),
7517-
/// Divergence from `infer_scope_types`.
7518-
InferScopeTypes(ScopeId<'db>),
7519-
/// Divergence from `infer_unpack_types`.
7520-
InferUnpackTypes(Unpack<'db>),
7521-
}
7522-
7523-
pub(crate) type CycleRecoveryType<'db> = Type<'db>;
7524-
75257423
/// A type that is determined to be divergent during recursive type inference.
75267424
/// This type must never be eliminated by dynamic type reduction
75277425
/// (e.g. `Divergent` is assignable to `@Todo`, but `@Todo | Divergent` must not be reducted to `@Todo`).
75287426
/// Otherwise, type inference cannot converge properly.
75297427
/// For detailed properties of this type, see the unit test at the end of the file.
7530-
#[salsa::interned(debug, heap_size=ruff_memory_usage::heap_size)]
7531-
#[derive(PartialOrd, Ord)]
7428+
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, salsa::Update, get_size2::GetSize)]
75327429
pub struct DivergentType<'db> {
7533-
/// The kind of divergence.
7534-
#[returns(ref)]
7535-
kind: DivergenceKind<'db>,
7430+
/// The scope where this divergence was detected.
7431+
scope: ScopeId<'db>,
75367432
}
75377433

7538-
// The Salsa heap is tracked separately.
7539-
impl get_size2::GetSize for DivergentType<'_> {}
7540-
75417434
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, salsa::Update, get_size2::GetSize)]
75427435
pub enum DynamicType<'db> {
75437436
/// An explicitly annotated `typing.Any`
@@ -12000,11 +11893,7 @@ pub(crate) mod tests {
1200011893
let file = system_path_to_file(&db, "src/foo.py").unwrap();
1200111894
let file_scope_id = FileScopeId::global();
1200211895
let scope = file_scope_id.to_scope_id(&db, file);
12003-
12004-
let div = Type::divergent(DivergentType::new(
12005-
&db,
12006-
DivergenceKind::InferReturnType(scope),
12007-
));
11896+
let div = Type::divergent(scope);
1200811897

1200911898
// The `Divergent` type must not be eliminated in union with other dynamic types,
1201011899
// as this would prevent detection of divergent type inference using `Divergent`.

0 commit comments

Comments
 (0)