2
lorentz
275d

Diesel is an incredibly beautiful ORM, but the size of the DSL means that despite Rust's state-of-the-art IDE integration I'm back to editing code, waiting for it to compile (as soon as I stop typing) and changing random shit if there are red squiggles.

The error messages are totally unreadable, all in-code references point me to meaninglessly generic abstractions, and a good portion of the impls are generated by macros so I can't even look at an actual final definition.

The confidence that if it compiles it'll run is stil there, but nothing else.

Comments
  • 1
    If there was at least a book with answers to anything past the basic questions, that would be great. For example, for the most part you can't put a subexpression in a variable and iteratively extend it in a loop, because the combination will have a different type that mentions the types of the arguments. There are some query fragments that explicitly allow you to do this by ensuring that the type of the return value just happens to always be the same as the type of the first argument, but which ones these are is anyone's guess. I found no document, no SO question, no source file that exhaustively lists which query fragments have the same type.
  • 2
    Sounds similar to some template debugging in C++. Or trying to sort out macros.
  • 1
    @lorentz im always impressed that library devs think it'll be fine not giving the users the error messages they need, specifically when the language makes it actually possible to do so.
    Like.. whats the point of a library, you don't understand, because the error messages are Voodoo.

    if you mean by extending adding parameters to a closure, then yeah, that won't work, atleast in no way i'm aware of (atleast not during runtime)
  • 0
    @thebiochemic I mean this

    let mut constraint = owner.eq(user_id);
    for x in foos {
    constraint = constraint.and(... some constraint involving x ...);
    }

    This is not allowed because a.and(b) has a type kinda like A::AndClause<A, B> which can be the same thing as A if that's a use case the author of the DSL considers important but natural design choices would make it different.

    I try to simplify something I don't fully understand, but I hope you get the gist of it.
  • 1
    @lorentz oooh yeah i remember doing the same thing with stacking iterators a few days ago.
    You just Box::(...) them
    then you can put them into a variable that holds a Box<dyn YourTrait>.
    I can check later how i did it
  • 1
    @thebiochemic most of the traits involved with diesel aren't object safe, but tracking down which ones are is a good starting point I agree.
  • 1
    @thebiochemic I'm still on the fence about dyn Iterator even though I've been intensively using it for well over a year. It sounds very slow but I didn't experience a serious performance bottleneck yet.
  • 1
    @lorentz yeah i think the compiller's usually optimizing shit away. I wouldn't necessarily rely on it, but more often than not some ops will be replaced by simpler ones, or more efficient ones.
    Like in some cases a clone gets replaces by references, when certain conditions hit.
    I can imagine that this might happen with Boxes, Rc's and Arc's too.
  • 1
    @thebiochemic I'm not even sure the heap is actually as expensive as it's made out to be. It's a datastructure, sure, it *might* incur a syscall, and it locks a mutex, but realistically, if I'm allocating 16 bytes from a 4k page and my program is single-threaded I'm pretty sure all that's left is a 0.4% chance for a syscall and a pop from the list of available 16 byte spaces.
  • 1
    i guess the other problem with the unsized stuff is actually quite tricky. Because what you'd need to do is to relax the Sized bound by

    impl<T: YourTrait + ?Sized> YourTrait for &T {}

    but if you don't own it, it becomes tricky.

    Im just speculating here, but you could try to create a super trait, that just requires YourTrait to be implemented and do the impl that way.
    Something like:
    trait YourSuperTrait: YourTrait {}
    impl<T: YourSuperTrait + ?Sized> YourSuperTrait for &T {}

    Then you can just box YourSuperTrait instead
  • 1
    @thebiochemic That's a classic, yeah, good idea. Sadly, the Diesel query building DSL passes associated types all the way through the expression so type erasure is only ever an option if it's intentionally supported by the db provider.
Add Comment