-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Using Cow with the Vec/slice ToOwned impl for creating a recursive type fails to typecheck due to overflow #38962
Comments
Something like BarOwned(Vec<Foo<'static>>),
BarBorrowed(&'a [Foo<'a>]), Also works FWIW (and then implementing Clone accordingly). Is the compiler for whatever reason evaluating the plain Independent of that, I also see another problem here when using Cow: the lifetime of Foo. For the Borrowed variant of Cow it should be 'a (&'a [Foo<'a>]), for the Owned variant it should be 'static (i.e. Vec<Foo<'static>>, it's cloned after all). This does not seem to be possible at all currently |
@sdroege the lifetime of In any case, I'm also running into this problem in my code. I have several hypotheses on what's causing this, and (fair warning) I'm about to ramble on about all of them. One thing that's pretty clear is that the problem is being triggered by the pub enum Cow<'a, B: ?Sized + 'a>
where B: ToOwned
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
pub struct Foo<'a>(Cow<'a, [Foo<'a>]>); This is the definition of
...well, maybe not. Suppose that the cause of the error is the cycle between
rustc begins to dive down the rabbit-hole. It finds Hypothesis number two: when rustc finds Hypothesis number three: when rustc finds Out of all of these I feel that the last is the most likely, while still somewhat improbable. It is supported somewhat by the way the error says "within the type Hypothesis number four: rustc is actually checking to be certain that Number four feels like the smoking gun for this overflow. It deals with |
In addition, this seems to show that indeed, overflows are happening calculating the |
Variant that works: use std::borrow::Cow;
// Does not work either: #[derive(Clone)]
enum Foo<'a> {
// Does not work:
Bar(Cow<'a, [Foo<'static>]>, ()),
// Works: Bar(Vec<Foo<'a>>),
Baz(&'a str),
}
impl<'a> Clone for Foo<'a> {
fn clone(&self) -> Self {
unimplemented!();
}
}
fn main() {} |
It's a bit surprising I accidentally allowed possibly-infinite structs back with |
I don't quite follow what you mean by this -- do you mean it is surprising that you chose to do that? Or surprising that the error interacts with that? |
I didn't realize I accidentally re-allowed infinite structs when I implemented that. |
Just ran across this too. I had unrelated thought few days ago which seems could help here too: would it be possible to change pub enum Cow<'a, B, O = <B as ToOwned>::Owned> where
B: 'a + ?Sized,
O: Borrow<B>
{
Borrowed(&'a B),
Owned(O),
} Note that this change is backwards-compatible thanks to default generics still having // works as it did before
let old_style: Cow<[u8]>; But it also enables interesting new cases: // works now too despite [u8]::ToOwned being Vec<u8> not Box<[u8]>
let new_style: Cow<[u8], Box<[u8]>>; and struct A {}
struct B(A);
impl Borrow<A> for B {
fn borrow(&self) -> &A {
&self.0
}
}
// works despite A not having ToOwned
let d: Cow<A, B>; And even allows to work around this particular issue: enum Foo<'a> {
// works now too thanks to the explicit owned type
Bar(Cow<'a, [Foo<'a>], Vec<Foo<'a>>>),
// can do even this now
Baz(Cow<'a, Foo<'a>, Box<Foo<'a>>>),
} @nikomatsakis @arielb1 @sdleffler What do you think? |
@RReverser you'd need an extra trait bound on I'm not sure if there's a stdlib trait right now which represents this accurately. In any case, I feel that using such a workaround for this is the wrong approach, as this is pretty clearly a bug (some sort of missing inductive hypothesis inside the is-this-type-sized checker.) Would still be interesting to have a generalized |
That's already covered by
That's the beauty of having second type param - it doesn't have to implement any built-in trait as long as
Yeah, as I said, it's mostly unrelated (I need it to deal with boxed slices and with custom reference / owned type pairs), it just happens to help with this bug as well. |
@RReverser no, it's not covered by i.e. there is no way to construct an owned version |
@RReverser I suppose the impact of not being able to construct an |
Yup :) Thanks for confirmation. |
I also just ran into this issue, with the same use case (nested Cow). What is the actual conclusion here? Is this a compiler bug, a limitation of the type checker, or behaving as intended? |
#47032 is the same as this one but also has a workaround - wrap the |
See the following code
This currently fails to compile with
However in the end the Cow here is just an enum that is either a &[Foo] or a Vec (the ToOwned instance of [T] uses Vec for the owned variant), both having a known size and thus this all should really work, or am I missing something?
Is this a bug, a missing feature or can't this possibly work?
The text was updated successfully, but these errors were encountered: