Hi Joel,

On Sat, Jul 17, 2021 at 10:25:48PM +0800, The Other wrote:
> >> - I noticed some expressions didn't parse because of what looks to me
> >>   operator precedence issues. e.g the following:
> >>
> >>   const S: usize = 64;
> >>
> >>   pub fn main ()
> >>   {
> >>     let a:u8 = 1;
> >>     let b:u8 = 2;
> >>     let _c = S * a as usize + b as usize;
> >>   }
> >>
> >>   $ gcc/gccrs -Bgcc as.rs
> >>
> >>   as.rs:7:27: error: type param bounds (in TraitObjectType) are not
> >>   allowed as TypeNoBounds
> >>     7 |   let _c = S * a as usize + b as usize;
> >>       |                           ^
> >>
> >>   How does one fix such operator precedence issues in the parser?
> 
> > Off the top of my head it looks as though the parse_type_cast_expr has a
> > FIXME for the precedence issue for it. The Pratt parser uses the notion
> > of binding powers to handle this and i think it needs to follow in a
> > similar style to the ::parse_expr piece.
> 
> Yes, this is probably a precedence issue. The actual issue is that while
> expressions have precedence, types (such as "usize", which is what is being
> parsed) do not, and greedily parse tokens like "+". Additionally, the
> interactions of types and expressions and precedence between them is
> something that I have no idea how to approach.
> I believe that this specific issue could be fixed by modifying the
> parse_type_no_bounds method - if instead of erroring when finding a plus,
> it simply returned (treating it like an expression would treat a semicolon,
> basically), then this would have the desired functionality. I don't believe
> that parse_type_no_bounds (TypeNoBounds do not have '+' in them) would ever
> be called in an instance where a Type (that allows bounds) is allowable, so
> this change should hopefully not cause any correct programs to parse
> incorrectly.

I think you are correct. The issue is that parse_type_no_bounds tries
to be helpful and greedily looks for a PLUS so it can produce an
error. Simply removing that case makes things parse.

Patch attached and also here:
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=as-type

This cannot be fully tested yet, because as Cast Expressions aren't
lowered from AST to HIR yet. I didn't get very far trying to lower the
CastExpr to HIR. This is what I came up with. But I didn't know how to
handle the type path yet.

diff --git a/gcc/rust/hir/rust-ast-lower-expr.h 
b/gcc/rust/hir/rust-ast-lower-expr.h
index 19ce8c2cf1f..96f6073cd86 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -405,6 +405,24 @@ public:
                               expr.get_locus ());
   }
 
+  void visit (AST::TypeCastExpr &expr) override
+  {
+    HIR::Expr *expr_to_cast_to
+      = ASTLoweringExpr::translate (expr.get_casted_expr ().get ());
+
+    HIR::TypeNoBounds *type_to_cast_to
+      = nullptr; /* ... (expr._get_type_to_cast_to ().get ())); */
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+                                  mappings->get_next_hir_id (crate_num),
+                                  UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::TypeCastExpr (
+      mapping, std::unique_ptr<HIR::Expr> (expr_to_cast_to),
+      std::unique_ptr<HIR::TypeNoBounds> (type_to_cast_to), expr.get_locus ());
+  }
+
   /* Compound assignment expression is compiled away. */
   void visit (AST::CompoundAssignmentExpr &expr) override
   {

It does get us a little bit further into the type checker:

as2.rs:7:12: error: failed to type resolve expression
    7 |   let _c = a as usize + b as usize;
      |            ^
as2.rs:7:25: error: failed to type resolve expression
    7 |   let _c = a as usize + b as usize;


Cheers,

Mark
>From 4c92de44cde1bdd8d0fcb8a19adafd529d6c759c Mon Sep 17 00:00:00 2001
From: Mark Wielaard <m...@klomp.org>
Date: Sun, 18 Jul 2021 22:12:20 +0200
Subject: [PATCH] Remove error handling in parse_type_no_bounds for PLUS token

parse_type_no_bounds tries to be helpful and greedily looks for a PLUS
token after having parsed a typepath so it can produce an error. But
that error breaks parsing expressions that contain "as" Cast
Expressions like "a as usize + b as usize". Drop the explicit error on
seeing a PLUS token and just return the type path parsed.
---
 gcc/rust/parse/rust-parse-impl.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index eedc76db43e..a0607926950 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -9996,13 +9996,6 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
 				       std::move (tok_tree)),
 		  {}, locus));
 	    }
-	  case PLUS:
-	    // type param bounds - not allowed, here for error message
-	    add_error (Error (t->get_locus (),
-			      "type param bounds (in TraitObjectType) are not "
-			      "allowed as TypeNoBounds"));
-
-	    return nullptr;
 	  default:
 	    // assume that this is a type path and not an error
 	    return std::unique_ptr<AST::TypePath> (
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust

Reply via email to