Skip to content

Conversation

@isabelmu
Copy link
Contributor

It was possible to trigger a stack overflow in rustc because the routine used to verify enum representability,
type_structurally_contains, would recurse on inner types until hitting the original type. The overflow condition was when a different structurally recursive type (enum or struct) was contained in the type being checked.

I suspect my solution isn't as efficient as it could be. I pondered adding a cache of previously-seen types to avoid duplicating work (if enums A and B both contain type C, my code goes through C twice), but I didn't want to do anything that may not be necessary.

I'm a new contributor, so please pay particular attention to any unidiomatic code, misuse of terminology, bad naming of tests, or similar horribleness :)

Updated to verify struct representability as well.

Fixes #3008.
Fixes #3779.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be return if i == 0 { SelfRecursive } else { ContainsRecursive }. (Also, the ; at the end of the if here is not required.)

@huonw
Copy link
Contributor

huonw commented Jan 27, 2014

Looks reasonable to me; this is a cool first contribution!

I'd guess this fixes struct Foo { x: Option<Foo> } too? In which case, you can add that test case and "fixes #3779" to a commit message or the PR text.

(Btw you had "fixes issue #3008" before, but github doesn't recognise that as a special command. It has to be "fixes #3008" without "issue".)

@isabelmu
Copy link
Contributor Author

Oh! Didn't realize #3779 existed. I thought structs were somehow OK (and say as much in a comment somewhere) already. Clearly they aren't. I will add an is_type_representable call for structs, and a test case.

@isabelmu
Copy link
Contributor Author

I'm actually still able to trigger a stack overflow in fun cases like:

enum E1 { V1(E2<E1>), } enum E2<T> { V2(E2<E1>), } 

I'll try to work out what's going on later today. (This stack overflow happens later, like the one in #3779).

I suppose #[deriving(Eq)] is totally wrong for ReprItem?

@brson
Copy link
Contributor

brson commented Jan 27, 2014

Woo! Nice 1.0 fix.

@isabelmu
Copy link
Contributor Author

This should be OK now. @huonw what next?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you reckon you could put a comment above this like check_instantiable has below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be OK?

/// Checks whether a type can be represented in memory. In particular, it /// identifies types that contain themselves without indirection through a /// pointer, which would mean their size is unbounded. This is different from /// the question of whether a type can be instantiated. See the definition of /// `check_instantiable`. 
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@isabelmu
Copy link
Contributor Author

(thanks for all the feedback!)

@isabelmu
Copy link
Contributor Author

@huonw I just realized that struct Foo { x: [Foo, .. 0] } and enum Foo { A([Foo, .. 0]) } still present a problem after this patch. The struct gives a stack overflow on use (let y = Foo { x: [] };) and the enum gives a stack overflow on declaration (not sure where in the code the stack overflow happens).

Right now, is_type_representable considers fixed-length-zero vectors as representable--is this OK? Are these Foo definitions supposed to be legal and usable (a new issue)?

@huonw
Copy link
Contributor

huonw commented Jan 30, 2014

Hm, good catch... I'm not sure the semantics of that corner case are decided.

I'd recommend removing the len == 0 special case (so that those Foo you've given there are not representable), filing an issue about it and leaving a FIXME #<issue number> at the relevant place in the code.

@isabelmu
Copy link
Contributor Author

For the struct and enum both, the debug output loops on "Representing: Foo", printed from trans::adt::represent_type--maybe a zero-length check is all that is needed?

@isabelmu
Copy link
Contributor Author

OK, will do.

@huonw
Copy link
Contributor

huonw commented Jan 30, 2014

Fixing the downstream code would be acceptable too. However, I do think filling an issue so that the precise semantics are decided upon (rather than just "this is what the compiler happens to do") would be good. :)

@isabelmu
Copy link
Contributor Author

@huonw Removed the if len != 0 check as discussed.

bors added a commit that referenced this pull request Jan 30, 2014
It was possible to trigger a stack overflow in rustc because the routine used to verify enum representability, type_structurally_contains, would recurse on inner types until hitting the original type. The overflow condition was when a different structurally recursive type (enum or struct) was contained in the type being checked. I suspect my solution isn't as efficient as it could be. I pondered adding a cache of previously-seen types to avoid duplicating work (if enums A and B both contain type C, my code goes through C twice), but I didn't want to do anything that may not be necessary. I'm a new contributor, so please pay particular attention to any unidiomatic code, misuse of terminology, bad naming of tests, or similar horribleness :) Updated to verify struct representability as well. Fixes #3008. Fixes #3779.
@bors bors closed this Jan 30, 2014
@bors bors merged commit 8d097b3 into rust-lang:master Jan 30, 2014
@isabelmu isabelmu mentioned this pull request Feb 1, 2014
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 25, 2022
…nment, r=flodiebold feat: implement destructuring assignment This is an attempt to implement destructuring assignments, or more specifically, type inference for [assignee expressions](https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions). I'm not sure if this is the right approach, so I don't even expect this to be merged (hence the branch name 😉) but rather want to propose one direction we could choose. I don't mind getting merged if this is good enough though! Some notes on the implementation choices: - Assignee expressions are **not** desugared on HIR level unlike rustc, but are inferred directly along with other expressions. This matches the processing of other syntaxes that are desugared in rustc but not in r-a. I find this reasonable because r-a only needs to infer types and it's easier to relate AST nodes and HIR nodes, so I followed it. - Assignee expressions obviously resemble patterns, so type inference for each kind of pattern and its corresponding assignee expressions share a significant amount of logic. I tried to reuse the type inference functions for patterns by introducing `PatLike` trait which generalizes assignee expressions and patterns. - This is not the most elegant solution I suspect (and I really don't like the name of the trait!), but it's cleaner and the change is smaller than other ways I experimented, like making the functions generic without such trait, or making them take `Either<ExprId, PatId>` in place of `PatId`. in case this is merged: Closes rust-lang#11532 Closes rust-lang#11839 Closes rust-lang#12322
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants