mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-44589: raise a SyntaxError when mapping patterns have duplicate literal keys (GH-27131)
This commit is contained in:
parent
3b8075f907
commit
2693132292
4 changed files with 82 additions and 19 deletions
|
@ -6176,20 +6176,53 @@ compiler_pattern_mapping(struct compiler *c, pattern_ty p, pattern_context *pc)
|
|||
}
|
||||
// Collect all of the keys into a tuple for MATCH_KEYS and
|
||||
// COPY_DICT_WITHOUT_KEYS. They can either be dotted names or literals:
|
||||
|
||||
// Maintaining a set of Constant_kind kind keys allows us to raise a
|
||||
// SyntaxError in the case of duplicates.
|
||||
PyObject *seen = PySet_New(NULL);
|
||||
if (seen == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: goto error on failure in the loop below to avoid leaking `seen`
|
||||
for (Py_ssize_t i = 0; i < size; i++) {
|
||||
expr_ty key = asdl_seq_GET(keys, i);
|
||||
if (key == NULL) {
|
||||
const char *e = "can't use NULL keys in MatchMapping "
|
||||
"(set 'rest' parameter instead)";
|
||||
SET_LOC(c, ((pattern_ty) asdl_seq_GET(patterns, i)));
|
||||
return compiler_error(c, e);
|
||||
compiler_error(c, e);
|
||||
goto error;
|
||||
}
|
||||
if (!MATCH_VALUE_EXPR(key)) {
|
||||
|
||||
if (key->kind == Constant_kind) {
|
||||
int in_seen = PySet_Contains(seen, key->v.Constant.value);
|
||||
if (in_seen < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (in_seen) {
|
||||
const char *e = "mapping pattern checks duplicate key (%R)";
|
||||
compiler_error(c, e, key->v.Constant.value);
|
||||
goto error;
|
||||
}
|
||||
if (PySet_Add(seen, key->v.Constant.value)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
else if (key->kind != Attribute_kind) {
|
||||
const char *e = "mapping pattern keys may only match literals and attribute lookups";
|
||||
return compiler_error(c, e);
|
||||
compiler_error(c, e);
|
||||
goto error;
|
||||
}
|
||||
if (!compiler_visit_expr(c, key)) {
|
||||
goto error;
|
||||
}
|
||||
VISIT(c, expr, key);
|
||||
}
|
||||
|
||||
// all keys have been checked; there are no duplicates
|
||||
Py_DECREF(seen);
|
||||
|
||||
ADDOP_I(c, BUILD_TUPLE, size);
|
||||
ADDOP(c, MATCH_KEYS);
|
||||
// There's now a tuple of keys and a tuple of values on top of the subject:
|
||||
|
@ -6224,6 +6257,10 @@ compiler_pattern_mapping(struct compiler *c, pattern_ty p, pattern_context *pc)
|
|||
pc->on_top--;
|
||||
ADDOP(c, POP_TOP);
|
||||
return 1;
|
||||
|
||||
error:
|
||||
Py_DECREF(seen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue