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 (expr_to_cast_to), + std::unique_ptr (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