Skip to content
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

Trying to use same existential type for two functions cause cycle dependency #61863

Closed
shootingsyh opened this issue Jun 15, 2019 · 1 comment
Closed

Comments

@shootingsyh
Copy link

@shootingsyh shootingsyh commented Jun 15, 2019

On a nightly rustup 1.18.3 (435397f48 2019-05-22)
Some code like this

#![feature(existential_type)]
pub trait T {
    fn bla() -> ();
}

pub struct S {
  v: u64
}

impl T for S {
    fn bla() -> () {}
}

existential type TE: T;
pub fn bla() -> TE {
    return S {v:1}
}

pub fn bla2() -> TE {
    bla()
}

cause error

Compiling playground v0.0.1 (/playground)
error[E0391]: cycle detected when processing TE
--> src/lib.rs:14:1
|
14 | existential type TE: T;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires processing bla2...
--> src/lib.rs:19:21
|
19 | pub fn bla2() -> TE {
| ___________________^
20 | | bla()
21 | | }
| |
^
= note: ...which again requires processing TE, completing the cycle
note: cycle used when collecting item types in top-level module
--> src/lib.rs:1:1
|
1 | / #![feature(existential_type)]
2 | | pub trait T {
3 | | fn bla() -> ();
4 | | }
... |
20 | | bla()
21 | | }
| |
^

error: concrete type differs from previous defining existential type use
--> src/lib.rs:19:1
|
19 | / pub fn bla2() -> TE {
20 | | bla()
21 | | }
| |^ expected S, got TE
|
note: previous use here
--> src/lib.rs:15:1
|
15 | / pub fn bla() -> TE {
16 | | return S {v:1}
17 | | }
| |
^

error: aborting due to 2 previous errors

playground link:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=71c724f92b074d0b6f355a6aaf8d3d1a

@Aaron1011
Copy link
Member

@Aaron1011 Aaron1011 commented Jul 5, 2019

I think the most straightforward way to resolve this would be to try to 'recover' from the cycle error, and see if processing any other items allows us to constraint the existential type. Unfortunately, the docs state that cycle recovery was removed.

Aaron1011 added a commit to Aaron1011/rust that referenced this issue Jul 5, 2019
Fixes rust-lang#61863

We now allow uses of 'existential type's that aren't defining uses -
that is, uses which don't constrain the underlying concrete type.

To make this work correctly, we also modify eq_opaque_type_and_type to
not try to apply additional constraints to an opaque type. If we have
code like this:

```
existential type Foo;
fn foo1() -> Foo { ... }
fn foo2() -> Foo { foo1() }
```

then 'foo2' doesn't end up constraining 'Foo', which means that
'foo2' will end up using the type 'Foo' internally - that is, an actual
'TyKind::Opaque'. We don't want to equate this to the underlying
concrete type - we just need to enforce the basic equality constraint
between the two types (here, the return type of 'foo1' and the return
type of 'foo2')
Aaron1011 added a commit to Aaron1011/rust that referenced this issue Jul 5, 2019
Fixes rust-lang#61863

We now allow uses of 'existential type's that aren't defining uses -
that is, uses which don't constrain the underlying concrete type.

To make this work correctly, we also modify eq_opaque_type_and_type to
not try to apply additional constraints to an opaque type. If we have
code like this:

```
existential type Foo;
fn foo1() -> Foo { ... }
fn foo2() -> Foo { foo1() }
```

then 'foo2' doesn't end up constraining 'Foo', which means that
'foo2' will end up using the type 'Foo' internally - that is, an actual
'TyKind::Opaque'. We don't want to equate this to the underlying
concrete type - we just need to enforce the basic equality constraint
between the two types (here, the return type of 'foo1' and the return
type of 'foo2')
Aaron1011 added a commit to Aaron1011/rust that referenced this issue Jul 7, 2019
Fixes rust-lang#61863

We now allow uses of 'existential type's that aren't defining uses -
that is, uses which don't constrain the underlying concrete type.

To make this work correctly, we also modify eq_opaque_type_and_type to
not try to apply additional constraints to an opaque type. If we have
code like this:

```
existential type Foo;
fn foo1() -> Foo { ... }
fn foo2() -> Foo { foo1() }
```

then 'foo2' doesn't end up constraining 'Foo', which means that
'foo2' will end up using the type 'Foo' internally - that is, an actual
'TyKind::Opaque'. We don't want to equate this to the underlying
concrete type - we just need to enforce the basic equality constraint
between the two types (here, the return type of 'foo1' and the return
type of 'foo2')
Centril added a commit to Centril/rust that referenced this issue Jul 27, 2019
…oli-obk

Fix cycle error with existential types

Fixes rust-lang#61863

We now allow uses of `existential type`'s that aren't defining uses - that is, uses which don't constrain the underlying concrete type.

To make this work correctly, we also modify `eq_opaque_type_and_type` to not try to apply additional constraints to an opaque type. If we have code like this:

```rust
existential type Foo;
fn foo1() -> Foo { ... }
fn foo2() -> Foo { foo1() }
```

then `foo2` doesn't end up constraining `Foo`, which means that `foo2` will end up using the type `Foo` internally - that is, an actual `TyKind::Opaque`. We don't want to equate this to the underlying concrete type - we just need to enforce the basic equality constraint between the two types (here, the return type of `foo1` and the return type of `foo2`)
@bors bors closed this in #62423 Jul 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

3 participants