From: Arthur Cohen <arthur.cohen@embecosm.com>
The parser now recursively tries to parse a reference type after seeing
a `&` or `&&` token.
gcc/rust/ChangeLog:
* parse/rust-parse-impl.h (Parser::parse_type): Handle double ampersan
properly
(Parser::parse_reference_type): Call into `parse_reference_type_inner`
and wrap double reference types in another `AST::ReferenceType` node
(Parser::parse_reference_type_inner): Add parsing implementation
which does not care about the leading token (& or &&)
(Parser::parse_type_no_bounds): Handle double ampersand properly
* parse/rust-parse.h: Declare `parse_reference_type_inner`
gcc/testsuite/ChangeLog:
* rust/compile/multi_reference_type.rs: New test.
---
gcc/rust/parse/rust-parse-impl.h | 33 +++++++++++++++----
gcc/rust/parse/rust-parse.h | 2 ++
.../rust/compile/multi_reference_type.rs | 12 +++++++
3 files changed, 41 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/multi_reference_type.rs
@@ -9237,6 +9237,7 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
// raw pointer type
return parse_raw_pointer_type ();
case AMP: // does this also include AMP_AMP?
+ case LOGICAL_AND:
// reference type
return parse_reference_type ();
case LIFETIME: {
@@ -9886,14 +9887,10 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
std::move (return_type), best_try_locus));
}
-// Parses a reference type (mutable or immutable, with given lifetime).
template <typename ManagedTokenSource>
std::unique_ptr<AST::ReferenceType>
-Parser<ManagedTokenSource>::parse_reference_type ()
+Parser<ManagedTokenSource>::parse_reference_type_inner (Location locus)
{
- Location locus = lexer.peek_token ()->get_locus ();
- skip_token (AMP);
-
// parse optional lifetime
AST::Lifetime lifetime = AST::Lifetime::error ();
if (lexer.peek_token ()->get_id () == LIFETIME)
@@ -9932,6 +9929,29 @@ Parser<ManagedTokenSource>::parse_reference_type ()
std::move (lifetime)));
}
+// Parses a reference type (mutable or immutable, with given lifetime).
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::ReferenceType>
+Parser<ManagedTokenSource>::parse_reference_type ()
+{
+ auto t = lexer.peek_token ();
+ auto locus = t->get_locus ();
+
+ switch (t->get_id ())
+ {
+ case AMP:
+ skip_token (AMP);
+ return parse_reference_type_inner (locus);
+ case LOGICAL_AND:
+ skip_token (LOGICAL_AND);
+ return std::unique_ptr<AST::ReferenceType> (
+ new AST::ReferenceType (false, parse_reference_type_inner (locus),
+ locus));
+ default:
+ gcc_unreachable ();
+ }
+}
+
// Parses a raw (unsafe) pointer type.
template <typename ManagedTokenSource>
std::unique_ptr<AST::RawPointerType>
@@ -10079,7 +10099,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
case ASTERISK:
// raw pointer type
return parse_raw_pointer_type ();
- case AMP: // does this also include AMP_AMP?
+ case AMP: // does this also include AMP_AMP? Yes! Which is... LOGICAL_AND?
+ case LOGICAL_AND:
// reference type
return parse_reference_type ();
case LIFETIME:
@@ -604,6 +604,8 @@ private:
std::unique_ptr<AST::TypeNoBounds> parse_type_no_bounds ();
std::unique_ptr<AST::TypeNoBounds> parse_slice_or_array_type ();
std::unique_ptr<AST::RawPointerType> parse_raw_pointer_type ();
+ std::unique_ptr<AST::ReferenceType>
+ parse_reference_type_inner (Location locus);
std::unique_ptr<AST::ReferenceType> parse_reference_type ();
std::unique_ptr<AST::BareFunctionType>
parse_bare_function_type (std::vector<AST::LifetimeParam> for_lifetimes);
new file mode 100644
@@ -0,0 +1,12 @@
+fn main() {
+ let a = 15u8;
+ let a: &u8 = &a;
+ let a: &&u8 = &a;
+ let a: &&&u8 = &a;
+ let _: &&&&u8 = &a;
+
+ let _: &&u8;
+ let _: &mut &u8;
+ let _: &&mut u8;
+ let _: &mut &mut &u8;
+}