-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Originally from @adetaylor:
I'm looking for advice on the diagnostics around the Sized
ness of a receiver, and I'm hoping @estebank can advise (or of course anyone else @wesleywiser @compiler-errors ).
The background (for Esteban):
- This is the tracking issue for "arbitrary self types v2", which allows methods like this:
impl Foo { fn bar(self: MySmartPtr<Self>) {} // note type of self }
- The key part of this is that types (such as
MySmartPtr
, above) which wish to act as method receivers must implement a new traitReceiver
- Before writing the RFC, I happened to make a mistake which I think might be quite common, so in the Diagnostics section of the RFC I proposed adding a diagnostic specifically for this case (the second bullet in that linked section).
The case I want to generate an error for: see this code but, in short, someone implements Receiver
for T
but not T: ?Sized
.
Questions. Even partial answers to some questions might point me in the right direction.
Overall approach
- I can quite easily get hold of an unmet obligation for why the type of
self
doesn't implementReceiver
. But how can I determine if some missing?Sized
bound is the problem?
a. Re-run the resolution process with some simulated fake sizedSelf
type? See if the obligation resolves in that case, and if so, show a diagnostic.
b. Simulate that someimpl<T> Receiver for T
block is actuallyimpl <T: ?Sized> Receiver for T
, elsewhere in the program or even in another crate. See if the obligation resolves in that case, and if so, show a diagnostic.
c. Suggest "ensure any Receiver implementations cover !Sized" without actually checking that this is the problem. This might give lots of false positives.
@adetaylor: I've split this out into its own issue. Let's try to avoid discussion on tracking issues. It's really not the purpose of a tracking issue, and we've locked tracking issues in the past for exactly the same reason (it often pings like... 40 people who are subscribed to the issue).
These days tracking issues carry the note:
As with all tracking issues for the language, please file anything unrelated to implementation history, that is: bugs and design questions, as separate issues as opposed to leaving comments here. The status of the feature should also be covered by the feature gate label. Please do not ask about developments here.
Activity
arbitrary_self_types
#44874compiler-errors commentedon Dec 16, 2024
Well, if you put that unmet obligation into an
ObligationCtxt::new_with_diagnostics
, then you should get aFulfillmentError
out whose predicate will be aSized
goal.adetaylor commentedon Dec 17, 2024
Unfortunately it doesn't seem to have figured out its way through to the
Sized
problem. I get one of these:for this test case.
I'll poke at why that's the case.
compiler-errors commentedon Dec 19, 2024
On second though, you probably won't have the compiler choose the a specific Receiver impl since there's also a blanket impl for Deref types.
cramertj commentedon Jan 3, 2025
This does actually appear to be the real issue here. The error message still doesn't provide the hint even when it doesn't originate from an autoderef:
gives
Note the lack of a
Sized
hint.compiler-errors commentedon Jan 3, 2025
Yeah, unfortunately to the compiler it's not obviously clear that we should prefer a more specific impl over a blanket. For the trait solver, if neither impl applies they're basically just... equally invalid. For diagnostics, it seems like a special case that's motivated for this example but could also be misleading in other places, especially when the blanket impls and concrete impls get more complex and "close" to overlapping.
cramertj commentedon Jan 3, 2025
In that case, I think this issue generalizes to examples like this which have nothing to do with
Receiver
(or withSized
):generates
but with the non-applicable blanket impl removed, it gives a more specific error:
edit: jinx
cramertj commentedon Jan 10, 2025
One option would be to prefer impls whose type-without params (e.g.
Wrapper<T>
for someWrapper<usize>
) matches. If such an impl exists, it must be where the impl would come from-- the type can't plausibly be covered by the blanket impl without a conflict (well, until a hypothetical future with intersection impls).This would also only work for generic record types, not type aliases (because e.g.
type Wrapper<T> = <T as Trait>::Assoc;
), but we already have to distinguish these two things for the purposes of e.g. coherence, whereimpl<T> Trait for SomeLocalType<T>
is valid butimpl<T> Trait for SomeLocalTypeAliasThatMayPointToANonLocalType<T>
is not.