Rename SemanticModel::is_builtin to SemanticModel::has_builtin_binding (#10991)

This commit is contained in:
Alex Waygood 2024-04-18 11:11:42 +01:00 committed by GitHub
parent 2cc487eb22
commit e09180b1df
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
46 changed files with 74 additions and 67 deletions

View file

@ -1909,7 +1909,7 @@ impl<'a> Checker<'a> {
} }
{ {
let (all_names, all_flags) = let (all_names, all_flags) =
extract_all_names(parent, |name| self.semantic.is_builtin(name)); extract_all_names(parent, |name| self.semantic.has_builtin_binding(name));
if all_flags.intersects(DunderAllFlags::INVALID_OBJECT) { if all_flags.intersects(DunderAllFlags::INVALID_OBJECT) {
flags |= BindingFlags::INVALID_ALL_OBJECT; flags |= BindingFlags::INVALID_ALL_OBJECT;

View file

@ -246,7 +246,7 @@ impl<'a> Importer<'a> {
at: TextSize, at: TextSize,
semantic: &SemanticModel, semantic: &SemanticModel,
) -> Result<(Option<Edit>, String), ResolutionError> { ) -> Result<(Option<Edit>, String), ResolutionError> {
if semantic.is_builtin(symbol) { if semantic.has_builtin_binding(symbol) {
return Ok((None, symbol.to_string())); return Ok((None, symbol.to_string()));
} }
let (import_edit, binding) = let (import_edit, binding) =

View file

@ -464,7 +464,7 @@ fn find_shell_keyword<'a>(
semantic: &SemanticModel, semantic: &SemanticModel,
) -> Option<ShellKeyword<'a>> { ) -> Option<ShellKeyword<'a>> {
arguments.find_keyword("shell").map(|keyword| ShellKeyword { arguments.find_keyword("shell").map(|keyword| ShellKeyword {
truthiness: Truthiness::from_expr(&keyword.value, |id| semantic.is_builtin(id)), truthiness: Truthiness::from_expr(&keyword.value, |id| semantic.has_builtin_binding(id)),
keyword, keyword,
}) })
} }

View file

@ -148,7 +148,7 @@ pub(crate) fn boolean_type_hint_positional_argument(
} }
// If `bool` isn't actually a reference to the `bool` built-in, return. // If `bool` isn't actually a reference to the `bool` built-in, return.
if !checker.semantic().is_builtin("bool") { if !checker.semantic().has_builtin_binding("bool") {
return; return;
} }

View file

@ -107,7 +107,7 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, stmt_for: &ast
// Avoid fixing any variables that _may_ be used, but undetectably so. // Avoid fixing any variables that _may_ be used, but undetectably so.
let certainty = let certainty =
Certainty::from(!helpers::uses_magic_variable_access(&stmt_for.body, |id| { Certainty::from(!helpers::uses_magic_variable_access(&stmt_for.body, |id| {
checker.semantic().is_builtin(id) checker.semantic().has_builtin_binding(id)
})); }));
// Attempt to rename the variable by prepending an underscore, but avoid // Attempt to rename the variable by prepending an underscore, but avoid

View file

@ -95,7 +95,7 @@ pub(crate) fn useless_expression(checker: &mut Checker, value: &Expr) {
} }
// Ignore statements that have side effects. // Ignore statements that have side effects.
if contains_effect(value, |id| checker.semantic().is_builtin(id)) { if contains_effect(value, |id| checker.semantic().has_builtin_binding(id)) {
// Flag attributes as useless expressions, even if they're attached to calls or other // Flag attributes as useless expressions, even if they're attached to calls or other
// expressions. // expressions.
if value.is_attribute_expr() { if value.is_attribute_expr() {

View file

@ -60,7 +60,7 @@ fn add_diagnostic(checker: &mut Checker, expr: &Expr) {
Expr::DictComp(_) => "dict", Expr::DictComp(_) => "dict",
_ => return, _ => return,
}; };
if !checker.semantic().is_builtin(id) { if !checker.semantic().has_builtin_binding(id) {
return; return;
} }
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(

View file

@ -71,7 +71,7 @@ pub(crate) fn unnecessary_generator_list(checker: &mut Checker, call: &ast::Expr
) else { ) else {
return; return;
}; };
if !checker.semantic().is_builtin("list") { if !checker.semantic().has_builtin_binding("list") {
return; return;
} }

View file

@ -72,7 +72,7 @@ pub(crate) fn unnecessary_generator_set(checker: &mut Checker, call: &ast::ExprC
) else { ) else {
return; return;
}; };
if !checker.semantic().is_builtin("set") { if !checker.semantic().has_builtin_binding("set") {
return; return;
} }

View file

@ -53,7 +53,7 @@ pub(crate) fn unnecessary_list_call(
let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else { let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else {
return; return;
}; };
if !checker.semantic().is_builtin("list") { if !checker.semantic().has_builtin_binding("list") {
return; return;
} }
if !argument.is_list_comp_expr() { if !argument.is_list_comp_expr() {

View file

@ -56,7 +56,7 @@ pub(crate) fn unnecessary_list_comprehension_dict(
else { else {
return; return;
}; };
if !checker.semantic().is_builtin("dict") { if !checker.semantic().has_builtin_binding("dict") {
return; return;
} }
let Expr::ListComp(ast::ExprListComp { elt, .. }) = argument else { let Expr::ListComp(ast::ExprListComp { elt, .. }) = argument else {

View file

@ -52,7 +52,7 @@ pub(crate) fn unnecessary_list_comprehension_set(checker: &mut Checker, call: &a
) else { ) else {
return; return;
}; };
if !checker.semantic().is_builtin("set") { if !checker.semantic().has_builtin_binding("set") {
return; return;
} }
if argument.is_list_comp_expr() { if argument.is_list_comp_expr() {

View file

@ -63,7 +63,7 @@ pub(crate) fn unnecessary_literal_dict(
else { else {
return; return;
}; };
if !checker.semantic().is_builtin("dict") { if !checker.semantic().has_builtin_binding("dict") {
return; return;
} }
let (kind, elts) = match argument { let (kind, elts) = match argument {

View file

@ -60,7 +60,7 @@ pub(crate) fn unnecessary_literal_set(checker: &mut Checker, call: &ast::ExprCal
) else { ) else {
return; return;
}; };
if !checker.semantic().is_builtin("set") { if !checker.semantic().has_builtin_binding("set") {
return; return;
} }
let kind = match argument { let kind = match argument {

View file

@ -75,7 +75,7 @@ pub(crate) fn unnecessary_literal_within_dict_call(checker: &mut Checker, call:
else { else {
return; return;
}; };
if !checker.semantic().is_builtin("dict") { if !checker.semantic().has_builtin_binding("dict") {
return; return;
} }
let argument_kind = match argument { let argument_kind = match argument {

View file

@ -77,7 +77,7 @@ pub(crate) fn unnecessary_literal_within_list_call(checker: &mut Checker, call:
else { else {
return; return;
}; };
if !checker.semantic().is_builtin("list") { if !checker.semantic().has_builtin_binding("list") {
return; return;
} }
let argument_kind = match argument { let argument_kind = match argument {

View file

@ -80,7 +80,7 @@ pub(crate) fn unnecessary_literal_within_tuple_call(checker: &mut Checker, call:
) else { ) else {
return; return;
}; };
if !checker.semantic().is_builtin("tuple") { if !checker.semantic().has_builtin_binding("tuple") {
return; return;
} }
let argument_kind = match argument { let argument_kind = match argument {

View file

@ -85,7 +85,8 @@ fn exc_info_arg_is_falsey(call: &ExprCall, checker: &mut Checker) -> bool {
.find_keyword("exc_info") .find_keyword("exc_info")
.map(|keyword| &keyword.value) .map(|keyword| &keyword.value)
.is_some_and(|value| { .is_some_and(|value| {
let truthiness = Truthiness::from_expr(value, |id| checker.semantic().is_builtin(id)); let truthiness =
Truthiness::from_expr(value, |id| checker.semantic().has_builtin_binding(id));
matches!(truthiness, Truthiness::False | Truthiness::Falsey) matches!(truthiness, Truthiness::False | Truthiness::Falsey)
}) })
} }

View file

@ -71,7 +71,7 @@ pub(crate) fn invalid_get_logger_argument(checker: &mut Checker, call: &ast::Exp
return; return;
} }
if !checker.semantic().is_builtin(id) { if !checker.semantic().has_builtin_binding(id) {
return; return;
} }
@ -84,7 +84,7 @@ pub(crate) fn invalid_get_logger_argument(checker: &mut Checker, call: &ast::Exp
} }
let mut diagnostic = Diagnostic::new(InvalidGetLoggerArgument, expr.range()); let mut diagnostic = Diagnostic::new(InvalidGetLoggerArgument, expr.range());
if checker.semantic().is_builtin("__name__") { if checker.semantic().has_builtin_binding("__name__") {
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
"__name__".to_string(), "__name__".to_string(),
expr.range(), expr.range(),

View file

@ -97,7 +97,7 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr)
union.range(), union.range(),
); );
if semantic.is_builtin("type") { if semantic.has_builtin_binding("type") {
let content = if let Some(subscript) = subscript { let content = if let Some(subscript) = subscript {
let types = &Expr::Subscript(ast::ExprSubscript { let types = &Expr::Subscript(ast::ExprSubscript {
value: Box::new(Expr::Name(ast::ExprName { value: Box::new(Expr::Name(ast::ExprName {

View file

@ -488,7 +488,7 @@ fn to_pytest_raises_args<'a>(
/// PT015 /// PT015
pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) { pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) {
let truthiness = Truthiness::from_expr(test, |id| checker.semantic().is_builtin(id)); let truthiness = Truthiness::from_expr(test, |id| checker.semantic().has_builtin_binding(id));
if matches!(truthiness, Truthiness::False | Truthiness::Falsey) { if matches!(truthiness, Truthiness::False | Truthiness::Falsey) {
checker checker
.diagnostics .diagnostics

View file

@ -385,7 +385,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
}, },
expr.range(), expr.range(),
); );
if !contains_effect(target, |id| checker.semantic().is_builtin(id)) { if !contains_effect(target, |id| checker.semantic().has_builtin_binding(id)) {
// Grab the types used in each duplicate `isinstance` call (e.g., `int` and `str` // Grab the types used in each duplicate `isinstance` call (e.g., `int` and `str`
// in `isinstance(obj, int) or isinstance(obj, str)`). // in `isinstance(obj, int) or isinstance(obj, str)`).
let types: Vec<&Expr> = indices let types: Vec<&Expr> = indices
@ -520,7 +520,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
// Avoid rewriting (e.g.) `a == "foo" or a == f()`. // Avoid rewriting (e.g.) `a == "foo" or a == f()`.
if comparators if comparators
.iter() .iter()
.any(|expr| contains_effect(expr, |id| checker.semantic().is_builtin(id))) .any(|expr| contains_effect(expr, |id| checker.semantic().has_builtin_binding(id)))
{ {
continue; continue;
} }
@ -614,7 +614,7 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
return; return;
} }
if contains_effect(expr, |id| checker.semantic().is_builtin(id)) { if contains_effect(expr, |id| checker.semantic().has_builtin_binding(id)) {
return; return;
} }
@ -671,7 +671,7 @@ pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) {
return; return;
} }
if contains_effect(expr, |id| checker.semantic().is_builtin(id)) { if contains_effect(expr, |id| checker.semantic().has_builtin_binding(id)) {
return; return;
} }
@ -748,14 +748,15 @@ fn is_short_circuit(
for (index, (value, next_value)) in values.iter().tuple_windows().enumerate() { for (index, (value, next_value)) in values.iter().tuple_windows().enumerate() {
// Keep track of the location of the furthest-right, truthy or falsey expression. // Keep track of the location of the furthest-right, truthy or falsey expression.
let value_truthiness = Truthiness::from_expr(value, |id| checker.semantic().is_builtin(id)); let value_truthiness =
Truthiness::from_expr(value, |id| checker.semantic().has_builtin_binding(id));
let next_value_truthiness = let next_value_truthiness =
Truthiness::from_expr(next_value, |id| checker.semantic().is_builtin(id)); Truthiness::from_expr(next_value, |id| checker.semantic().has_builtin_binding(id));
// Keep track of the location of the furthest-right, non-effectful expression. // Keep track of the location of the furthest-right, non-effectful expression.
if value_truthiness.is_unknown() if value_truthiness.is_unknown()
&& (!checker.semantic().in_boolean_test() && (!checker.semantic().in_boolean_test()
|| contains_effect(value, |id| checker.semantic().is_builtin(id))) || contains_effect(value, |id| checker.semantic().has_builtin_binding(id)))
{ {
furthest = next_value; furthest = next_value;
continue; continue;

View file

@ -172,7 +172,7 @@ pub(crate) fn if_expr_with_true_false(
.to_string(), .to_string(),
expr.range(), expr.range(),
))); )));
} else if checker.semantic().is_builtin("bool") { } else if checker.semantic().has_builtin_binding("bool") {
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
checker.generator().expr( checker.generator().expr(
&ast::ExprCall { &ast::ExprCall {

View file

@ -270,7 +270,7 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: UnaryOp, o
checker.locator().slice(operand.as_ref()).to_string(), checker.locator().slice(operand.as_ref()).to_string(),
expr.range(), expr.range(),
))); )));
} else if checker.semantic().is_builtin("bool") { } else if checker.semantic().has_builtin_binding("bool") {
let node = ast::ExprName { let node = ast::ExprName {
id: "bool".into(), id: "bool".into(),
ctx: ExprContext::Load, ctx: ExprContext::Load,

View file

@ -161,7 +161,9 @@ pub(crate) fn if_else_block_instead_of_dict_get(checker: &mut Checker, stmt_if:
} }
// Check that the default value is not "complex". // Check that the default value is not "complex".
if contains_effect(default_value, |id| checker.semantic().is_builtin(id)) { if contains_effect(default_value, |id| {
checker.semantic().has_builtin_binding(id)
}) {
return; return;
} }
@ -261,7 +263,9 @@ pub(crate) fn if_exp_instead_of_dict_get(
} }
// Check that the default value is not "complex". // Check that the default value is not "complex".
if contains_effect(default_value, |id| checker.semantic().is_builtin(id)) { if contains_effect(default_value, |id| {
checker.semantic().has_builtin_binding(id)
}) {
return; return;
} }

View file

@ -77,10 +77,9 @@ pub(crate) fn if_else_block_instead_of_dict_lookup(checker: &mut Checker, stmt_i
return; return;
}; };
if value if value.as_ref().is_some_and(|value| {
.as_ref() contains_effect(value, |id| checker.semantic().has_builtin_binding(id))
.is_some_and(|value| contains_effect(value, |id| checker.semantic().is_builtin(id))) }) {
{
return; return;
} }
@ -112,7 +111,7 @@ pub(crate) fn if_else_block_instead_of_dict_lookup(checker: &mut Checker, stmt_i
return; return;
}; };
if value.as_ref().is_some_and(|value| { if value.as_ref().is_some_and(|value| {
contains_effect(value, |id| checker.semantic().is_builtin(id)) contains_effect(value, |id| checker.semantic().has_builtin_binding(id))
}) { }) {
return; return;
}; };
@ -138,7 +137,7 @@ pub(crate) fn if_else_block_instead_of_dict_lookup(checker: &mut Checker, stmt_i
}; };
if value.as_ref().is_some_and(|value| { if value.as_ref().is_some_and(|value| {
contains_effect(value, |id| checker.semantic().is_builtin(id)) contains_effect(value, |id| checker.semantic().has_builtin_binding(id))
}) { }) {
return; return;
}; };

View file

@ -207,7 +207,7 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) {
// If the condition is a comparison, we can replace it with the condition, since we // If the condition is a comparison, we can replace it with the condition, since we
// know it's a boolean. // know it's a boolean.
Some(if_test.clone()) Some(if_test.clone())
} else if checker.semantic().is_builtin("bool") { } else if checker.semantic().has_builtin_binding("bool") {
// Otherwise, we need to wrap the condition in a call to `bool`. // Otherwise, we need to wrap the condition in a call to `bool`.
let func_node = ast::ExprName { let func_node = ast::ExprName {
id: "bool".into(), id: "bool".into(),

View file

@ -113,7 +113,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) {
}, },
TextRange::new(stmt.start(), terminal.stmt.end()), TextRange::new(stmt.start(), terminal.stmt.end()),
); );
if checker.semantic().is_builtin("any") { if checker.semantic().has_builtin_binding("any") {
diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement(
contents, contents,
stmt.start(), stmt.start(),
@ -199,7 +199,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) {
}, },
TextRange::new(stmt.start(), terminal.stmt.end()), TextRange::new(stmt.start(), terminal.stmt.end()),
); );
if checker.semantic().is_builtin("all") { if checker.semantic().has_builtin_binding("all") {
diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement(
contents, contents,
stmt.start(), stmt.start(),

View file

@ -134,7 +134,7 @@ fn deprecated_type_comparison(checker: &mut Checker, compare: &ast::ExprCompare)
| "dict" | "dict"
| "set" | "set"
| "memoryview" | "memoryview"
) && semantic.is_builtin(id) ) && semantic.has_builtin_binding(id)
{ {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
TypeComparison { TypeComparison {
@ -289,7 +289,7 @@ fn is_type(expr: &Expr, semantic: &SemanticModel) -> bool {
| "ValueError" | "ValueError"
| "Warning" | "Warning"
| "ZeroDivisionError" | "ZeroDivisionError"
) && semantic.is_builtin(id) ) && semantic.has_builtin_binding(id)
} }
_ => false, _ => false,
} }

View file

@ -219,7 +219,7 @@ fn remove_unused_variable(binding: &Binding, checker: &Checker) -> Option<Fix> {
{ {
if target.is_name_expr() { if target.is_name_expr() {
return if targets.len() > 1 return if targets.len() > 1
|| contains_effect(value, |id| checker.semantic().is_builtin(id)) || contains_effect(value, |id| checker.semantic().has_builtin_binding(id))
{ {
// If the expression is complex (`x = foo()`), remove the assignment, // If the expression is complex (`x = foo()`), remove the assignment,
// but preserve the right-hand side. // but preserve the right-hand side.
@ -265,7 +265,7 @@ fn remove_unused_variable(binding: &Binding, checker: &Checker) -> Option<Fix> {
}) = statement }) = statement
{ {
if target.is_name_expr() { if target.is_name_expr() {
return if contains_effect(value, |id| checker.semantic().is_builtin(id)) { return if contains_effect(value, |id| checker.semantic().has_builtin_binding(id)) {
// If the expression is complex (`x = foo()`), remove the assignment, // If the expression is complex (`x = foo()`), remove the assignment,
// but preserve the right-hand side. // but preserve the right-hand side.
let start = statement.start(); let start = statement.start();

View file

@ -177,7 +177,7 @@ pub(crate) fn if_stmt_min_max(checker: &mut Checker, stmt_if: &ast::StmtIf) {
stmt_if.range(), stmt_if.range(),
); );
if checker.semantic().is_builtin(min_max.as_str()) { if checker.semantic().has_builtin_binding(min_max.as_str()) {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
replacement, replacement,
stmt_if.range(), stmt_if.range(),

View file

@ -116,7 +116,7 @@ fn get_undecorated_methods(checker: &mut Checker, class_stmt: &Stmt, method_type
}) = value.as_ref() }) = value.as_ref()
{ {
if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() {
if id == method_name && checker.semantic().is_builtin(method_name) { if id == method_name && checker.semantic().has_builtin_binding(method_name) {
if arguments.args.len() != 1 { if arguments.args.len() != 1 {
continue; continue;
} }
@ -159,7 +159,7 @@ fn get_undecorated_methods(checker: &mut Checker, class_stmt: &Stmt, method_type
// if we find the decorator we're looking for, skip // if we find the decorator we're looking for, skip
if decorator_list.iter().any(|decorator| { if decorator_list.iter().any(|decorator| {
if let Expr::Name(ast::ExprName { id, .. }) = &decorator.expression { if let Expr::Name(ast::ExprName { id, .. }) = &decorator.expression {
if id == method_name && checker.semantic().is_builtin(method_name) { if id == method_name && checker.semantic().has_builtin_binding(method_name) {
return true; return true;
} }
} }

View file

@ -72,7 +72,7 @@ pub(crate) fn super_without_brackets(checker: &mut Checker, func: &Expr) {
return; return;
} }
if !checker.semantic().is_builtin(id.as_str()) { if !checker.semantic().has_builtin_binding(id.as_str()) {
return; return;
} }

View file

@ -93,7 +93,7 @@ pub(crate) fn unnecessary_dunder_call(checker: &mut Checker, call: &ast::ExprCal
// Ignore dunder methods used on `super`. // Ignore dunder methods used on `super`.
if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
if checker.semantic().is_builtin("super") { if checker.semantic().has_builtin_binding("super") {
if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() {
if id == "super" { if id == "super" {
return; return;
@ -113,7 +113,7 @@ pub(crate) fn unnecessary_dunder_call(checker: &mut Checker, call: &ast::ExprCal
if let Some(dunder) = DunderReplacement::from_method(attr) { if let Some(dunder) = DunderReplacement::from_method(attr) {
match (&*call.arguments.args, dunder) { match (&*call.arguments.args, dunder) {
([], DunderReplacement::Builtin(replacement, message)) => { ([], DunderReplacement::Builtin(replacement, message)) => {
if !checker.semantic().is_builtin(replacement) { if !checker.semantic().has_builtin_binding(replacement) {
return; return;
} }
fixed = Some(format!( fixed = Some(format!(

View file

@ -95,7 +95,7 @@ fn atom_diagnostic(checker: &mut Checker, target: &Expr) {
fn tuple_diagnostic(checker: &mut Checker, tuple: &ast::ExprTuple, aliases: &[&Expr]) { fn tuple_diagnostic(checker: &mut Checker, tuple: &ast::ExprTuple, aliases: &[&Expr]) {
let mut diagnostic = Diagnostic::new(OSErrorAlias { name: None }, tuple.range()); let mut diagnostic = Diagnostic::new(OSErrorAlias { name: None }, tuple.range());
let semantic = checker.semantic(); let semantic = checker.semantic();
if semantic.is_builtin("OSError") { if semantic.has_builtin_binding("OSError") {
// Filter out any `OSErrors` aliases. // Filter out any `OSErrors` aliases.
let mut remaining: Vec<Expr> = tuple let mut remaining: Vec<Expr> = tuple
.elts .elts

View file

@ -107,7 +107,7 @@ fn atom_diagnostic(checker: &mut Checker, target: &Expr) {
fn tuple_diagnostic(checker: &mut Checker, tuple: &ast::ExprTuple, aliases: &[&Expr]) { fn tuple_diagnostic(checker: &mut Checker, tuple: &ast::ExprTuple, aliases: &[&Expr]) {
let mut diagnostic = Diagnostic::new(TimeoutErrorAlias { name: None }, tuple.range()); let mut diagnostic = Diagnostic::new(TimeoutErrorAlias { name: None }, tuple.range());
let semantic = checker.semantic(); let semantic = checker.semantic();
if semantic.is_builtin("TimeoutError") { if semantic.has_builtin_binding("TimeoutError") {
// Filter out any `TimeoutErrors` aliases. // Filter out any `TimeoutErrors` aliases.
let mut remaining: Vec<Expr> = tuple let mut remaining: Vec<Expr> = tuple
.elts .elts

View file

@ -67,7 +67,7 @@ pub(crate) fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr,
} }
let mut diagnostic = Diagnostic::new(TypeOfPrimitive { primitive }, expr.range()); let mut diagnostic = Diagnostic::new(TypeOfPrimitive { primitive }, expr.range());
let builtin = primitive.builtin(); let builtin = primitive.builtin();
if semantic.is_builtin(&builtin) { if semantic.has_builtin_binding(&builtin) {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
pad(primitive.builtin(), expr.range(), checker.locator()), pad(primitive.builtin(), expr.range(), checker.locator()),
expr.range(), expr.range(),

View file

@ -89,7 +89,7 @@ pub(crate) fn check_and_remove_from_set(checker: &mut Checker, if_stmt: &ast::St
// `element` in the check should be the same as `element` in the body // `element` in the check should be the same as `element` in the body
|| !compare(&check_element.into(), &remove_element.into()) || !compare(&check_element.into(), &remove_element.into())
// `element` shouldn't have a side effect, otherwise we might change the semantics of the program. // `element` shouldn't have a side effect, otherwise we might change the semantics of the program.
|| contains_effect(check_element, |id| checker.semantic().is_builtin(id)) || contains_effect(check_element, |id| checker.semantic().has_builtin_binding(id))
{ {
return; return;
} }

View file

@ -90,7 +90,7 @@ pub(crate) fn if_exp_instead_of_or_operator(checker: &mut Checker, if_expr: &ast
), ),
if_expr.range(), if_expr.range(),
), ),
if contains_effect(body, |id| checker.semantic().is_builtin(id)) { if contains_effect(body, |id| checker.semantic().has_builtin_binding(id)) {
Applicability::Unsafe Applicability::Unsafe
} else { } else {
Applicability::Safe Applicability::Safe

View file

@ -139,7 +139,7 @@ pub(crate) fn if_expr_min_max(checker: &mut Checker, if_exp: &ast::ExprIf) {
if_exp.range(), if_exp.range(),
); );
if checker.semantic().is_builtin(min_max.as_str()) { if checker.semantic().has_builtin_binding(min_max.as_str()) {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
replacement, replacement,
if_exp.range(), if_exp.range(),

View file

@ -275,7 +275,7 @@ fn try_construct_call(
) -> Result<String> { ) -> Result<String> {
// We can only do our fix if `builtin` identifier is still bound to // We can only do our fix if `builtin` identifier is still bound to
// the built-in type. // the built-in type.
if !checker.semantic().is_builtin(builtin) { if !checker.semantic().has_builtin_binding(builtin) {
bail!("Can't use built-in `{builtin}` constructor") bail!("Can't use built-in `{builtin}` constructor")
} }

View file

@ -173,7 +173,9 @@ pub(crate) fn unnecessary_enumerate(checker: &mut Checker, stmt_for: &ast::StmtF
}, },
func.range(), func.range(),
); );
if checker.semantic().is_builtin("range") && checker.semantic().is_builtin("len") { if checker.semantic().has_builtin_binding("range")
&& checker.semantic().has_builtin_binding("len")
{
// If the `start` argument is set to something other than the `range` default, // If the `start` argument is set to something other than the `range` default,
// there's no clear fix. // there's no clear fix.
let start = arguments.find_argument("start", 1); let start = arguments.find_argument("start", 1);

View file

@ -108,7 +108,7 @@ pub(crate) fn unnecessary_dict_comprehension_for_iterable(
dict_comp.range(), dict_comp.range(),
); );
if checker.semantic().is_builtin("dict") { if checker.semantic().has_builtin_binding("dict") {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
checker checker
.generator() .generator()

View file

@ -96,8 +96,8 @@ pub(crate) fn unnecessary_key_check(checker: &mut Checker, expr: &Expr) {
return; return;
} }
if contains_effect(obj_left, |id| checker.semantic().is_builtin(id)) if contains_effect(obj_left, |id| checker.semantic().has_builtin_binding(id))
|| contains_effect(key_left, |id| checker.semantic().is_builtin(id)) || contains_effect(key_left, |id| checker.semantic().has_builtin_binding(id))
{ {
return; return;
} }

View file

@ -67,7 +67,7 @@ pub(crate) fn try_consider_else(
if let Some(stmt) = body.last() { if let Some(stmt) = body.last() {
if let Stmt::Return(ast::StmtReturn { value, range: _ }) = stmt { if let Stmt::Return(ast::StmtReturn { value, range: _ }) = stmt {
if let Some(value) = value { if let Some(value) = value {
if contains_effect(value, |id| checker.semantic().is_builtin(id)) { if contains_effect(value, |id| checker.semantic().has_builtin_binding(id)) {
return; return;
} }
} }

View file

@ -255,7 +255,7 @@ impl<'a> SemanticModel<'a> {
/// Note that a "builtin binding" does *not* include explicit lookups via the `builtins` /// Note that a "builtin binding" does *not* include explicit lookups via the `builtins`
/// module, e.g. `import builtins; builtins.open`. It *only* includes the bindings /// module, e.g. `import builtins; builtins.open`. It *only* includes the bindings
/// that are pre-populated in Python's global scope before any imports have taken place. /// that are pre-populated in Python's global scope before any imports have taken place.
pub fn is_builtin(&self, member: &str) -> bool { pub fn has_builtin_binding(&self, member: &str) -> bool {
self.lookup_symbol(member) self.lookup_symbol(member)
.map(|binding_id| &self.bindings[binding_id]) .map(|binding_id| &self.bindings[binding_id])
.is_some_and(|binding| binding.kind.is_builtin()) .is_some_and(|binding| binding.kind.is_builtin())
@ -274,7 +274,7 @@ impl<'a> SemanticModel<'a> {
// Fast path: we only need to worry about name expressions // Fast path: we only need to worry about name expressions
if !self.seen_module(Modules::BUILTINS) { if !self.seen_module(Modules::BUILTINS) {
let name = &expr.as_name_expr()?.id; let name = &expr.as_name_expr()?.id;
return if self.is_builtin(name) { return if self.has_builtin_binding(name) {
Some(name) Some(name)
} else { } else {
None None
@ -299,7 +299,7 @@ impl<'a> SemanticModel<'a> {
let Expr::Name(ast::ExprName { id, .. }) = expr else { let Expr::Name(ast::ExprName { id, .. }) = expr else {
return false; return false;
}; };
return id == symbol && self.is_builtin(symbol); return id == symbol && self.has_builtin_binding(symbol);
} }
// slow path: we need to consider attribute accesses and aliased imports // slow path: we need to consider attribute accesses and aliased imports