mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:09:22 +00:00
Upgrade to Rust 1.80 (#12586)
This commit is contained in:
parent
ee103ffb25
commit
138e70bd5c
29 changed files with 57 additions and 48 deletions
|
@ -156,6 +156,7 @@ zip = { version = "0.6.6", default-features = false, features = ["zstd"] }
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
unsafe_code = "warn"
|
unsafe_code = "warn"
|
||||||
unreachable_pub = "warn"
|
unreachable_pub = "warn"
|
||||||
|
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] }
|
||||||
|
|
||||||
[workspace.lints.clippy]
|
[workspace.lints.clippy]
|
||||||
pedantic = { level = "warn", priority = -2 }
|
pedantic = { level = "warn", priority = -2 }
|
||||||
|
|
|
@ -11,3 +11,11 @@ doc-valid-idents = [
|
||||||
"SQLAlchemy",
|
"SQLAlchemy",
|
||||||
"StackOverflow",
|
"StackOverflow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
ignore-interior-mutability = [
|
||||||
|
# Interned is read-only. The wrapped `Rc` never gets updated.
|
||||||
|
"ruff_formatter::format_element::Interned",
|
||||||
|
|
||||||
|
# The expression is read-only.
|
||||||
|
"ruff_python_ast::hashable::HashableExpr",
|
||||||
|
]
|
||||||
|
|
|
@ -330,7 +330,7 @@ where
|
||||||
function_def.type_params.as_deref(),
|
function_def.type_params.as_deref(),
|
||||||
|builder| {
|
|builder| {
|
||||||
builder.visit_parameters(&function_def.parameters);
|
builder.visit_parameters(&function_def.parameters);
|
||||||
for expr in &function_def.returns {
|
if let Some(expr) = &function_def.returns {
|
||||||
builder.visit_annotation(expr);
|
builder.visit_annotation(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -719,7 +719,7 @@ impl<'a> Visitor<'a> for Checker<'a> {
|
||||||
self.visit_expr(expr);
|
self.visit_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for expr in returns {
|
if let Some(expr) = returns {
|
||||||
match annotation {
|
match annotation {
|
||||||
AnnotationContext::RuntimeRequired => {
|
AnnotationContext::RuntimeRequired => {
|
||||||
self.visit_runtime_required_annotation(expr);
|
self.visit_runtime_required_annotation(expr);
|
||||||
|
@ -1240,7 +1240,7 @@ impl<'a> Visitor<'a> for Checker<'a> {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.visit_type_definition(arg);
|
self.visit_type_definition(arg);
|
||||||
}
|
}
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
let Keyword {
|
let Keyword {
|
||||||
arg,
|
arg,
|
||||||
value,
|
value,
|
||||||
|
@ -1286,7 +1286,7 @@ impl<'a> Visitor<'a> for Checker<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
let Keyword { arg, value, .. } = keyword;
|
let Keyword { arg, value, .. } = keyword;
|
||||||
match (arg.as_ref(), value) {
|
match (arg.as_ref(), value) {
|
||||||
// Ex) NamedTuple("a", **{"a": int})
|
// Ex) NamedTuple("a", **{"a": int})
|
||||||
|
@ -1331,7 +1331,7 @@ impl<'a> Visitor<'a> for Checker<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex) TypedDict("a", a=int)
|
// Ex) TypedDict("a", a=int)
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
let Keyword { value, .. } = keyword;
|
let Keyword { value, .. } = keyword;
|
||||||
self.visit_type_definition(value);
|
self.visit_type_definition(value);
|
||||||
}
|
}
|
||||||
|
@ -1345,13 +1345,13 @@ impl<'a> Visitor<'a> for Checker<'a> {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.visit_non_type_definition(arg);
|
self.visit_non_type_definition(arg);
|
||||||
}
|
}
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
let Keyword { value, .. } = keyword;
|
let Keyword { value, .. } = keyword;
|
||||||
self.visit_non_type_definition(value);
|
self.visit_non_type_definition(value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Ex) DefaultNamedArg(type="bool", name="some_prop_name")
|
// Ex) DefaultNamedArg(type="bool", name="some_prop_name")
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
let Keyword {
|
let Keyword {
|
||||||
value,
|
value,
|
||||||
arg,
|
arg,
|
||||||
|
@ -1369,10 +1369,10 @@ impl<'a> Visitor<'a> for Checker<'a> {
|
||||||
// If we're in a type definition, we need to treat the arguments to any
|
// If we're in a type definition, we need to treat the arguments to any
|
||||||
// other callables as non-type definitions (i.e., we don't want to treat
|
// other callables as non-type definitions (i.e., we don't want to treat
|
||||||
// any strings as deferred type definitions).
|
// any strings as deferred type definitions).
|
||||||
for arg in arguments.args.iter() {
|
for arg in &*arguments.args {
|
||||||
self.visit_non_type_definition(arg);
|
self.visit_non_type_definition(arg);
|
||||||
}
|
}
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
let Keyword { value, .. } = keyword;
|
let Keyword { value, .. } = keyword;
|
||||||
self.visit_non_type_definition(value);
|
self.visit_non_type_definition(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,9 @@ impl Emitter for JsonLinesEmitter {
|
||||||
messages: &[Message],
|
messages: &[Message],
|
||||||
context: &EmitterContext,
|
context: &EmitterContext,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut w = writer;
|
|
||||||
for message in messages {
|
for message in messages {
|
||||||
serde_json::to_writer(&mut w, &message_to_json_value(message, context))?;
|
serde_json::to_writer(&mut *writer, &message_to_json_value(message, context))?;
|
||||||
w.write_all(b"\n")?;
|
writer.write_all(b"\n")?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
||||||
match func.as_ref() {
|
match func.as_ref() {
|
||||||
Expr::Name(ast::ExprName { id, .. }) => {
|
Expr::Name(ast::ExprName { id, .. }) => {
|
||||||
if matches!(id.as_str(), "filter" | "reduce" | "map") {
|
if matches!(id.as_str(), "filter" | "reduce" | "map") {
|
||||||
for arg in arguments.args.iter() {
|
for arg in &*arguments.args {
|
||||||
if arg.is_lambda_expr() {
|
if arg.is_lambda_expr() {
|
||||||
self.safe_functions.push(arg);
|
self.safe_functions.push(arg);
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
||||||
if attr == "reduce" {
|
if attr == "reduce" {
|
||||||
if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() {
|
if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() {
|
||||||
if id == "functools" {
|
if id == "functools" {
|
||||||
for arg in arguments.args.iter() {
|
for arg in &*arguments.args {
|
||||||
if arg.is_lambda_expr() {
|
if arg.is_lambda_expr() {
|
||||||
self.safe_functions.push(arg);
|
self.safe_functions.push(arg);
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
if keyword.arg.as_ref().is_some_and(|arg| arg == "key")
|
if keyword.arg.as_ref().is_some_and(|arg| arg == "key")
|
||||||
&& keyword.value.is_lambda_expr()
|
&& keyword.value.is_lambda_expr()
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,7 +116,7 @@ fn is_infinite_iterator(arg: &Expr, semantic: &SemanticModel) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex) `iterools.repeat(1, times=None)`
|
// Ex) `iterools.repeat(1, times=None)`
|
||||||
for keyword in keywords.iter() {
|
for keyword in &**keywords {
|
||||||
if keyword.arg.as_ref().is_some_and(|name| name == "times") {
|
if keyword.arg.as_ref().is_some_and(|name| name == "times") {
|
||||||
if keyword.value.is_none_literal_expr() {
|
if keyword.value.is_none_literal_expr() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -88,7 +88,7 @@ fn is_nullable_field<'a>(value: &'a Expr, semantic: &'a SemanticModel) -> Option
|
||||||
let mut null_key = false;
|
let mut null_key = false;
|
||||||
let mut blank_key = false;
|
let mut blank_key = false;
|
||||||
let mut unique_key = false;
|
let mut unique_key = false;
|
||||||
for keyword in call.arguments.keywords.iter() {
|
for keyword in &*call.arguments.keywords {
|
||||||
let Some(argument) = &keyword.arg else {
|
let Some(argument) = &keyword.arg else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -110,7 +110,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
if checker.semantic().match_builtin_expr(func, "dict") {
|
if checker.semantic().match_builtin_expr(func, "dict") {
|
||||||
for keyword in keywords.iter() {
|
for keyword in &**keywords {
|
||||||
if let Some(attr) = &keyword.arg {
|
if let Some(attr) = &keyword.arg {
|
||||||
if is_reserved_attr(attr) {
|
if is_reserved_attr(attr) {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl Violation for UnnecessaryDictKwargs {
|
||||||
/// PIE804
|
/// PIE804
|
||||||
pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, call: &ast::ExprCall) {
|
pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, call: &ast::ExprCall) {
|
||||||
let mut duplicate_keywords = None;
|
let mut duplicate_keywords = None;
|
||||||
for keyword in call.arguments.keywords.iter() {
|
for keyword in &*call.arguments.keywords {
|
||||||
// keyword is a spread operator (indicated by None).
|
// keyword is a spread operator (indicated by None).
|
||||||
if keyword.arg.is_some() {
|
if keyword.arg.is_some() {
|
||||||
continue;
|
continue;
|
||||||
|
@ -152,7 +152,7 @@ fn duplicates(call: &ast::ExprCall) -> FxHashSet<&str> {
|
||||||
FxHashSet::with_capacity_and_hasher(call.arguments.keywords.len(), FxBuildHasher);
|
FxHashSet::with_capacity_and_hasher(call.arguments.keywords.len(), FxBuildHasher);
|
||||||
let mut duplicates =
|
let mut duplicates =
|
||||||
FxHashSet::with_capacity_and_hasher(call.arguments.keywords.len(), FxBuildHasher);
|
FxHashSet::with_capacity_and_hasher(call.arguments.keywords.len(), FxBuildHasher);
|
||||||
for keyword in call.arguments.keywords.iter() {
|
for keyword in &*call.arguments.keywords {
|
||||||
if let Some(name) = &keyword.arg {
|
if let Some(name) = &keyword.arg {
|
||||||
if !seen.insert(name.as_str()) {
|
if !seen.insert(name.as_str()) {
|
||||||
duplicates.insert(name.as_str());
|
duplicates.insert(name.as_str());
|
||||||
|
|
|
@ -180,8 +180,8 @@ fn is_type(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||||
/// Returns `true` if the [`Expr`] appears to be a reference to a NumPy dtype, since:
|
/// Returns `true` if the [`Expr`] appears to be a reference to a NumPy dtype, since:
|
||||||
/// > `dtype` are a bit of a strange beast, but definitely best thought of as instances, not
|
/// > `dtype` are a bit of a strange beast, but definitely best thought of as instances, not
|
||||||
/// > classes, and they are meant to be comparable not just to their own class, but also to the
|
/// > classes, and they are meant to be comparable not just to their own class, but also to the
|
||||||
/// corresponding scalar types (e.g., `x.dtype == np.float32`) and strings (e.g.,
|
/// > corresponding scalar types (e.g., `x.dtype == np.float32`) and strings (e.g.,
|
||||||
/// `x.dtype == ['i1,i4']`; basically, __eq__ always tries to do `dtype(other)`).
|
/// > `x.dtype == ['i1,i4']`; basically, __eq__ always tries to do `dtype(other)`).
|
||||||
fn is_dtype(expr: &Expr, semantic: &SemanticModel) -> bool {
|
fn is_dtype(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||||
match expr {
|
match expr {
|
||||||
// Ex) `np.dtype(obj)`
|
// Ex) `np.dtype(obj)`
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub(crate) fn duplicate_bases(checker: &mut Checker, name: &str, arguments: Opti
|
||||||
let bases = &arguments.args;
|
let bases = &arguments.args;
|
||||||
|
|
||||||
let mut seen: FxHashSet<&str> = FxHashSet::with_capacity_and_hasher(bases.len(), FxBuildHasher);
|
let mut seen: FxHashSet<&str> = FxHashSet::with_capacity_and_hasher(bases.len(), FxBuildHasher);
|
||||||
for base in bases.iter() {
|
for base in &**bases {
|
||||||
if let Expr::Name(ast::ExprName { id, .. }) = base {
|
if let Expr::Name(ast::ExprName { id, .. }) = base {
|
||||||
if !seen.insert(id) {
|
if !seen.insert(id) {
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
|
|
@ -40,7 +40,7 @@ pub(crate) fn repeated_keyword_argument(checker: &mut Checker, call: &ExprCall)
|
||||||
|
|
||||||
let mut seen = FxHashSet::with_capacity_and_hasher(arguments.keywords.len(), FxBuildHasher);
|
let mut seen = FxHashSet::with_capacity_and_hasher(arguments.keywords.len(), FxBuildHasher);
|
||||||
|
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
if let Some(id) = &keyword.arg {
|
if let Some(id) = &keyword.arg {
|
||||||
// Ex) `func(a=1, a=2)`
|
// Ex) `func(a=1, a=2)`
|
||||||
if !seen.insert(id.as_str()) {
|
if !seen.insert(id.as_str()) {
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl<'a> FormatSummaryValues<'a> {
|
||||||
let mut extracted_args: Vec<&Expr> = Vec::new();
|
let mut extracted_args: Vec<&Expr> = Vec::new();
|
||||||
let mut extracted_kwargs: FxHashMap<&str, &Expr> = FxHashMap::default();
|
let mut extracted_kwargs: FxHashMap<&str, &Expr> = FxHashMap::default();
|
||||||
|
|
||||||
for arg in call.arguments.args.iter() {
|
for arg in &*call.arguments.args {
|
||||||
if matches!(arg, Expr::Starred(..))
|
if matches!(arg, Expr::Starred(..))
|
||||||
|| contains_quotes(locator.slice(arg))
|
|| contains_quotes(locator.slice(arg))
|
||||||
|| locator.contains_line_break(arg.range())
|
|| locator.contains_line_break(arg.range())
|
||||||
|
@ -80,7 +80,7 @@ impl<'a> FormatSummaryValues<'a> {
|
||||||
}
|
}
|
||||||
extracted_args.push(arg);
|
extracted_args.push(arg);
|
||||||
}
|
}
|
||||||
for keyword in call.arguments.keywords.iter() {
|
for keyword in &*call.arguments.keywords {
|
||||||
let Keyword {
|
let Keyword {
|
||||||
arg,
|
arg,
|
||||||
value,
|
value,
|
||||||
|
|
|
@ -108,7 +108,7 @@ pub(crate) fn replace_str_enum(checker: &mut Checker, class_def: &ast::StmtClass
|
||||||
// Determine whether the class inherits from both `str` and `enum.Enum`.
|
// Determine whether the class inherits from both `str` and `enum.Enum`.
|
||||||
let mut inherits_str = false;
|
let mut inherits_str = false;
|
||||||
let mut inherits_enum = false;
|
let mut inherits_enum = false;
|
||||||
for base in arguments.args.iter() {
|
for base in &*arguments.args {
|
||||||
if let Some(qualified_name) = checker.semantic().resolve_qualified_name(base) {
|
if let Some(qualified_name) = checker.semantic().resolve_qualified_name(base) {
|
||||||
match qualified_name.segments() {
|
match qualified_name.segments() {
|
||||||
["" | "builtins", "str"] => inherits_str = true,
|
["" | "builtins", "str"] => inherits_str = true,
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub(crate) fn useless_object_inheritance(checker: &mut Checker, class_def: &ast:
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
for base in arguments.args.iter() {
|
for base in &*arguments.args {
|
||||||
if !checker.semantic().match_builtin_expr(base, "object") {
|
if !checker.semantic().match_builtin_expr(base, "object") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ pub(crate) fn sorted_min_max(checker: &mut Checker, subscript: &ast::ExprSubscri
|
||||||
let mut key_keyword_expr = None;
|
let mut key_keyword_expr = None;
|
||||||
|
|
||||||
// Check if the call to `sorted()` has the `reverse` and `key` keywords.
|
// Check if the call to `sorted()` has the `reverse` and `key` keywords.
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
// If the call contains `**kwargs`, return.
|
// If the call contains `**kwargs`, return.
|
||||||
let Some(arg) = keyword.arg.as_ref() else {
|
let Some(arg) = keyword.arg.as_ref() else {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -174,12 +174,12 @@ fn should_be_fstring(
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for keyword in keywords.iter() {
|
for keyword in &**keywords {
|
||||||
if let Some(ident) = keyword.arg.as_ref() {
|
if let Some(ident) = keyword.arg.as_ref() {
|
||||||
arg_names.insert(ident.as_str());
|
arg_names.insert(ident.as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for arg in args.iter() {
|
for arg in &**args {
|
||||||
if let ast::Expr::Name(ast::ExprName { id, .. }) = arg {
|
if let ast::Expr::Name(ast::ExprName { id, .. }) = arg {
|
||||||
arg_names.insert(id.as_str());
|
arg_names.insert(id.as_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ fn function_def_visit_preorder_except_body<'a, V>(
|
||||||
|
|
||||||
visitor.visit_parameters(parameters);
|
visitor.visit_parameters(parameters);
|
||||||
|
|
||||||
for expr in returns {
|
if let Some(expr) = returns {
|
||||||
visitor.visit_annotation(expr);
|
visitor.visit_annotation(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -785,7 +785,7 @@ impl AstNode for ast::StmtFunctionDef {
|
||||||
|
|
||||||
visitor.visit_parameters(parameters);
|
visitor.visit_parameters(parameters);
|
||||||
|
|
||||||
for expr in returns {
|
if let Some(expr) = returns {
|
||||||
visitor.visit_annotation(expr);
|
visitor.visit_annotation(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
visitor.visit_type_params(type_params);
|
visitor.visit_type_params(type_params);
|
||||||
}
|
}
|
||||||
visitor.visit_parameters(parameters);
|
visitor.visit_parameters(parameters);
|
||||||
for expr in returns {
|
if let Some(expr) = returns {
|
||||||
visitor.visit_annotation(expr);
|
visitor.visit_annotation(expr);
|
||||||
}
|
}
|
||||||
visitor.visit_body(body);
|
visitor.visit_body(body);
|
||||||
|
@ -593,10 +593,10 @@ pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &
|
||||||
// Note that the there might be keywords before the last arg, e.g. in
|
// Note that the there might be keywords before the last arg, e.g. in
|
||||||
// f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then
|
// f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then
|
||||||
// `keywords`. See also [Arguments::arguments_source_order`].
|
// `keywords`. See also [Arguments::arguments_source_order`].
|
||||||
for arg in arguments.args.iter() {
|
for arg in &*arguments.args {
|
||||||
visitor.visit_expr(arg);
|
visitor.visit_expr(arg);
|
||||||
}
|
}
|
||||||
for keyword in arguments.keywords.iter() {
|
for keyword in &*arguments.keywords {
|
||||||
visitor.visit_keyword(keyword);
|
visitor.visit_keyword(keyword);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ pub fn walk_stmt<V: Transformer + ?Sized>(visitor: &V, stmt: &mut Stmt) {
|
||||||
visitor.visit_type_params(type_params);
|
visitor.visit_type_params(type_params);
|
||||||
}
|
}
|
||||||
visitor.visit_parameters(parameters);
|
visitor.visit_parameters(parameters);
|
||||||
for expr in returns {
|
if let Some(expr) = returns {
|
||||||
visitor.visit_annotation(expr);
|
visitor.visit_annotation(expr);
|
||||||
}
|
}
|
||||||
visitor.visit_body(body);
|
visitor.visit_body(body);
|
||||||
|
@ -579,10 +579,10 @@ pub fn walk_arguments<V: Transformer + ?Sized>(visitor: &V, arguments: &mut Argu
|
||||||
// Note that the there might be keywords before the last arg, e.g. in
|
// Note that the there might be keywords before the last arg, e.g. in
|
||||||
// f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then
|
// f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then
|
||||||
// `keywords`. See also [Arguments::arguments_source_order`].
|
// `keywords`. See also [Arguments::arguments_source_order`].
|
||||||
for arg in arguments.args.iter_mut() {
|
for arg in &mut *arguments.args {
|
||||||
visitor.visit_expr(arg);
|
visitor.visit_expr(arg);
|
||||||
}
|
}
|
||||||
for keyword in arguments.keywords.iter_mut() {
|
for keyword in &mut *arguments.keywords {
|
||||||
visitor.visit_keyword(keyword);
|
visitor.visit_keyword(keyword);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ use crate::{has_skip_comment, prelude::*};
|
||||||
/// > A compound statement consists of one or more ‘clauses.’ A clause consists of a header and a ‘suite.’
|
/// > A compound statement consists of one or more ‘clauses.’ A clause consists of a header and a ‘suite.’
|
||||||
/// > The clause headers of a particular compound statement are all at the same indentation level.
|
/// > The clause headers of a particular compound statement are all at the same indentation level.
|
||||||
/// > Each clause header begins with a uniquely identifying keyword and ends with a colon.
|
/// > Each clause header begins with a uniquely identifying keyword and ends with a colon.
|
||||||
|
///
|
||||||
/// [source](https://docs.python.org/3/reference/compound_stmts.html#compound-statements)
|
/// [source](https://docs.python.org/3/reference/compound_stmts.html#compound-statements)
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum ClauseHeader<'a> {
|
pub(crate) enum ClauseHeader<'a> {
|
||||||
|
|
|
@ -2295,7 +2295,7 @@ impl<'src> Parser<'src> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments.len() > 1 {
|
if arguments.len() > 1 {
|
||||||
for arg in arguments.args.iter() {
|
for arg in &*arguments.args {
|
||||||
if let Some(ast::ExprGenerator {
|
if let Some(ast::ExprGenerator {
|
||||||
range,
|
range,
|
||||||
parenthesized: false,
|
parenthesized: false,
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "1.79"
|
channel = "1.80"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue