Skip to content

Commit fd83799

Browse files
committed
Use tl::expected in the parser to avoid error state
We made heavy use of error state within some AST node and it was the source of multiple errors, and caused confusion with (null) pointers. This commit removes some error state use within our parser in an attempt to remove those error states later. gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_inner_attributes): Change return type to avoid empty/error values that may break invariants in the AST. (Parser::parse_inner_attribute): Likewise. (Parser::parse_outer_attribute): Likewise. (Parser::parse_outer_attributes): Likewise. (Parser::parse_attribute_body): Likewise. (Parser::parse_simple_path): Likewise. (Parser::parse_macro_invocation): Likewise. (Parser::parse_visibility): Likewise. (Parser::parse_use_tree): Likewise. (Parser::parse_delim_token_tree): Likewise. (Parser::parse_identifier_or_keyword_token): Likewise. (Parser::parse_token_tree): Likewise. (Parser::parse_macro_rules_def): Likewise. (Parser::parse_decl_macro_def): Likewise. (Parser::parse_macro_invocation): Likewise. (Parser::parse_macro_rule): Likewise. (Parser::parse_macro_matcher): Likewise. (Parser::parse_type_path_segment): Likewise. (Parser::parse_path_expr_segment): Likewise. (Parser::parse_type): Likewise. (Parser::parse_type_no_bounds): Likewise. (is_simple_path_segment): Move to utility file. (token_id_matches_delims): Likewise. (is_likely_path_next): Remove unused function. (Parser::parse_attr_input): Return a structure instead of a tuple. * expand/rust-macro-builtins-offset-of.cc: Adapt call to expected. * ast/rust-ast.cc (AttributeParser::parse_path_meta_item): Use empty vector when an error is encountered. * parse/rust-parse.h: Update prototypes. * parse/rust-parse-utils.h: New file. * parse/rust-parse-error.h: New file. Signed-off-by: Pierre-Emmanuel Patry <[email protected]>
1 parent fe2320d commit fd83799

14 files changed

+715
-312
lines changed

gcc/rust/ast/rust-ast.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3478,7 +3478,9 @@ Module::load_items ()
34783478

34793479
// we need to parse any possible inner attributes for this module
34803480
inner_attrs = parser.parse_inner_attributes ();
3481-
auto parsed_items = parser.parse_items ();
3481+
auto parsed_items = parser.parse_items ().value_or (
3482+
std::vector<std::unique_ptr<AST::Item>>{});
3483+
34823484
for (const auto &error : parser.get_errors ())
34833485
error.emit ();
34843486

@@ -3693,8 +3695,8 @@ AttributeParser::is_end_meta_item_tok (TokenId id) const
36933695
std::unique_ptr<MetaItem>
36943696
AttributeParser::parse_path_meta_item ()
36953697
{
3696-
SimplePath path = parser->parse_simple_path ();
3697-
if (path.is_empty ())
3698+
auto path = parser->parse_simple_path ();
3699+
if (!path)
36983700
{
36993701
rust_error_at (lexer->peek_token ()->get_locus (),
37003702
"failed to parse simple path in attribute");
@@ -3709,7 +3711,7 @@ AttributeParser::parse_path_meta_item ()
37093711
= parse_meta_item_seq ();
37103712

37113713
return std::unique_ptr<MetaItemSeq> (
3712-
new MetaItemSeq (std::move (path), std::move (meta_items)));
3714+
new MetaItemSeq (std::move (path.value ()), std::move (meta_items)));
37133715
}
37143716
case EQUAL:
37153717
{
@@ -3723,12 +3725,12 @@ AttributeParser::parse_path_meta_item ()
37233725
return nullptr;
37243726

37253727
return std::unique_ptr<MetaItemPathExpr> (
3726-
new MetaItemPathExpr (std::move (path), std::move (expr)));
3728+
new MetaItemPathExpr (std::move (path.value ()), std::move (expr)));
37273729
}
37283730
case COMMA:
37293731
// just simple path
37303732
return std::unique_ptr<MetaItemPath> (
3731-
new MetaItemPath (std::move (path)));
3733+
new MetaItemPath (std::move (path.value ())));
37323734
default:
37333735
rust_error_at (lexer->peek_token ()->get_locus (),
37343736
"unrecognised token '%s' in meta item",

gcc/rust/ast/rust-ast.h

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -477,38 +477,21 @@ struct Visibility
477477
SimplePath in_path;
478478
location_t locus;
479479

480-
// should this store location info?
481-
482-
public:
483-
// Creates a Visibility - TODO make constructor protected or private?
484480
Visibility (VisType vis_type, SimplePath in_path, location_t locus)
485481
: vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
486482
{}
487483

484+
public:
488485
VisType get_vis_type () const { return vis_type; }
489486

490-
// Returns whether visibility is in an error state.
491-
bool is_error () const
492-
{
493-
return vis_type == PUB_IN_PATH && in_path.is_empty ();
494-
}
495-
496487
// Returns whether a visibility has a path
497-
bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
488+
bool has_path () const { return vis_type >= PUB_CRATE; }
498489

499490
// Returns whether visibility is public or not.
500-
bool is_public () const { return vis_type != PRIV && !is_error (); }
491+
bool is_public () const { return vis_type != PRIV; }
501492

502493
location_t get_locus () const { return locus; }
503494

504-
// empty?
505-
// Creates an error visibility.
506-
static Visibility create_error ()
507-
{
508-
return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
509-
UNDEF_LOCATION);
510-
}
511-
512495
// Unique pointer custom clone function
513496
/*std::unique_ptr<Visibility> clone_visibility() const {
514497
return std::unique_ptr<Visibility>(clone_visibility_impl());

gcc/rust/ast/rust-item.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ class Module : public VisItem
814814
// Loaded module constructor, with items
815815
Module (Identifier name, location_t locus,
816816
std::vector<std::unique_ptr<Item>> items,
817-
Visibility visibility = Visibility::create_error (),
817+
Visibility visibility = Visibility::create_private (),
818818
Unsafety safety = Unsafety::Normal,
819819
std::vector<Attribute> inner_attrs = std::vector<Attribute> (),
820820
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
@@ -1743,7 +1743,7 @@ class StructField
17431743
bool has_outer_attributes () const { return !outer_attrs.empty (); }
17441744

17451745
// Returns whether struct field has a non-private (non-default) visibility.
1746-
bool has_visibility () const { return !visibility.is_error (); }
1746+
bool has_visibility () const { return true; }
17471747

17481748
StructField (Identifier field_name, std::unique_ptr<Type> field_type,
17491749
Visibility vis, location_t locus,
@@ -1797,8 +1797,8 @@ class StructField
17971797
// Creates an error state struct field.
17981798
static StructField create_error ()
17991799
{
1800-
return StructField (std::string (""), nullptr, Visibility::create_error (),
1801-
UNDEF_LOCATION);
1800+
return StructField (std::string (""), nullptr,
1801+
Visibility::create_private (), UNDEF_LOCATION);
18021802
}
18031803

18041804
std::string as_string () const;
@@ -1902,7 +1902,7 @@ class TupleField
19021902

19031903
/* Returns whether tuple field has a non-default visibility (i.e. a public
19041904
* one) */
1905-
bool has_visibility () const { return !visibility.is_error (); }
1905+
bool has_visibility () const { return true; }
19061906

19071907
// Complete constructor
19081908
TupleField (std::unique_ptr<Type> field_type, Visibility vis,
@@ -1952,7 +1952,7 @@ class TupleField
19521952
// Creates an error state tuple field.
19531953
static TupleField create_error ()
19541954
{
1955-
return TupleField (nullptr, Visibility::create_error (), UNDEF_LOCATION);
1955+
return TupleField (nullptr, Visibility::create_private (), UNDEF_LOCATION);
19561956
}
19571957

19581958
std::string as_string () const;
@@ -3368,7 +3368,7 @@ class ExternalTypeItem : public ExternalItem
33683368
bool has_outer_attrs () const { return !outer_attrs.empty (); }
33693369

33703370
// Returns whether item has non-default visibility.
3371-
bool has_visibility () const { return !visibility.is_error (); }
3371+
bool has_visibility () const { return true; }
33723372

33733373
location_t get_locus () const { return locus; }
33743374

@@ -3460,7 +3460,7 @@ class ExternalStaticItem : public ExternalItem
34603460
bool has_outer_attrs () const { return !outer_attrs.empty (); }
34613461

34623462
// Returns whether item has non-default visibility.
3463-
bool has_visibility () const { return !visibility.is_error (); }
3463+
bool has_visibility () const { return true; }
34643464

34653465
location_t get_locus () const { return locus; }
34663466

gcc/rust/ast/rust-macro.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ class MacroRulesDefinition : public VisItem
529529
return std::make_unique<MacroRulesDefinition> (
530530
MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
531531
AST::MacroRulesDefinition::MacroKind::MBE,
532-
AST::Visibility::create_error ()));
532+
AST::Visibility::create_private ()));
533533
}
534534

535535
static std::unique_ptr<MacroRulesDefinition>

gcc/rust/expand/rust-macro-builtins-include.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ MacroBuiltin::include_handler (location_t invoc_locus,
248248
std::vector<std::unique_ptr<AST::Item>> parsed_items{};
249249

250250
if (is_semicoloned)
251-
parsed_items = parser.parse_items ();
251+
parsed_items = parser.parse_items ().value_or (
252+
std::vector<std::unique_ptr<AST::Item>>{});
252253
else
253254
parsed_expr = parser.parse_expr ();
254255

gcc/rust/expand/rust-macro-builtins-offset-of.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ MacroBuiltin::offset_of_handler (location_t invoc_locus,
5656
parser.skip_token (COMMA);
5757

5858
auto field_tok = parser.parse_identifier_or_keyword_token ();
59-
auto invalid_field = !field_tok || !field_tok->should_have_str ();
59+
auto invalid_field = !field_tok || !field_tok.value ()->should_have_str ();
6060

6161
if (invalid_field)
6262
rust_error_at (invoc_locus, "could not parse field argument for %qs",
@@ -65,7 +65,7 @@ MacroBuiltin::offset_of_handler (location_t invoc_locus,
6565
if (!type || invalid_field)
6666
return tl::nullopt;
6767

68-
auto field = Identifier (field_tok->get_str ());
68+
auto field = Identifier (field_tok.value ()->get_str ());
6969

7070
// FIXME: Do we need to do anything to handle the optional comma at the end?
7171
parser.maybe_skip_token (COMMA);

gcc/rust/expand/rust-macro-expand.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,9 @@ transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
858858
{
859859
return parse_many (parser, delimiter, [&parser] () {
860860
auto item = parser.parse_item (true);
861-
return AST::SingleASTNode (std::move (item));
861+
if (!item)
862+
return AST::SingleASTNode (std::unique_ptr<AST::Item> (nullptr));
863+
return AST::SingleASTNode (std::move (item.value ()));
862864
});
863865
}
864866

@@ -1188,9 +1190,9 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts)
11881190
while (lex.peek_token ()->get_id () != END_OF_FILE)
11891191
{
11901192
auto result = parser.parse_item (false);
1191-
if (result == nullptr)
1193+
if (!result)
11921194
break;
1193-
nodes.emplace_back (std::move (result));
1195+
nodes.emplace_back (std::move (result.value ()));
11941196
}
11951197
break;
11961198
case ContextType::STMT:

gcc/rust/hir/rust-ast-lower.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ translate_visibility (const AST::Visibility &vis)
3838
// the AST vis is an error?
3939
// FIXME: We need to add a `create_private()` static function to the
4040
// AST::Visibility class and use it when the vis is empty in the parser...
41-
if (vis.is_error ())
42-
return Visibility::create_error ();
4341

4442
switch (vis.get_vis_type ())
4543
{
@@ -57,7 +55,7 @@ translate_visibility (const AST::Visibility &vis)
5755
break;
5856
}
5957

60-
return Visibility::create_error ();
58+
rust_unreachable ();
6159
}
6260

6361
ASTLowering::ASTLowering (AST::Crate &astCrate) : astCrate (astCrate) {}

0 commit comments

Comments
 (0)