Skip to content

Commit

Permalink
Improve inference capabilities of the BuiltinTypeChecker (#10976)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexWaygood committed Apr 16, 2024
1 parent 65edbfe commit 4284e07
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,8 @@ def __contains__(self, key: object) -> bool:
.keys()
):
continue

from builtins import dict as SneakyDict

d = SneakyDict()
key in d.keys() # SIM118
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,11 @@ def foo():
result = {}
for idx, name in enumerate(fruit):
result[name] = idx # PERF403


def foo():
from builtins import dict as SneakyDict
fruit = ["apple", "pear", "orange"]
result = SneakyDict()
for idx, name in enumerate(fruit):
result[name] = idx # PERF403
8 changes: 8 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/refurb/FURB131.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ def yes_five(x: Dict[int, str]):

x = 1


from builtins import list as SneakyList


sneaky = SneakyList()
# FURB131
del sneaky[:]

# these should not

del names["key"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,5 +397,19 @@ SIM118.py:55:5: SIM118 [*] Use `key in dict` instead of `key in dict.keys()`
58 |+
59 59 | ):
60 60 | continue
61 61 |

SIM118.py:65:1: SIM118 [*] Use `key in dict` instead of `key in dict.keys()`
|
64 | d = SneakyDict()
65 | key in d.keys() # SIM118
| ^^^^^^^^^^^^^^^ SIM118
|
= help: Remove `.keys()`

Safe fix
62 62 | from builtins import dict as SneakyDict
63 63 |
64 64 | d = SneakyDict()
65 |-key in d.keys() # SIM118
65 |+key in d # SIM118
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,10 @@ PERF403.py:83:9: PERF403 Use a dictionary comprehension instead of a for-loop
| ^^^^^^^^^^^^^^^^^^ PERF403
|


PERF403.py:91:9: PERF403 Use a dictionary comprehension instead of a for-loop
|
89 | result = SneakyDict()
90 | for idx, name in enumerate(fruit):
91 | result[name] = idx # PERF403
| ^^^^^^^^^^^^^^^^^^ PERF403
|
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,23 @@ FURB131.py:48:5: FURB131 [*] Prefer `clear` over deleting a full slice
50 50 | x = 1
51 51 |

FURB131.py:58:1: FURB131 [*] Prefer `clear` over deleting a full slice
|
56 | sneaky = SneakyList()
57 | # FURB131
58 | del sneaky[:]
| ^^^^^^^^^^^^^ FURB131
59 |
60 | # these should not
|
= help: Replace with `clear()`

Unsafe fix
55 55 |
56 56 | sneaky = SneakyList()
57 57 | # FURB131
58 |-del sneaky[:]
58 |+sneaky.clear()
59 59 |
60 60 | # these should not
61 61 |
12 changes: 2 additions & 10 deletions crates/ruff_python_semantic/src/analyze/typing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ trait BuiltinTypeChecker {
/// Check annotation expression to match the intended type.
fn match_annotation(annotation: &Expr, semantic: &SemanticModel) -> bool {
let value = map_subscript(annotation);
Self::match_builtin_type(value, semantic)
semantic.match_builtin_expr(value, Self::BUILTIN_TYPE_NAME)
|| semantic.match_typing_expr(value, Self::TYPING_NAME)
}

Expand All @@ -562,15 +562,7 @@ trait BuiltinTypeChecker {
let Expr::Call(ast::ExprCall { func, .. }) = initializer else {
return false;
};
Self::match_builtin_type(func.as_ref(), semantic)
}

/// Check if the given expression names the builtin type.
fn match_builtin_type(type_expr: &Expr, semantic: &SemanticModel) -> bool {
let Expr::Name(ast::ExprName { id, .. }) = type_expr else {
return false;
};
id == Self::BUILTIN_TYPE_NAME && semantic.is_builtin(Self::BUILTIN_TYPE_NAME)
semantic.match_builtin_expr(func, Self::BUILTIN_TYPE_NAME)
}
}

Expand Down

0 comments on commit 4284e07

Please sign in to comment.