Live data from Hacker News

Mistakes with Rust smart pointers: when Deref goes wrong

fuzzypixelz.com

21–30 of 64 posts

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

#21
post #14

Earlier quoted context omitted.

Perhaps a case where after removing the unused parameter and updating all the call sites, none of the calls resolve to the original function anymore.

And we would expect this behavior why?

If you start with

    void foo(std::string x, int y);
    void foo(const char* x);
Then calls to foo("bar", 0) would resolve to the first overload: the second isn't a match at all, but the first is a match with an implicit conversion from const char* to std::string. But if you removed the second parameter, including arguments at all call sites, then foo("bar") would match the second better because it doesn't involve any conversions, so it would be selected instead of the first.

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

#23
post #15

Earlier quoted context omitted.

This feels analogous to hiding in C++. In C++ by default member functions in a base class don't overload with member functions of the same name in a derived class. They get hidden.

Not disagreeing with you but what's interesting is that C++ doesn't hide in this particular situation. Smart pointers implement operator-> and operator* but then ptr.foo() is still always the foo() method of the pointer type (and won't compile if it doesn't have it) - you need ptr->foo() or (*ptr).foo() to get the method of the pointed-to type. It's one of the few places that C++ is more explicit than Rust. I wonder…

I've always liked that feature of C and C++. There's a lot of people that really hate it and in new languages they unify it to be just a dot. Zig does this as well, for instance. I always liked that the distinction was very explicit: use a.b() if you're calling b() on the object itself, use a->b() if you're de-referencing a first.

There are lots of things wrong with C and C++ that Zig and Rust fixes, but I never thought of this one being problematic in any way. It's as easy to type, the difference is obvious, and it's easy to see from a glance what's going on.

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

#24
post #15

Earlier quoted context omitted.

This feels analogous to hiding in C++. In C++ by default member functions in a base class don't overload with member functions of the same name in a derived class. They get hidden.

Not disagreeing with you but what's interesting is that C++ doesn't hide in this particular situation. Smart pointers implement operator-> and operator* but then ptr.foo() is still always the foo() method of the pointer type (and won't compile if it doesn't have it) - you need ptr->foo() or (*ptr).foo() to get the method of the pointed-to type. It's one of the few places that C++ is more explicit than Rust. I wonder…

People have been trying to get 'operator.' overloading in C++ for the last 20 years. Unfortunately this confusion between pointer operations and pointee operations has always been an obstacle :(.

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

#25
post #23

Earlier quoted context omitted.

Not disagreeing with you but what's interesting is that C++ doesn't hide in this particular situation. Smart pointers implement operator-> and operator* but then ptr.foo() is still always the foo() method of the pointer type (and won't compile if it doesn't have it) - you need ptr->foo() or (*ptr).foo() to get the method of the pointed-to type. It's one of the few places that C++ is more explicit than Rust. I wonder…

I've always liked that feature of C and C++. There's a lot of people that really hate it and in new languages they unify it to be just a dot. Zig does this as well, for instance. I always liked that the distinction was very explicit: use a.b() if you're calling b() on the object itself, use a->b() if you're de-referencing a first. There are lots of things wrong with C and C++ that Zig and Rust fixes, but I never thou…

I'm mostly indifferent to it because it doesn't really harm readability, and it's not hard to know when to use it, but I can seem why it might be more strongly disliked. You can't entirely rely on it to know a dereference is happening because references (e.g. `int&`) aren't subject to the `->` requirement. It's also annoying if you find that you can refactor `func(T*)` to `func(T&)` and now you have to replace all `->`s with `.`s.

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

#26
post #23

Earlier quoted context omitted.

Not disagreeing with you but what's interesting is that C++ doesn't hide in this particular situation. Smart pointers implement operator-> and operator* but then ptr.foo() is still always the foo() method of the pointer type (and won't compile if it doesn't have it) - you need ptr->foo() or (*ptr).foo() to get the method of the pointed-to type. It's one of the few places that C++ is more explicit than Rust. I wonder…

I've always liked that feature of C and C++. There's a lot of people that really hate it and in new languages they unify it to be just a dot. Zig does this as well, for instance. I always liked that the distinction was very explicit: use a.b() if you're calling b() on the object itself, use a->b() if you're de-referencing a first. There are lots of things wrong with C and C++ that Zig and Rust fixes, but I never thou…

I'm among the people who would have liked to eliminate even this special case and have a convenient postfix derefence for this. So instead of a->b() you'd have a*.b(), and if you need to dereference again, write a**.b() and so on. But as you said, lots of people really seem to hate this kind of thing. Zig is almost there with its dereference syntax, but still kept the magic dereferencing dot.

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

#27
post #23

Earlier quoted context omitted.

I've always liked that feature of C and C++. There's a lot of people that really hate it and in new languages they unify it to be just a dot. Zig does this as well, for instance. I always liked that the distinction was very explicit: use a.b() if you're calling b() on the object itself, use a->b() if you're de-referencing a first. There are lots of things wrong with C and C++ that Zig and Rust fixes, but I never thou…

I'm mostly indifferent to it because it doesn't really harm readability, and it's not hard to know when to use it, but I can seem why it might be more strongly disliked. You can't entirely rely on it to know a dereference is happening because references (e.g. `int&`) aren't subject to the `->` requirement. It's also annoying if you find that you can refactor `func(T*)` to `func(T&)` and now you have to replace all `-…

> You can't entirely rely on it to know a dereference is happening because references (e.g. `int&`) aren't subject to the `->` requirement.

To the extent that this is a problem, it's a problem with references as a language feature in general, not with the arrow syntax.

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

#28
post #15

Earlier quoted context omitted.

This feels analogous to hiding in C++. In C++ by default member functions in a base class don't overload with member functions of the same name in a derived class. They get hidden.

Not disagreeing with you but what's interesting is that C++ doesn't hide in this particular situation. Smart pointers implement operator-> and operator* but then ptr.foo() is still always the foo() method of the pointer type (and won't compile if it doesn't have it) - you need ptr->foo() or (*ptr).foo() to get the method of the pointed-to type. It's one of the few places that C++ is more explicit than Rust. I wonder…

One of the downsides of the C++ approach is that it makes it more cumbersome to make changes in your code. If you for instance make a trivial change where you change a variable from a stack-allocated object accessed directly via .foo() into a heap-allocated one accessed via ->foo(), you have to either manually change all .foo()s into ->foo()s or do some sort of weird work-around, such as making a separate variable that's a reference to the heap allocated object so that you can keep using those .foo()s. This is all relatively pointless busywork, which also pollutes the commit history with relatively meaningless changes.

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

#29
post #2

In case the author happens to see this thread – there seems to be a missing less-than sign: str::from_utf8( as Deref>::deref(&self.0)) Thanks for the article! ^_^

You're welcome :) I finally found out what was going wrong here. All angle brackets and other characters were being escaped in other parts of the document, even in blocks. Except when it came to code blocks inside blocks. For context, I use Zola and Cloudflare pages. It turns out there is a bug[^0] in Zola 1.40.0 which reads: > Fix code blocks content not being escaped when not using syntax highlighting I presume tha…

For the record, I have noticed two other places where the angle brackets are missing:

    struct AsciiString(Vec);
and

    impl Index> for AsciiString {
Post reply on HN