-
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
Defining scope of existential type
defined by associated type
#57961
Comments
cc @oli-obk |
I'm not surprised this doesn't work. "defining uses" are hardcoded to be function bodies (either by return value or by let binding) right now. While I'm not sure we want to support this though, as it is very hard to reason about, and it also seems slightly weird that we now know that In any way, the implications are well beyond what was suggested in the RFC and I am very certain we'd need an RFC for anything in this direction. |
I don't think a new RFC is warranted per se. I think that tweaking the idea of what a "defining use" is falls pretty squarely under the "experiment in master" heading. (In fact, I'll have to re-read the RFCs, but I'm not sure they even include the concept of defining uses, do they?) In any case, if we want to support trait Foo {
type Bar: Iterator<Item = impl Display>
} which I think we do, as that is part of RFC 2289, right? |
I think what @nikomatsakis says intuitively makes sense. I'll try to do some experimentation there, but any advice on how to go about implementing it would be much appreciated. |
Not in so many words, but it quite explicitly talks about bodies:
Not with that syntax, no. It's also not super clear what that means; it could either be an As for needing an RFC; I think that depends on how far reaching implications the suggested change has re. complier, user, and type system complexity. |
My worry is less about whether it's in the spirit of the RFC (it definitely is), but more about the kind of constraints used to figure out an existential type's concrete type. Right now there's a obvious ordered dependency tree for computing the concrete type: when run the If we added the system proposed above with a similar scheme, we'd need to start creating TypeckTables for associated types and figure out when we want an existential type use in an associated type to be defining or just using. And while thinking about the latter I realized that I utterly misread the example... So consider my worries moot. It should be simple enough extend the search space for defining uses from bodies to also include associated type definitions in impl blocks. |
Modern repro:
|
This actually feels like a blocker, I think this should count as a "defining use". |
I need to run some traces, but I'm assuming we're actually figuring out the hidden type, but not storing it somewhere where we can find it again. Should this block stabilization? It seems forward compatible to allow later |
This appears to be a result of overlooking obligations, as @oli-obk suggested, here is an example that causes an ICE (but ought to error in type checking): #![feature(type_alias_impl_trait)]
type X = impl Sized;
trait Foo {
type Bar: Iterator<Item = X>;
}
impl Foo for () {
type Bar = std::vec::IntoIter<u32>;
}
fn incoherent() {
let f: X = 22_i32;
}
fn main() {} |
The problem as debugged by @ouz-a is that the hidden type of I worry that there are more similar cases lurking in the compiler, so we're going to expose them as type mismatch errors for now and then look into whether they can be made to compile successfully with reasonable compiler changes. |
@oli-obk and I discussed this today. My take is that it is fine if this code gives an error. We can always adapt it later -- but there is no backwards compatibility risk, the only code that would successfully compile is code that works independently of the value of #![feature(type_alias_impl_trait)]
type X = impl Sized;
trait Foo {
type Bar: Iterator<Item = X>;
fn into_bar(self) -> Self::Bar;
}
impl Foo for () {
type Bar = std::vec::IntoIter<X>;
fn into_bar(self) -> Self::Bar {
vec![22, 44].into_iter()
}
}
fn incoherent() {
let f: X = 22_i32;
}
fn main() {} |
Formalize defining_use_anchor This tackles issue rust-lang#57961 Introduces new enum called `DefiningAnchor` that replaces `Option<LocalDefId>` of `defining_use_anchor`. Now every use of it is explicit and exhaustively matched, catching errors like one in the linked issue. This is not a perfect fix but it's a step in the right direction. r? `@oli-obk`
So, during our discussion earlier today, @nikomatsakis brought up this interesting example of code that should really compile, we think:
Error:
Playground
It seems that
type _0 = X;
isn't being considered as a "defining use", even though it clearly does constrainX
. The question is, what sort of changes do we need for this to work? (I'm pretty sure it should work.) Do we need Chalk perhaps?CC @nikomatsakis @cramertj @scalexm
The text was updated successfully, but these errors were encountered: