Skip to content

Add DesugaringKind::FormatLiteral #142594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions compiler/rustc_ast/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ pub struct FormatArgs {
///
/// Generally only useful for lints that care about the raw bytes the user wrote.
pub uncooked_fmt_str: (LitKind, Symbol),
/// Was the format literal written in the source?
/// - `format!("boo")` => true,
/// - `format!(concat!("b", "o", "o"))` => false,
/// - `format!(include_str!("boo.txt"))` => false,
///
/// If it wasn't written in the source then we have to be careful with spans pointing into it
/// and suggestions about rewriting it.
pub is_source_literal: bool,
}

/// A piece of a format template string.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,7 @@ macro_rules! common_visitor_and_walkers {

// FIXME: visit the template exhaustively.
pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result {
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt;
let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _, is_source_literal: _ } = fmt;
let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ;
for FormatArgument { kind, expr } in args {
match kind {
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_ast_lowering/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_ast::*;
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_session::config::FmtDebug;
use rustc_span::{Ident, Span, Symbol, sym};
use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym};

use super::LoweringContext;

Expand All @@ -16,6 +16,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// format_args!() had any arguments _before_ flattening/inlining.
let allow_const = fmt.arguments.all_args().is_empty();
let mut fmt = Cow::Borrowed(fmt);

let sp = self.mark_span_with_reason(
DesugaringKind::FormatLiteral { source: fmt.is_source_literal },
sp,
sp.ctxt().outer_expn_data().allow_internal_unstable,
);

if self.tcx.sess.opts.unstable_opts.flatten_format_args {
fmt = flatten_format_args(fmt);
fmt = self.inline_literals(fmt);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ fn make_format_args(
template,
arguments: args,
uncooked_fmt_str,
is_source_literal,
}))
}

Expand Down
16 changes: 16 additions & 0 deletions compiler/rustc_span/src/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,17 @@ pub enum DesugaringKind {
Contract,
/// A pattern type range start/end
PatTyRange,
/// A format literal.
FormatLiteral {
/// Was this format literal written in the source?
/// - `format!("boo")` => Yes,
/// - `format!(concat!("b", "o", "o"))` => No,
/// - `format!(include_str!("boo.txt"))` => No,
///
/// If it wasn't written in the source then we have to be careful with suggestions about
/// rewriting it.
source: bool,
},
}

impl DesugaringKind {
Expand All @@ -1231,6 +1242,10 @@ impl DesugaringKind {
DesugaringKind::BoundModifier => "trait bound modifier",
DesugaringKind::Contract => "contract check",
DesugaringKind::PatTyRange => "pattern type",
DesugaringKind::FormatLiteral { source: true } => "format string literal",
DesugaringKind::FormatLiteral { source: false } => {
"expression that expanded into a format string literal"
}
}
}

Expand All @@ -1250,6 +1265,7 @@ impl DesugaringKind {
DesugaringKind::BoundModifier => value == "BoundModifier",
DesugaringKind::Contract => value == "Contract",
DesugaringKind::PatTyRange => value == "PatTyRange",
DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral",
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2872,13 +2872,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
_ => (),
}
}
let descr = format!("required by {a} bound in `{item_name}`");
if span.is_visible(sm) {
let msg = format!("required by {this} in `{short_item_name}`");
multispan.push_span_label(span, msg);
err.span_note(multispan, descr);

// If this is from a format string literal desugaring,
// we've already said "required by this formatting parameter"
let is_in_fmt_lit = if let Some(s) = err.span.primary_span() {
matches!(s.desugaring_kind(), Some(DesugaringKind::FormatLiteral { .. }))
} else {
err.span_note(tcx.def_span(item_def_id), descr);
false
};
if !is_in_fmt_lit {
let descr = format!("required by {a} bound in `{item_name}`");
if span.is_visible(sm) {
let msg = format!("required by {this} in `{short_item_name}`");
multispan.push_span_label(span, msg);
err.span_note(multispan, descr);
} else {
err.span_note(tcx.def_span(item_def_id), descr);
}
}
if let Some(note) = note {
err.note(note);
Expand Down Expand Up @@ -3977,7 +3987,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
) = expr.kind
{
if Some(*span) != err.span.primary_span() {
err.span_label(*span, "required by a bound introduced by this call");
let msg = if span.is_desugaring(DesugaringKind::FormatLiteral { source: true })
{
"required by this formatting parameter"
} else if span.is_desugaring(DesugaringKind::FormatLiteral { source: false }) {
"required by a formatting parameter in this expression"
} else {
"required by a bound introduced by this call"
};
err.span_label(*span, msg);
}
}

Expand Down
19 changes: 12 additions & 7 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -855,11 +855,13 @@ impl Display for Arguments<'_> {
#[rustc_on_unimplemented(
on(
crate_local,
label = "`{Self}` cannot be formatted using `{{:?}}`",
note = "add `#[derive(Debug)]` to `{Self}` or manually `impl {This} for {Self}`"
),
message = "`{Self}` doesn't implement `{This}`",
label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{This}`"
on(
from_desugaring = "FormatLiteral",
label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{This}`"
),
message = "`{Self}` doesn't implement `{This}`"
)]
#[doc(alias = "{:?}")]
#[rustc_diagnostic_item = "Debug"]
Expand Down Expand Up @@ -986,11 +988,14 @@ pub use macros::Debug;
any(Self = "std::path::Path", Self = "std::path::PathBuf"),
label = "`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
note = "call `.display()` or `.to_string_lossy()` to safely print paths, \
as they may contain non-Unicode data"
as they may contain non-Unicode data",
),
on(
from_desugaring = "FormatLiteral",
note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead",
label = "`{Self}` cannot be formatted with the default formatter",
),
message = "`{Self}` doesn't implement `{This}`",
label = "`{Self}` cannot be formatted with the default formatter",
note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead"
message = "`{Self}` doesn't implement `{This}`"
)]
#[doc(alias = "{}")]
#[rustc_diagnostic_item = "Display"]
Expand Down
9 changes: 8 additions & 1 deletion library/std/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,14 @@ macro_rules! dbg {
match $val {
tmp => {
$crate::eprintln!("[{}:{}:{}] {} = {:#?}",
$crate::file!(), $crate::line!(), $crate::column!(), $crate::stringify!($val), &tmp);
$crate::file!(),
$crate::line!(),
$crate::column!(),
$crate::stringify!($val),
// The `&T: Debug` check happens here (not in the format literal desugaring)
// to avoid format literal related messages and suggestions.
&&tmp as &dyn $crate::fmt::Debug,
);
tmp
}
}
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/argument-suggestions/issue-100154.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ error[E0277]: `()` doesn't implement `std::fmt::Display`
--> $DIR/issue-100154.rs:4:11
|
LL | foo::<()>(());
| ^^ `()` cannot be formatted with the default formatter
| ^^ the trait `std::fmt::Display` is not implemented for `()`
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `foo`
--> $DIR/issue-100154.rs:1:16
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ `Self` cannot be formatted with the default formatter
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:24:86
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-1.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ `Self` cannot be formatted with the default formatter
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-1.rs:24:86
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-2.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ `Self` cannot be formatted with the default formatter
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-2.rs:24:86
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
--> $DIR/defaults-unsound-62211-2.rs:24:96
|
LL | type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
| ^^^^ `Self` cannot be formatted with the default formatter
| ^^^^ the trait `std::fmt::Display` is not implemented for `Self`
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `UncheckedCopy::Output`
--> $DIR/defaults-unsound-62211-2.rs:24:86
|
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/binop/issue-77910-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ LL | fn foo(s: &i32) -> &i32 {
| --- consider calling this function
...
LL | assert_eq!(foo, y);
| ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
| ^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}`
|
= help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}`
= help: use parentheses to call this function: `foo(/* &i32 */)`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

Expand Down
4 changes: 1 addition & 3 deletions tests/ui/closures/issue-111932.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ error[E0277]: the size for values of type `dyn Foo` cannot be known at compilati
LL | println!("{:?}", foo);
| ---- ^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
| required by this formatting parameter
|
= help: the trait `Sized` is not implemented for `dyn Foo`
note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'_>::new_debug`
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
= 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)

error: aborting due to 2 previous errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ LL | #[derive(Debug)]
| ----- in this derive macro expansion
...
LL | x: Error
| ^^^^^^^^ `Error` cannot be formatted using `{:?}`
| ^^^^^^^^ the trait `Debug` is not implemented for `Error`
|
= help: the trait `Debug` is not implemented for `Error`
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
help: consider annotating `Error` with `#[derive(Debug)]`
|
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/derives/derives-span-Debug-enum.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ LL | #[derive(Debug)]
| ----- in this derive macro expansion
...
LL | Error
| ^^^^^ `Error` cannot be formatted using `{:?}`
| ^^^^^ the trait `Debug` is not implemented for `Error`
|
= help: the trait `Debug` is not implemented for `Error`
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
help: consider annotating `Error` with `#[derive(Debug)]`
|
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/derives/derives-span-Debug-struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ LL | #[derive(Debug)]
| ----- in this derive macro expansion
LL | struct Struct {
LL | x: Error
| ^^^^^^^^ `Error` cannot be formatted using `{:?}`
| ^^^^^^^^ the trait `Debug` is not implemented for `Error`
|
= help: the trait `Debug` is not implemented for `Error`
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
help: consider annotating `Error` with `#[derive(Debug)]`
|
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/derives/derives-span-Debug-tuple-struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ LL | #[derive(Debug)]
| ----- in this derive macro expansion
LL | struct Struct(
LL | Error
| ^^^^^ `Error` cannot be formatted using `{:?}`
| ^^^^^ the trait `Debug` is not implemented for `Error`
|
= help: the trait `Debug` is not implemented for `Error`
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
help: consider annotating `Error` with `#[derive(Debug)]`
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
--> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL
|
LL | impl r#trait::Trait for A {}
| ^ `A` cannot be formatted with the default formatter
| ^ the trait `std::fmt::Display` is not implemented for `A`
|
= help: the trait `std::fmt::Display` is not implemented for `A`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Trait`
--> $DIR/auxiliary/trait.rs:LL:COL
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
|
LL | impl r#trait::Trait for A {}
| ^ `A` cannot be formatted with the default formatter
| ^ the trait `std::fmt::Display` is not implemented for `A`
|
= help: the trait `std::fmt::Display` is not implemented for `A`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Trait`
--> $DIR/auxiliary/trait-debuginfo.rs:LL:COL
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
|
LL | impl r#trait::Trait for A {}
| ^ `A` cannot be formatted with the default formatter
| ^ the trait `std::fmt::Display` is not implemented for `A`
|
= help: the trait `std::fmt::Display` is not implemented for `A`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Trait`
--> $DIR/auxiliary/trait-diag.rs:LL:COL
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
|
LL | impl r#trait::Trait for A {}
| ^ `A` cannot be formatted with the default formatter
| ^ the trait `std::fmt::Display` is not implemented for `A`
|
= help: the trait `std::fmt::Display` is not implemented for `A`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Trait`
--> $DIR/auxiliary/trait-macro.rs:LL:COL
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
|
LL | impl r#trait::Trait for A {}
| ^ `A` cannot be formatted with the default formatter
| ^ the trait `std::fmt::Display` is not implemented for `A`
|
= help: the trait `std::fmt::Display` is not implemented for `A`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Trait`
--> $DIR/auxiliary/trait-debuginfo.rs:LL:COL
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
--> remapped/errors/remap-path-prefix-diagnostics.rs:LL:COL
|
LL | impl r#trait::Trait for A {}
| ^ `A` cannot be formatted with the default formatter
| ^ the trait `std::fmt::Display` is not implemented for `A`
|
= help: the trait `std::fmt::Display` is not implemented for `A`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Trait`
--> remapped/errors/auxiliary/trait-diag.rs:LL:COL
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ error[E0277]: `A` doesn't implement `std::fmt::Display`
--> $DIR/remap-path-prefix-diagnostics.rs:LL:COL
|
LL | impl r#trait::Trait for A {}
| ^ `A` cannot be formatted with the default formatter
| ^ the trait `std::fmt::Display` is not implemented for `A`
|
= help: the trait `std::fmt::Display` is not implemented for `A`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Trait`
--> $DIR/auxiliary/trait-macro.rs:LL:COL
|
Expand Down
Loading
Loading