From 3a7038adc8d5d5d7bcda72871f053af3090df886 Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Mon, 23 Jun 2014 18:02:39 +0200 Subject: [PATCH] libsyntax: no inheritance with tuple/unit structs Struct inheritance, unstable as it is, only really makes sense for "record-like" structs and previously produced bad code when used with unit-like structs or tuple structs. So this commit stops parsing super-structs for unit-like structs and tuple structs, and rejects virtual unit-like structs and tuple structs. [breaking-change] --- src/libsyntax/parse/parser.rs | 81 ++++++++++++++--------- src/test/compile-fail/inherit-struct1.rs | 2 +- src/test/compile-fail/inherit-struct10.rs | 17 +++++ src/test/compile-fail/inherit-struct11.rs | 17 +++++ src/test/compile-fail/inherit-struct12.rs | 17 +++++ src/test/compile-fail/inherit-struct13.rs | 18 +++++ src/test/compile-fail/inherit-struct5.rs | 2 +- src/test/compile-fail/inherit-struct9.rs | 4 +- 8 files changed, 122 insertions(+), 36 deletions(-) create mode 100644 src/test/compile-fail/inherit-struct10.rs create mode 100644 src/test/compile-fail/inherit-struct11.rs create mode 100644 src/test/compile-fail/inherit-struct12.rs create mode 100644 src/test/compile-fail/inherit-struct13.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4a75473ac1141..1aa90d22abcd7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4064,43 +4064,19 @@ impl<'a> Parser<'a> { // parse struct Foo { ... } fn parse_item_struct(&mut self, is_virtual: bool) -> ItemInfo { + let name_span = self.span; let class_name = self.parse_ident(); let generics = self.parse_generics(); - let super_struct = if self.eat(&token::COLON) { - let ty = self.parse_ty(true); - match ty.node { - TyPath(_, None, _) => { - Some(ty) - } - _ => { - self.span_err(ty.span, "not a struct"); - None - } - } - } else { - None - }; + let super_struct; let mut fields: Vec; let is_tuple_like; - if self.eat(&token::LBRACE) { - // It's a record-like struct. - is_tuple_like = false; - fields = Vec::new(); - while self.token != token::RBRACE { - fields.push(self.parse_struct_decl_field()); - } - if fields.len() == 0 { - self.fatal(format!("unit-like struct definition should be \ - written as `struct {};`", - token::get_ident(class_name)).as_slice()); - } - self.bump(); - } else if self.token == token::LPAREN { + if self.token == token::LPAREN { // It's a tuple-like struct. is_tuple_like = true; + super_struct = None; fields = self.parse_unspanned_seq( &token::LPAREN, &token::RPAREN, @@ -4125,12 +4101,53 @@ impl<'a> Parser<'a> { } else if self.eat(&token::SEMI) { // It's a unit-like struct. is_tuple_like = true; + super_struct = None; fields = Vec::new(); } else { - let token_str = self.this_token_to_str(); - self.fatal(format!("expected `{}`, `(`, or `;` after struct \ - name but found `{}`", "{", - token_str).as_slice()) + // It can only be a record-like struct now. + is_tuple_like = false; + super_struct = if self.eat(&token::COLON) { + let ty = self.parse_ty(true); + match ty.node { + TyPath(_, None, _) => { + Some(ty) + } + _ => { + self.span_err(ty.span, "not a struct"); + None + } + } + } else { + None + }; + + if !self.eat(&token::LBRACE) { + let token_str = self.this_token_to_str(); + let expected = if super_struct.is_some() { + "`{` after super-struct path" + } else { + // not advertising struct inheritance here + "`{`, `(`, or `;` after struct name" + }; + self.fatal(format!("expected {} but found `{}`", + expected, token_str).as_slice()) + } + + fields = Vec::new(); + while self.token != token::RBRACE { + fields.push(self.parse_struct_decl_field()); + } + if fields.len() == 0 { + self.fatal(format!("unit-like struct definition should be \ + written as `struct {};`", + token::get_ident(class_name)).as_slice()); + } + self.bump(); + } + + if is_virtual && is_tuple_like { + self.span_err(name_span, + "unit-like and tuple structs cannot be virtual"); } let _ = ast::DUMMY_NODE_ID; // FIXME: Workaround for crazy bug. diff --git a/src/test/compile-fail/inherit-struct1.rs b/src/test/compile-fail/inherit-struct1.rs index 47f2b29118702..3568314cc58df 100644 --- a/src/test/compile-fail/inherit-struct1.rs +++ b/src/test/compile-fail/inherit-struct1.rs @@ -12,7 +12,7 @@ #![feature(struct_inherit)] -struct S6 : int; //~ ERROR super-struct could not be resolved +struct S6 : int { x: () } //~ ERROR super-struct could not be resolved pub fn main() { } diff --git a/src/test/compile-fail/inherit-struct10.rs b/src/test/compile-fail/inherit-struct10.rs new file mode 100644 index 0000000000000..7fbdc7b59e975 --- /dev/null +++ b/src/test/compile-fail/inherit-struct10.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test struct inheritance. +#![feature(struct_inherit)] + +virtual struct UnitLikeVirtual; //~ ERROR unit-like and tuple structs cannot be virtual +virtual struct TupleStructVirtual(int); //~ ERROR unit-like and tuple structs cannot be virtual + +fn main() {} diff --git a/src/test/compile-fail/inherit-struct11.rs b/src/test/compile-fail/inherit-struct11.rs new file mode 100644 index 0000000000000..1c731f0df52fb --- /dev/null +++ b/src/test/compile-fail/inherit-struct11.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test struct inheritance. +#![feature(struct_inherit)] + +virtual struct RecordLikeVirtual { i: int } +struct UnitLike : RecordLikeVirtual; //~ ERROR expected `{` after super-struct path but found `;` + +fn main() {} diff --git a/src/test/compile-fail/inherit-struct12.rs b/src/test/compile-fail/inherit-struct12.rs new file mode 100644 index 0000000000000..4134a0790fd32 --- /dev/null +++ b/src/test/compile-fail/inherit-struct12.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test struct inheritance. +#![feature(struct_inherit)] + +virtual struct RecordLikeVirtual { i: int } +struct TupleStruct(int) : RecordLikeVirtual; //~ ERROR expected `;` but found `:` + +fn main() {} diff --git a/src/test/compile-fail/inherit-struct13.rs b/src/test/compile-fail/inherit-struct13.rs new file mode 100644 index 0000000000000..146f22e615d57 --- /dev/null +++ b/src/test/compile-fail/inherit-struct13.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test struct inheritance. +#![feature(struct_inherit)] + +virtual struct RecordLikeVirtual { i: int } +struct TupleStruct : RecordLikeVirtual (int); +//~^ ERROR expected `{` after super-struct path but found `(` + +fn main() {} diff --git a/src/test/compile-fail/inherit-struct5.rs b/src/test/compile-fail/inherit-struct5.rs index c40d27c3b6b3b..506146720be60 100644 --- a/src/test/compile-fail/inherit-struct5.rs +++ b/src/test/compile-fail/inherit-struct5.rs @@ -14,7 +14,7 @@ // aux-build:inherit_struct_lib.rs extern crate inherit_struct_lib; -struct S3 : inherit_struct_lib::S1; //~ ERROR super-struct is defined in a different crate +struct S3 : inherit_struct_lib::S1 { x: () } //~ ERROR super-struct is defined in a different crate pub fn main() { } diff --git a/src/test/compile-fail/inherit-struct9.rs b/src/test/compile-fail/inherit-struct9.rs index 70e341d589cc7..211bfbd6dcaf8 100644 --- a/src/test/compile-fail/inherit-struct9.rs +++ b/src/test/compile-fail/inherit-struct9.rs @@ -11,8 +11,8 @@ // Test struct inheritance. #![feature(struct_inherit)] -struct s9; -struct s10 : s9; //~ ERROR struct inheritance is only allowed from virtual structs +struct s9 { i: int } +struct s10 : s9 { j: int } //~ ERROR struct inheritance is only allowed from virtual structs pub fn main() { }