Sitelet https://github.com/starkware-libs/cairo/commit/030ea75ff92f0c273151a5088123ec55ba7d9f17
Skip to content

Commit 030ea75

Browse files
committed
bugfix(semantic): writeln!(f) with no format string writes a newline.
`writeln!(f)` (a formatter with no format string) errored with "Macro expected format string argument", though in Rust it writes just a newline. Accept the no-format-string case for `writeln!` and emit a newline; `write!(f)` still requires a format string. This also makes `println!()` valid — it expands to `writeln!(f, )` — matching its documented "prints an empty line" example, while `print!()` → `write!(f, )` still errors.
1 parent 808c713 commit 030ea75

3 files changed

Lines changed: 29 additions & 15 deletions

File tree

‎corelib/src/test/fmt_test.cairo‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ fn test_format() {
2929
);
3030
}
3131

32+
#[test]
33+
fn test_writeln() {
34+
let mut f: core::fmt::Formatter = Default::default();
35+
// `writeln!` with no format string writes just a newline.
36+
let _ = writeln!(f);
37+
assert(f.buffer == "\n", 'empty writeln bad formatting');
38+
let _ = writeln!(f, "hello");
39+
assert(f.buffer == "\nhello\n", 'writeln bad formatting');
40+
}
41+
3242
#[derive(Debug, Drop)]
3343
struct StructExample {
3444
felt_value: felt252,

‎crates/cairo-lang-semantic/src/expr/test_data/inline_macros‎

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -575,11 +575,6 @@ error[E2200]: Plugin diagnostic: Macro expected formatter argument.
575575
writeln!();
576576
^
577577

578-
error[E2200]: Plugin diagnostic: Macro expected format string argument.
579-
--> lib.cairo:12:13
580-
writeln!(f);
581-
^
582-
583578
error[E2200]: Plugin diagnostic: Formatter argument must not be a string literal.
584579
--> lib.cairo:15:14
585580
writeln!("{}", ba);
@@ -943,11 +938,6 @@ error[E2200]: Plugin diagnostic: Macro `writeln` does not support this bracket t
943938
println!["{}", ba];
944939
^
945940

946-
error[E2200]: Plugin diagnostic: Macro expected format string argument.
947-
--> lib.cairo:8:13
948-
println!();
949-
^
950-
951941
error[E2200]: Plugin diagnostic: Format string argument must be a string literal.
952942
--> lib.cairo:11:14
953943
println!(ba);

‎crates/cairo-lang-semantic/src/inline_macros/write.rs‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ fn generate_code_inner<'db>(
113113
db: &'db dyn Database,
114114
with_newline: bool,
115115
) -> InlinePluginResult<'db> {
116-
let info = match FormattingInfo::extract(db, syntax) {
116+
let info = match FormattingInfo::extract(db, syntax, with_newline) {
117117
Ok(info) => info,
118118
Err(diagnostics) => return InlinePluginResult { code: None, diagnostics },
119119
};
@@ -163,6 +163,7 @@ impl<'db> FormattingInfo<'db> {
163163
fn extract(
164164
db: &'db dyn Database,
165165
syntax: &ast::ExprInlineMacro<'db>,
166+
with_newline: bool,
166167
) -> Result<FormattingInfo<'db>, Vec<PluginDiagnostic<'db>>> {
167168
let Some(legacy_inline_macro) = syntax.as_legacy_inline_macro(db) else {
168169
return Err(vec![not_legacy_macro_diagnostic(syntax.as_syntax_node().stable_ptr(db))]);
@@ -206,10 +207,23 @@ impl<'db> FormattingInfo<'db> {
206207
)]);
207208
}
208209
let Some(format_string_arg) = args_iter.next() else {
209-
return Err(vec![error_with_inner_span(
210-
arguments.lparen(db).as_syntax_node(),
211-
"Macro expected format string argument.",
212-
)]);
210+
// `writeln!(f)` (no format string) writes just a newline; `write!(f)` still errors.
211+
// There is no format string, so the arg node is unused here — reuse the formatter's.
212+
return if with_newline {
213+
Ok(FormattingInfo {
214+
formatter_arg_node: RewriteNode::from_ast_trimmed(&formatter_arg),
215+
format_string_arg: formatter_arg.clone(),
216+
format_string: String::new(),
217+
format_string_source: "",
218+
args: vec![],
219+
macro_ast: syntax.clone(),
220+
})
221+
} else {
222+
Err(vec![error_with_inner_span(
223+
arguments.lparen(db).as_syntax_node(),
224+
"Macro expected format string argument.",
225+
)])
226+
};
213227
};
214228
let Some(format_string_expr) = try_extract_unnamed_arg(db, &format_string_arg) else {
215229
return Err(vec![error_with_inner_span(

0 commit comments

Comments
 (0)