From: Philip Herron <herron.phi...@googlemail.com>

This patch adds support for raw references which enforce the pointer
type away from a reference type.

Fixes Rust-GCC#3667

gcc/rust/ChangeLog:

        * backend/rust-compile-base.cc (HIRCompileBase::address_expression): 
allow optional type
        * backend/rust-compile-base.h: update prototype
        * backend/rust-compile-expr.cc (CompileExpr::visit): update borrow expr
        * backend/rust-compile-extern.h: remove unused debug
        * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): 
update usage
        * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): lower raw ref
        * hir/tree/rust-hir-expr.cc (BorrowExpr::BorrowExpr): add flag for raw 
ref
        * hir/tree/rust-hir-expr.h (class BorrowExpr): add new raw ref field
        * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): add 
handle for raw ref

gcc/testsuite/ChangeLog:

        * rust/compile/issue-3667.rs: New test.

Signed-off-by: Philip Herron <herron.phi...@googlemail.com>
---
 gcc/rust/backend/rust-compile-base.cc         |  7 ++++--
 gcc/rust/backend/rust-compile-base.h          |  3 ++-
 gcc/rust/backend/rust-compile-expr.cc         |  3 ++-
 gcc/rust/backend/rust-compile-extern.h        |  6 -----
 gcc/rust/backend/rust-compile-resolve-path.cc |  4 ++--
 gcc/rust/hir/rust-ast-lower-expr.cc           | 11 ++++-----
 gcc/rust/hir/tree/rust-hir-expr.cc            |  4 ++--
 gcc/rust/hir/tree/rust-hir-expr.h             |  4 +++-
 .../typecheck/rust-hir-type-check-expr.cc     |  9 +++++++
 gcc/testsuite/rust/compile/issue-3667.rs      | 24 +++++++++++++++++++
 10 files changed, 53 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-3667.rs

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index b6bee8f9c2f..0647718c841 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -549,7 +549,7 @@ HIRCompileBase::mark_addressable (tree exp, location_t 
locus)
 }
 
 tree
-HIRCompileBase::address_expression (tree expr, location_t location)
+HIRCompileBase::address_expression (tree expr, location_t location, tree ptrty)
 {
   if (expr == error_mark_node)
     return error_mark_node;
@@ -557,7 +557,10 @@ HIRCompileBase::address_expression (tree expr, location_t 
location)
   if (!mark_addressable (expr, location))
     return error_mark_node;
 
-  return build_fold_addr_expr_loc (location, expr);
+  if (ptrty == NULL || ptrty == error_mark_node)
+    ptrty = build_pointer_type (TREE_TYPE (expr));
+
+  return build_fold_addr_expr_with_type_loc (location, expr, ptrty);
 }
 
 tree
diff --git a/gcc/rust/backend/rust-compile-base.h 
b/gcc/rust/backend/rust-compile-base.h
index 64c8106d1c2..467bfd0a4f7 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -29,7 +29,8 @@ class HIRCompileBase
 public:
   virtual ~HIRCompileBase () {}
 
-  static tree address_expression (tree expr, location_t locus);
+  static tree address_expression (tree expr, location_t locus,
+                                 tree ptrty = NULL_TREE);
 
   static tree compile_constant_expr (
     Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type,
diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index e4ab9f010b8..37856a77f2c 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -905,7 +905,8 @@ CompileExpr::visit (HIR::BorrowExpr &expr)
                                       &tyty))
     return;
 
-  translated = address_expression (main_expr, expr.get_locus ());
+  tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
+  translated = address_expression (main_expr, expr.get_locus (), 
expected_type);
 }
 
 void
diff --git a/gcc/rust/backend/rust-compile-extern.h 
b/gcc/rust/backend/rust-compile-extern.h
index bacd1c044ec..d6aa5899f62 100644
--- a/gcc/rust/backend/rust-compile-extern.h
+++ b/gcc/rust/backend/rust-compile-extern.h
@@ -34,16 +34,10 @@ class CompileExternItem : public HIRCompileBase,
 public:
   static tree compile (HIR::ExternalItem *item, Context *ctx,
                       TyTy::BaseType *concrete = nullptr,
-                      bool is_query_mode = false,
                       location_t ref_locus = UNDEF_LOCATION)
   {
     CompileExternItem compiler (ctx, concrete, ref_locus);
     item->accept_vis (compiler);
-
-    if (is_query_mode && compiler.reference == error_mark_node)
-      rust_internal_error_at (ref_locus, "failed to compile extern item: %s",
-                             item->as_string ().c_str ());
-
     return compiler.reference;
   }
 
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc 
b/gcc/rust/backend/rust-compile-resolve-path.cc
index bba0498ddfa..81d2dbb033f 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -261,10 +261,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType 
*lookup,
       HIR::ExternalItem *resolved_extern_item = hir_extern_item->first;
       if (!lookup->has_substitutions_defined ())
        return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
-                                          true, expr_locus);
+                                          expr_locus);
       else
        return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
-                                          true, expr_locus);
+                                          expr_locus);
     }
   else
     {
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc 
b/gcc/rust/hir/rust-ast-lower-expr.cc
index 9f363c0b504..9c763806c80 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -633,9 +633,6 @@ ASTLoweringExpr::visit (AST::ContinueExpr &expr)
 void
 ASTLoweringExpr::visit (AST::BorrowExpr &expr)
 {
-  if (expr.is_raw_borrow ())
-    rust_unreachable ();
-
   HIR::Expr *borrow_lvalue
     = ASTLoweringExpr::translate (expr.get_borrowed_expr ());
 
@@ -646,8 +643,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr)
 
   auto *borrow_expr
     = new HIR::BorrowExpr (mapping, std::unique_ptr<HIR::Expr> (borrow_lvalue),
-                          expr.get_mutability (), expr.get_outer_attrs (),
-                          expr.get_locus ());
+                          expr.get_mutability (), expr.is_raw_borrow (),
+                          expr.get_outer_attrs (), expr.get_locus ());
 
   if (expr.get_is_double_borrow ())
     {
@@ -659,8 +656,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr)
       borrow_expr
        = new HIR::BorrowExpr (mapping,
                               std::unique_ptr<HIR::Expr> (borrow_expr),
-                              expr.get_mutability (), expr.get_outer_attrs (),
-                              expr.get_locus ());
+                              expr.get_mutability (), expr.is_raw_borrow (),
+                              expr.get_outer_attrs (), expr.get_locus ());
     }
 
   translated = borrow_expr;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc 
b/gcc/rust/hir/tree/rust-hir-expr.cc
index 2ded789e60b..bb7ebfbc617 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.cc
+++ b/gcc/rust/hir/tree/rust-hir-expr.cc
@@ -81,10 +81,10 @@ OperatorExpr::operator= (OperatorExpr const &other)
 
 BorrowExpr::BorrowExpr (Analysis::NodeMapping mappings,
                        std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
-                       AST::AttrVec outer_attribs, location_t locus)
+                       bool raw, AST::AttrVec outer_attribs, location_t locus)
   : OperatorExpr (std::move (mappings), std::move (borrow_lvalue),
                  std::move (outer_attribs), locus),
-    mut (mut)
+    mut (mut), raw (raw)
 {}
 
 DereferenceExpr::DereferenceExpr (Analysis::NodeMapping mappings,
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h 
b/gcc/rust/hir/tree/rust-hir-expr.h
index f8f212884b6..3ff38b34065 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -199,12 +199,13 @@ public:
 class BorrowExpr : public OperatorExpr
 {
   Mutability mut;
+  bool raw;
 
 public:
   std::string as_string () const override;
 
   BorrowExpr (Analysis::NodeMapping mappings,
-             std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
+             std::unique_ptr<Expr> borrow_lvalue, Mutability mut, bool raw,
              AST::AttrVec outer_attribs, location_t locus);
 
   void accept_vis (HIRFullVisitor &vis) override;
@@ -212,6 +213,7 @@ public:
 
   Mutability get_mut () const { return mut; }
   bool is_mut () const { return mut == Mutability::Mut; }
+  bool is_raw_borrow () const { return raw; }
 
 protected:
   /* Use covariance to implement clone function as returning this object rather
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index b7fdc139615..791795f3b0e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1463,6 +1463,15 @@ TypeCheckExpr::visit (HIR::BorrowExpr &expr)
        }
     }
 
+  if (expr.is_raw_borrow ())
+    {
+      infered = new TyTy::PointerType (expr.get_mappings ().get_hirid (),
+                                      TyTy::TyVar (resolved_base->get_ref ()),
+                                      expr.get_mut ());
+
+      return;
+    }
+
   infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (),
                                     TyTy::TyVar (resolved_base->get_ref ()),
                                     expr.get_mut ());
diff --git a/gcc/testsuite/rust/compile/issue-3667.rs 
b/gcc/testsuite/rust/compile/issue-3667.rs
new file mode 100644
index 00000000000..e72069cf6e4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3667.rs
@@ -0,0 +1,24 @@
+// { dg-options "-w" }
+#![feature(raw_ref_op)]
+
+const pq1: () = {
+    let mut x = 2;
+    &raw mut x;
+}; //~ mutable reference
+
+static B: () = {
+    let mut x = 2;
+    &raw mut x;
+}; //~ mutable reference
+
+static mut C: () = {
+    let mut x = 2;
+    &raw mut x;
+}; //~ mutable reference
+
+const fn foo() {
+    let mut x = 0;
+    let y = &raw mut x; //~ mutable reference
+}
+
+fn main() {}
-- 
2.49.0

Reply via email to