[ty] Supress inlay hints when assigning a trivial initializer call (#21848)

## Summary

By taking a purely syntactic approach to the problem of trivial
initializer calls we can supress `x: T = T()`, `x: T = x.y.T()` and `x:
MyNewType = MyNewType(0)` but still display `x: T[U] = T()`.

The place where we drop a ball is this does not compose with our
analysis for supressing `x = (0, "hello")` as `x = (0, T())` and `x =
(T(), T())` will still get inlay hints (I don't think this is a huge
deal).

* fixes https://github.com/astral-sh/ty/issues/1516

## Test Plan

Existing snapshots cover this well.
This commit is contained in:
Aria Desires 2025-12-08 10:54:30 -05:00 committed by GitHub
parent 385dd2770b
commit 3981a23ee9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 87 additions and 321 deletions

View File

@ -19,11 +19,22 @@ pub struct InlayHint {
} }
impl InlayHint { impl InlayHint {
fn variable_type(expr: &Expr, ty: Type, db: &dyn Db, allow_edits: bool) -> Self { fn variable_type(
expr: &Expr,
rhs: &Expr,
ty: Type,
db: &dyn Db,
allow_edits: bool,
) -> Option<Self> {
let position = expr.range().end(); let position = expr.range().end();
// Render the type to a string, and get subspans for all the types that make it up // Render the type to a string, and get subspans for all the types that make it up
let details = ty.display(db).to_string_parts(); let details = ty.display(db).to_string_parts();
// Filter out a reptitive hints like `x: T = T()`
if call_matches_name(rhs, &details.label) {
return None;
}
// Ok so the idea here is that we potentially have a random soup of spans here, // Ok so the idea here is that we potentially have a random soup of spans here,
// and each byte of the string can have at most one target associate with it. // and each byte of the string can have at most one target associate with it.
// Thankfully, they were generally pushed in print order, with the inner smaller types // Thankfully, they were generally pushed in print order, with the inner smaller types
@ -73,12 +84,12 @@ impl InlayHint {
vec![] vec![]
}; };
Self { Some(Self {
position, position,
kind: InlayHintKind::Type, kind: InlayHintKind::Type,
label: InlayHintLabel { parts: label_parts }, label: InlayHintLabel { parts: label_parts },
text_edits, text_edits,
} })
} }
fn call_argument_name( fn call_argument_name(
@ -250,7 +261,7 @@ struct InlayHintVisitor<'a, 'db> {
db: &'db dyn Db, db: &'db dyn Db,
model: SemanticModel<'db>, model: SemanticModel<'db>,
hints: Vec<InlayHint>, hints: Vec<InlayHint>,
in_assignment: bool, assignment_rhs: Option<&'a Expr>,
range: TextRange, range: TextRange,
settings: &'a InlayHintSettings, settings: &'a InlayHintSettings,
in_no_edits_allowed: bool, in_no_edits_allowed: bool,
@ -262,21 +273,21 @@ impl<'a, 'db> InlayHintVisitor<'a, 'db> {
db, db,
model: SemanticModel::new(db, file), model: SemanticModel::new(db, file),
hints: Vec::new(), hints: Vec::new(),
in_assignment: false, assignment_rhs: None,
range, range,
settings, settings,
in_no_edits_allowed: false, in_no_edits_allowed: false,
} }
} }
fn add_type_hint(&mut self, expr: &Expr, ty: Type<'db>, allow_edits: bool) { fn add_type_hint(&mut self, expr: &Expr, rhs: &Expr, ty: Type<'db>, allow_edits: bool) {
if !self.settings.variable_types { if !self.settings.variable_types {
return; return;
} }
let inlay_hint = InlayHint::variable_type(expr, ty, self.db, allow_edits); if let Some(inlay_hint) = InlayHint::variable_type(expr, rhs, ty, self.db, allow_edits) {
self.hints.push(inlay_hint);
self.hints.push(inlay_hint); }
} }
fn add_call_argument_name( fn add_call_argument_name(
@ -299,8 +310,8 @@ impl<'a, 'db> InlayHintVisitor<'a, 'db> {
} }
} }
impl SourceOrderVisitor<'_> for InlayHintVisitor<'_, '_> { impl<'a> SourceOrderVisitor<'a> for InlayHintVisitor<'a, '_> {
fn enter_node(&mut self, node: AnyNodeRef<'_>) -> TraversalSignal { fn enter_node(&mut self, node: AnyNodeRef<'a>) -> TraversalSignal {
if self.range.intersect(node.range()).is_some() { if self.range.intersect(node.range()).is_some() {
TraversalSignal::Traverse TraversalSignal::Traverse
} else { } else {
@ -308,7 +319,7 @@ impl SourceOrderVisitor<'_> for InlayHintVisitor<'_, '_> {
} }
} }
fn visit_stmt(&mut self, stmt: &Stmt) { fn visit_stmt(&mut self, stmt: &'a Stmt) {
let node = AnyNodeRef::from(stmt); let node = AnyNodeRef::from(stmt);
if !self.enter_node(node).is_traverse() { if !self.enter_node(node).is_traverse() {
@ -317,7 +328,9 @@ impl SourceOrderVisitor<'_> for InlayHintVisitor<'_, '_> {
match stmt { match stmt {
Stmt::Assign(assign) => { Stmt::Assign(assign) => {
self.in_assignment = !type_hint_is_excessive_for_expr(&assign.value); if !type_hint_is_excessive_for_expr(&assign.value) {
self.assignment_rhs = Some(&*assign.value);
}
if !annotations_are_valid_syntax(assign) { if !annotations_are_valid_syntax(assign) {
self.in_no_edits_allowed = true; self.in_no_edits_allowed = true;
} }
@ -325,7 +338,7 @@ impl SourceOrderVisitor<'_> for InlayHintVisitor<'_, '_> {
self.visit_expr(target); self.visit_expr(target);
} }
self.in_no_edits_allowed = false; self.in_no_edits_allowed = false;
self.in_assignment = false; self.assignment_rhs = None;
self.visit_expr(&assign.value); self.visit_expr(&assign.value);
@ -344,22 +357,22 @@ impl SourceOrderVisitor<'_> for InlayHintVisitor<'_, '_> {
source_order::walk_stmt(self, stmt); source_order::walk_stmt(self, stmt);
} }
fn visit_expr(&mut self, expr: &'_ Expr) { fn visit_expr(&mut self, expr: &'a Expr) {
match expr { match expr {
Expr::Name(name) => { Expr::Name(name) => {
if self.in_assignment { if let Some(rhs) = self.assignment_rhs {
if name.ctx.is_store() { if name.ctx.is_store() {
let ty = expr.inferred_type(&self.model); let ty = expr.inferred_type(&self.model);
self.add_type_hint(expr, ty, !self.in_no_edits_allowed); self.add_type_hint(expr, rhs, ty, !self.in_no_edits_allowed);
} }
} }
source_order::walk_expr(self, expr); source_order::walk_expr(self, expr);
} }
Expr::Attribute(attribute) => { Expr::Attribute(attribute) => {
if self.in_assignment { if let Some(rhs) = self.assignment_rhs {
if attribute.ctx.is_store() { if attribute.ctx.is_store() {
let ty = expr.inferred_type(&self.model); let ty = expr.inferred_type(&self.model);
self.add_type_hint(expr, ty, !self.in_no_edits_allowed); self.add_type_hint(expr, rhs, ty, !self.in_no_edits_allowed);
} }
} }
source_order::walk_expr(self, expr); source_order::walk_expr(self, expr);
@ -416,6 +429,26 @@ fn arg_matches_name(arg_or_keyword: &ArgOrKeyword, name: &str) -> bool {
} }
} }
/// Given a function call, check if the expression is the "same name"
/// as the function being called.
///
/// This allows us to filter out reptitive inlay hints like `x: T = T(...)`.
/// While still allowing non-trivial ones like `x: T[U] = T()`.
fn call_matches_name(expr: &Expr, name: &str) -> bool {
// Only care about function calls
let Expr::Call(call) = expr else {
return false;
};
match &*call.func {
// `x: T = T()` is a match
Expr::Name(expr_name) => expr_name.id.as_str() == name,
// `x: T = a.T()` is a match
Expr::Attribute(expr_attribute) => expr_attribute.attr.as_str() == name,
_ => false,
}
}
/// Given an expression that's the RHS of an assignment, would it be excessive to /// Given an expression that's the RHS of an assignment, would it be excessive to
/// emit an inlay type hint for the variable assigned to it? /// emit an inlay type hint for the variable assigned to it?
/// ///
@ -1829,35 +1862,16 @@ mod tests {
", ",
); );
assert_snapshot!(test.inlay_hints(), @r#" assert_snapshot!(test.inlay_hints(), @r"
class A: class A:
def __init__(self, y): def __init__(self, y):
self.x[: int] = int(1) self.x = int(1)
self.y[: Unknown] = y self.y[: Unknown] = y
a[: A] = A([y=]2) a = A([y=]2)
a.y[: int] = int(3) a.y = int(3)
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|
347 | @disjoint_base
348 | class int:
| ^^^
349 | """int([x]) -> integer
350 | int(x, base=10) -> integer
|
info: Source
--> main2.py:4:18
|
2 | class A:
3 | def __init__(self, y):
4 | self.x[: int] = int(1)
| ^^^
5 | self.y[: Unknown] = y
|
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> stdlib/ty_extensions.pyi:20:1 --> stdlib/ty_extensions.pyi:20:1
| |
@ -1871,29 +1885,11 @@ mod tests {
--> main2.py:5:18 --> main2.py:5:18
| |
3 | def __init__(self, y): 3 | def __init__(self, y):
4 | self.x[: int] = int(1) 4 | self.x = int(1)
5 | self.y[: Unknown] = y 5 | self.y[: Unknown] = y
| ^^^^^^^ | ^^^^^^^
6 | 6 |
7 | a[: A] = A([y=]2) 7 | a = A([y=]2)
|
info[inlay-hint-location]: Inlay Hint Target
--> main.py:2:7
|
2 | class A:
| ^
3 | def __init__(self, y):
4 | self.x = int(1)
|
info: Source
--> main2.py:7:5
|
5 | self.y[: Unknown] = y
6 |
7 | a[: A] = A([y=]2)
| ^
8 | a.y[: int] = int(3)
| |
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
@ -1906,30 +1902,13 @@ mod tests {
5 | self.y = y 5 | self.y = y
| |
info: Source info: Source
--> main2.py:7:13 --> main2.py:7:8
| |
5 | self.y[: Unknown] = y 5 | self.y[: Unknown] = y
6 | 6 |
7 | a[: A] = A([y=]2) 7 | a = A([y=]2)
| ^ | ^
8 | a.y[: int] = int(3) 8 | a.y = int(3)
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|
347 | @disjoint_base
348 | class int:
| ^^^
349 | """int([x]) -> integer
350 | int(x, base=10) -> integer
|
info: Source
--> main2.py:8:7
|
7 | a[: A] = A([y=]2)
8 | a.y[: int] = int(3)
| ^^^
| |
--------------------------------------------- ---------------------------------------------
@ -1938,12 +1917,12 @@ mod tests {
class A: class A:
def __init__(self, y): def __init__(self, y):
self.x: int = int(1) self.x = int(1)
self.y: Unknown = y self.y: Unknown = y
a: A = A(2) a = A(2)
a.y: int = int(3) a.y = int(3)
"#); ");
} }
#[test] #[test]
@ -2937,31 +2916,12 @@ mod tests {
def __init__(self): def __init__(self):
self.x: int = 1 self.x: int = 1
x[: MyClass] = MyClass() x = MyClass()
y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass()) y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass())
a[: MyClass], b[: MyClass] = MyClass(), MyClass() a[: MyClass], b[: MyClass] = MyClass(), MyClass()
c[: MyClass], d[: MyClass] = (MyClass(), MyClass()) c[: MyClass], d[: MyClass] = (MyClass(), MyClass())
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> main.py:2:7
|
2 | class MyClass:
| ^^^^^^^
3 | def __init__(self):
4 | self.x: int = 1
|
info: Source
--> main2.py:6:5
|
4 | self.x: int = 1
5 |
6 | x[: MyClass] = MyClass()
| ^^^^^^^
7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass())
8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass()
|
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:2695:7 --> stdlib/builtins.pyi:2695:7
| |
@ -2973,7 +2933,7 @@ mod tests {
info: Source info: Source
--> main2.py:7:5 --> main2.py:7:5
| |
6 | x[: MyClass] = MyClass() 6 | x = MyClass()
7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass()) 7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass())
| ^^^^^ | ^^^^^
8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass() 8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass()
@ -2991,7 +2951,7 @@ mod tests {
info: Source info: Source
--> main2.py:7:11 --> main2.py:7:11
| |
6 | x[: MyClass] = MyClass() 6 | x = MyClass()
7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass()) 7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass())
| ^^^^^^^ | ^^^^^^^
8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass() 8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass()
@ -3009,7 +2969,7 @@ mod tests {
info: Source info: Source
--> main2.py:7:20 --> main2.py:7:20
| |
6 | x[: MyClass] = MyClass() 6 | x = MyClass()
7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass()) 7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass())
| ^^^^^^^ | ^^^^^^^
8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass() 8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass()
@ -3027,7 +2987,7 @@ mod tests {
info: Source info: Source
--> main2.py:8:5 --> main2.py:8:5
| |
6 | x[: MyClass] = MyClass() 6 | x = MyClass()
7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass()) 7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass())
8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass() 8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass()
| ^^^^^^^ | ^^^^^^^
@ -3045,7 +3005,7 @@ mod tests {
info: Source info: Source
--> main2.py:8:19 --> main2.py:8:19
| |
6 | x[: MyClass] = MyClass() 6 | x = MyClass()
7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass()) 7 | y[: tuple[MyClass, MyClass]] = (MyClass(), MyClass())
8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass() 8 | a[: MyClass], b[: MyClass] = MyClass(), MyClass()
| ^^^^^^^ | ^^^^^^^
@ -3094,7 +3054,7 @@ mod tests {
def __init__(self): def __init__(self):
self.x: int = 1 self.x: int = 1
x: MyClass = MyClass() x = MyClass()
y: tuple[MyClass, MyClass] = (MyClass(), MyClass()) y: tuple[MyClass, MyClass] = (MyClass(), MyClass())
a, b = MyClass(), MyClass() a, b = MyClass(), MyClass()
c, d = (MyClass(), MyClass()) c, d = (MyClass(), MyClass())
@ -4097,31 +4057,11 @@ mod tests {
def __init__(self): def __init__(self):
self.x: int = 1 self.x: int = 1
self.y: int = 2 self.y: int = 2
val[: MyClass] = MyClass() val = MyClass()
foo(val.x) foo(val.x)
foo([x=]val.y) foo([x=]val.y)
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> main.py:3:7
|
2 | def foo(x: int): pass
3 | class MyClass:
| ^^^^^^^
4 | def __init__(self):
5 | self.x: int = 1
|
info: Source
--> main2.py:7:7
|
5 | self.x: int = 1
6 | self.y: int = 2
7 | val[: MyClass] = MyClass()
| ^^^^^^^
8 |
9 | foo(val.x)
|
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> main.py:2:9 --> main.py:2:9
| |
@ -4137,20 +4077,6 @@ mod tests {
10 | foo([x=]val.y) 10 | foo([x=]val.y)
| ^ | ^
| |
---------------------------------------------
info[inlay-hint-edit]: File after edits
info: Source
def foo(x: int): pass
class MyClass:
def __init__(self):
self.x: int = 1
self.y: int = 2
val: MyClass = MyClass()
foo(val.x)
foo(val.y)
"); ");
} }
@ -4176,31 +4102,11 @@ mod tests {
def __init__(self): def __init__(self):
self.x: int = 1 self.x: int = 1
self.y: int = 2 self.y: int = 2
x[: MyClass] = MyClass() x = MyClass()
foo(x.x) foo(x.x)
foo([x=]x.y) foo([x=]x.y)
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> main.py:3:7
|
2 | def foo(x: int): pass
3 | class MyClass:
| ^^^^^^^
4 | def __init__(self):
5 | self.x: int = 1
|
info: Source
--> main2.py:7:5
|
5 | self.x: int = 1
6 | self.y: int = 2
7 | x[: MyClass] = MyClass()
| ^^^^^^^
8 |
9 | foo(x.x)
|
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> main.py:2:9 --> main.py:2:9
| |
@ -4216,20 +4122,6 @@ mod tests {
10 | foo([x=]x.y) 10 | foo([x=]x.y)
| ^ | ^
| |
---------------------------------------------
info[inlay-hint-edit]: File after edits
info: Source
def foo(x: int): pass
class MyClass:
def __init__(self):
self.x: int = 1
self.y: int = 2
x: MyClass = MyClass()
foo(x.x)
foo(x.y)
"); ");
} }
@ -4258,31 +4150,11 @@ mod tests {
return 1 return 1
def y() -> int: def y() -> int:
return 2 return 2
val[: MyClass] = MyClass() val = MyClass()
foo(val.x()) foo(val.x())
foo([x=]val.y()) foo([x=]val.y())
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> main.py:3:7
|
2 | def foo(x: int): pass
3 | class MyClass:
| ^^^^^^^
4 | def __init__(self):
5 | def x() -> int:
|
info: Source
--> main2.py:9:7
|
7 | def y() -> int:
8 | return 2
9 | val[: MyClass] = MyClass()
| ^^^^^^^
10 |
11 | foo(val.x())
|
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> main.py:2:9 --> main.py:2:9
| |
@ -4298,22 +4170,6 @@ mod tests {
12 | foo([x=]val.y()) 12 | foo([x=]val.y())
| ^ | ^
| |
---------------------------------------------
info[inlay-hint-edit]: File after edits
info: Source
def foo(x: int): pass
class MyClass:
def __init__(self):
def x() -> int:
return 1
def y() -> int:
return 2
val: MyClass = MyClass()
foo(val.x())
foo(val.y())
"); ");
} }
@ -4346,31 +4202,11 @@ mod tests {
return 1 return 1
def y() -> List[int]: def y() -> List[int]:
return 2 return 2
val[: MyClass] = MyClass() val = MyClass()
foo(val.x()[0]) foo(val.x()[0])
foo([x=]val.y()[1]) foo([x=]val.y()[1])
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> main.py:5:7
|
4 | def foo(x: int): pass
5 | class MyClass:
| ^^^^^^^
6 | def __init__(self):
7 | def x() -> List[int]:
|
info: Source
--> main2.py:11:7
|
9 | def y() -> List[int]:
10 | return 2
11 | val[: MyClass] = MyClass()
| ^^^^^^^
12 |
13 | foo(val.x()[0])
|
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> main.py:4:9 --> main.py:4:9
| |
@ -4388,24 +4224,6 @@ mod tests {
14 | foo([x=]val.y()[1]) 14 | foo([x=]val.y()[1])
| ^ | ^
| |
---------------------------------------------
info[inlay-hint-edit]: File after edits
info: Source
from typing import List
def foo(x: int): pass
class MyClass:
def __init__(self):
def x() -> List[int]:
return 1
def y() -> List[int]:
return 2
val: MyClass = MyClass()
foo(val.x()[0])
foo(val.y()[1])
"); ");
} }
@ -4697,7 +4515,7 @@ mod tests {
class Foo: class Foo:
def __init__(self, x: int): pass def __init__(self, x: int): pass
Foo([x=]1) Foo([x=]1)
f[: Foo] = Foo([x=]1) f = Foo([x=]1)
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> main.py:3:24 --> main.py:3:24
@ -4715,24 +4533,7 @@ mod tests {
3 | def __init__(self, x: int): pass 3 | def __init__(self, x: int): pass
4 | Foo([x=]1) 4 | Foo([x=]1)
| ^ | ^
5 | f[: Foo] = Foo([x=]1) 5 | f = Foo([x=]1)
|
info[inlay-hint-location]: Inlay Hint Target
--> main.py:2:7
|
2 | class Foo:
| ^^^
3 | def __init__(self, x: int): pass
4 | Foo(1)
|
info: Source
--> main2.py:5:5
|
3 | def __init__(self, x: int): pass
4 | Foo([x=]1)
5 | f[: Foo] = Foo([x=]1)
| ^^^
| |
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
@ -4745,22 +4546,13 @@ mod tests {
5 | f = Foo(1) 5 | f = Foo(1)
| |
info: Source info: Source
--> main2.py:5:17 --> main2.py:5:10
| |
3 | def __init__(self, x: int): pass 3 | def __init__(self, x: int): pass
4 | Foo([x=]1) 4 | Foo([x=]1)
5 | f[: Foo] = Foo([x=]1) 5 | f = Foo([x=]1)
| ^ | ^
| |
---------------------------------------------
info[inlay-hint-edit]: File after edits
info: Source
class Foo:
def __init__(self, x: int): pass
Foo(1)
f: Foo = Foo(1)
"); ");
} }
@ -4778,7 +4570,7 @@ mod tests {
class Foo: class Foo:
def __new__(cls, x: int): pass def __new__(cls, x: int): pass
Foo([x=]1) Foo([x=]1)
f[: Foo] = Foo([x=]1) f = Foo([x=]1)
--------------------------------------------- ---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
--> main.py:3:22 --> main.py:3:22
@ -4796,24 +4588,7 @@ mod tests {
3 | def __new__(cls, x: int): pass 3 | def __new__(cls, x: int): pass
4 | Foo([x=]1) 4 | Foo([x=]1)
| ^ | ^
5 | f[: Foo] = Foo([x=]1) 5 | f = Foo([x=]1)
|
info[inlay-hint-location]: Inlay Hint Target
--> main.py:2:7
|
2 | class Foo:
| ^^^
3 | def __new__(cls, x: int): pass
4 | Foo(1)
|
info: Source
--> main2.py:5:5
|
3 | def __new__(cls, x: int): pass
4 | Foo([x=]1)
5 | f[: Foo] = Foo([x=]1)
| ^^^
| |
info[inlay-hint-location]: Inlay Hint Target info[inlay-hint-location]: Inlay Hint Target
@ -4826,22 +4601,13 @@ mod tests {
5 | f = Foo(1) 5 | f = Foo(1)
| |
info: Source info: Source
--> main2.py:5:17 --> main2.py:5:10
| |
3 | def __new__(cls, x: int): pass 3 | def __new__(cls, x: int): pass
4 | Foo([x=]1) 4 | Foo([x=]1)
5 | f[: Foo] = Foo([x=]1) 5 | f = Foo([x=]1)
| ^ | ^
| |
---------------------------------------------
info[inlay-hint-edit]: File after edits
info: Source
class Foo:
def __new__(cls, x: int): pass
Foo(1)
f: Foo = Foo(1)
"); ");
} }