Live data from Hacker News

Mistakes with Rust smart pointers: when Deref goes wrong

fuzzypixelz.com

51–60 of 64 posts

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#51
post #5

"The issue, it turns out, is that method search does not check method parameter types against argument types." Right. Rust's doesn't allow much overloading of function names. Partly because C++ did. The C++ overload resolution rules got very complex, especially since they interact with implicit conversions. To keep those rules from introducing errors, there's a rule in C++ that the overload chosen must be at least on…

I worked on a C++ codebase where there was a method that had two overloads - one with 36 char* arguments, and one with 37. Obviously one hardly knows where to begin pointing out the problems. I'd like to report that it was some sort of elaborate joke, but honestly not sure. I think Rust, as in so many areas, made the right call here.

I'm currently trying to figure out who calls this C++ method in a large code base:

    bool operator()(const LLDispatcher* dispatcher, const std::string& key
    ...
Yes, they actually overloaded "()".

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#52
post #7

Earlier quoted context omitted.

Yes, I've had equally confusing compile errors from C++ due to its lookup rules. For example removing an unused parameter from a function can cause that function not to be found anymore! I'd argue that is more confusing than this Rust issue.

What does this comment mean? Function parameters used or not are part of the function signature, so obviously would participate in any form of argument dependent lookup.

There was an argument that was not used by the function implementation. I removed it from the signature entirely - at the definition and the call sites.

Boom. No longer compiles.

Yes I understand the complex and surprising rules that cause this to happen. That doesn't make them any less complex and surprising.

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#53
post #51

Earlier quoted context omitted.

I worked on a C++ codebase where there was a method that had two overloads - one with 36 char* arguments, and one with 37. Obviously one hardly knows where to begin pointing out the problems. I'd like to report that it was some sort of elaborate joke, but honestly not sure. I think Rust, as in so many areas, made the right call here.

I'm currently trying to figure out who calls this C++ method in a large code base: bool operator()(const LLDispatcher* dispatcher, const std::string& key ... Yes, they actually overloaded "()".

I don't follow. How does this declaration overloads "()"?

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#54

Earlier quoted context omitted.

What does this comment mean? Function parameters used or not are part of the function signature, so obviously would participate in any form of argument dependent lookup.

There was an argument that was not used by the function implementation. I removed it from the signature entirely - at the definition and the call sites. Boom. No longer compiles. Yes I understand the complex and surprising rules that cause this to happen. That doesn't make them any less complex and surprising.

"not used by the function implementation" doesn't mean "not passed in by callers".

The callers won't find a matching signature once there is 1 less parameter. I don't see what is confusing about it.

You probably misunderstood that warning as "No callers pass this parameter", which btw would only make sense for a parameter with a default value.

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#55

Earlier quoted context omitted.

Deref for Vec and String is fine because they are owning containers that decay to their "view" types (slices). Strings and vectors own memory, while views borrow it and can be used to operate on them without reallocating or moving the container itself, treating it as a contiguous list of values. A similar relationship exists between C++'s `std::string` and `std::string_view`, and `std::vector` and `std::span`. IMHO t…

> You don't need to own a string in order to check if all of its ASCII characters are all caps, for instance, because it's an operation that's also valid on any array of bytes, without the whole concept of "owning memory". Interestingly you can ask whether a string is ASCII, "this".is_ascii() is a predicate which does exactly that, but for what I think is your question, "are they all ASCII caps?" you'd need to go via…

Am I correct in thinking this is the type of thing change that fits the criteria to be implemented in a new edition? Assuming the issue is the same one I often run into (i.e. 'a versus for), it seems like special casing this for closures passed as arguments would be quite nice, but the fact that it wasn't done for 2018 or 2021 makes me think that maybe it's not something that would qualify for introducing in this way.

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#56
post #4

I think I've hit the same kind of problem once. What I learned is that true smart pointers are types that (at least in Rust) aren't really supposed to have methods on their own, to avoid this type of ambiguity during method resolution. For example, Box implements Deref so that you can conveniently use T's methods. If you look at the documentation of Box, the things you can do with the Box itself , like Box::leak, are…

> AFAICT, the "outer" methods always wins regardless of the arguments at the call site I imagine this is explicitly state in some portion that I have never read of the Deref documentation. The thing is, every introductory text ignores this, and there is no itemized rule in a more global document so that things like Rc and Cell can point directly to it. The Rust docs have a very general discoverability problem, and th…

It definitely would make sens to include this in the docs for `Deref`. I suspect the reason people hadn't thought to do that yet is because there's nothing specific to `Deref` about this behavior; it works the same whenever methods are present on a type due to trait definition[0] (although I imagine it's potentially less confusing for other traits given that the methods they provide are explicitly listed rather than implicit via the associated type).

It's also worth noting that if the ambiguity is between two trait impls rather than the concrete type and one of its trait impls, the compiler does require explicit disambiguation (either by calling the method as a top-level function on the trait and passing in the `self` parameter or by casting before calling the method)[1].

[0]: https://play.rust-lang.org/?version=stable&mode=debug&editio... [1]: https://play.rust-lang.org/?version=stable&mode=debug&editio...

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#58
post #55

Earlier quoted context omitted.

> You don't need to own a string in order to check if all of its ASCII characters are all caps, for instance, because it's an operation that's also valid on any array of bytes, without the whole concept of "owning memory". Interestingly you can ask whether a string is ASCII, "this".is_ascii() is a predicate which does exactly that, but for what I think is your question, "are they all ASCII caps?" you'd need to go via…

Am I correct in thinking this is the type of thing change that fits the criteria to be implemented in a new edition? Assuming the issue is the same one I often run into (i.e. 'a versus for ), it seems like special casing this for closures passed as arguments would be quite nice, but the fact that it wasn't done for 2018 or 2021 makes me think that maybe it's not something that would qualify for introducing in this wa…

It's not "just" syntax, so it couldn't "just" be a new edition, but I suppose it's conceivable that a hack could be invented and then the old behaviour grandfathered into prior editions as was done for impl IntoIterator for [T; N] in 2021 Edition.

That's a heavy lift though, you may need to carry this special code around in every compiler, forever, and I haven't even figured out what such code should look like, it might be really hard to even write it.

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#59
post #55

Earlier quoted context omitted.

Am I correct in thinking this is the type of thing change that fits the criteria to be implemented in a new edition? Assuming the issue is the same one I often run into (i.e. 'a versus for ), it seems like special casing this for closures passed as arguments would be quite nice, but the fact that it wasn't done for 2018 or 2021 makes me think that maybe it's not something that would qualify for introducing in this wa…

It's not "just" syntax, so it couldn't "just" be a new edition, but I suppose it's conceivable that a hack could be invented and then the old behaviour grandfathered into prior editions as was done for impl IntoIterator for [T; N] in 2021 Edition. That's a heavy lift though, you may need to carry this special code around in every compiler, forever, and I haven't even figured out what such code should look like, it mi…

Good to know! I appreciate the insight

Re: Mistakes with Rust smart pointers: when Deref goes wrong

#60

Earlier quoted context omitted.

Deref for Vec and String is fine because they are owning containers that decay to their "view" types (slices). Strings and vectors own memory, while views borrow it and can be used to operate on them without reallocating or moving the container itself, treating it as a contiguous list of values. A similar relationship exists between C++'s `std::string` and `std::string_view`, and `std::vector` and `std::span`. IMHO t…

> You don't need to own a string in order to check if all of its ASCII characters are all caps, for instance, because it's an operation that's also valid on any array of bytes, without the whole concept of "owning memory". Interestingly you can ask whether a string is ASCII, "this".is_ascii() is a predicate which does exactly that, but for what I think is your question, "are they all ASCII caps?" you'd need to go via…

How would removing the lambda affect back compat?
Post reply on HN