Repository navigation
Fix AST generated from a dict literal containing dict unpacking - #4449
Conversation
| // let (keys, values) = match pairs.iter().position(|(k,_)| k.is_none()) { | ||
| // Some(unpack_idx) => { | ||
| // let mut pairs = pairs; | ||
| // let (keys, mut values): (_, Vec<_>) = pairs.drain(..unpack_idx).map(|(k, v)| (*k.unwrap(), v)).unzip(); | ||
| // | ||
| // fn build_map(items: &mut Vec<(ast::Expr, ast::Expr)>) -> ast::Expr { | ||
| // let location = items[0].0.location; | ||
| // let end_location = items[0].0.end_location; | ||
| // let (keys, values) = items.drain(..).unzip(); | ||
| // ast::Expr { | ||
| // location, | ||
| // end_location, | ||
| // custom: (), | ||
| // node: ast::ExprKind::Dict { keys, values } | ||
| // } | ||
| // } | ||
| // | ||
| // let mut items = Vec::new(); | ||
| // for (key, value) in pairs.into_iter() { | ||
| // if let Some(key) = key { | ||
| // items.push((*key, value)); | ||
| // continue; | ||
| // } | ||
| // if !items.is_empty() { | ||
| // values.push(build_map(&mut items)); | ||
| // } | ||
| // values.push(value); | ||
| // } | ||
| // if !items.is_empty() { | ||
| // values.push(build_map(&mut items)); | ||
| // } | ||
| // (keys, values) | ||
| // }, | ||
| // None => pairs.into_iter().map(|(k, v)| (k, v)).unzip() | ||
| // }; |
There was a problem hiding this comment.
What this block does is:
{
"a": "b",
**c,
"d": "e", # <- treat this as Dict so we can process this item with Instruction::DictUpdate
**f,
}We can remove this.
| keys: &[Option<ast::Expr>], | ||
| values: &[ast::Expr], | ||
| ) -> CompileResult<()> { | ||
| emit!(self, Instruction::BuildMap { size: 0 }); |
There was a problem hiding this comment.
This implementation looks like to make performance regression
This reverts commit b31b08a.
|
@youknowone @coolreader18 Would you mind taking a look? |
| }, | ||
| Dict { | ||
| keys: Vec<Expr<U>>, | ||
| keys: Vec<Option<Expr<U>>>, |
There was a problem hiding this comment.
@youknowone Why did you change it to the previous form?
There was a problem hiding this comment.
I can't remember well so looking in it again.
I thought CPython's Python.asdl actually changed it to not optional here.
https://github.com/RustPython/RustPython/pull/4042/files#diff-242a44b9d53b6c6212a752e0c97d6cf2f87794f579700aa8015bb99cef63925cR63
But I still can see ast.parse generate None for empty keys in Python 3.10 as you described. I am confused.
Do you know what the '?' means in Python.asdl?
There was a problem hiding this comment.
I think ? means optional.
There was a problem hiding this comment.
Yes, that was the reason I thought CPython changed it from optional key to non-optional one in 3.10. How they still have None in parse.dump?
| }, | ||
| Dict { | ||
| keys: Vec<Expr<U>>, | ||
| keys: Vec<Option<Box<Expr<U>>>>, |
There was a problem hiding this comment.
| keys: Vec<Option<Box<Expr<U>>>>, | |
| keys: Vec<Option<Expr<U>>>, |
@youknowone Is Box necessary?
| | Lambda(arguments args, expr body) | ||
| | IfExp(expr test, expr body, expr orelse) | ||
| | Dict(expr* keys, expr* values) | ||
| | Dict(expr?* keys, expr* values) |
There was a problem hiding this comment.
CPython doesn't have ? in keys anymore.
https://github.com/python/cpython/blob/main/Parser/Python.asdl#L64
There was a problem hiding this comment.
@youknowone True, but dict.keys does contain None.
There was a problem hiding this comment.
https://github.com/python/cpython/blob/main/Parser/Python.asdl#L64 used to look like | Dict(expr?* keys, expr* values)?
There was a problem hiding this comment.
It looks like this line hasn't changed for 11 years: https://github.com/python/cpython/blame/3325f054e33b318aa56b74472f76a56b8afc0510/Parser/Python.asdl#L64
There was a problem hiding this comment.
double_starred_kvpair[KeyValuePair*]:
| '**' a=bitwise_or { _PyPegen_key_value_pair(p, NULL, a) }
^^^^
| kvpair
There was a problem hiding this comment.
@youknowone Can we move forward with expr?* keys or should we fix compiler/ast/asdl_rs.py as I did in
ea9db0e?
There was a problem hiding this comment.
I don't think expr?* is the right thing here. Not only is it probably not valid ASDL syntax (see here, the modifiers are in brackets as opposed to braces, though this might not really be an issue), but it is also kinda ambiguous, is it an Optional list or a list of optionals?
Can't we get the same behavior by modifying asdl_rs and keeping Python.asdl the same as CPythons?
There was a problem hiding this comment.
Not only is it probably not valid ASDL syntax (see here, the modifiers are in brackets as opposed to braces, though this might not really be an issue), but it is also kinda ambiguous, is it an Optional list or a list of optional?
Agreed!
Can't we get the same behavior by modifying asdl_rs and keeping Python.asdl the same as CPythons?
We can. I'm happy to revert the last commit.
@youknowone What do you think?
There was a problem hiding this comment.
If we could do, I prefer to keep Python.asdl as same as CPython. It was your original approach, right?
There was a problem hiding this comment.
Yes, updated the code.
|
Sure, i am sorry for that.I will add a comment that part is our local patch not to break it again in future2023. 1. 21. 12:16, Harutaka Kawamura ***@***.***> 작성:
@harupy commented on this pull request.
In compiler/ast/Python.asdl:
@@ -60,7 +60,7 @@ module Python
| UnaryOp(unaryop op, expr operand)
| Lambda(arguments args, expr body)
| IfExp(expr test, expr body, expr orelse)
- | Dict(expr* keys, expr* values)
+ | Dict(expr?* keys, expr* values)
@youknowone Can we move forward with expr?* keys?
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Makes sense! Feel free to push a commit to this PR if necessary :) |
b0df453 to
88e3c83
Compare
|
@youknowone @DimitrisJim Updated the code! Would you mind taking another look? |
youknowone
left a comment
There was a problem hiding this comment.
Thank you! And I am really sorry for confusing review for this PR 😅
|
Not a problem at all! |
This PR upgrades RustPython to fix the type of `Dict.keys` to `Vec<Option<Expr>>` (see RustPython/RustPython#4449 for why this change was needed) and unblock #1884.
This PR upgrades RustPython to fix the type of `Dict.keys` to `Vec<Option<Expr>>` (see RustPython/RustPython#4449 for why this change was needed) and unblock #1884.
Related to astral-sh/ruff#1879.
{"foo": 1, **{"bar": 1}}is parsed into the AST below in CPython and RustPython. In CPython,Dict.keyscontains two keys (ConstantandNone), but in RustPython,Dict.keysonly contains one key. This PR fixes it.CPython:
Expand
RustPython
Expand