Skip to content
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

Tracking Issue for debug_closure_helpers #117729

Open
1 of 6 tasks
jmillikin opened this issue Nov 8, 2023 · 4 comments
Open
1 of 6 tasks

Tracking Issue for debug_closure_helpers #117729

jmillikin opened this issue Nov 8, 2023 · 4 comments
Labels
C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@jmillikin
Copy link
Contributor

jmillikin commented Nov 8, 2023

Feature gate: #![feature(debug_closure_helpers)]

This is a tracking issue for adding helpers to core::fmt that can use closures for formatting values.

ACP: rust-lang/libs-team#288

Public API

// core::fmt

impl DebugList<'_, '_> {
    fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
    where
        F: FnOnce(&mut Formatter) -> fmt::Result;
}

impl DebugMap<'_, '_> {
    fn key_with<F>(&mut self, key_fmt: F) -> &mut Self
    where
        F: FnOnce(&mut Formatter) -> fmt::Result;

    fn value_with<F>(&mut self, value_fmt: F) -> &mut Self
    where
        F: FnOnce(&mut Formatter) -> fmt::Result;
}

impl DebugSet<'_, '_> {
    fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
    where
        F: FnOnce(&mut Formatter) -> fmt::Result;
}

impl DebugStruct<'_, '_> {
    fn field_with<F>(&mut self, name: &str, field_fmt: F) -> &mut Self
    where
        F: FnOnce(&mut Formatter) -> fmt::Result;
}

impl DebugTuple<'_, '_> {  // also DebugSet
    fn field_with<F>(&mut self, field_fmt: F) -> &mut Self
    where
        F: FnOnce(&mut Formatter) -> fmt::Result;
}

pub struct FormatterFn<F>(pub F);

impl<F> Debug for FormatterFn<F>
where
    F: Fn(&mut Formatter) -> fmt::Result;

impl<F> Display for FormatterFn<F>
where
    F: Fn(&mut Formatter) -> fmt::Result;

Steps / History

Unresolved Questions

  • Naming: Do any strong preferences exist regarding the new method names?
    • For now I've named them {orig_method}_with, for example DebugStruct::field_with() is like DebugStruct::field().
  • The DebugMap struct got key_with() and value_with(), but not entry_with() -- is it worth adding that?
  • Should FormatterFn<F> place a trait bound on F so that call sites can be tidier?

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html

@jmillikin jmillikin added C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Nov 8, 2023
bors added a commit to rust-lang-ci/rust that referenced this issue Nov 10, 2023
…viper

Closure-consuming helper functions for `fmt::Debug` helpers

ACP: rust-lang/libs-team#288

Tracking issue: rust-lang#117729
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Nov 10, 2023
…cuviper

Closure-consuming helper functions for `fmt::Debug` helpers

ACP: rust-lang/libs-team#288

Tracking issue: rust-lang#117729
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Nov 10, 2023
Rollup merge of rust-lang#117730 - jmillikin:fmt-debug-helper-fns, r=cuviper

Closure-consuming helper functions for `fmt::Debug` helpers

ACP: rust-lang/libs-team#288

Tracking issue: rust-lang#117729
@QuineDot
Copy link

QuineDot commented Dec 3, 2023

Taking inspiration from iter::from_fn, I suggest a module level helper function:

core::fmt::from_fn<F>(f: F) -> FormatterFn<F>
where
    F: Fn(&mut Formatter<'_>) -> Result
{
    FormatterFn(f)
}

Plus perhaps also

  • Renaming the struct to fmt::FromFn
  • Making the field private
  • Removing the bound from the struct definition

Is there any particular reason it doesn't implement Binary, LowerExp, etc? (Why both Debug and Display but not all formats?)

@steffahn
Copy link
Member

steffahn commented Mar 3, 2024

Is there any particular reason it doesn't implement Binary, LowerExp, etc? (Why both Debug and Display but not all formats?)

With “just” Debug and Display it would kind-of follow the precedent of fmt::Arguments<'_>.

@workingjubilee
Copy link
Contributor

these are really nice btw. I think QuineDot's suggestion could be a cool refactoring of this, but it's very nice to be able to basically randomly throw in a simple closure that provides debug formatting, without having to roll the internals yourself, since it's just... like, the case you're most likely doing this, you're already implementing some kind of explicit Debug or "Debug adapter" and you don't wanna have to do another one for every custom field.

@workingjubilee
Copy link
Contributor

workingjubilee commented May 6, 2024

QuineDot's suggestion is in fact very close to one of the listed alternatives in the original idea! The main difference is the use of a free higher-order function instead of a constructor, which might be better for type inference reasons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants