6

I have the following type:

type RangeFn = fn(&Value, &Value) -> bool;

Now I want to put it with this struct:

#[derive(Debug)]
struct Range {
    fun: RangeFn,
}

But if I have a struct that takes RangeFn as a parameter, then I can't seem to have it derive from Debug. How do I make RangeFn compatible with the Debug trait?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Max Alexander
  • 5,471
  • 6
  • 38
  • 52
  • 1
    I believe your question is answered by the answers of [Is it possible to implement inherent methods on type aliases?](https://stackoverflow.com/q/35568871/155423) and [How do I implement a trait I don't own for a type I don't own?](https://stackoverflow.com/q/25413201/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 26 '18 at 20:04
  • 3
    TL;DR: You don't, you can't, and that's by design. – Shepmaster Aug 26 '18 at 20:04
  • Possible duplicate of [Is it possible to implement inherent methods on type aliases?](https://stackoverflow.com/questions/35568871/is-it-possible-to-implement-inherent-methods-on-type-aliases) – E_net4 Aug 26 '18 at 20:30
  • 1
    @E_net4 I don't think he actually wants to implement `Debug` on the type alias, but to implement `Debug` on `Range`, which cannot simply derive it, as it is usually done. – mcarton Aug 26 '18 at 20:32
  • 1
    Looks a bit like an XY problem to me – mcarton Aug 26 '18 at 20:33

1 Answers1

11

You can't implement (or derive) a trait you don't own on a type you don't own.

However, that's not what you want to do. What you want is to implement Debug for Range, but you can't do that by deriving because fns don't implement Debug. Indeed, deriving Debug requires all fields to be Debug as well. Then you are stuck with implementing Debug by yourself; It is after all, just a normal trait:

type RangeFn = fn(&(), &()) -> bool;

struct Range {
    fun: RangeFn,
    other_field: u32,
}

impl std::fmt::Debug for Range {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
        f.debug_struct("Range")
            .field("other_field", &self.other_field)
            .finish()
    }
}

fn main() {
    let r = Range {
        fun: |_, _| true,
        other_field: 42,
    };

    println!("{:?}", r);
}

(link to playground)

mcarton
  • 27,633
  • 5
  • 85
  • 95
  • Ah thank you! Only thing is I wonder how to capture the signature of the function when printing it. – Max Alexander Aug 29 '18 at 20:21
  • @MaxAlexander that's not possible in stable Rust. See [Expose the `type_name` intrinsic](https://github.com/rust-lang/rfcs/issues/1428), and maybe drop your use case there, there has been recent activity. – mcarton Aug 29 '18 at 20:52
  • Since my previous comment was posted, [`type_name`](https://doc.rust-lang.org/core/any/fn.type_name.html) has been stabilized. – mcarton Jan 24 '22 at 15:16