> I eventually ended up abusing the unsafe code in Vec to get what I wanted:

That code isn't unsafe. It uses the [T] DST, which isn't a common type, but it's safe code.

Yeah, I thought you were implementing a vector or a doubly linked list or something, not a matrix. Lack of integer generics does make matrices a bit harder to implement -- heapifying is the simpler solution here which you did try, and heapifying should work, really.

> . (I've had a good look at the num crate, and I think it got a lot of things wrong, so that's not an attractive option.)

It does give you the Float and Signed traits, which get you exactly what you need here? You may need to cast to float for integers. It's not great, but it should be good enough.

> I've read an explanation or two, but this is a binary operator! Why does the order of the arguments matter for coherence here?
>
> but maybe operator traits shouldn't be restricted with the same logic as other traits.

I mean, operators have the same conflicting impl problem regardless of how you implement them (as traits or otherwise). C++ solves this with overload resolution rules. Rust doesn't want that, and instead doesn't allow overlaps to occur in the first place. An order-independent coherence system here would be stricter than the order-dependent one we have here. So as to be less strict, a choice has been made -- to make it easier to implement operator overloads for the first type than for the second.

(I think C++ has a similar asymmetry when it comes to choosing between overlapping operator overloads when the overlap is in the pre or in the post type)

> You've mentioned that before (at least I think it was you), around the time I was looking at this. I thought specialization had already been accepted, but I haven't stayed all that current.

Probably wasn't me. A simpler form of specialization has been accepted and it's currently experimental (so, nightly-only, but should stabilize). The design of the stronger form ("intersection impls") is still being discussed I think.

Not sure if the current form of specialization would help for that impl (it looks like it would, but I'm not sure), but intersection impls might. Either way, stabilization helps by letting you explicitly opt in to your impl being overridden by another (giving you a system more like C++), and in turn will relax coherence requirements since overlaps are now allowed.

Like I said, this is all ongoing work. Not there yet :)

> Anyways, these are all really simple things in C++, and they aren't simple in Rust, and that was my main point a few comments back.

But here's the thing -- you're not actually doing anything with these. This is sort of my point, and similar to Patrick's point about "languages can do fine without generics". You're designing a library for general use, but you're designing it with the concerns for use in C++. Asymmetric operators are considered bad in C++. Not in Rust; many operators are asymmetric. But ultimately, how much do asymmetric operators really affect you when programming? Just reorder the things. No big deal.

To give an analogy, I can make a similar complaint about C++ that it's hard to design bounded generic APIs (C++ concepts fixes this, but it's not there yet). This is a true complaint, but it doesn't really say anything about a programmer's ability to get things done in C++. I wouldn't say that it's hard to "get my car on the road" in C++ because I can't use strict bounds on my APIs. It just means that this feature is not one I can rely on when designing my overall code. I can make similar complaints about how hard it is to use algebraic datatypes in C++. The point is that I shouldn't be designing my abstractions around the assumption that these features work well in C++.

Rust and C++ differ in many areas when it comes to expressiveness. But ultimately you're still able to get things done well in both languages, in comparable time. There are some design patterns that work well in C++ and don't in Rust, and the reverse is true too. On an average this does not affect your ability to get stuff done -- to "get your card on the road" as you say.