Skip to content

Commit f8e71ad

Browse files
authored
Merge 921c9c7 into c6aad02
2 parents c6aad02 + 921c9c7 commit f8e71ad

11 files changed

+155
-40
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+24
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
204204
return guar;
205205
}
206206

207+
// Check for the write!/writeln! macro special case
208+
let is_write_fmt = item_name.name == sym::write_fmt;
209+
let is_write_macro =
210+
expr_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
211+
self.tcx.is_diagnostic_item(sym::write_macro, def_id)
212+
|| self.tcx.is_diagnostic_item(sym::writeln_macro, def_id)
213+
});
214+
215+
if is_write_fmt && is_write_macro {
216+
// This is a write!/writeln! macro call with write_fmt method error
217+
let mut file = None;
218+
let mut err = struct_span_code_err!(
219+
self.dcx(),
220+
span,
221+
E0599,
222+
"cannot write into `{}`",
223+
self.tcx.short_string(rcvr_ty, &mut file)
224+
);
225+
*err.long_ty_path() = file;
226+
err.note("type does not implement the `write_fmt` method");
227+
err.help("try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope");
228+
return err.emit();
229+
}
230+
207231
match error {
208232
MethodError::NoMatch(mut no_match_data) => self.report_no_match_method_error(
209233
span,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Issue #139051 - Test for the case where io::Write would be more appropriate
2+
//
3+
// Test that when using write! on a type that doesn't implement std::io::Write trait,
4+
// we get a clear error message suggesting to import the appropriate trait.
5+
//
6+
// edition:2021
7+
// ignore-msvc
8+
// ignore-emscripten
9+
// run-fail
10+
// check-pass
11+
12+
fn main() {
13+
// Simple struct that doesn't implement std::io::Write
14+
struct MyIoStruct {
15+
value: i32,
16+
}
17+
18+
let mut s = MyIoStruct { value: 42 };
19+
20+
// This should generate E0599 with the improved error message
21+
// suggesting io::Write instead
22+
write!(s, "Hello, world!"); //~ ERROR cannot write into `MyIoStruct`
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0599]: cannot write into `MyIoStruct`
2+
--> $DIR/io-write-fmt-method-error.rs:22:5
3+
|
4+
LL | write!(s, "Hello, world!");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: type does not implement the `write_fmt` method
8+
= help: try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
9+
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0599`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Issue #139051 - Ensure we don't get confusing suggestions for E0599
2+
// on write!/writeln! macros
3+
//
4+
// Test that when using write!/writeln! macros with a type that doesn't implement
5+
// std::fmt::Write trait, we get a clear error message without irrelevant suggestions.
6+
//
7+
// edition:2021
8+
// ignore-msvc
9+
// ignore-emscripten
10+
// run-fail
11+
// check-pass
12+
13+
fn main() {
14+
// Simple struct that doesn't implement std::fmt::Write
15+
struct MyStruct {
16+
value: i32,
17+
}
18+
19+
let mut s = MyStruct { value: 42 };
20+
21+
// This should generate E0599 with the improved error message
22+
// and not suggest irrelevant methods like write_str or push_str
23+
write!(s, "Hello, world!"); //~ ERROR cannot write into `MyStruct`
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0599]: cannot write into `MyStruct`
2+
--> $DIR/write-fmt-method-error.rs:23:5
3+
|
4+
LL | write!(s, "Hello, world!");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: type does not implement the `write_fmt` method
8+
= help: try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
9+
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0599`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Issue #139051 - Ensure we don't get confusing suggestions for E0599
2+
// on write!/writeln! macros
3+
//
4+
// Test that when using write!/writeln! macros with a type that doesn't implement
5+
// std::fmt::Write trait, we get a clear error message without irrelevant suggestions.
6+
//
7+
// edition:2021
8+
// ignore-msvc
9+
// ignore-emscripten
10+
// run-fail
11+
// check-pass
12+
13+
fn main() {
14+
// Simple struct that doesn't implement std::fmt::Write
15+
struct MyStruct {
16+
value: i32,
17+
}
18+
19+
let mut s = MyStruct { value: 42 };
20+
21+
// This should generate E0599 with the improved error message
22+
// and not suggest irrelevant methods like write_str or push_str
23+
writeln!(s, "Hello, world!"); //~ ERROR cannot write into `MyStruct`
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0599]: cannot write into `MyStruct`
2+
--> $DIR/writeln-fmt-method-error.rs:23:5
3+
|
4+
LL | writeln!(s, "Hello, world!");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: type does not implement the `write_fmt` method
8+
= help: try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
9+
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0599`.

tests/ui/macros/missing-writer.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ fn main() {
66
//~^ ERROR format argument must be a string literal
77
//~| HELP you might be missing a string literal to format with
88
//~| ERROR cannot write into `&'static str`
9-
//~| NOTE must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
10-
//~| HELP a writer is needed before this format string
9+
//~| NOTE type does not implement the `write_fmt` method
10+
//~| HELP try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
1111
writeln!("{}_{}", x, y);
1212
//~^ ERROR format argument must be a string literal
1313
//~| HELP you might be missing a string literal to format with
1414
//~| ERROR cannot write into `&'static str`
15-
//~| NOTE must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
16-
//~| HELP a writer is needed before this format string
15+
//~| NOTE type does not implement the `write_fmt` method
16+
//~| HELP try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
1717
}

tests/ui/macros/missing-writer.stderr

+10-24
Original file line numberDiff line numberDiff line change
@@ -21,38 +21,24 @@ LL | writeln!("{}_{}", "{} {}", x, y);
2121
| ++++++++
2222

2323
error[E0599]: cannot write into `&'static str`
24-
--> $DIR/missing-writer.rs:5:12
24+
--> $DIR/missing-writer.rs:5:5
2525
|
2626
LL | write!("{}_{}", x, y);
27-
| -------^^^^^^^------- method not found in `&str`
27+
| ^^^^^^^^^^^^^^^^^^^^^
2828
|
29-
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
30-
--> $DIR/missing-writer.rs:5:12
31-
|
32-
LL | write!("{}_{}", x, y);
33-
| ^^^^^^^
34-
help: a writer is needed before this format string
35-
--> $DIR/missing-writer.rs:5:12
36-
|
37-
LL | write!("{}_{}", x, y);
38-
| ^
29+
= note: type does not implement the `write_fmt` method
30+
= help: try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
31+
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
3932

4033
error[E0599]: cannot write into `&'static str`
41-
--> $DIR/missing-writer.rs:11:14
34+
--> $DIR/missing-writer.rs:11:5
4235
|
4336
LL | writeln!("{}_{}", x, y);
44-
| ---------^^^^^^^------- method not found in `&str`
37+
| ^^^^^^^^^^^^^^^^^^^^^^^
4538
|
46-
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
47-
--> $DIR/missing-writer.rs:11:14
48-
|
49-
LL | writeln!("{}_{}", x, y);
50-
| ^^^^^^^
51-
help: a writer is needed before this format string
52-
--> $DIR/missing-writer.rs:11:14
53-
|
54-
LL | writeln!("{}_{}", x, y);
55-
| ^
39+
= note: type does not implement the `write_fmt` method
40+
= help: try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
41+
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
5642

5743
error: aborting due to 4 previous errors
5844

tests/ui/suggestions/mut-borrow-needed-by-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ fn main() {
1818
//~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
1919
//~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
2020

21-
writeln!(fp, "hello world").unwrap(); //~ ERROR the method
21+
writeln!(fp, "hello world").unwrap(); //~ ERROR cannot write into `BufWriter<&dyn std::io::Write>`
2222
}

tests/ui/suggestions/mut-borrow-needed-by-trait.stderr

+6-11
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,15 @@ LL | let fp = BufWriter::new(fp);
2020
note: required by a bound in `BufWriter`
2121
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
2222

23-
error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
24-
--> $DIR/mut-borrow-needed-by-trait.rs:21:14
23+
error[E0599]: cannot write into `BufWriter<&dyn std::io::Write>`
24+
--> $DIR/mut-borrow-needed-by-trait.rs:21:5
2525
|
2626
LL | writeln!(fp, "hello world").unwrap();
27-
| ---------^^---------------- method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
2828
|
29-
note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
30-
--> $DIR/mut-borrow-needed-by-trait.rs:21:14
31-
|
32-
LL | writeln!(fp, "hello world").unwrap();
33-
| ^^
34-
= note: the following trait bounds were not satisfied:
35-
`&dyn std::io::Write: std::io::Write`
36-
which is required by `BufWriter<&dyn std::io::Write>: std::io::Write`
29+
= note: type does not implement the `write_fmt` method
30+
= help: try adding `use std::fmt::Write;` or `use std::io::Write;` to bring the appropriate trait into scope
31+
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
3732

3833
error: aborting due to 3 previous errors
3934

0 commit comments

Comments
 (0)