diff options
| author | bors <bors@rust-lang.org> | 2016-09-03 07:48:06 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-09-03 07:48:06 -0700 |
| commit | d748fa6ecccf6f5b4c7ae4abee0a2d206b165de2 (patch) | |
| tree | 5ada2c11762533ba6c6f21a7593b015cb1a89912 /src/libsyntax/parse | |
| parent | 01b35d82e51458870f61cf850b73479f253fcb54 (diff) | |
| parent | 436cfe56534b405786816d4bbcccd11ed7571981 (diff) | |
| download | rust-d748fa6ecccf6f5b4c7ae4abee0a2d206b165de2.tar.gz rust-d748fa6ecccf6f5b4c7ae4abee0a2d206b165de2.zip | |
Auto merge of #36016 - petrochenkov:union, r=nikomatsakis
Implement untagged unions (RFC 1444)
cc https://github.com/rust-lang/rust/issues/32836
Notes:
- The RFC doesn't talk about `#[packed]` unions, this implementation supports them, packing changes union's alignment to 1 and removes trailing padding.
- The RFC doesn't talk about dynamically sized unions, this implementation doesn't support them and rejects them during wf-checking (similarly, dynamically sized enums are not supported as well).
- The lint for drop fields in unions can't work precisely before monomorphization, so it works pessimistically - non-`Copy` generic fields are reported, types not implementing `Drop` directly, but having non-trivial drop code are reported.
```
struct S(String); // Doesn't implement `Drop`
union U<T> {
a: S, // Reported
b: T, // Reported
}
```
- https://github.com/rust-lang/rust/pull/35764 was indeed helpful and landed timely, I didn't have to implement internal drop flags for unions.
- Unions are not permitted in constant patterns, because matching on union fields is unsafe, I didn't want unsafety checker to dig into all constants to uncover this possible unsafety.
- The RFC doesn't talk about `#[derive]`, generally trait impls cannot be derived for unions, but some of them can. I implemented only `#[derive(Copy)]` so far. In theory shallow `#[derive(Clone)]` can be derived as well if all union fields are `Copy`, I left it for later though, it requires changing how `Clone` impls are generated.
- Moving union fields is implemented as per https://github.com/rust-lang/rust/issues/32836#issuecomment-242511491.
- Testing strategy: union specific behavior is tested, sometimes very basically (e.g. debuginfo), behavior common for all ADTs (e.g. something like coherence
checks) is not generally tested.
r? @eddyb
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 92ec0fdb3de..ec9dc1bae5a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5102,6 +5102,25 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Struct(vdata, generics), None)) } + /// Parse union Foo { ... } + fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> { + let class_name = self.parse_ident()?; + let mut generics = self.parse_generics()?; + + let vdata = if self.token.is_keyword(keywords::Where) { + generics.where_clause = self.parse_where_clause()?; + VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) + } else if self.token == token::OpenDelim(token::Brace) { + VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) + } else { + let token_str = self.this_token_to_string(); + return Err(self.fatal(&format!("expected `where` or `{{` after union \ + name, found `{}`", token_str))) + }; + + Ok((class_name, ItemKind::Union(vdata, generics), None)) + } + pub fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> { let mut fields = Vec::new(); if self.eat(&token::OpenDelim(token::Brace)) { @@ -5938,6 +5957,20 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(Some(item)); } + if self.check_keyword(keywords::Union) && + self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword()) { + // UNION ITEM + self.bump(); + let (ident, item_, extra_attrs) = self.parse_item_union()?; + let last_span = self.last_span; + let item = self.mk_item(lo, + last_span.hi, + ident, + item_, + visibility, + maybe_append(attrs, extra_attrs)); + return Ok(Some(item)); + } self.parse_macro_use_or_failure(attrs,macros_allowed,attributes_allowed,lo,visibility) } |
