Skip to content

Commit 2cdaedf

Browse files
committed
Implement literal promotion
1 parent c491e71 commit 2cdaedf

File tree

5 files changed

+34
-24
lines changed

5 files changed

+34
-24
lines changed

crates/ty_ide/src/goto.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,8 @@ pub(crate) fn find_goto_target(
895895
| TokenKind::Float
896896
| TokenKind::Int => 1,
897897

898+
TokenKind::Comment => -1,
899+
898900
// if we have a<CURSOR>+b`, prefer the `+` token (by respecting the token ordering)
899901
// This matches VS Code's behavior where it sends the start of the clicked token as offset.
900902
kind if kind.as_binary_operator().is_some() || kind.as_unary_operator().is_some() => 1,

crates/ty_ide/src/goto_definition.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,25 +1284,7 @@ class Test:
12841284
)
12851285
.build();
12861286

1287-
assert_snapshot!(test.goto_definition(), @r"
1288-
info[goto-definition]: Definition
1289-
--> main.py:3:9
1290-
|
1291-
2 | class Test:
1292-
3 | def __add__(self, other):
1293-
| ^^^^^^^
1294-
4 | return Test()
1295-
|
1296-
info: Source
1297-
--> main.py:8:5
1298-
|
1299-
7 | (
1300-
8 | / Test() # comment
1301-
9 | | + Test()
1302-
| |____________^
1303-
10 | )
1304-
|
1305-
");
1287+
assert_snapshot!(test.goto_definition(), @"No goto target found");
13061288
}
13071289

13081290
#[test]

crates/ty_ide/src/hover.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,15 +2522,14 @@ def ab(a: int, *, c: int):
25222522
"#,
25232523
);
25242524

2525-
// TODO: It would be ncie to show `int.__add__(...)` instead of `Literal[5].__add__(...)` here.
25262525
assert_snapshot!(test.hover(), @r"
2527-
bound method Literal[5].__add__(value: int, /) -> int
2526+
bound method int.__add__(value: int, /) -> int
25282527
---------------------------------------------
25292528
Return self+value.
25302529
25312530
---------------------------------------------
25322531
```python
2533-
bound method Literal[5].__add__(value: int, /) -> int
2532+
bound method int.__add__(value: int, /) -> int
25342533
```
25352534
---
25362535
```text

crates/ty_python_semantic/src/types.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9970,6 +9970,14 @@ impl<'db> BoundMethodType<'db> {
99709970
self_instance
99719971
}
99729972

9973+
pub(crate) fn map_self_type(
9974+
self,
9975+
db: &'db dyn Db,
9976+
f: impl FnOnce(Type<'db>) -> Type<'db>,
9977+
) -> Self {
9978+
Self::new(db, self.function(db), f(self.self_instance(db)))
9979+
}
9980+
99739981
#[salsa::tracked(cycle_fn=into_callable_type_cycle_recover, cycle_initial=into_callable_type_cycle_initial, heap_size=ruff_memory_usage::heap_size)]
99749982
pub(crate) fn into_callable_type(self, db: &'db dyn Db) -> CallableType<'db> {
99759983
let function = self.function(db);

crates/ty_python_semantic/src/types/ide_support.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,8 @@ pub fn definitions_for_bin_op<'db>(
943943
return None;
944944
};
945945

946-
let callable_type = bindings.callable_type();
946+
let callable_type = promote_literals_for_self(db, bindings.callable_type());
947+
947948
let definitions: Vec<_> = bindings
948949
.into_iter()
949950
.flat_map(std::iter::IntoIterator::into_iter)
@@ -981,7 +982,7 @@ pub fn definitions_for_unary_op<'db>(
981982
return None;
982983
};
983984

984-
let callable_type = bindings.callable_type();
985+
let callable_type = promote_literals_for_self(db, bindings.callable_type());
985986

986987
let definitions = bindings
987988
.into_iter()
@@ -996,6 +997,24 @@ pub fn definitions_for_unary_op<'db>(
996997
Some((definitions, callable_type))
997998
}
998999

1000+
/// Promotes literal types in `self` positions to their fallback instance types.
1001+
///
1002+
/// This is so that we show `int.__add__` instead of `IntLiteral.__add__`.
1003+
fn promote_literals_for_self<'db>(db: &'db dyn Db, ty: Type<'db>) -> Type<'db> {
1004+
match ty {
1005+
Type::BoundMethod(method) => Type::BoundMethod(method.map_self_type(db, |self_ty| {
1006+
self_ty.literal_fallback_instance(db).unwrap_or(self_ty)
1007+
})),
1008+
Type::Union(elements) => elements.map(db, |ty| match ty {
1009+
Type::BoundMethod(method) => Type::BoundMethod(method.map_self_type(db, |self_ty| {
1010+
self_ty.literal_fallback_instance(db).unwrap_or(self_ty)
1011+
})),
1012+
_ => *ty,
1013+
}),
1014+
ty => ty,
1015+
}
1016+
}
1017+
9991018
/// Find the active signature index from `CallSignatureDetails`.
10001019
/// The active signature is the first signature where all arguments present in the call
10011020
/// have valid mappings to parameters (i.e., none of the mappings are None).

0 commit comments

Comments
 (0)