mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-19 02:55:50 +00:00
Prohibit starred arguments after double-starred arguments
CPython prohibits ‘f(**kwargs, *args)’; we should too. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
This commit is contained in:
parent
313fd7d28c
commit
661b210391
2 changed files with 17 additions and 1 deletions
|
@ -22,6 +22,7 @@ pub enum LexicalErrorType {
|
||||||
TabsAfterSpaces,
|
TabsAfterSpaces,
|
||||||
DefaultArgumentError,
|
DefaultArgumentError,
|
||||||
PositionalArgumentError,
|
PositionalArgumentError,
|
||||||
|
UnpackedArgumentError,
|
||||||
DuplicateKeywordArgumentError,
|
DuplicateKeywordArgumentError,
|
||||||
UnrecognizedToken { tok: char },
|
UnrecognizedToken { tok: char },
|
||||||
FStringError(FStringErrorType),
|
FStringError(FStringErrorType),
|
||||||
|
@ -55,6 +56,12 @@ impl fmt::Display for LexicalErrorType {
|
||||||
LexicalErrorType::PositionalArgumentError => {
|
LexicalErrorType::PositionalArgumentError => {
|
||||||
write!(f, "positional argument follows keyword argument")
|
write!(f, "positional argument follows keyword argument")
|
||||||
}
|
}
|
||||||
|
LexicalErrorType::UnpackedArgumentError => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"iterable argument unpacking follows keyword argument unpacking"
|
||||||
|
)
|
||||||
|
}
|
||||||
LexicalErrorType::UnrecognizedToken { tok } => {
|
LexicalErrorType::UnrecognizedToken { tok } => {
|
||||||
write!(f, "Got unexpected token {tok}")
|
write!(f, "Got unexpected token {tok}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ArgumentList, Lexi
|
||||||
|
|
||||||
let mut keyword_names =
|
let mut keyword_names =
|
||||||
FxHashSet::with_capacity_and_hasher(func_args.len(), Default::default());
|
FxHashSet::with_capacity_and_hasher(func_args.len(), Default::default());
|
||||||
|
let mut double_starred = false;
|
||||||
for (name, value) in func_args {
|
for (name, value) in func_args {
|
||||||
match name {
|
match name {
|
||||||
Some((start, end, name)) => {
|
Some((start, end, name)) => {
|
||||||
|
@ -67,6 +68,8 @@ pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ArgumentList, Lexi
|
||||||
}
|
}
|
||||||
|
|
||||||
keyword_names.insert(keyword_name.clone());
|
keyword_names.insert(keyword_name.clone());
|
||||||
|
} else {
|
||||||
|
double_starred = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
keywords.push(ast::Keyword::new(
|
keywords.push(ast::Keyword::new(
|
||||||
|
@ -76,12 +79,18 @@ pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ArgumentList, Lexi
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Allow starred args after keyword arguments.
|
// Allow starred arguments after keyword arguments but
|
||||||
|
// not after double-starred arguments.
|
||||||
if !keywords.is_empty() && !is_starred(&value) {
|
if !keywords.is_empty() && !is_starred(&value) {
|
||||||
return Err(LexicalError {
|
return Err(LexicalError {
|
||||||
error: LexicalErrorType::PositionalArgumentError,
|
error: LexicalErrorType::PositionalArgumentError,
|
||||||
location: value.location,
|
location: value.location,
|
||||||
});
|
});
|
||||||
|
} else if double_starred {
|
||||||
|
return Err(LexicalError {
|
||||||
|
error: LexicalErrorType::UnpackedArgumentError,
|
||||||
|
location: value.location,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
args.push(value);
|
args.push(value);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue