Sitelet https://github.com/starkware-libs/cairo/pull/10182/commits/030ea75ff92f0c273151a5088123ec55ba7d9f17
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
  • Loading branch information
orizi committed Jul 2, 2026
commit 030ea75ff92f0c273151a5088123ec55ba7d9f17
10 changes: 10 additions & 0 deletions corelib/src/test/fmt_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ fn test_format() {
);
}

#[test]
fn test_writeln() {
let mut f: core::fmt::Formatter = Default::default();
// `writeln!` with no format string writes just a newline.
let _ = writeln!(f);
assert(f.buffer == "\n", 'empty writeln bad formatting');
let _ = writeln!(f, "hello");
assert(f.buffer == "\nhello\n", 'writeln bad formatting');
}

#[derive(Debug, Drop)]
struct StructExample {
felt_value: felt252,
Expand Down
10 changes: 0 additions & 10 deletions crates/cairo-lang-semantic/src/expr/test_data/inline_macros
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,6 @@ error[E2200]: Plugin diagnostic: Macro expected formatter argument.
writeln!();
^

error[E2200]: Plugin diagnostic: Macro expected format string argument.
--> lib.cairo:12:13
writeln!(f);
^

error[E2200]: Plugin diagnostic: Formatter argument must not be a string literal.
--> lib.cairo:15:14
writeln!("{}", ba);
Expand Down Expand Up @@ -943,11 +938,6 @@ error[E2200]: Plugin diagnostic: Macro `writeln` does not support this bracket t
println!["{}", ba];
^

error[E2200]: Plugin diagnostic: Macro expected format string argument.
--> lib.cairo:8:13
println!();
^

error[E2200]: Plugin diagnostic: Format string argument must be a string literal.
--> lib.cairo:11:14
println!(ba);
Expand Down
24 changes: 19 additions & 5 deletions crates/cairo-lang-semantic/src/inline_macros/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ fn generate_code_inner<'db>(
db: &'db dyn Database,
with_newline: bool,
) -> InlinePluginResult<'db> {
let info = match FormattingInfo::extract(db, syntax) {
let info = match FormattingInfo::extract(db, syntax, with_newline) {
Ok(info) => info,
Err(diagnostics) => return InlinePluginResult { code: None, diagnostics },
};
Expand Down Expand Up @@ -163,6 +163,7 @@ impl<'db> FormattingInfo<'db> {
fn extract(
db: &'db dyn Database,
syntax: &ast::ExprInlineMacro<'db>,
with_newline: bool,
) -> Result<FormattingInfo<'db>, Vec<PluginDiagnostic<'db>>> {
let Some(legacy_inline_macro) = syntax.as_legacy_inline_macro(db) else {
return Err(vec![not_legacy_macro_diagnostic(syntax.as_syntax_node().stable_ptr(db))]);
Expand Down Expand Up @@ -206,10 +207,23 @@ impl<'db> FormattingInfo<'db> {
)]);
}
let Some(format_string_arg) = args_iter.next() else {
return Err(vec![error_with_inner_span(
arguments.lparen(db).as_syntax_node(),
"Macro expected format string argument.",
)]);
// `writeln!(f)` (no format string) writes just a newline; `write!(f)` still errors.
// There is no format string, so the arg node is unused here — reuse the formatter's.
return if with_newline {
Ok(FormattingInfo {
formatter_arg_node: RewriteNode::from_ast_trimmed(&formatter_arg),
format_string_arg: formatter_arg.clone(),
format_string: String::new(),
format_string_source: "",
args: vec![],
macro_ast: syntax.clone(),
})
} else {
Err(vec![error_with_inner_span(
arguments.lparen(db).as_syntax_node(),
"Macro expected format string argument.",
)])
};
};
let Some(format_string_expr) = try_extract_unnamed_arg(db, &format_string_arg) else {
return Err(vec![error_with_inner_span(
Expand Down
Loading