Implement &pin const self and &pin mut self sugars
This commit is contained in:
@@ -2641,6 +2641,8 @@ pub enum SelfKind {
|
||||
Value(Mutability),
|
||||
/// `&'lt self`, `&'lt mut self`
|
||||
Region(Option<Lifetime>, Mutability),
|
||||
/// `&'lt pin const self`, `&'lt pin mut self`
|
||||
Pinned(Option<Lifetime>, Mutability),
|
||||
/// `self: TYPE`, `mut self: TYPE`
|
||||
Explicit(P<Ty>, Mutability),
|
||||
}
|
||||
@@ -2650,6 +2652,8 @@ impl SelfKind {
|
||||
match self {
|
||||
SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(),
|
||||
SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()),
|
||||
SelfKind::Pinned(None, mutbl) => format!("&pin {}", mutbl.ptr_str()),
|
||||
SelfKind::Pinned(Some(lt), mutbl) => format!("&{lt} pin {}", mutbl.ptr_str()),
|
||||
SelfKind::Value(_) | SelfKind::Explicit(_, _) => {
|
||||
unreachable!("if we had an explicit self, we wouldn't be here")
|
||||
}
|
||||
@@ -2666,11 +2670,13 @@ impl Param {
|
||||
if ident.name == kw::SelfLower {
|
||||
return match self.ty.kind {
|
||||
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
||||
TyKind::Ref(lt, MutTy { ref ty, mutbl })
|
||||
| TyKind::PinnedRef(lt, MutTy { ref ty, mutbl })
|
||||
TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
|
||||
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
|
||||
}
|
||||
TyKind::PinnedRef(lt, MutTy { ref ty, mutbl })
|
||||
if ty.kind.is_implicit_self() =>
|
||||
{
|
||||
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
|
||||
Some(respan(self.pat.span, SelfKind::Pinned(lt, mutbl)))
|
||||
}
|
||||
_ => Some(respan(
|
||||
self.pat.span.to(self.ty.span),
|
||||
@@ -2712,6 +2718,15 @@ impl Param {
|
||||
tokens: None,
|
||||
}),
|
||||
),
|
||||
SelfKind::Pinned(lt, mutbl) => (
|
||||
mutbl,
|
||||
P(Ty {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: TyKind::PinnedRef(lt, MutTy { ty: infer_ty, mutbl }),
|
||||
span,
|
||||
tokens: None,
|
||||
}),
|
||||
),
|
||||
};
|
||||
Param {
|
||||
attrs,
|
||||
|
||||
@@ -1783,6 +1783,13 @@ impl<'a> State<'a> {
|
||||
self.print_mutability(*m, false);
|
||||
self.word("self")
|
||||
}
|
||||
SelfKind::Pinned(lt, m) => {
|
||||
self.word("&");
|
||||
self.print_opt_lifetime(lt);
|
||||
self.word("pin ");
|
||||
self.print_mutability(*m, true);
|
||||
self.word("self")
|
||||
}
|
||||
SelfKind::Explicit(typ, m) => {
|
||||
self.print_mutability(*m, false);
|
||||
self.word("self");
|
||||
|
||||
@@ -2959,9 +2959,20 @@ impl<'a> Parser<'a> {
|
||||
this.is_keyword_ahead(n, &[kw::SelfLower])
|
||||
&& this.look_ahead(n + 1, |t| t != &token::PathSep)
|
||||
};
|
||||
// Is `pin const self` `n` tokens ahead?
|
||||
let is_isolated_pin_const_self = |this: &Self, n| {
|
||||
this.look_ahead(n, |token| token.is_ident_named(sym::pin))
|
||||
&& this.is_keyword_ahead(n + 1, &[kw::Const])
|
||||
&& is_isolated_self(this, n + 2)
|
||||
};
|
||||
// Is `mut self` `n` tokens ahead?
|
||||
let is_isolated_mut_self =
|
||||
|this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
|
||||
// Is `pin mut self` `n` tokens ahead?
|
||||
let is_isolated_pin_mut_self = |this: &Self, n| {
|
||||
this.look_ahead(n, |token| token.is_ident_named(sym::pin))
|
||||
&& is_isolated_mut_self(this, n + 1)
|
||||
};
|
||||
// Parse `self` or `self: TYPE`. We already know the current token is `self`.
|
||||
let parse_self_possibly_typed = |this: &mut Self, m| {
|
||||
let eself_ident = expect_self_ident(this);
|
||||
@@ -3021,6 +3032,20 @@ impl<'a> Parser<'a> {
|
||||
self.bump();
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Mut)
|
||||
} else if is_isolated_pin_const_self(self, 1) {
|
||||
// `&pin const self`
|
||||
self.bump(); // &
|
||||
self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
|
||||
self.bump(); // pin
|
||||
self.bump(); // const
|
||||
SelfKind::Pinned(None, Mutability::Not)
|
||||
} else if is_isolated_pin_mut_self(self, 1) {
|
||||
// `&pin mut self`
|
||||
self.bump(); // &
|
||||
self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
|
||||
self.bump(); // pin
|
||||
self.bump(); // mut
|
||||
SelfKind::Pinned(None, Mutability::Mut)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) {
|
||||
// `&'lt self`
|
||||
self.bump();
|
||||
@@ -3032,6 +3057,26 @@ impl<'a> Parser<'a> {
|
||||
let lt = self.expect_lifetime();
|
||||
self.bump();
|
||||
SelfKind::Region(Some(lt), Mutability::Mut)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime())
|
||||
&& is_isolated_pin_const_self(self, 2)
|
||||
{
|
||||
// `&'lt pin const self`
|
||||
self.bump(); // &
|
||||
let lt = self.expect_lifetime();
|
||||
self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
|
||||
self.bump(); // pin
|
||||
self.bump(); // const
|
||||
SelfKind::Pinned(Some(lt), Mutability::Not)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime())
|
||||
&& is_isolated_pin_mut_self(self, 2)
|
||||
{
|
||||
// `&'lt pin mut self`
|
||||
self.bump(); // &
|
||||
let lt = self.expect_lifetime();
|
||||
self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
|
||||
self.bump(); // pin
|
||||
self.bump(); // mut
|
||||
SelfKind::Pinned(Some(lt), Mutability::Mut)
|
||||
} else {
|
||||
// `¬_self`
|
||||
return Ok(None);
|
||||
|
||||
Reference in New Issue
Block a user