-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cycle detected when processing existential type #55997
Comments
I almost filed a duplicate for this. Can someone please tag this Separately, is it intentional that existential types don't auto-implement auto traits like |
It appears that existential types do leak auto traits: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=de5ba08a8f48bd7859c252c9ba81c849 |
That is intended by the RFC. At least it was for |
That is actually the intended behavior (at least by me). I specifically implemented existential types in a way that mean every use inside the current module or a submodule will be checked for being a defining use. We should definitely improve the error message though. It should point to the |
I guess I understand the rules (current and submodules are defining uses + auto-trait impls are only inferred outside the defining scope), but the overall experience is this:
I feel this will be a big source of confusion because of how contradictory it seems. "Testing that the type impls Send makes it not impl Send. Leaving it untested makes it impl Send." I hope the error message can elaborate that submodules count as defining uses, maybe list all the uses or something. The code that I had a problem was a unit test, something like this: pub existential type Foo: Debug;
pub fn foo() -> Foo {
5
}
#[cfg(test)]
mod tests {
#[test]
fn test_foo() {
assert_send(foo());
}
}
The "move to a submodule" strategy will mean either the unit test has to move to the parent module, or I would have to make a temporary inner module for It'll also look weird if For my own case I solved it by doing option 1, ie I added an explicit |
The problem is that I don't see any way we can detect ahead of time that The RFC on existential types also talks about So we do need to process I just had an idea while writing this text. Maybe we can defer the checking of such "magic" bounds (Send + Sync an existential types) to after the query finishes. I'll have a look. |
@eddyb back when you created Then again, the way existential types work, they violate how queries run by going through every function in their parent module and checking them for some information that only can be inferred by their body. This is not much of a problem for |
Just to be clear, I think the current implementation is fine. But submodules or tests can end up being unexpected defining uses (submodules, tests), so I'd like the error to be clear what they are. Eg:
It can then suggest moving to a submodule as you said, or explicitly adding I suppose it's too late to require an "explicit" defining use like |
That's not actually the issue. The issue is that we are looking at |
Oops, wrong button.
We can go back, that's no problem, everything is still behind a feature gate, but the RFCs explicitly state that we want |
The |
Oh, heh, I misunderstood what you wrote. You acutally want a |
I think the simplest approach would be to require explicitly adding the auto-trait as a bound to the impl trait definition. That is, instead of writing It's important to note that the auto traits 'leaked' by an impl trait (both RPIT and type-alias) implicitly create a Semver guarantee. That is, downstream crates can write code that relies on a particular Adding the auto trait as a bound in the definition just makes this more explicit. It doesn't actually promise anything more (even though it may look like it at first), and avoids the need for any complicated handling of auto-trait predicates. It would probably be a good idea to detect these kinds of cycle errors, and emit a suggestion to add the auto-trait as a bound. EDIT: This won't work when the underlying type is generic and doesn't implement the auto trait unconditionally. |
Modern repro:
|
playground using |
I think this is "behaving as expected". It's certainly not a blocker for stabilization. It would be nice if this worked, but it's ultimately expected based on the current implementation. |
We should make the cycle diagnostic point at the |
playground
Commenting out the
assert_send(&f);
line compiles and runs fine (playground), movingFoo
andfoo
into a sub-module correctly identifies thatFoo: !Send
(playground).The text was updated successfully, but these errors were encountered: