Skip to content

Commit fe3b238

Browse files
committed
Implement DesugaringKind::FormatLiteral
1 parent 9822e3d commit fe3b238

File tree

59 files changed

+262
-160
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+262
-160
lines changed

compiler/rustc_ast/src/format.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ pub struct FormatArgs {
5050
///
5151
/// Generally only useful for lints that care about the raw bytes the user wrote.
5252
pub uncooked_fmt_str: (LitKind, Symbol),
53+
/// Was the format literal written in the source?
54+
/// - `format!("boo")` => true,
55+
/// - `format!(concat!("b", "o", "o"))` => false,
56+
/// - `format!(include_str!("boo.txt"))` => false,
57+
///
58+
/// If it wasn't written in the source then we have to be careful with spans pointing into it
59+
/// and suggestions about rewriting it.
60+
pub is_source_literal: bool,
5361
}
5462

5563
/// A piece of a format template string.

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1389,7 +1389,7 @@ macro_rules! common_visitor_and_walkers {
13891389

13901390
// FIXME: visit the template exhaustively.
13911391
pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result {
1392-
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt;
1392+
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _, is_source_literal: _ } = fmt;
13931393
let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ;
13941394
for FormatArgument { kind, expr } in args {
13951395
match kind {

compiler/rustc_ast_lowering/src/format.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_ast::*;
66
use rustc_data_structures::fx::FxIndexMap;
77
use rustc_hir as hir;
88
use rustc_session::config::FmtDebug;
9-
use rustc_span::{Ident, Span, Symbol, sym};
9+
use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym};
1010

1111
use super::LoweringContext;
1212

@@ -16,6 +16,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
1616
// format_args!() had any arguments _before_ flattening/inlining.
1717
let allow_const = fmt.arguments.all_args().is_empty();
1818
let mut fmt = Cow::Borrowed(fmt);
19+
20+
let sp = self.mark_span_with_reason(
21+
DesugaringKind::FormatLiteral { source: fmt.is_source_literal },
22+
sp,
23+
sp.ctxt().outer_expn_data().allow_internal_unstable,
24+
);
25+
1926
if self.tcx.sess.opts.unstable_opts.flatten_format_args {
2027
fmt = flatten_format_args(fmt);
2128
fmt = self.inline_literals(fmt);

compiler/rustc_builtin_macros/src/format.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ fn make_format_args(
606606
template,
607607
arguments: args,
608608
uncooked_fmt_str,
609+
is_source_literal,
609610
}))
610611
}
611612

compiler/rustc_span/src/hygiene.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,17 @@ pub enum DesugaringKind {
12131213
Contract,
12141214
/// A pattern type range start/end
12151215
PatTyRange,
1216+
/// A format literal.
1217+
FormatLiteral {
1218+
/// Was this format literal written in the source?
1219+
/// - `format!("boo")` => Yes,
1220+
/// - `format!(concat!("b", "o", "o"))` => No,
1221+
/// - `format!(include_str!("boo.txt"))` => No,
1222+
///
1223+
/// If it wasn't written in the source then we have to be careful with suggestions about
1224+
/// rewriting it.
1225+
source: bool,
1226+
},
12161227
}
12171228

12181229
impl DesugaringKind {
@@ -1231,6 +1242,10 @@ impl DesugaringKind {
12311242
DesugaringKind::BoundModifier => "trait bound modifier",
12321243
DesugaringKind::Contract => "contract check",
12331244
DesugaringKind::PatTyRange => "pattern type",
1245+
DesugaringKind::FormatLiteral { source: true } => "format string literal",
1246+
DesugaringKind::FormatLiteral { source: false } => {
1247+
"expression that expanded into a format string literal"
1248+
}
12341249
}
12351250
}
12361251

@@ -1250,6 +1265,7 @@ impl DesugaringKind {
12501265
DesugaringKind::BoundModifier => value == "BoundModifier",
12511266
DesugaringKind::Contract => value == "Contract",
12521267
DesugaringKind::PatTyRange => value == "PatTyRange",
1268+
DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral",
12531269
}
12541270
}
12551271
}

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2872,13 +2872,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
28722872
_ => (),
28732873
}
28742874
}
2875-
let descr = format!("required by {a} bound in `{item_name}`");
2876-
if span.is_visible(sm) {
2877-
let msg = format!("required by {this} in `{short_item_name}`");
2878-
multispan.push_span_label(span, msg);
2879-
err.span_note(multispan, descr);
2875+
2876+
// If this is from a format string literal desugaring,
2877+
// we've already said "required by this formatting parameter"
2878+
let is_in_fmt_lit = if let Some(s) = err.span.primary_span() {
2879+
matches!(s.desugaring_kind(), Some(DesugaringKind::FormatLiteral { .. }))
28802880
} else {
2881-
err.span_note(tcx.def_span(item_def_id), descr);
2881+
false
2882+
};
2883+
if !is_in_fmt_lit {
2884+
let descr = format!("required by {a} bound in `{item_name}`");
2885+
if span.is_visible(sm) {
2886+
let msg = format!("required by {this} in `{short_item_name}`");
2887+
multispan.push_span_label(span, msg);
2888+
err.span_note(multispan, descr);
2889+
} else {
2890+
err.span_note(tcx.def_span(item_def_id), descr);
2891+
}
28822892
}
28832893
if let Some(note) = note {
28842894
err.note(note);
@@ -3977,7 +3987,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
39773987
) = expr.kind
39783988
{
39793989
if Some(*span) != err.span.primary_span() {
3980-
err.span_label(*span, "required by a bound introduced by this call");
3990+
let msg = if span.is_desugaring(DesugaringKind::FormatLiteral { source: true })
3991+
{
3992+
"required by this formatting parameter"
3993+
} else if span.is_desugaring(DesugaringKind::FormatLiteral { source: false }) {
3994+
"required by a formatting parameter in this expression"
3995+
} else {
3996+
"required by a bound introduced by this call"
3997+
};
3998+
err.span_label(*span, msg);
39813999
}
39824000
}
39834001

library/core/src/fmt/mod.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -855,11 +855,13 @@ impl Display for Arguments<'_> {
855855
#[rustc_on_unimplemented(
856856
on(
857857
crate_local,
858-
label = "`{Self}` cannot be formatted using `{{:?}}`",
859858
note = "add `#[derive(Debug)]` to `{Self}` or manually `impl {This} for {Self}`"
860859
),
861-
message = "`{Self}` doesn't implement `{This}`",
862-
label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{This}`"
860+
on(
861+
from_desugaring = "FormatLiteral",
862+
label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{This}`"
863+
),
864+
message = "`{Self}` doesn't implement `{This}`"
863865
)]
864866
#[doc(alias = "{:?}")]
865867
#[rustc_diagnostic_item = "Debug"]
@@ -986,11 +988,14 @@ pub use macros::Debug;
986988
any(Self = "std::path::Path", Self = "std::path::PathBuf"),
987989
label = "`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
988990
note = "call `.display()` or `.to_string_lossy()` to safely print paths, \
989-
as they may contain non-Unicode data"
991+
as they may contain non-Unicode data",
992+
),
993+
on(
994+
from_desugaring = "FormatLiteral",
995+
note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead",
996+
label = "`{Self}` cannot be formatted with the default formatter",
990997
),
991-
message = "`{Self}` doesn't implement `{This}`",
992-
label = "`{Self}` cannot be formatted with the default formatter",
993-
note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead"
998+
message = "`{Self}` doesn't implement `{This}`"
994999
)]
9951000
#[doc(alias = "{}")]
9961001
#[rustc_diagnostic_item = "Display"]

tests/ui/argument-suggestions/issue-100154.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@ error[E0277]: `()` doesn't implement `std::fmt::Display`
1717
--> $DIR/issue-100154.rs:4:11
1818
|
1919
LL | foo::<()>(());
20-
| ^^ `()` cannot be formatted with the default formatter
20+
| ^^ the trait `std::fmt::Display` is not implemented for `()`
2121
|
22-
= help: the trait `std::fmt::Display` is not implemented for `()`
23-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
2422
note: required by a bound in `foo`
2523
--> $DIR/issue-100154.rs:1:16
2624
|

tests/ui/associated-types/defaults-unsound-62211-1.current.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
22
--> $DIR/defaults-unsound-62211-1.rs:24:96
33
|
44
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
5-
| ^^^^ `Self` cannot be formatted with the default formatter
5+
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
66
|
7-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
87
note: required by a bound in `UncheckedCopy::Output`
98
--> $DIR/defaults-unsound-62211-1.rs:24:86
109
|

tests/ui/associated-types/defaults-unsound-62211-1.next.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
22
--> $DIR/defaults-unsound-62211-1.rs:24:96
33
|
44
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
5-
| ^^^^ `Self` cannot be formatted with the default formatter
5+
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
66
|
7-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
87
note: required by a bound in `UncheckedCopy::Output`
98
--> $DIR/defaults-unsound-62211-1.rs:24:86
109
|

tests/ui/associated-types/defaults-unsound-62211-2.current.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
22
--> $DIR/defaults-unsound-62211-2.rs:24:96
33
|
44
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
5-
| ^^^^ `Self` cannot be formatted with the default formatter
5+
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
66
|
7-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
87
note: required by a bound in `UncheckedCopy::Output`
98
--> $DIR/defaults-unsound-62211-2.rs:24:86
109
|

tests/ui/associated-types/defaults-unsound-62211-2.next.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
22
--> $DIR/defaults-unsound-62211-2.rs:24:96
33
|
44
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
5-
| ^^^^ `Self` cannot be formatted with the default formatter
5+
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
66
|
7-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
87
note: required by a bound in `UncheckedCopy::Output`
98
--> $DIR/defaults-unsound-62211-2.rs:24:86
109
|

tests/ui/binop/issue-77910-1.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ LL | fn foo(s: &i32) -> &i32 {
1616
| --- consider calling this function
1717
...
1818
LL | assert_eq!(foo, y);
19-
| ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
19+
| ^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}`
2020
|
21-
= help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}`
2221
= help: use parentheses to call this function: `foo(/* &i32 */)`
2322
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
2423

tests/ui/closures/issue-111932.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@ error[E0277]: the size for values of type `dyn Foo` cannot be known at compilati
1414
LL | println!("{:?}", foo);
1515
| ---- ^^^ doesn't have a size known at compile-time
1616
| |
17-
| required by a bound introduced by this call
17+
| required by this formatting parameter
1818
|
1919
= help: the trait `Sized` is not implemented for `dyn Foo`
20-
note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'_>::new_debug`
21-
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
2220
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
2321

2422
error: aborting due to 2 previous errors

tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ LL | #[derive(Debug)]
55
| ----- in this derive macro expansion
66
...
77
LL | x: Error
8-
| ^^^^^^^^ `Error` cannot be formatted using `{:?}`
8+
| ^^^^^^^^ the trait `Debug` is not implemented for `Error`
99
|
10-
= help: the trait `Debug` is not implemented for `Error`
1110
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1211
help: consider annotating `Error` with `#[derive(Debug)]`
1312
|

tests/ui/derives/derives-span-Debug-enum.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ LL | #[derive(Debug)]
55
| ----- in this derive macro expansion
66
...
77
LL | Error
8-
| ^^^^^ `Error` cannot be formatted using `{:?}`
8+
| ^^^^^ the trait `Debug` is not implemented for `Error`
99
|
10-
= help: the trait `Debug` is not implemented for `Error`
1110
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1211
help: consider annotating `Error` with `#[derive(Debug)]`
1312
|

tests/ui/derives/derives-span-Debug-struct.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ LL | #[derive(Debug)]
55
| ----- in this derive macro expansion
66
LL | struct Struct {
77
LL | x: Error
8-
| ^^^^^^^^ `Error` cannot be formatted using `{:?}`
8+
| ^^^^^^^^ the trait `Debug` is not implemented for `Error`
99
|
10-
= help: the trait `Debug` is not implemented for `Error`
1110
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1211
help: consider annotating `Error` with `#[derive(Debug)]`
1312
|

tests/ui/derives/derives-span-Debug-tuple-struct.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ LL | #[derive(Debug)]
55
| ----- in this derive macro expansion
66
LL | struct Struct(
77
LL | Error
8-
| ^^^^^ `Error` cannot be formatted using `{:?}`
8+
| ^^^^^ the trait `Debug` is not implemented for `Error`
99
|
10-
= help: the trait `Debug` is not implemented for `Error`
1110
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
1211
help: consider annotating `Error` with `#[derive(Debug)]`
1312
|

tests/ui/errors/remap-path-prefix-diagnostics.not-diag-in-deps.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
22
--> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL
33
|
44
LL | impl r#trait::Trait for A {}
5-
| ^ `A` cannot be formatted with the default formatter
5+
| ^ the trait `std::fmt::Display` is not implemented for `A`
66
|
7-
= help: the trait `std::fmt::Display` is not implemented for `A`
8-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
97
note: required by a bound in `Trait`
108
--> $DIR/auxiliary/trait.rs:LL:COL
119
|

tests/ui/errors/remap-path-prefix-diagnostics.only-debuginfo-in-deps.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
22
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
33
|
44
LL | impl r#trait::Trait for A {}
5-
| ^ `A` cannot be formatted with the default formatter
5+
| ^ the trait `std::fmt::Display` is not implemented for `A`
66
|
7-
= help: the trait `std::fmt::Display` is not implemented for `A`
8-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
97
note: required by a bound in `Trait`
108
--> $DIR/auxiliary/trait-debuginfo.rs:LL:COL
119
|

tests/ui/errors/remap-path-prefix-diagnostics.only-diag-in-deps.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
22
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
33
|
44
LL | impl r#trait::Trait for A {}
5-
| ^ `A` cannot be formatted with the default formatter
5+
| ^ the trait `std::fmt::Display` is not implemented for `A`
66
|
7-
= help: the trait `std::fmt::Display` is not implemented for `A`
8-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
97
note: required by a bound in `Trait`
108
--> $DIR/auxiliary/trait-diag.rs:LL:COL
119
|

tests/ui/errors/remap-path-prefix-diagnostics.only-macro-in-deps.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
22
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
33
|
44
LL | impl r#trait::Trait for A {}
5-
| ^ `A` cannot be formatted with the default formatter
5+
| ^ the trait `std::fmt::Display` is not implemented for `A`
66
|
7-
= help: the trait `std::fmt::Display` is not implemented for `A`
8-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
97
note: required by a bound in `Trait`
108
--> $DIR/auxiliary/trait-macro.rs:LL:COL
119
|

tests/ui/errors/remap-path-prefix-diagnostics.with-debuginfo-in-deps.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
22
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
33
|
44
LL | impl r#trait::Trait for A {}
5-
| ^ `A` cannot be formatted with the default formatter
5+
| ^ the trait `std::fmt::Display` is not implemented for `A`
66
|
7-
= help: the trait `std::fmt::Display` is not implemented for `A`
8-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
97
note: required by a bound in `Trait`
108
--> $DIR/auxiliary/trait-debuginfo.rs:LL:COL
119
|

tests/ui/errors/remap-path-prefix-diagnostics.with-diag-in-deps.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
22
--> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL
33
|
44
LL | impl r#trait::Trait for A {}
5-
| ^ `A` cannot be formatted with the default formatter
5+
| ^ the trait `std::fmt::Display` is not implemented for `A`
66
|
7-
= help: the trait `std::fmt::Display` is not implemented for `A`
8-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
97
note: required by a bound in `Trait`
108
--> remapped/errors/auxiliary/trait-diag.rs:LL:COL
119
|

tests/ui/errors/remap-path-prefix-diagnostics.with-macro-in-deps.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
22
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
33
|
44
LL | impl r#trait::Trait for A {}
5-
| ^ `A` cannot be formatted with the default formatter
5+
| ^ the trait `std::fmt::Display` is not implemented for `A`
66
|
7-
= help: the trait `std::fmt::Display` is not implemented for `A`
8-
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
97
note: required by a bound in `Trait`
108
--> $DIR/auxiliary/trait-macro.rs:LL:COL
119
|

0 commit comments

Comments
 (0)