From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gnu.wildebeest.org (wildebeest.demon.nl [212.238.236.112]) by sourceware.org (Postfix) with ESMTPS id 1561E383D827 for ; Wed, 21 Jul 2021 21:09:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1561E383D827 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=klomp.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=klomp.org Received: from reform (deer0x18.wildebeest.org [172.31.17.154]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id 9DAA3300066F for ; Wed, 21 Jul 2021 23:09:38 +0200 (CEST) Received: by reform (Postfix, from userid 1000) id 273EC2E8071C; Wed, 21 Jul 2021 23:09:38 +0200 (CEST) Date: Wed, 21 Jul 2021 23:09:38 +0200 From: Mark Wielaard To: gcc-rust@gcc.gnu.org Subject: Using unsafe blocks in let expressions Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="NokW1il9uX58uNbn" Content-Disposition: inline X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-rust@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: gcc-rust mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Jul 2021 21:09:44 -0000 --NokW1il9uX58uNbn Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 and 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 --NokW1il9uX58uNbn Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0001-unsafe-blocks-can-be-used-in-expressions.patch" >From 3e9c4eff383cd1a23a148f5a7d556345b7972e26 Mon Sep 17 00:00:00 2001 From: Mark Wielaard 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::parse_async_block_expr (AST::AttrVec outer_attrs) // Parses an unsafe block expression. template std::unique_ptr -Parser::parse_unsafe_block_expr (AST::AttrVec outer_attrs) +Parser::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 block_expr = parse_block_expr (); @@ -12823,6 +12830,8 @@ Parser::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 parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); - std::unique_ptr - parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); std::unique_ptr parse_grouped_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); std::unique_ptr parse_closure_expr (AST::AttrVec outer_attrs @@ -522,6 +520,9 @@ private: std::unique_ptr parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (), bool pratt_parse = false); + std::unique_ptr + parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + bool pratt_parse = false); std::unique_ptr parse_array_expr (AST::AttrVec outer_attrs = AST::AttrVec (), bool pratt_parse = false); -- 2.32.0 --NokW1il9uX58uNbn--