Skip to content

Commit 89a9842

Browse files
committed
Honor eval-mode assignment invalid syntax
Assisted-by: Grok:grok-4.6
1 parent 8dbc33e commit 89a9842

1 file changed

Lines changed: 49 additions & 24 deletions

File tree

‎crates/compiler/src/lib.rs‎

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -316,33 +316,39 @@ fn cpython_parse_diagnostic_override(
316316
}
317317

318318
source_error!(invalid_dict_error(source_text));
319-
source_error!(invalid_collection_assignment_error(source_text));
319+
if !matches!(mode, Mode::Eval) {
320+
source_error!(invalid_collection_assignment_error(source_text));
321+
}
320322
source_error!(invalid_group_error(source_text));
321323
source_error!(invalid_def_type_params_error(source_text));
322324
source_error!(invalid_expression_error(source_text));
323325
source_error!(invalid_named_expression_error(source_text));
324-
source_error!(invalid_plain_assignment_error(source_text));
325-
source_error!(expression_assignment_error(source_text));
326-
source_error!(invalid_annotation_target_error(source_text));
327-
source_error!(invalid_assignment_target_error(source_text));
328-
source_error!(invalid_condition_assignment_error(
329-
source_text,
330-
error.location.start().to_usize()
331-
));
332-
source_error!(invalid_augassign_target_error(source_text));
333-
source_error!(invalid_for_target_error(source_text));
334-
source_error!(invalid_with_target_error(source_text));
335-
source_error!(invalid_delete_target_error(source_text));
336-
source_error!(invalid_standalone_except_error(source_text));
337-
source_error!(invalid_import_statement_error(source_text));
338-
source_error!(invalid_import_target_error(source_text));
339-
source_error!(invalid_except_as_target_error(source_text));
340-
source_error!(invalid_match_mapping_rest_wildcard_error(source_text));
341-
source_error!(invalid_match_as_target_error(source_text));
342-
source_error!(invalid_for_if_clause_error(source_text));
343-
source_error!(invalid_if_expression_statement_error(source_text));
344-
source_error!(invalid_else_elif_error(source_text));
345-
source_error!(mixed_except_handlers_error(source_text));
326+
// Assignment and other statements are not expressions. Eval keeps the
327+
// generic parse error rather than a statement-target rewrite.
328+
if !matches!(mode, Mode::Eval) {
329+
source_error!(invalid_plain_assignment_error(source_text));
330+
source_error!(expression_assignment_error(source_text));
331+
source_error!(invalid_annotation_target_error(source_text));
332+
source_error!(invalid_assignment_target_error(source_text));
333+
source_error!(invalid_condition_assignment_error(
334+
source_text,
335+
error.location.start().to_usize()
336+
));
337+
source_error!(invalid_augassign_target_error(source_text));
338+
source_error!(invalid_for_target_error(source_text));
339+
source_error!(invalid_with_target_error(source_text));
340+
source_error!(invalid_delete_target_error(source_text));
341+
source_error!(invalid_standalone_except_error(source_text));
342+
source_error!(invalid_import_statement_error(source_text));
343+
source_error!(invalid_import_target_error(source_text));
344+
source_error!(invalid_except_as_target_error(source_text));
345+
source_error!(invalid_match_mapping_rest_wildcard_error(source_text));
346+
source_error!(invalid_match_as_target_error(source_text));
347+
source_error!(invalid_for_if_clause_error(source_text));
348+
source_error!(invalid_if_expression_statement_error(source_text));
349+
source_error!(invalid_else_elif_error(source_text));
350+
source_error!(mixed_except_handlers_error(source_text));
351+
}
346352

347353
if matches!(
348354
&error.error,
@@ -381,7 +387,11 @@ fn cpython_parse_diagnostic_override(
381387
// into the generic "invalid syntax" message. rustpython-vm's `vm_new.rs`
382388
// does this same collapse for its own callers; rustpython-compiler has no
383389
// vm dependency, so mirror it here.
384-
if matches!(&error.error, parser::ParseErrorType::ExpectedExpression) {
390+
if matches!(
391+
&error.error,
392+
parser::ParseErrorType::ExpectedExpression
393+
| parser::ParseErrorType::UnexpectedExpressionToken
394+
) {
385395
let (loc, end_loc) = adjusted_error_locations(source_file, error.location);
386396
return Some(NormalizedParseDiagnostic::new(
387397
parser::ParseErrorType::OtherError("invalid syntax".into()),
@@ -7630,6 +7640,21 @@ mod tests {
76307640
);
76317641
}
76327642

7643+
#[test]
7644+
fn eval_fstring_assignment_keeps_invalid_syntax() {
7645+
for source in ["f'' = 3", "f'{0}' = x", "f'{x}' = x"] {
7646+
let err = compile(source, Mode::Eval, "<eval>", CompileOpts::default())
7647+
.expect_err("assignment is invalid in eval");
7648+
assert_eq!(err.to_string(), "invalid syntax", "{source}");
7649+
}
7650+
let err = compile("f'' = 3", Mode::Exec, "<exec>", CompileOpts::default())
7651+
.expect_err("f-string is not an assignment target");
7652+
assert_eq!(
7653+
err.to_string(),
7654+
"cannot assign to f-string expression here. Maybe you meant '==' instead of '='?"
7655+
);
7656+
}
7657+
76337658
#[test]
76347659
fn if_assignment_uses_eq_or_walrus_message() {
76357660
let err = compile(

0 commit comments

Comments
 (0)