https://gcc.gnu.org/g:46673ec062176f4c2826dabbde6a401167d73441

commit 46673ec062176f4c2826dabbde6a401167d73441
Author: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com>
Date:   Tue Apr 1 19:55:28 2025 +0200

    Migrate error state to optionals
    
    gcc/rust/ChangeLog:
    
            * ast/rust-ast-builder.cc (Builder::self_ref_param): Remove error 
state
            and use optional.
            * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check label
            before visiting.
            * ast/rust-ast.cc (ContinueExpr::as_string): Retrieve label value.
            (Lifetime::as_string): Retrieve lifetime value.
            (ReferenceType::as_string): Likewise.
            (SelfParam::as_string): Likewise.
            * ast/rust-ast.h: Remove lifetime and LifetimeParam error state.
            * ast/rust-desugar-for-loops.cc 
(DesugarForLoops::DesugarCtx::make_break_arm):
            Use optional instead of error state.
            * ast/rust-expr.h (class ContinueExpr): Make label optional.
            * ast/rust-item.h (class SelfParam): Make lifetime optional.
            * ast/rust-type.h (class ReferenceType): Likewise.
            * backend/rust-compile-base.cc: Use optional for self param instead
            of error state.
            * backend/rust-compile-base.h: Update function prototype.
            * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Use optional.
            * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_self): Lower
            lifetime only if it exists.
            * hir/rust-ast-lower-block.h: Lower loop label only if it exists.
            * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
            * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Remove
            references to error state.
            (ASTLowerTraitItem::visit): Lower self param only if it exists.
            * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Use nullopt
            for default value instead of SelfParam error state.
            * hir/rust-ast-lower.cc (ASTLoweringExprWithBlock::visit): Lower 
label
            only if it exists.
            * hir/rust-hir-dump.cc (Dump::do_traitfunctiondecl): Print self 
only if
            it exists.
            (Dump::visit): Liewise.
            * hir/tree/rust-hir-bound.h: Remove error state.
            * hir/tree/rust-hir-expr.cc (ContinueExpr::ContinueExpr): Use 
optional
            in constructor for loop label.
            (BreakExpr::BreakExpr): Likewise.
            * hir/tree/rust-hir-expr.h (class ContinueExpr): Remove error state
            implementation.
            (class BreakExpr): Likewise.
            * hir/tree/rust-hir-generic-param.h: Likewise.
            * hir/tree/rust-hir-item.cc (SelfParam::SelfParam): Make lifetime
            optional.
            (Function::Function): Make self param optional.
            * hir/tree/rust-hir-item.h (class Function): Likewise.
            * hir/tree/rust-hir-type.cc (ReferenceType::ReferenceType): Make
            lifetime optional.
            * hir/tree/rust-hir-type.h (class ReferenceType): Likewise.
            * hir/tree/rust-hir.cc (ContinueExpr::as_string): Use new getter.
            (BreakExpr::as_string): Likewise.
            (Lifetime::as_string): Likewise.
            (ReferenceType::as_string): Likewise.
            (TraitFunctionDecl::as_string): Likewise.
            (SelfParam::as_string): Remove error state checking.
            * parse/rust-parse-impl.h (Parser::parse_generic_param): Adapt to
            optional.
            (Parser::parse_lifetime_params): Likewise.
            (Parser::parse_lifetime_params_objs): Likewise.
            (Parser::parse_lifetime_param): Likewise.
            (Parser::parse_lifetime_where_clause_item): Likewise.
            (Parser::parse_type_param_bound): Likewise.
            (Parser::parse_lifetime_bounds): Likewise.
            (Parser::parse_path_generic_args): Likewise.
            (Parser::parse_self_param): Likewise.
            (Parser::parse_break_expr): Likewise.
            (Parser::parse_continue_expr): Likewise.
            (Parser::parse_reference_type_inner): Likewise.
            * parse/rust-parse.h (class ParseLifetimeParamError): Add new class 
for
            lifetime param parsing errors.
            (class ParseLifetimeError): Add new class for lifetime parsing 
errors.
            (enum ParseSelfError): Add new class for self param parsing errors.
            * typecheck/rust-hir-type-check-implitem.cc 
(TypeCheckImplItem::visit):
            Use unchecked getter in checked context. And make anonymous region.
            * typecheck/rust-hir-type-check.cc 
(TraitItemReference::get_type_from_fn):
            Likewise.
    
    Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com>

Diff:
---
 gcc/rust/ast/rust-ast-builder.cc                   |   2 +-
 gcc/rust/ast/rust-ast-visitor.cc                   |   6 +-
 gcc/rust/ast/rust-ast.cc                           |   9 +-
 gcc/rust/ast/rust-ast.h                            |  17 ----
 gcc/rust/ast/rust-desugar-for-loops.cc             |   4 +-
 gcc/rust/ast/rust-expr.h                           |  14 +--
 gcc/rust/ast/rust-item.h                           |  15 +--
 gcc/rust/ast/rust-type.h                           |  10 +-
 gcc/rust/backend/rust-compile-base.cc              |  13 +--
 gcc/rust/backend/rust-compile-base.h               |   2 +-
 gcc/rust/expand/rust-derive-clone.cc               |   2 +-
 gcc/rust/hir/rust-ast-lower-base.cc                |   8 +-
 gcc/rust/hir/rust-ast-lower-block.h                |   4 +-
 gcc/rust/hir/rust-ast-lower-expr.cc                |  10 +-
 gcc/rust/hir/rust-ast-lower-implitem.cc            |  23 ++---
 gcc/rust/hir/rust-ast-lower-item.cc                |   2 +-
 gcc/rust/hir/rust-ast-lower.cc                     |   5 +-
 gcc/rust/hir/rust-hir-dump.cc                      |   6 +-
 gcc/rust/hir/tree/rust-hir-bound.h                 |  12 ---
 gcc/rust/hir/tree/rust-hir-expr.cc                 |   6 +-
 gcc/rust/hir/tree/rust-hir-expr.h                  |  22 ++---
 gcc/rust/hir/tree/rust-hir-generic-param.h         |   3 -
 gcc/rust/hir/tree/rust-hir-item.cc                 |  21 +++--
 gcc/rust/hir/tree/rust-hir-item.h                  |  48 +++++-----
 gcc/rust/hir/tree/rust-hir-type.cc                 |   2 +-
 gcc/rust/hir/tree/rust-hir-type.h                  |   9 +-
 gcc/rust/hir/tree/rust-hir.cc                      | 100 +++++++++-----------
 gcc/rust/parse/rust-parse-impl.h                   | 103 +++++++++++----------
 gcc/rust/parse/rust-parse.h                        |  27 ++++--
 gcc/rust/typecheck/rust-hir-type-check-implitem.cc |  42 ++++++---
 gcc/rust/typecheck/rust-hir-type-check.cc          |   2 +-
 31 files changed, 283 insertions(+), 266 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 437ba1b56ea0..1f49c6411975 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -137,7 +137,7 @@ Builder::tuple (std::vector<std::unique_ptr<Expr>> 
&&values) const
 std::unique_ptr<Param>
 Builder::self_ref_param (bool mutability) const
 {
-  return std::make_unique<SelfParam> (Lifetime::error (), mutability, loc);
+  return std::make_unique<SelfParam> (tl::nullopt, mutability, loc);
 }
 
 std::unique_ptr<Param>
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 3a06d2ddc4b7..87364a0b0f5b 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -477,7 +477,8 @@ void
 DefaultASTVisitor::visit (AST::ContinueExpr &expr)
 {
   visit_outer_attrs (expr);
-  visit (expr.get_label ());
+  if (expr.has_label ())
+    visit (expr.get_label ());
 }
 
 void
@@ -591,7 +592,8 @@ DefaultASTVisitor::visit (AST::ForLoopExpr &expr)
   visit_outer_attrs (expr);
   visit (expr.get_pattern ());
   visit (expr.get_iterator_expr ());
-  visit (expr.get_loop_label ());
+  if (expr.has_loop_label ())
+    visit (expr.get_loop_label ());
   visit (expr.get_loop_block ());
 }
 
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 2d286cdf3d70..bba4b156b5f7 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -1631,7 +1631,7 @@ ContinueExpr::as_string () const
   std::string str ("continue ");
 
   if (has_label ())
-    str += label.as_string ();
+    str += get_label ().as_string ();
 
   return str;
 }
@@ -2485,9 +2485,6 @@ MacroMatchRepetition::as_string () const
 std::string
 Lifetime::as_string () const
 {
-  if (is_error ())
-    return "error lifetime";
-
   switch (lifetime_type)
     {
     case NAMED:
@@ -2612,7 +2609,7 @@ ReferenceType::as_string () const
   std::string str ("&");
 
   if (has_lifetime ())
-    str += lifetime.as_string () + " ";
+    str += get_lifetime ().as_string () + " ";
 
   if (has_mut)
     str += "mut ";
@@ -3070,7 +3067,7 @@ SelfParam::as_string () const
       else if (has_lifetime ())
        {
          // ref and lifetime
-         std::string str = "&" + lifetime.as_string () + " ";
+         std::string str = "&" + get_lifetime ().as_string () + " ";
 
          if (is_mut)
            str += "mut ";
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index c74b1c46448a..53bf1bc1c86c 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1587,17 +1587,9 @@ public:
       lifetime_name (std::move (name)), locus (locus)
   {}
 
-  // Creates an "error" lifetime.
-  static Lifetime error () { return Lifetime (NAMED, ""); }
-
   static Lifetime elided () { return Lifetime (WILDCARD, ""); }
 
   // Returns true if the lifetime is in an error state.
-  bool is_error () const
-  {
-    return lifetime_type == NAMED && lifetime_name.empty ();
-  }
-
   std::string as_string () const override;
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1688,15 +1680,6 @@ public:
   // Returns whether the lifetime param has an outer attribute.
   bool has_outer_attribute () const { return !outer_attrs.empty (); }
 
-  // Creates an error state lifetime param.
-  static LifetimeParam create_error ()
-  {
-    return LifetimeParam (Lifetime::error (), {}, {}, UNDEF_LOCATION);
-  }
-
-  // Returns whether the lifetime param is in an error state.
-  bool is_error () const { return lifetime.is_error (); }
-
   // Constructor
   LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
                 AST::AttrVec outer_attrs, location_t locus)
diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc 
b/gcc/rust/ast/rust-desugar-for-loops.cc
index 5e5cbbc6b383..ffc3470b656e 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.cc
+++ b/gcc/rust/ast/rust-desugar-for-loops.cc
@@ -59,8 +59,8 @@ DesugarForLoops::DesugarCtx::make_break_arm ()
   auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression (
     builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
 
-  auto break_expr = std::unique_ptr<Expr> (
-    new BreakExpr (Lifetime::error (), nullptr, {}, loc));
+  auto break_expr
+    = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
 
   return MatchCase (std::move (arm), std::move (break_expr));
 }
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index e6cfa2709f93..70cb6d403551 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -2844,7 +2844,7 @@ protected:
 class ContinueExpr : public ExprWithoutBlock
 {
   std::vector<Attribute> outer_attrs;
-  Lifetime label;
+  tl::optional<Lifetime> label;
   location_t locus;
 
   // TODO: find another way to store this to save memory?
@@ -2854,11 +2854,11 @@ public:
   std::string as_string () const override;
 
   // Returns true if the continue expr has a label.
-  bool has_label () const { return !label.is_error (); }
+  bool has_label () const { return label.has_value (); }
 
   // Constructor for a ContinueExpr with a label.
-  ContinueExpr (Lifetime label, std::vector<Attribute> outer_attribs,
-               location_t locus)
+  ContinueExpr (tl::optional<Lifetime> label,
+               std::vector<Attribute> outer_attribs, location_t locus)
     : outer_attrs (std::move (outer_attribs)), label (std::move (label)),
       locus (locus)
   {}
@@ -2879,7 +2879,8 @@ public:
     outer_attrs = std::move (new_attrs);
   }
 
-  Lifetime &get_label () { return label; }
+  Lifetime &get_label () { return label.value (); }
+  const Lifetime &get_label () const { return label.value (); }
 
   Expr::Kind get_expr_kind () const override { return Expr::Kind::Continue; }
 
@@ -2915,7 +2916,8 @@ public:
   bool has_break_expr () const { return break_expr != nullptr; }
 
   // Constructor for a break expression
-  BreakExpr (LoopLabel break_label, std::unique_ptr<Expr> expr_in_break,
+  BreakExpr (tl::optional<LoopLabel> break_label,
+            std::unique_ptr<Expr> expr_in_break,
             std::vector<Attribute> outer_attribs, location_t locus)
     : outer_attrs (std::move (outer_attribs)), label (std::move (break_label)),
       break_expr (std::move (expr_in_break)), locus (locus)
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 0c94f168f869..f507c90dc962 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -434,13 +434,14 @@ class SelfParam : public Param
   bool has_ref;
   bool is_mut;
   // bool has_lifetime; // only possible if also ref
-  Lifetime lifetime;
+  tl::optional<Lifetime> lifetime;
 
   // bool has_type; // only possible if not ref
   std::unique_ptr<Type> type;
 
   // Unrestricted constructor used for error state
-  SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type)
+  SelfParam (tl::optional<Lifetime> lifetime, bool has_ref, bool is_mut,
+            Type *type)
     : Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut),
       lifetime (std::move (lifetime)), type (type)
   {}
@@ -453,7 +454,7 @@ public:
   bool has_type () const { return type != nullptr; }
 
   // Returns whether the self-param has a valid lifetime.
-  bool has_lifetime () const { return !lifetime.is_error (); }
+  bool has_lifetime () const { return lifetime.has_value (); }
 
   // Returns whether the self-param is in an error state.
   bool is_error () const
@@ -472,11 +473,11 @@ public:
   // Type-based self parameter (not ref, no lifetime)
   SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
     : Param ({}, locus), has_ref (false), is_mut (is_mut),
-      lifetime (Lifetime::error ()), type (std::move (type))
+      lifetime (tl::nullopt), type (std::move (type))
   {}
 
   // Lifetime-based self parameter (is ref, no type)
-  SelfParam (Lifetime lifetime, bool is_mut, location_t locus)
+  SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus)
     : Param ({}, locus), has_ref (true), is_mut (is_mut),
       lifetime (std::move (lifetime))
   {}
@@ -522,8 +523,8 @@ public:
   bool get_has_ref () const { return has_ref; };
   bool get_is_mut () const { return is_mut; }
 
-  Lifetime get_lifetime () const { return lifetime; }
-  Lifetime &get_lifetime () { return lifetime; }
+  Lifetime get_lifetime () const { return lifetime.value (); }
+  Lifetime &get_lifetime () { return lifetime.value (); }
 
   NodeId get_node_id () const { return node_id; }
 
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index b6b76497d3ba..48539a23cebe 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -542,7 +542,7 @@ protected:
 class ReferenceType : public TypeNoBounds
 {
   // bool has_lifetime; // TODO: handle in lifetime or something?
-  Lifetime lifetime;
+  tl::optional<Lifetime> lifetime;
 
   bool has_mut;
   std::unique_ptr<TypeNoBounds> type;
@@ -553,11 +553,12 @@ public:
   bool is_mut () const { return has_mut; }
 
   // Returns whether the reference has a lifetime.
-  bool has_lifetime () const { return !lifetime.is_error (); }
+  bool has_lifetime () const { return lifetime.has_value (); }
 
   // Constructor
   ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
-                location_t locus, Lifetime lifetime = Lifetime::elided ())
+                location_t locus,
+                tl::optional<Lifetime> lifetime = Lifetime::elided ())
     : lifetime (std::move (lifetime)), has_mut (is_mut),
       type (std::move (type_no_bounds)), locus (locus)
   {}
@@ -598,7 +599,8 @@ public:
 
   bool get_has_mut () const { return has_mut; }
 
-  Lifetime &get_lifetime () { return lifetime; }
+  Lifetime &get_lifetime () { return lifetime.value (); }
+  const Lifetime &get_lifetime () const { return lifetime.value (); }
 
   TypeNoBounds &get_base_type () { return *type; }
 
diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 04e3e75ed7d0..f4b578d78112 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -666,7 +666,8 @@ get_abi (const AST::AttrVec &outer_attrs,
 
 tree
 HIRCompileBase::compile_function (
-  bool is_root_item, const std::string &fn_name, HIR::SelfParam &self_param,
+  bool is_root_item, const std::string &fn_name,
+  tl::optional<HIR::SelfParam> &self_param,
   std::vector<HIR::FunctionParam> &function_params,
   const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility,
   AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body,
@@ -713,24 +714,24 @@ HIRCompileBase::compile_function (
   // setup the params
   TyTy::BaseType *tyret = fntype->get_return_type ();
   std::vector<Bvariable *> param_vars;
-  if (!self_param.is_error ())
+  if (self_param)
     {
       rust_assert (fntype->is_method ());
       TyTy::BaseType *self_tyty_lookup = fntype->get_self_type ();
 
       tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup);
       Bvariable *compiled_self_param
-       = CompileSelfParam::compile (ctx, fndecl, self_param, self_type,
-                                    self_param.get_locus ());
+       = CompileSelfParam::compile (ctx, fndecl, self_param.value (),
+                                    self_type, self_param->get_locus ());
 
       param_vars.push_back (compiled_self_param);
-      ctx->insert_var_decl (self_param.get_mappings ().get_hirid (),
+      ctx->insert_var_decl (self_param->get_mappings ().get_hirid (),
                            compiled_self_param);
     }
 
   // offset from + 1 for the TyTy::FnType being used when this is a method to
   // skip over Self on the FnType
-  bool is_method = !self_param.is_error ();
+  bool is_method = self_param.has_value ();
   size_t i = is_method ? 1 : 0;
   for (auto &referenced_param : function_params)
     {
diff --git a/gcc/rust/backend/rust-compile-base.h 
b/gcc/rust/backend/rust-compile-base.h
index 69f565cea2b4..65dc350f1611 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -104,7 +104,7 @@ protected:
                              location_t expr_locus);
 
   tree compile_function (bool is_root_item, const std::string &fn_name,
-                        HIR::SelfParam &self_param,
+                        tl::optional<HIR::SelfParam> &self_param,
                         std::vector<HIR::FunctionParam> &function_params,
                         const HIR::FunctionQualifiers &qualifiers,
                         HIR::Visibility &visibility, AST::AttrVec &outer_attrs,
diff --git a/gcc/rust/expand/rust-derive-clone.cc 
b/gcc/rust/expand/rust-derive-clone.cc
index d8f79d00106d..ca5ef0e69a93 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -64,7 +64,7 @@ DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr)
     new BlockExpr ({}, std::move (clone_expr), {}, {}, tl::nullopt, loc, loc));
   auto big_self_type = builder.single_type_path ("Self");
 
-  std::unique_ptr<SelfParam> self (new SelfParam (Lifetime::error (),
+  std::unique_ptr<SelfParam> self (new SelfParam (tl::nullopt,
                                                  /* is_mut */ false, loc));
 
   std::vector<std::unique_ptr<Param>> params;
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc 
b/gcc/rust/hir/rust-ast-lower-base.cc
index 749fe09f3baa..a933f1baa589 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -690,8 +690,12 @@ ASTLoweringBase::lower_self (AST::Param &param)
                             self.get_is_mut (), self.get_locus ());
     }
 
-  AST::Lifetime l = self.get_lifetime ();
-  return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (),
+  tl::optional<HIR::Lifetime> lifetime = tl::nullopt;
+
+  if (self.has_lifetime ())
+    lifetime = lower_lifetime (self.get_lifetime ());
+
+  return HIR::SelfParam (mapping, lifetime, self.get_is_mut (),
                         self.get_locus ());
 }
 
diff --git a/gcc/rust/hir/rust-ast-lower-block.h 
b/gcc/rust/hir/rust-ast-lower-block.h
index 55541a5ad684..d60088bba70c 100644
--- a/gcc/rust/hir/rust-ast-lower-block.h
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -195,7 +195,9 @@ public:
     HIR::BlockExpr *loop_block
       = ASTLoweringBlock::translate (expr.get_loop_block (), &terminated);
 
-    HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+    tl::optional<HIR::LoopLabel> loop_label = tl::nullopt;
+    if (expr.has_loop_label ())
+      loop_label = lower_loop_label (expr.get_loop_label ());
 
     auto crate_num = mappings.get_current_crate ();
     Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc 
b/gcc/rust/hir/rust-ast-lower-expr.cc
index 575eea6b6248..7bb732033cb7 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -597,8 +597,10 @@ ASTLoweringExpr::visit (AST::ForLoopExpr &expr)
 void
 ASTLoweringExpr::visit (AST::BreakExpr &expr)
 {
-  HIR::Lifetime break_label
-    = lower_lifetime (expr.get_label ().get_lifetime ());
+  tl::optional<HIR::Lifetime> break_label = tl::nullopt;
+  if (expr.has_label ())
+    break_label = lower_lifetime (expr.get_label ().get_lifetime ());
+
   HIR::Expr *break_expr
     = expr.has_break_expr ()
        ? ASTLoweringExpr::translate (expr.get_break_expr ())
@@ -618,7 +620,9 @@ ASTLoweringExpr::visit (AST::BreakExpr &expr)
 void
 ASTLoweringExpr::visit (AST::ContinueExpr &expr)
 {
-  HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
+  tl::optional<HIR::Lifetime> break_label;
+  if (expr.has_label ())
+    break_label = lower_lifetime (expr.get_label ());
 
   auto crate_num = mappings.get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc 
b/gcc/rust/hir/rust-ast-lower-implitem.cc
index 3229f57c38f2..66488ac7892d 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.cc
+++ b/gcc/rust/hir/rust-ast-lower-implitem.cc
@@ -132,7 +132,7 @@ ASTLowerImplItem::visit (AST::Function &function)
   Identifier function_name = function.get_function_name ();
   location_t locus = function.get_locus ();
 
-  HIR::SelfParam self_param = HIR::SelfParam::error ();
+  tl::optional<HIR::SelfParam> self_param = tl::nullopt;
   if (function.has_self_param ())
     self_param = lower_self (function.get_self_param ());
 
@@ -189,13 +189,13 @@ ASTLowerImplItem::visit (AST::Function &function)
                         std::move (vis), function.get_outer_attrs (),
                         std::move (self_param), defaultness, locus);
 
-  if (!fn->get_self_param ().is_error ())
+  if (fn->is_method ())
     {
       // insert mappings for self
-      mappings.insert_hir_self_param (&fn->get_self_param ());
+      mappings.insert_hir_self_param (&fn->get_self_param_unchecked ());
       mappings.insert_location (
-       fn->get_self_param ().get_mappings ().get_hirid (),
-       fn->get_self_param ().get_locus ());
+       fn->get_self_param_unchecked ().get_mappings ().get_hirid (),
+       fn->get_self_param_unchecked ().get_locus ());
     }
 
   // add the mappings for the function params at the end
@@ -249,9 +249,9 @@ ASTLowerTraitItem::visit (AST::Function &func)
 
   // set self parameter to error if this is a method
   // else lower to hir
-  HIR::SelfParam self_param = func.has_self_param ()
-                               ? lower_self (func.get_self_param ())
-                               : HIR::SelfParam::error ();
+  tl::optional<HIR::SelfParam> self_param = tl::nullopt;
+  if (func.has_self_param ())
+    self_param = lower_self (func.get_self_param ());
 
   std::vector<HIR::FunctionParam> function_params;
   for (auto &p : func.get_function_params ())
@@ -303,9 +303,10 @@ ASTLowerTraitItem::visit (AST::Function &func)
   if (func.has_self_param ())
     {
       // insert mappings for self
-      mappings.insert_hir_self_param (&self_param);
-      mappings.insert_location (self_param.get_mappings ().get_hirid (),
-                               self_param.get_locus ());
+      // TODO: Is this correct ? Looks fishy
+      mappings.insert_hir_self_param (&*self_param);
+      mappings.insert_location (self_param->get_mappings ().get_hirid (),
+                               self_param->get_locus ());
     }
 
   // add the mappings for the function params at the end
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc 
b/gcc/rust/hir/rust-ast-lower-item.cc
index 73ddedf117de..47b4b71974a4 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -460,7 +460,7 @@ ASTLoweringItem::visit (AST::Function &function)
                         std::move (function_params), std::move (return_type),
                         std::move (where_clause), std::move (function_body),
                         std::move (vis), function.get_outer_attrs (),
-                        HIR::SelfParam::error (), defaultness, locus);
+                        tl::nullopt, defaultness, locus);
 
   // add the mappings for the function params at the end
   for (auto &param : fn->get_function_params ())
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index c6446aa1bcbd..f70c7878216e 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -402,7 +402,10 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
   HIR::BlockExpr *loop_block
     = ASTLoweringBlock::translate (expr.get_loop_block (), &terminated);
 
-  HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+  tl::optional<HIR::LoopLabel> loop_label;
+  if (expr.has_loop_label ())
+    loop_label = lower_loop_label (expr.get_loop_label ());
+
   HIR::Expr *loop_condition
     = ASTLoweringExpr::translate (expr.get_predicate_expr (), &terminated);
 
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index b6dcf184ae4e..468d85527961 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -546,7 +546,8 @@ Dump::do_traitfunctiondecl (TraitFunctionDecl &e)
   else
     put_field ("where_clause", "none");
 
-  put_field ("self", e.get_self ().as_string ());
+  if (e.is_method ())
+    put_field ("self", e.get_self_unchecked ().as_string ());
 
   end ("TraitFunctionDecl");
 }
@@ -1693,7 +1694,8 @@ Dump::visit (Function &e)
     put_field ("where clause", e.get_where_clause ().as_string ());
 
   visit_field ("function_body", e.get_definition ());
-  put_field ("self", e.get_self_param ().as_string ());
+  if (e.is_method ())
+    put_field ("self", e.get_self_param_unchecked ().as_string ());
 
   end ("Function");
 }
diff --git a/gcc/rust/hir/tree/rust-hir-bound.h 
b/gcc/rust/hir/tree/rust-hir-bound.h
index 78bb133f6d4b..8fa6a2258b16 100644
--- a/gcc/rust/hir/tree/rust-hir-bound.h
+++ b/gcc/rust/hir/tree/rust-hir-bound.h
@@ -44,18 +44,6 @@ public:
   {}
 
   // Returns true if the lifetime is in an error state.
-  bool is_error () const
-  {
-    return lifetime_type == AST::Lifetime::LifetimeType::NAMED
-          && lifetime_name.empty ();
-  }
-
-  static Lifetime error ()
-  {
-    return Lifetime (Analysis::NodeMapping::get_error (),
-                    AST::Lifetime::LifetimeType::NAMED, "", UNDEF_LOCATION);
-  }
-
   std::string as_string () const override;
 
   void accept_vis (HIRFullVisitor &vis) override;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc 
b/gcc/rust/hir/tree/rust-hir-expr.cc
index 82a09e935887..266c79c2fe89 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.cc
+++ b/gcc/rust/hir/tree/rust-hir-expr.cc
@@ -791,13 +791,15 @@ BlockExpr::operator= (BlockExpr const &other)
 }
 
 ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
-                           Lifetime label, AST::AttrVec outer_attribs)
+                           tl::optional<Lifetime> label,
+                           AST::AttrVec outer_attribs)
   : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
     label (std::move (label)), locus (locus)
 {}
 
 BreakExpr::BreakExpr (Analysis::NodeMapping mappings, location_t locus,
-                     Lifetime break_label, std::unique_ptr<Expr> expr_in_break,
+                     tl::optional<Lifetime> break_label,
+                     std::unique_ptr<Expr> expr_in_break,
                      AST::AttrVec outer_attribs)
   : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
     label (std::move (break_label)), break_expr (std::move (expr_in_break)),
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h 
b/gcc/rust/hir/tree/rust-hir-expr.h
index b304d27fc590..20287b830f9c 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -45,9 +45,6 @@ public:
   LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
             location_t locus);
 
-  // Returns whether the LoopLabel is in an error state.
-  bool is_error () const { return label.is_error (); }
-
   location_t get_locus () const { return locus; }
 
   Analysis::NodeMapping &get_mappings () { return mappings; }
@@ -1806,25 +1803,27 @@ protected:
 // HIR node representing continue expression within loops
 class ContinueExpr : public ExprWithoutBlock
 {
-  Lifetime label;
+  tl::optional<Lifetime> label;
   location_t locus;
 
 public:
   std::string as_string () const override;
 
   // Returns true if the continue expr has a label.
-  bool has_label () const { return !label.is_error (); }
+  bool has_label () const { return label.has_value (); }
 
   // Constructor for a ContinueExpr with a label.
   ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
-               Lifetime label, AST::AttrVec outer_attribs = AST::AttrVec ());
+               tl::optional<Lifetime> label,
+               AST::AttrVec outer_attribs = AST::AttrVec ());
 
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
 
-  Lifetime &get_label () { return label; }
+  Lifetime &get_label () { return label.value (); }
+  const Lifetime &get_label () const { return label.value (); }
 
   ExprType get_expression_type () const final override
   {
@@ -1851,7 +1850,7 @@ protected:
 class BreakExpr : public ExprWithoutBlock
 {
   // bool has_label;
-  Lifetime label;
+  tl::optional<Lifetime> label;
 
   // bool has_break_expr;
   std::unique_ptr<Expr> break_expr;
@@ -1862,7 +1861,7 @@ public:
   std::string as_string () const override;
 
   // Returns whether the break expression has a label or not.
-  bool has_label () const { return !label.is_error (); }
+  bool has_label () const { return label.has_value (); }
 
   /* Returns whether the break expression has an expression used in the break 
or
    * not. */
@@ -1870,7 +1869,7 @@ public:
 
   // Constructor for a break expression
   BreakExpr (Analysis::NodeMapping mappings, location_t locus,
-            Lifetime break_label,
+            tl::optional<Lifetime> break_label,
             std::unique_ptr<Expr> expr_in_break = nullptr,
             AST::AttrVec outer_attribs = AST::AttrVec ());
 
@@ -1889,7 +1888,8 @@ public:
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
 
-  Lifetime &get_label () { return label; }
+  Lifetime &get_label () { return label.value (); }
+  const Lifetime &get_label () const { return label.value (); }
 
   Expr &get_expr () { return *break_expr; }
 
diff --git a/gcc/rust/hir/tree/rust-hir-generic-param.h 
b/gcc/rust/hir/tree/rust-hir-generic-param.h
index a1c59bf0d6bf..960de565c142 100644
--- a/gcc/rust/hir/tree/rust-hir-generic-param.h
+++ b/gcc/rust/hir/tree/rust-hir-generic-param.h
@@ -97,9 +97,6 @@ public:
 
   AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
 
-  // Returns whether the lifetime param is in an error state.
-  bool is_error () const { return lifetime.is_error (); }
-
   // Constructor
   LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime,
                 location_t locus = UNDEF_LOCATION,
diff --git a/gcc/rust/hir/tree/rust-hir-item.cc 
b/gcc/rust/hir/tree/rust-hir-item.cc
index 14f53ce3771d..160f710408af 100644
--- a/gcc/rust/hir/tree/rust-hir-item.cc
+++ b/gcc/rust/hir/tree/rust-hir-item.cc
@@ -123,7 +123,8 @@ TypeBoundWhereClauseItem::get_type_param_bounds ()
 }
 
 SelfParam::SelfParam (Analysis::NodeMapping mappings,
-                     ImplicitSelfKind self_kind, Lifetime lifetime, Type *type)
+                     ImplicitSelfKind self_kind,
+                     tl::optional<Lifetime> lifetime, Type *type)
   : self_kind (self_kind), lifetime (std::move (lifetime)), type (type),
     mappings (mappings)
 {}
@@ -131,13 +132,13 @@ SelfParam::SelfParam (Analysis::NodeMapping mappings,
 SelfParam::SelfParam (Analysis::NodeMapping mappings,
                      std::unique_ptr<Type> type, bool is_mut, location_t locus)
   : self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM),
-    lifetime (
-      Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)),
-    type (std::move (type)), locus (locus), mappings (mappings)
+    lifetime (tl::nullopt), type (std::move (type)), locus (locus),
+    mappings (mappings)
 {}
 
-SelfParam::SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime,
-                     bool is_mut, location_t locus)
+SelfParam::SelfParam (Analysis::NodeMapping mappings,
+                     tl::optional<Lifetime> lifetime, bool is_mut,
+                     location_t locus)
   : self_kind (is_mut ? ImplicitSelfKind::MUT_REF : ImplicitSelfKind::IMM_REF),
     lifetime (std::move (lifetime)), locus (locus), mappings (mappings)
 {}
@@ -263,7 +264,7 @@ Function::Function (Analysis::NodeMapping mappings, 
Identifier function_name,
                    std::vector<FunctionParam> function_params,
                    std::unique_ptr<Type> return_type, WhereClause where_clause,
                    std::unique_ptr<BlockExpr> function_body, Visibility vis,
-                   AST::AttrVec outer_attrs, SelfParam self,
+                   AST::AttrVec outer_attrs, tl::optional<SelfParam> self,
                    Defaultness defaultness, location_t locus)
   : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
     qualifiers (std::move (qualifiers)),
@@ -612,9 +613,9 @@ StaticItem::operator= (StaticItem const &other)
 
 TraitFunctionDecl::TraitFunctionDecl (
   Identifier function_name, FunctionQualifiers qualifiers,
-  std::vector<std::unique_ptr<GenericParam>> generic_params, SelfParam self,
-  std::vector<FunctionParam> function_params, std::unique_ptr<Type> 
return_type,
-  WhereClause where_clause)
+  std::vector<std::unique_ptr<GenericParam>> generic_params,
+  tl::optional<SelfParam> self, std::vector<FunctionParam> function_params,
+  std::unique_ptr<Type> return_type, WhereClause where_clause)
   : qualifiers (std::move (qualifiers)),
     function_name (std::move (function_name)),
     generic_params (std::move (generic_params)),
diff --git a/gcc/rust/hir/tree/rust-hir-item.h 
b/gcc/rust/hir/tree/rust-hir-item.h
index 0a59a537da1c..f45d743dceb6 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -371,13 +371,13 @@ public:
 
 private:
   ImplicitSelfKind self_kind;
-  Lifetime lifetime;
+  tl::optional<Lifetime> lifetime;
   std::unique_ptr<Type> type;
   location_t locus;
   Analysis::NodeMapping mappings;
 
   SelfParam (Analysis::NodeMapping mappings, ImplicitSelfKind self_kind,
-            Lifetime lifetime, Type *type);
+            tl::optional<Lifetime> lifetime, Type *type);
 
 public:
   // Type-based self parameter (not ref, no lifetime)
@@ -385,8 +385,8 @@ public:
             bool is_mut, location_t locus);
 
   // Lifetime-based self parameter (is ref, no type)
-  SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut,
-            location_t locus);
+  SelfParam (Analysis::NodeMapping mappings, tl::optional<Lifetime> lifetime,
+            bool is_mut, location_t locus);
 
   // Copy constructor requires clone
   SelfParam (SelfParam const &other);
@@ -398,22 +398,13 @@ public:
   SelfParam (SelfParam &&other) = default;
   SelfParam &operator= (SelfParam &&other) = default;
 
-  static SelfParam error ()
-  {
-    return SelfParam (Analysis::NodeMapping::get_error (),
-                     ImplicitSelfKind::NONE, Lifetime::error (), nullptr);
-  }
-
   // Returns whether the self-param has a type field.
   bool has_type () const { return type != nullptr; }
 
   // Returns whether the self-param has a valid lifetime.
-  bool has_lifetime () const { return !lifetime.is_error (); }
-
-  const Lifetime &get_lifetime () const { return lifetime; }
+  bool has_lifetime () const { return lifetime.has_value (); }
 
-  // Returns whether the self-param is in an error state.
-  bool is_error () const { return self_kind == ImplicitSelfKind::NONE; }
+  const Lifetime &get_lifetime () const { return lifetime.value (); }
 
   std::string as_string () const;
 
@@ -961,7 +952,7 @@ class Function : public VisItem, public ImplItem
   std::unique_ptr<Type> return_type;
   WhereClause where_clause;
   std::unique_ptr<BlockExpr> function_body;
-  SelfParam self;
+  tl::optional<SelfParam> self;
   location_t locus;
 
   // NOTE: This should be moved to the trait item base class once we start
@@ -1001,8 +992,8 @@ public:
            std::vector<FunctionParam> function_params,
            std::unique_ptr<Type> return_type, WhereClause where_clause,
            std::unique_ptr<BlockExpr> function_body, Visibility vis,
-           AST::AttrVec outer_attrs, SelfParam self, Defaultness defaultness,
-           location_t locus);
+           AST::AttrVec outer_attrs, tl::optional<SelfParam> self,
+           Defaultness defaultness, location_t locus);
 
   // Copy constructor with clone
   Function (Function const &other);
@@ -1056,9 +1047,13 @@ public:
   // TODO: is this better? Or is a "vis_block" better?
   Type &get_return_type () { return *return_type; }
 
-  bool is_method () const { return !self.is_error (); }
+  bool is_method () const { return self.has_value (); }
 
-  SelfParam &get_self_param () { return self; }
+  tl::optional<SelfParam> &get_self_param () { return self; }
+  const tl::optional<SelfParam> &get_self_param () const { return self; }
+
+  SelfParam &get_self_param_unchecked () { return self.value (); }
+  const SelfParam &get_self_param_unchecked () const { return self.value (); }
 
   std::string get_impl_item_name () const override final
   {
@@ -1913,13 +1908,14 @@ private:
   std::vector<FunctionParam> function_params;
   std::unique_ptr<Type> return_type;
   WhereClause where_clause;
-  SelfParam self;
+  tl::optional<SelfParam> self;
 
 public:
   // Mega-constructor
   TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
                     std::vector<std::unique_ptr<GenericParam>> generic_params,
-                    SelfParam self, std::vector<FunctionParam> function_params,
+                    tl::optional<SelfParam> self,
+                    std::vector<FunctionParam> function_params,
                     std::unique_ptr<Type> return_type,
                     WhereClause where_clause);
 
@@ -1951,9 +1947,13 @@ public:
 
   WhereClause &get_where_clause () { return where_clause; }
 
-  bool is_method () const { return !self.is_error (); }
+  bool is_method () const { return self.has_value (); }
+
+  SelfParam &get_self_unchecked () { return self.value (); }
+  const SelfParam &get_self_unchecked () const { return self.value (); }
 
-  SelfParam &get_self () { return self; }
+  tl::optional<SelfParam> &get_self () { return self; }
+  const tl::optional<SelfParam> &get_self () const { return self; }
 
   Identifier get_function_name () const { return function_name; }
 
diff --git a/gcc/rust/hir/tree/rust-hir-type.cc 
b/gcc/rust/hir/tree/rust-hir-type.cc
index 6a6c319fc98e..ec484254138b 100644
--- a/gcc/rust/hir/tree/rust-hir-type.cc
+++ b/gcc/rust/hir/tree/rust-hir-type.cc
@@ -162,7 +162,7 @@ RawPointerType::operator= (RawPointerType const &other)
 
 ReferenceType::ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
                              std::unique_ptr<Type> type_no_bounds,
-                             location_t locus, Lifetime lifetime)
+                             location_t locus, tl::optional<Lifetime> lifetime)
   : TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)), mut (mut),
     type (std::move (type_no_bounds))
 {}
diff --git a/gcc/rust/hir/tree/rust-hir-type.h 
b/gcc/rust/hir/tree/rust-hir-type.h
index bf733e7261ad..d6a0e0972bd4 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -291,7 +291,7 @@ protected:
 class ReferenceType : public TypeNoBounds
 {
   // bool has_lifetime; // TODO: handle in lifetime or something?
-  Lifetime lifetime;
+  tl::optional<Lifetime> lifetime;
 
   Mutability mut;
   std::unique_ptr<Type> type;
@@ -301,12 +301,12 @@ public:
   bool is_mut () const { return mut == Mutability::Mut; }
 
   // Returns whether the reference has a lifetime.
-  bool has_lifetime () const { return !lifetime.is_error (); }
+  bool has_lifetime () const { return lifetime.has_value (); }
 
   // Constructor
   ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
                 std::unique_ptr<Type> type_no_bounds, location_t locus,
-                Lifetime lifetime);
+                tl::optional<Lifetime> lifetime);
 
   // Copy constructor with custom clone method
   ReferenceType (ReferenceType const &other);
@@ -323,7 +323,8 @@ public:
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRTypeVisitor &vis) override;
 
-  Lifetime &get_lifetime () { return lifetime; }
+  Lifetime &get_lifetime () { return lifetime.value (); }
+  const Lifetime &get_lifetime () const { return lifetime.value (); }
 
   Mutability get_mut () const { return mut; }
 
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 14f8646418c1..4fc6b1ae18f0 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -1314,7 +1314,7 @@ ContinueExpr::as_string () const
 
   if (has_label ())
     {
-      str += label.as_string ();
+      str += get_label ().as_string ();
     }
 
   return str;
@@ -1816,7 +1816,7 @@ BreakExpr::as_string () const
 
   if (has_label ())
     {
-      str += label.as_string () + " ";
+      str += get_label ().as_string () + " ";
     }
 
   if (has_break_expr ())
@@ -2101,11 +2101,6 @@ QualifiedPathInType::as_string () const
 std::string
 Lifetime::as_string () const
 {
-  if (is_error ())
-    {
-      return "error lifetime";
-    }
-
   switch (lifetime_type)
     {
     case AST::Lifetime::LifetimeType::NAMED:
@@ -2760,7 +2755,7 @@ ReferenceType::as_string () const
 
   if (has_lifetime ())
     {
-      str += lifetime.as_string () + " ";
+      str += get_lifetime ().as_string () + " ";
     }
 
   if (is_mut ())
@@ -3411,7 +3406,7 @@ TraitFunctionDecl::as_string () const
   str += "\n Function params: ";
   if (is_method ())
     {
-      str += self.as_string () + (has_params () ? ", " : "");
+      str += get_self_unchecked ().as_string () + (has_params () ? ", " : "");
     }
 
   if (has_params ())
@@ -3525,70 +3520,63 @@ TraitItemType::as_string () const
 std::string
 SelfParam::as_string () const
 {
-  if (is_error ())
-    {
-      return "error";
-    }
-  else
+  if (has_type ())
     {
-      if (has_type ())
+      // type (i.e. not ref, no lifetime)
+      std::string str;
+
+      if (is_mut ())
        {
-         // type (i.e. not ref, no lifetime)
-         std::string str;
+         str += "mut ";
+       }
 
-         if (is_mut ())
-           {
-             str += "mut ";
-           }
+      str += "self : ";
 
-         str += "self : ";
+      str += type->as_string ();
 
-         str += type->as_string ();
+      return str;
+    }
+  else if (has_lifetime ())
+    {
+      // ref and lifetime
+      std::string str = "&" + get_lifetime ().as_string () + " ";
 
-         return str;
-       }
-      else if (has_lifetime ())
+      if (is_mut ())
        {
-         // ref and lifetime
-         std::string str = "&" + lifetime.as_string () + " ";
+         str += "mut ";
+       }
 
-         if (is_mut ())
-           {
-             str += "mut ";
-           }
+      str += "self";
 
-         str += "self";
+      return str;
+    }
+  else if (is_ref ())
+    {
+      // ref with no lifetime
+      std::string str = "&";
 
-         return str;
-       }
-      else if (is_ref ())
+      if (is_mut ())
        {
-         // ref with no lifetime
-         std::string str = "&";
+         str += " mut ";
+       }
 
-         if (is_mut ())
-           {
-             str += " mut ";
-           }
+      str += "self";
 
-         str += "self";
+      return str;
+    }
+  else
+    {
+      // no ref, no type
+      std::string str;
 
-         return str;
-       }
-      else
+      if (is_mut ())
        {
-         // no ref, no type
-         std::string str;
-
-         if (is_mut ())
-           {
-             str += "mut ";
-           }
+         str += "mut ";
+       }
 
-         str += "self";
+      str += "self";
 
-         return str;
-       }
+      return str;
     }
 }
 
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index e2a3440efa93..32177c5ce2c0 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3102,7 +3102,7 @@ Parser<ManagedTokenSource>::parse_generic_param 
(EndTokenPred is_end_token)
     {
       case LIFETIME: {
        auto lifetime = parse_lifetime (false);
-       if (lifetime.is_error ())
+       if (!lifetime)
          {
            rust_error_at (
              token->get_locus (),
@@ -3122,7 +3122,7 @@ Parser<ManagedTokenSource>::parse_generic_param 
(EndTokenPred is_end_token)
          }
 
        param = std::unique_ptr<AST::LifetimeParam> (new AST::LifetimeParam (
-         std::move (lifetime), std::move (lifetime_bounds),
+         std::move (lifetime.value ()), std::move (lifetime_bounds),
          std::move (outer_attrs), token->get_locus ()));
        break;
       }
@@ -3276,16 +3276,16 @@ Parser<ManagedTokenSource>::parse_lifetime_params ()
 
   while (lexer.peek_token ()->get_id () != END_OF_FILE)
     {
-      AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+      auto lifetime_param = parse_lifetime_param ();
 
-      if (lifetime_param.is_error ())
+      if (!lifetime_param)
        {
          // can't treat as error as only way to get out with trailing comma
          break;
        }
 
       lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> (
-       new AST::LifetimeParam (std::move (lifetime_param))));
+       new AST::LifetimeParam (std::move (lifetime_param.value ()))));
 
       if (lexer.peek_token ()->get_id () != COMMA)
        break;
@@ -3311,9 +3311,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params 
(EndTokenPred is_end_token)
   // if end_token is not specified, it defaults to EOF, so should work fine
   while (!is_end_token (lexer.peek_token ()->get_id ()))
     {
-      AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+      auto lifetime_param = parse_lifetime_param ();
 
-      if (lifetime_param.is_error ())
+      if (!lifetime_param)
        {
          /* TODO: is it worth throwing away all lifetime params just because
           * one failed? */
@@ -3351,9 +3351,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ()
   // bad control structure as end token cannot be guaranteed
   while (true)
     {
-      AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+      auto lifetime_param = parse_lifetime_param ();
 
-      if (lifetime_param.is_error ())
+      if (!lifetime_param)
        {
          // not an error as only way to exit if trailing comma
          break;
@@ -3386,9 +3386,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs (
 
   while (!is_end_token (lexer.peek_token ()->get_id ()))
     {
-      AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+      auto lifetime_param = parse_lifetime_param ();
 
-      if (lifetime_param.is_error ())
+      if (!lifetime_param)
        {
          /* TODO: is it worth throwing away all lifetime params just because
           * one failed? */
@@ -3399,7 +3399,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs (
          return {};
        }
 
-      lifetime_params.push_back (std::move (lifetime_param));
+      lifetime_params.push_back (std::move (lifetime_param.value ()));
 
       if (lexer.peek_token ()->get_id () != COMMA)
        break;
@@ -3458,7 +3458,7 @@ Parser<ManagedTokenSource>::parse_non_ptr_sequence (
 
 /* Parses a single lifetime generic parameter (not including comma). */
 template <typename ManagedTokenSource>
-AST::LifetimeParam
+tl::expected<AST::LifetimeParam, ParseLifetimeParamError>
 Parser<ManagedTokenSource>::parse_lifetime_param ()
 {
   // parse outer attributes, which are optional and may not exist
@@ -3468,8 +3468,8 @@ Parser<ManagedTokenSource>::parse_lifetime_param ()
   const_TokenPtr lifetime_tok = lexer.peek_token ();
   if (lifetime_tok->get_id () != LIFETIME)
     {
-      // if lifetime is missing, must not be a lifetime param, so return null
-      return AST::LifetimeParam::create_error ();
+      // if lifetime is missing, must not be a lifetime param, so return error
+      return tl::make_unexpected<ParseLifetimeParamError> ({});
     }
   lexer.skip_token ();
   AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (),
@@ -3815,12 +3815,13 @@ template <typename ManagedTokenSource>
 std::unique_ptr<AST::LifetimeWhereClauseItem>
 Parser<ManagedTokenSource>::parse_lifetime_where_clause_item ()
 {
-  AST::Lifetime lifetime = parse_lifetime (false);
-  if (lifetime.is_error ())
+  auto parsed_lifetime = parse_lifetime (false);
+  if (!parsed_lifetime)
     {
       // TODO: error here?
       return nullptr;
     }
+  auto lifetime = parsed_lifetime.value ();
 
   if (!skip_token (COLON))
     {
@@ -4013,7 +4014,7 @@ Parser<ManagedTokenSource>::parse_type_param_bound ()
     {
     case LIFETIME:
       return std::unique_ptr<AST::Lifetime> (
-       new AST::Lifetime (parse_lifetime (false)));
+       new AST::Lifetime (parse_lifetime (false).value ()));
     case LEFT_PAREN:
     case QUESTION_MARK:
     case FOR:
@@ -4086,13 +4087,13 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds ()
 
   while (true)
     {
-      AST::Lifetime lifetime = parse_lifetime (false);
+      auto lifetime = parse_lifetime (false);
 
       // quick exit for parsing failure
-      if (lifetime.is_error ())
+      if (!lifetime)
        break;
 
-      lifetime_bounds.push_back (std::move (lifetime));
+      lifetime_bounds.push_back (std::move (lifetime.value ()));
 
       /* plus is maybe not allowed at end - spec defines it weirdly, so
        * assuming allowed at end */
@@ -4116,9 +4117,9 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds 
(EndTokenPred is_end_token)
 
   while (!is_end_token (lexer.peek_token ()->get_id ()))
     {
-      AST::Lifetime lifetime = parse_lifetime (false);
+      auto lifetime = parse_lifetime (false);
 
-      if (lifetime.is_error ())
+      if (!lifetime)
        {
          /* TODO: is it worth throwing away all lifetime bound info just
           * because one failed? */
@@ -4129,7 +4130,7 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds 
(EndTokenPred is_end_token)
          return {};
        }
 
-      lifetime_bounds.push_back (std::move (lifetime));
+      lifetime_bounds.push_back (std::move (lifetime.value ()));
 
       /* plus is maybe not allowed at end - spec defines it weirdly, so
        * assuming allowed at end */
@@ -4146,14 +4147,20 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds 
(EndTokenPred is_end_token)
 /* Parses a lifetime token (named, 'static, or '_). Also handles lifetime not
  * existing. */
 template <typename ManagedTokenSource>
-AST::Lifetime
+tl::expected<AST::Lifetime, ParseLifetimeError>
 Parser<ManagedTokenSource>::parse_lifetime (bool allow_elided)
 {
   const_TokenPtr lifetime_tok = lexer.peek_token ();
   if (lifetime_tok->get_id () != LIFETIME)
     {
-      return (allow_elided) ? AST::Lifetime::elided ()
-                           : AST::Lifetime::error ();
+      if (allow_elided)
+       {
+         return AST::Lifetime::elided ();
+       }
+      else
+       {
+         return tl::make_unexpected<ParseLifetimeError> ({});
+       }
     }
   lexer.skip_token ();
 
@@ -6340,14 +6347,14 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
   location_t locus = t->get_locus ();
   while (!is_right_angle_tok (t->get_id ()))
     {
-      AST::Lifetime lifetime = parse_lifetime (false);
-      if (lifetime.is_error ())
+      auto lifetime = parse_lifetime (false);
+      if (!lifetime)
        {
          // not necessarily an error
          break;
        }
 
-      lifetime_args.push_back (std::move (lifetime));
+      lifetime_args.push_back (std::move (lifetime.value ()));
 
       // if next token isn't comma, then it must be end of list
       if (lexer.peek_token ()->get_id () != COMMA)
@@ -6961,10 +6968,12 @@ Parser<ManagedTokenSource>::parse_self_param ()
       // now test whether it has a lifetime
       if (lexer.peek_token ()->get_id () == LIFETIME)
        {
-         lifetime = parse_lifetime (true);
-
          // something went wrong somehow
-         if (lifetime.is_error ())
+         if (auto parsed_lifetime = parse_lifetime (true))
+           {
+             lifetime = parsed_lifetime.value ();
+           }
+         else
            {
              Error error (lexer.peek_token ()->get_locus (),
                           "failed to parse lifetime in self param");
@@ -7519,12 +7528,10 @@ Parser<ManagedTokenSource>::parse_break_expr 
(AST::AttrVec outer_attrs,
       skip_token (BREAK);
     }
 
-  // parse label (lifetime) if it exists - create dummy first
-  AST::Lifetime label = AST::Lifetime::error ();
-  if (lexer.peek_token ()->get_id () == LIFETIME)
-    {
-      label = parse_lifetime (false);
-    }
+  auto parsed_label = parse_lifetime (false);
+  auto label = (parsed_label)
+                ? tl::optional<AST::Lifetime> (parsed_label.value ())
+                : tl::nullopt;
 
   // parse break return expression if it exists
   ParseRestrictions restrictions;
@@ -7550,12 +7557,10 @@ Parser<ManagedTokenSource>::parse_continue_expr 
(AST::AttrVec outer_attrs,
       skip_token (CONTINUE);
     }
 
-  // parse label (lifetime) if it exists - create dummy first
-  AST::Lifetime label = AST::Lifetime::error ();
-  if (lexer.peek_token ()->get_id () == LIFETIME)
-    {
-      label = parse_lifetime (false);
-    }
+  auto parsed_label = parse_lifetime (false);
+  auto label = (parsed_label)
+                ? tl::optional<AST::Lifetime> (parsed_label.value ())
+                : tl::nullopt;
 
   return std::unique_ptr<AST::ContinueExpr> (
     new AST::ContinueExpr (std::move (label), std::move (outer_attrs), locus));
@@ -9600,8 +9605,12 @@ Parser<ManagedTokenSource>::parse_reference_type_inner 
(location_t locus)
   AST::Lifetime lifetime = AST::Lifetime::elided ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
     {
-      lifetime = parse_lifetime (true);
-      if (lifetime.is_error ())
+      auto parsed_lifetime = parse_lifetime (true);
+      if (parsed_lifetime)
+       {
+         lifetime = parsed_lifetime.value ();
+       }
+      else
        {
          Error error (lexer.peek_token ()->get_locus (),
                       "failed to parse lifetime in reference type");
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index fc548141c44f..5373106c1890 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -25,6 +25,21 @@ along with GCC; see the file COPYING3.  If not see
 #include "expected.h"
 
 namespace Rust {
+
+class ParseLifetimeParamError
+{
+};
+
+class ParseLifetimeError
+{
+};
+enum ParseSelfError
+{
+  SELF_PTR,
+  PARSING,
+  NOT_SELF,
+};
+
 /* HACK: used to resolve the expression-or-statement problem at the end of a
  * block by allowing either to be returned (technically). Tagged union would
  * probably take up the same amount of space. */
@@ -95,12 +110,6 @@ struct ParseRestrictions
   bool allow_close_after_expr_stmt = false;
 };
 
-enum ParseSelfError
-{
-  SELF_PTR,
-  PARSING,
-  NOT_SELF,
-};
 // Parser implementation for gccrs.
 // TODO: if updated to C++20, ManagedTokenSource would be useful as a concept
 template <typename ManagedTokenSource> class Parser
@@ -277,7 +286,8 @@ private:
     ParseFunction parsing_function, EndTokenPred is_end_token,
     std::string error_msg = "failed to parse generic param in generic params")
     -> std::vector<decltype (parsing_function ())>;
-  AST::LifetimeParam parse_lifetime_param ();
+  tl::expected<AST::LifetimeParam, ParseLifetimeParamError>
+  parse_lifetime_param ();
   std::vector<std::unique_ptr<AST::TypeParam>> parse_type_params ();
   template <typename EndTokenPred>
   std::vector<std::unique_ptr<AST::TypeParam>>
@@ -306,7 +316,8 @@ private:
   std::vector<AST::Lifetime> parse_lifetime_bounds ();
   template <typename EndTokenPred>
   std::vector<AST::Lifetime> parse_lifetime_bounds (EndTokenPred is_end_token);
-  AST::Lifetime parse_lifetime (bool allow_elided);
+  tl::expected<AST::Lifetime, ParseLifetimeError>
+  parse_lifetime (bool allow_elided);
   AST::Lifetime lifetime_from_token (const_TokenPtr tok);
   std::unique_ptr<AST::ExternalTypeItem>
   parse_external_type_item (AST::Visibility vis, AST::AttrVec outer_attrs);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc 
b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index 55dd9514127c..ad1c7671f0a5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -242,7 +242,7 @@ TypeCheckImplItem::visit (HIR::Function &function)
       // add the synthetic self param at the front, this is a placeholder for
       // compilation to know parameter names. The types are ignored but we
       // reuse the HIR identifier pattern which requires it
-      HIR::SelfParam &self_param = function.get_self_param ();
+      HIR::SelfParam &self_param = function.get_self_param_unchecked ();
       // FIXME: which location should be used for Rust::Identifier for `self`?
       std::unique_ptr<HIR::Pattern> self_pattern
        = std::make_unique<HIR::IdentifierPattern> (
@@ -267,13 +267,21 @@ TypeCheckImplItem::visit (HIR::Function &function)
              break;
 
              case HIR::SelfParam::IMM_REF: {
-               auto region = context->lookup_and_resolve_lifetime (
-                 self_param.get_lifetime ());
-               if (!region.has_value ())
+               tl::optional<TyTy::Region> region;
+               if (self_param.has_lifetime ())
                  {
-                   rust_inform (self_param.get_locus (),
-                                "failed to resolve lifetime");
-                   region = TyTy::Region::make_anonymous (); // FIXME
+                   region = context->lookup_and_resolve_lifetime (
+                     self_param.get_lifetime ());
+                   if (!region.has_value ())
+                     {
+                       rust_inform (self_param.get_locus (),
+                                    "failed to resolve lifetime");
+                       return;
+                     }
+                 }
+               else
+                 {
+                   region = TyTy::Region::make_anonymous ();
                  }
                self_type = new TyTy::ReferenceType (
                  self_param.get_mappings ().get_hirid (),
@@ -283,13 +291,21 @@ TypeCheckImplItem::visit (HIR::Function &function)
              break;
 
              case HIR::SelfParam::MUT_REF: {
-               auto region = context->lookup_and_resolve_lifetime (
-                 self_param.get_lifetime ());
-               if (!region.has_value ())
+               tl::optional<TyTy::Region> region;
+               if (self_param.has_lifetime ())
+                 {
+                   region = context->lookup_and_resolve_lifetime (
+                     self_param.get_lifetime ());
+                   if (!region.has_value ())
+                     {
+                       rust_error_at (self_param.get_locus (),
+                                      "failed to resolve lifetime");
+                       return;
+                     }
+                 }
+               else
                  {
-                   rust_error_at (self_param.get_locus (),
-                                  "failed to resolve lifetime");
-                   return;
+                   region = TyTy::Region::make_anonymous ();
                  }
                self_type = new TyTy::ReferenceType (
                  self_param.get_mappings ().get_hirid (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc 
b/gcc/rust/typecheck/rust-hir-type-check.cc
index 3deb5b7ea496..ed3e8ec037a4 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -208,7 +208,7 @@ TraitItemReference::get_type_from_fn (/*const*/ 
HIR::TraitItemFunc &fn) const
       // add the synthetic self param at the front, this is a placeholder
       // for compilation to know parameter names. The types are ignored
       // but we reuse the HIR identifier pattern which requires it
-      HIR::SelfParam &self_param = function.get_self ();
+      HIR::SelfParam &self_param = function.get_self_unchecked ();
       std::unique_ptr<HIR::Pattern> self_pattern
        = std::make_unique<HIR::IdentifierPattern> (HIR::IdentifierPattern (
          mapping, {"self"}, self_param.get_locus (), self_param.is_ref (),

Reply via email to