Skip to content

Commit 8642c86

Browse files
authored
Fix edge case in Literal type handling (#92)
This is needed to handle literal types with literal strings that are syntactically valid, but not valid as a type, e.g. `Literal["foo[bar][baz]"]`. The mechanism for handling this is the same as in old parser: whenever we get a `RawExpressionType` from parsing a string literal, force-normalize it to a regular (valid) `RawExpressionType` that preserves the original string.
1 parent 3039f8b commit 8642c86

1 file changed

Lines changed: 29 additions & 15 deletions

File tree

src/serialize_ast.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,7 +1573,7 @@ impl Ser for ast::Stmt {
15731573
} else if let Some(ParsedTypeComment::Invalid(error)) = type_expr {
15741574
ser.add_error(error, a.range(), false);
15751575
ser.write_bool(true);
1576-
serialize_invalid_type(ser, None);
1576+
serialize_invalid_type(ser, None, None, None);
15771577
ser.write_location(a.range());
15781578
ser.write_end_tag();
15791579
} else {
@@ -2899,10 +2899,24 @@ fn serialize_fstring_elements(ser: &mut Serializer, elems: Vec<&ast::Interpolate
28992899

29002900
/// Helper to serialize an invalid type annotation as RawExpressionType with typing.Any.
29012901
/// This is used for expressions that are not valid in type contexts (e.g., 3.14, int + str).
2902-
fn serialize_invalid_type(ser: &mut Serializer, note: Option<&[u8]>) {
2902+
fn serialize_invalid_type(
2903+
ser: &mut Serializer,
2904+
note: Option<&[u8]>,
2905+
original_str_expr: Option<&str>,
2906+
original_str_fallback: Option<&str>,
2907+
) {
29032908
ser.write_tag(TAG_RAW_EXPRESSION_TYPE);
2904-
ser.write_bytes(b"typing.Any");
2905-
ser.write_tag(TAG_LITERAL_NONE);
2909+
if let Some(original_str_expr) = original_str_expr {
2910+
// Whenever this is called from parsing a string literal as type,
2911+
// convert it back to a regular (valid) RawExpressionType.
2912+
// This is needed for literal types (and matches old parser behavior).
2913+
ser.write_bytes(original_str_fallback.unwrap().as_bytes());
2914+
ser.write_bytes(original_str_expr.as_bytes());
2915+
return;
2916+
} else {
2917+
ser.write_bytes(b"typing.Any");
2918+
ser.write_tag(TAG_LITERAL_NONE);
2919+
}
29062920
if ser.options.cache_version() >= CV_RAW_EXPRESSION_TYPE_NOTES {
29072921
if let Some(note) = note {
29082922
ser.write_bytes(note);
@@ -2990,12 +3004,12 @@ fn serialize_type(ser: &mut Serializer, t: &ast::Expr) {
29903004
ser.write_tagged_int(int_val);
29913005
} else {
29923006
// Integer too large for i64 - serialize as invalid type
2993-
serialize_invalid_type(ser, None);
3007+
serialize_invalid_type(ser, None, None, None);
29943008
}
29953009
} else {
29963010
// Float/complex number literals are not valid in type annotations
29973011
// Serialize as invalid type
2998-
serialize_invalid_type(ser, None);
3012+
serialize_invalid_type(ser, None, None, None);
29993013
}
30003014
}
30013015
ast::Expr::BinOp(e) => {
@@ -3006,7 +3020,7 @@ fn serialize_type(ser: &mut Serializer, t: &ast::Expr) {
30063020
} else {
30073021
// Other binary operators are not valid in type annotations
30083022
// Serialize as invalid type
3009-
serialize_invalid_type(ser, None);
3023+
serialize_invalid_type(ser, None, None, None);
30103024
}
30113025
}
30123026
ast::Expr::List(e) => {
@@ -3058,7 +3072,7 @@ fn serialize_type(ser: &mut Serializer, t: &ast::Expr) {
30583072
serialize_type(ser, &item.value);
30593073
}
30603074
} else {
3061-
serialize_invalid_type(ser, None);
3075+
serialize_invalid_type(ser, None, None, None);
30623076
}
30633077
}
30643078
ast::Expr::Call(c) => {
@@ -3080,7 +3094,7 @@ fn serialize_type(ser: &mut Serializer, t: &ast::Expr) {
30803094
} else {
30813095
None
30823096
};
3083-
serialize_invalid_type(ser, note.as_deref());
3097+
serialize_invalid_type(ser, note.as_deref(), None, None);
30843098
}
30853099
ast::Expr::EllipsisLiteral(_) => {
30863100
ser.write_tag(TAG_ELLIPSIS_TYPE);
@@ -3106,7 +3120,7 @@ fn serialize_type(ser: &mut Serializer, t: &ast::Expr) {
31063120
return;
31073121
} else {
31083122
// Negative number too large - serialize as invalid type
3109-
serialize_invalid_type(ser, None);
3123+
serialize_invalid_type(ser, None, None, None);
31103124
}
31113125
} else if matches!(e.op, ast::UnaryOp::UAdd) {
31123126
// Positive unary operator (+) - preserve the underlying value
@@ -3121,12 +3135,12 @@ fn serialize_type(ser: &mut Serializer, t: &ast::Expr) {
31213135
return;
31223136
} else {
31233137
// Number too large or not an integer - serialize as invalid type
3124-
serialize_invalid_type(ser, None);
3138+
serialize_invalid_type(ser, None, None, None);
31253139
}
31263140
} else {
31273141
// Other unary operators (not, ~, etc.) are not valid in type annotations
31283142
// Serialize as invalid type
3129-
serialize_invalid_type(ser, None);
3143+
serialize_invalid_type(ser, None, None, None);
31303144
}
31313145
}
31323146
ast::Expr::StringLiteral(s) => {
@@ -3157,7 +3171,7 @@ fn serialize_type(ser: &mut Serializer, t: &ast::Expr) {
31573171
_ => {
31583172
// Unsupported expression type in type annotation
31593173
// Serialize as invalid type
3160-
serialize_invalid_type(ser, None);
3174+
serialize_invalid_type(ser, None, None, None);
31613175
}
31623176
}
31633177
ser.write_location(t.range());
@@ -3322,7 +3336,7 @@ fn serialize_attribute_type(
33223336
let mut v = Vec::new();
33233337
if !get_qualified_type_name(&mut v, expr) {
33243338
// Invalid expression for qualified name - serialize as invalid type
3325-
serialize_invalid_type(ser, None);
3339+
serialize_invalid_type(ser, None, original_str_expr, original_str_fallback);
33263340
return;
33273341
}
33283342
ser.write_tag(TAG_UNBOUND_TYPE);
@@ -3355,7 +3369,7 @@ fn serialize_subscript_type(
33553369
let mut v = Vec::new();
33563370
if !get_qualified_type_name(&mut v, &subscript.value) {
33573371
// Invalid expression for qualified name - serialize as invalid type
3358-
serialize_invalid_type(ser, None);
3372+
serialize_invalid_type(ser, None, original_str_expr, original_str_fallback);
33593373
return;
33603374
}
33613375
ser.write_tag(TAG_UNBOUND_TYPE);

0 commit comments

Comments
 (0)