Skip to content

Commit

Permalink
Handle incorrect and ambiguous use of pin sugar better
Browse files Browse the repository at this point in the history
  • Loading branch information
eholk committed Sep 20, 2024
1 parent c0746b9 commit 19eb307
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 25 deletions.
42 changes: 19 additions & 23 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,10 @@ impl<'a> Parser<'a> {
fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
let and_span = self.prev_token.span;
let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
let (pinned, mut mutbl) = self.parse_pin_and_mut();
let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
Some(pin_mut) => pin_mut,
None => (Pinnedness::Not, self.parse_mutability()),
};
if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
// it to be followed by a plus, but we disallow plus in the pointee type.
Expand Down Expand Up @@ -572,31 +575,24 @@ impl<'a> Parser<'a> {
/// Parses `pin` and `mut` annotations on references.
///
/// It must be either `pin const` or `pin mut`.
pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) {
let pinned = if self.eat(&TokenKind::Ident(sym::pin, IdentIsRaw::No)) {
Pinnedness::Pinned
} else {
Pinnedness::Not
};

if pinned == Pinnedness::Pinned {
self.psess.gated_spans.gate(sym::pin_ergonomics, self.prev_token.span);
}

match pinned {
Pinnedness::Pinned => {
if self.eat_keyword(kw::Const) {
(pinned, Mutability::Not)
} else if self.eat_keyword(kw::Mut) {
(pinned, Mutability::Mut)
pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
if self.token.is_ident_named(sym::pin) {
let result = self.look_ahead(1, |token| {
if token.is_keyword(kw::Const) {
Some((Pinnedness::Pinned, Mutability::Not))
} else if token.is_keyword(kw::Mut) {
Some((Pinnedness::Pinned, Mutability::Mut))
} else {
// FIXME: Emit an error here

// self.dcx().emit_err();
(pinned, Mutability::Not)
None
}
});
if result.is_some() {
self.bump();
self.bump();
}
Pinnedness::Not => (pinned, self.parse_mutability()),
result
} else {
None
}
}

Expand Down
15 changes: 15 additions & 0 deletions tests/ui/async-await/pin-sugar-ambiguity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ check-pass
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]

// Handle the case where there's ambiguity between pin as a contextual keyword and pin as a path.

struct Foo;

mod pin {
pub struct Foo;
}

fn main() {
let _x: &pin ::Foo = &pin::Foo;
}
8 changes: 8 additions & 0 deletions tests/ui/async-await/pin-sugar-no-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![feature(pin_ergonomics)]
#![allow(incomplete_features)]

// Makes sure we don't accidentally accept `&pin Foo` without the `const` keyword.

fn main() {
let _x: &pin i32 = todo!(); //~ ERROR found `i32`
}
15 changes: 15 additions & 0 deletions tests/ui/async-await/pin-sugar-no-const.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: expected one of `!`, `(`, `::`, `;`, `<`, or `=`, found `i32`
--> $DIR/pin-sugar-no-const.rs:7:18
|
LL | let _x: &pin i32 = todo!();
| - ^^^ expected one of `!`, `(`, `::`, `;`, `<`, or `=`
| |
| while parsing the type for `_x`
|
help: there is a keyword `in` with a similar name
|
LL | let _x: &in i32 = todo!();
| ~~

error: aborting due to 1 previous error

File renamed without changes.
5 changes: 3 additions & 2 deletions tests/ui/feature-gates/feature-gate-pin_ergonomics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ use std::pin::Pin;

struct Foo;

fn foo(_: Pin<&mut Foo>) {
}
fn foo(_: &pin mut Foo) {}

fn bar(mut x: Pin<&mut Foo>) {
foo(x);
foo(x); //~ ERROR use of moved value: `x`
}

fn baz(_: &pin Foo) {}

fn main() {}

0 comments on commit 19eb307

Please sign in to comment.