public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
* Using unsafe blocks in let expressions
@ 2021-07-21 21:09 Mark Wielaard
  2021-07-21 23:09 ` Mark Wielaard
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Wielaard @ 2021-07-21 21:09 UTC (permalink / raw)
  To: gcc-rust

[-- Attachment #1: Type: text/plain, Size: 1836 bytes --]

Hi,

I wanted to use an unsafe block in a let expression, which wasn't
accepted. The attached patch implements this.

I did want to add a testcase, but I couldn't come up with a test that
is correct and passes the type checker. The following works, but is
not correctly typed:

pub fn main ()
{
  let mut num = 2;
  // let r1 = &num as *const i32;
  // let r1: *const i32 = #
  let r1 = #
  let r2 = unsafe { *r1 } + unsafe { *r1 };
  let r3 = num;
  num = 4;
  let r4 = num + unsafe { *r1 } * r3;
  let _eightteen = r2 + r3 + r4;
}

In this case r1 is a reference, not a raw pointer, so the code
shouldn't work, but it does. It does correctly add up to 18.

The two ways to make this code type correct don't work. The first
gives:

let_unsafe.rs:4:12: fatal error: Failed to lower expr: [&num as *const i32]
    4 |   let r1 = &num as *const i32;
      |            ^

The second gives:

let_unsafe.rs:7:21: error: expected reference type got * const i32
    7 |   let r2 = unsafe { *r1 } + unsafe { *r1 };
      |                     ^
let_unsafe.rs:7:21: error: failed to type resolve expression
let_unsafe.rs:7:38: error: expected reference type got * const i32
    7 |   let r2 = unsafe { *r1 } + unsafe { *r1 };
      |                                      ^
let_unsafe.rs:7:38: error: failed to type resolve expression
let_unsafe.rs:7:18: error: cannot apply this operator to types <tyty::error> and <tyty::error>
    7 |   let r2 = unsafe { *r1 } + unsafe { *r1 };
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~      

Note that the error marker is wrong on the last line. I think that is
because of the way the pratt parser eats the token and then the code
does a locus - 1. Which ends up at the wrong place. I think instead of
a boolean we should pass the current token to get the correct
location.

Cheers,

Mark

[-- Attachment #2: 0001-unsafe-blocks-can-be-used-in-expressions.patch --]
[-- Type: text/x-diff, Size: 3077 bytes --]

From 3e9c4eff383cd1a23a148f5a7d556345b7972e26 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Wed, 21 Jul 2021 22:41:04 +0200
Subject: [PATCH] unsafe blocks can be used in expressions

To use an unsafe block expression handle it in null_denotation for the
pratt parser. Adjust parse_unsafe_block_expr to take a pratt_parse
bool that defaults to false.
---
 gcc/rust/parse/rust-parse-impl.h | 15 ++++++++++++---
 gcc/rust/parse/rust-parse.h      |  5 +++--
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index eedc76db43e..f75dd206963 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -8704,10 +8704,17 @@ Parser<ManagedTokenSource>::parse_async_block_expr (AST::AttrVec outer_attrs)
 // Parses an unsafe block expression.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::UnsafeBlockExpr>
-Parser<ManagedTokenSource>::parse_unsafe_block_expr (AST::AttrVec outer_attrs)
+Parser<ManagedTokenSource>::parse_unsafe_block_expr (AST::AttrVec outer_attrs,
+						     bool pratt_parse)
 {
-  Location locus = lexer.peek_token ()->get_locus ();
-  skip_token (UNSAFE);
+  Location locus;
+  if (!pratt_parse)
+    {
+      Location locus = lexer.peek_token ()->get_locus ();
+      skip_token (UNSAFE);
+    }
+  else
+    locus = lexer.peek_token ()->get_locus () - 1;
 
   // parse block expression (required)
   std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
@@ -12823,6 +12830,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
     case LEFT_SQUARE:
       // array definition expr (not indexing)
       return parse_array_expr (std::move (outer_attrs), true);
+    case UNSAFE:
+      return parse_unsafe_block_expr (std::move (outer_attrs), true);
     default:
       if (!restrictions.expr_can_be_null)
 	add_error (Error (tok->get_locus (),
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 1cd85eae8c2..1c7bd781b3f 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -504,8 +504,6 @@ private:
   AST::LoopLabel parse_loop_label ();
   std::unique_ptr<AST::AsyncBlockExpr>
   parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
-  std::unique_ptr<AST::UnsafeBlockExpr>
-  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
   std::unique_ptr<AST::GroupedExpr> parse_grouped_expr (AST::AttrVec outer_attrs
 							= AST::AttrVec ());
   std::unique_ptr<AST::ClosureExpr> parse_closure_expr (AST::AttrVec outer_attrs
@@ -522,6 +520,9 @@ private:
   std::unique_ptr<AST::ContinueExpr>
   parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
 		       bool pratt_parse = false);
+  std::unique_ptr<AST::UnsafeBlockExpr>
+  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+			   bool pratt_parse = false);
   std::unique_ptr<AST::ArrayExpr> parse_array_expr (AST::AttrVec outer_attrs
 						    = AST::AttrVec (),
 						    bool pratt_parse = false);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Using unsafe blocks in let expressions
  2021-07-21 21:09 Using unsafe blocks in let expressions Mark Wielaard
@ 2021-07-21 23:09 ` Mark Wielaard
  2021-07-23 11:23   ` Philip Herron
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Wielaard @ 2021-07-21 23:09 UTC (permalink / raw)
  To: gcc-rust

[-- Attachment #1: Type: text/plain, Size: 305 bytes --]

On Wed, Jul 21, 2021 at 11:09:38PM +0200, Mark Wielaard wrote:
> +  Location locus;
> +  if (!pratt_parse)
> +    {
> +      Location locus = lexer.peek_token ()->get_locus ();

Oops, shadowed locus.  Fixed patch attached, and also at
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=let-unsafe



[-- Attachment #2: 0001-unsafe-blocks-can-be-used-in-expressions.patch --]
[-- Type: text/x-diff, Size: 3068 bytes --]

From a7329b7fc0190920a9cf8bec77e34f2866b8af94 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Wed, 21 Jul 2021 22:41:04 +0200
Subject: [PATCH] unsafe blocks can be used in expressions

To use an unsafe block expression handle it in null_denotation for the
pratt parser. Adjust parse_unsafe_block_expr to take a pratt_parse
bool that defaults to false.
---
 gcc/rust/parse/rust-parse-impl.h | 15 ++++++++++++---
 gcc/rust/parse/rust-parse.h      |  5 +++--
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index eedc76db43e..bdf1e09a029 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -8704,10 +8704,17 @@ Parser<ManagedTokenSource>::parse_async_block_expr (AST::AttrVec outer_attrs)
 // Parses an unsafe block expression.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::UnsafeBlockExpr>
-Parser<ManagedTokenSource>::parse_unsafe_block_expr (AST::AttrVec outer_attrs)
+Parser<ManagedTokenSource>::parse_unsafe_block_expr (AST::AttrVec outer_attrs,
+						     bool pratt_parse)
 {
-  Location locus = lexer.peek_token ()->get_locus ();
-  skip_token (UNSAFE);
+  Location locus;
+  if (!pratt_parse)
+    {
+      locus = lexer.peek_token ()->get_locus ();
+      skip_token (UNSAFE);
+    }
+  else
+    locus = lexer.peek_token ()->get_locus () - 1;
 
   // parse block expression (required)
   std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
@@ -12823,6 +12830,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
     case LEFT_SQUARE:
       // array definition expr (not indexing)
       return parse_array_expr (std::move (outer_attrs), true);
+    case UNSAFE:
+      return parse_unsafe_block_expr (std::move (outer_attrs), true);
     default:
       if (!restrictions.expr_can_be_null)
 	add_error (Error (tok->get_locus (),
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 1cd85eae8c2..1c7bd781b3f 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -504,8 +504,6 @@ private:
   AST::LoopLabel parse_loop_label ();
   std::unique_ptr<AST::AsyncBlockExpr>
   parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
-  std::unique_ptr<AST::UnsafeBlockExpr>
-  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
   std::unique_ptr<AST::GroupedExpr> parse_grouped_expr (AST::AttrVec outer_attrs
 							= AST::AttrVec ());
   std::unique_ptr<AST::ClosureExpr> parse_closure_expr (AST::AttrVec outer_attrs
@@ -522,6 +520,9 @@ private:
   std::unique_ptr<AST::ContinueExpr>
   parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
 		       bool pratt_parse = false);
+  std::unique_ptr<AST::UnsafeBlockExpr>
+  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+			   bool pratt_parse = false);
   std::unique_ptr<AST::ArrayExpr> parse_array_expr (AST::AttrVec outer_attrs
 						    = AST::AttrVec (),
 						    bool pratt_parse = false);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Using unsafe blocks in let expressions
  2021-07-21 23:09 ` Mark Wielaard
@ 2021-07-23 11:23   ` Philip Herron
  0 siblings, 0 replies; 3+ messages in thread
From: Philip Herron @ 2021-07-23 11:23 UTC (permalink / raw)
  To: gcc-rust


[-- Attachment #1.1: Type: text/plain, Size: 1001 bytes --]


On 22/07/2021 00:09, Mark Wielaard wrote:
> On Wed, Jul 21, 2021 at 11:09:38PM +0200, Mark Wielaard wrote:
>> +  Location locus;
>> +  if (!pratt_parse)
>> +    {
>> +      Location locus = lexer.peek_token ()->get_locus ();
> Oops, shadowed locus.  Fixed patch attached, and also at
> https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=let-unsafe
>
>
>
This was merged yesterday https://github.com/Rust-GCC/gccrs/pull/582

I also merged a simple test case to show the parser is working
https://github.com/Rust-GCC/gccrs/pull/587

The final PR relating to this was:
https://github.com/Rust-GCC/gccrs/pull/589 in the type checker assumed
all dereference expressions were going to be for ReferenceTypes but this
extended it to support pointers. Some work is needed to ensure
derferences and union access outside of match expressions will emit an
error but this is a fairly simple change to make I will update a guide
on how to do this later.

Thanks again

--Phil



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 665 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-07-23 11:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-21 21:09 Using unsafe blocks in let expressions Mark Wielaard
2021-07-21 23:09 ` Mark Wielaard
2021-07-23 11:23   ` Philip Herron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).