diff options
| author | Oliver Schneider <github35764891676564198441@oli-obk.de> | 2018-07-03 19:38:14 +0200 |
|---|---|---|
| committer | Oliver Schneider <github35764891676564198441@oli-obk.de> | 2018-07-18 10:53:08 +0200 |
| commit | 53d2ebb0adbe677a811ae130523ebceb285a8029 (patch) | |
| tree | aa5bf290ab3240ee1028359cef335f22dc1a2cdb /src/libsyntax/parse | |
| parent | 1c84d8187395b641616649a0f16f15a78ea8bbce (diff) | |
| download | rust-53d2ebb0adbe677a811ae130523ebceb285a8029.tar.gz rust-53d2ebb0adbe677a811ae130523ebceb285a8029.zip | |
Implement existential types
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 73 |
1 files changed, 56 insertions, 17 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 62bb5fbd04f..2eaa56ebeb8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -63,6 +63,15 @@ use std::mem; use std::path::{self, Path, PathBuf}; use std::slice; +#[derive(Debug)] +/// Whether the type alias or associated type is a concrete type or an existential type +pub enum AliasKind { + /// Just a new name for the same type + Weak(P<Ty>), + /// Only trait impls of the type will be usable, not the actual type itself + Existential(GenericBounds), +} + bitflags! { struct Restrictions: u8 { const STMT_EXPR = 1 << 0; @@ -5502,16 +5511,13 @@ impl<'a> Parser<'a> { let lo = self.span; let vis = self.parse_visibility(false)?; let defaultness = self.parse_defaultness(); - let (name, node, generics) = if self.eat_keyword(keywords::Type) { - // This parses the grammar: - // ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";" - let name = self.parse_ident()?; - let mut generics = self.parse_generics()?; - generics.where_clause = self.parse_where_clause()?; - self.expect(&token::Eq)?; - let typ = self.parse_ty()?; - self.expect(&token::Semi)?; - (name, ast::ImplItemKind::Type(typ), generics) + let (name, node, generics) = if let Some(type_) = self.eat_type() { + let (name, alias, generics) = type_?; + let kind = match alias { + AliasKind::Weak(typ) => ast::ImplItemKind::Type(typ), + AliasKind::Existential(bounds) => ast::ImplItemKind::Existential(bounds), + }; + (name, kind, generics) } else if self.is_const_item() { // This parses the grammar: // ImplItemConst = "const" Ident ":" Ty "=" Expr ";" @@ -6563,14 +6569,43 @@ impl<'a> Parser<'a> { } /// Parse type Foo = Bar; - fn parse_item_type(&mut self) -> PResult<'a, ItemInfo> { + /// or + /// existential type Foo: Bar; + /// or + /// return None without modifying the parser state + fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> { + // This parses the grammar: + // Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";" + if self.check_keyword(keywords::Type) || + self.check_keyword(keywords::Existential) && + self.look_ahead(1, |t| t.is_keyword(keywords::Type)) { + let existential = self.eat_keyword(keywords::Existential); + assert!(self.eat_keyword(keywords::Type)); + Some(self.parse_existential_or_alias(existential)) + } else { + None + } + } + + /// Parse type alias or existential type + fn parse_existential_or_alias( + &mut self, + existential: bool, + ) -> PResult<'a, (Ident, AliasKind, ast::Generics)> { let ident = self.parse_ident()?; let mut tps = self.parse_generics()?; tps.where_clause = self.parse_where_clause()?; - self.expect(&token::Eq)?; - let ty = self.parse_ty()?; + let alias = if existential { + self.expect(&token::Colon)?; + let bounds = self.parse_generic_bounds()?; + AliasKind::Existential(bounds) + } else { + self.expect(&token::Eq)?; + let ty = self.parse_ty()?; + AliasKind::Weak(ty) + }; self.expect(&token::Semi)?; - Ok((ident, ItemKind::Ty(ty, tps), None)) + Ok((ident, alias, tps)) } /// Parse the part of an "enum" decl following the '{' @@ -6926,15 +6961,19 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return Ok(Some(item)); } - if self.eat_keyword(keywords::Type) { + if let Some(type_) = self.eat_type() { + let (ident, alias, generics) = type_?; // TYPE ITEM - let (ident, item_, extra_attrs) = self.parse_item_type()?; + let item_ = match alias { + AliasKind::Weak(ty) => ItemKind::Ty(ty, generics), + AliasKind::Existential(bounds) => ItemKind::Existential(bounds, generics), + }; let prev_span = self.prev_span; let item = self.mk_item(lo.to(prev_span), ident, item_, visibility, - maybe_append(attrs, extra_attrs)); + attrs); return Ok(Some(item)); } if self.eat_keyword(keywords::Enum) { |
