Skip to content

Commit bd45002

Browse files
committed
Add sugar for &pin (const|mut) types
1 parent a18800f commit bd45002

File tree

23 files changed

+243
-41
lines changed

23 files changed

+243
-41
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
use std::borrow::Cow;
2222
use std::{cmp, fmt, mem};
2323

24-
pub use rustc_ast_ir::{Movability, Mutability};
24+
pub use rustc_ast_ir::{Movability, Mutability, Pinnedness};
2525
use rustc_data_structures::packed::Pu128;
2626
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
2727
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -2159,6 +2159,8 @@ pub enum TyKind {
21592159
Ptr(MutTy),
21602160
/// A reference (`&'a T` or `&'a mut T`).
21612161
Ref(Option<Lifetime>, MutTy),
2162+
/// A pinned reference (`&'a pin const T` or `&'a pin mut T`).
2163+
PinnedRef(Option<Lifetime>, MutTy),
21622164
/// A bare function (e.g., `fn(usize) -> bool`).
21632165
BareFn(P<BareFnTy>),
21642166
/// The never type (`!`).
@@ -2481,7 +2483,10 @@ impl Param {
24812483
if ident.name == kw::SelfLower {
24822484
return match self.ty.kind {
24832485
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
2484-
TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
2486+
TyKind::Ref(lt, MutTy { ref ty, mutbl })
2487+
| TyKind::PinnedRef(lt, MutTy { ref ty, mutbl })
2488+
if ty.kind.is_implicit_self() =>
2489+
{
24852490
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
24862491
}
24872492
_ => Some(respan(

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
485485
}
486486
TyKind::Slice(ty) => vis.visit_ty(ty),
487487
TyKind::Ptr(mt) => vis.visit_mt(mt),
488-
TyKind::Ref(lt, mt) => {
488+
TyKind::Ref(lt, mt) | TyKind::PinnedRef(lt, mt) => {
489489
visit_opt(lt, |lt| vis.visit_lifetime(lt));
490490
vis.visit_mt(mt);
491491
}

compiler/rustc_ast/src/util/classify.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,9 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
247247
break (mac.args.delim == Delimiter::Brace).then_some(mac);
248248
}
249249

250-
ast::TyKind::Ptr(mut_ty) | ast::TyKind::Ref(_, mut_ty) => {
250+
ast::TyKind::Ptr(mut_ty)
251+
| ast::TyKind::Ref(_, mut_ty)
252+
| ast::TyKind::PinnedRef(_, mut_ty) => {
251253
ty = &mut_ty.ty;
252254
}
253255

compiler/rustc_ast/src/visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
499499
match kind {
500500
TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
501501
TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)),
502-
TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ }) => {
502+
TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ })
503+
| TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => {
503504
visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
504505
try_visit!(visitor.visit_ty(ty));
505506
}

compiler/rustc_ast_ir/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,10 @@ impl Mutability {
7979
matches!(self, Self::Not)
8080
}
8181
}
82+
83+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
84+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
85+
pub enum Pinnedness {
86+
Not,
87+
Pinned,
88+
}

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
638638
self.lower_span(span),
639639
Some(self.allow_gen_future.clone()),
640640
);
641-
let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span);
641+
let resume_ty =
642+
self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None);
642643
let input_ty = hir::Ty {
643644
hir_id: self.next_id(),
644645
kind: hir::TyKind::Path(resume_ty),
@@ -2063,7 +2064,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
20632064
lang_item: hir::LangItem,
20642065
name: Symbol,
20652066
) -> hir::Expr<'hir> {
2066-
let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span));
2067+
let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span), None);
20672068
let path = hir::ExprKind::Path(hir::QPath::TypeRelative(
20682069
self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))),
20692070
self.arena.alloc(hir::PathSegment::new(

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
5555
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5656
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
5757
use rustc_hir::{
58-
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName,
59-
TraitCandidate,
58+
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, MissingLifetimeKind,
59+
ParamName, TraitCandidate,
6060
};
6161
use rustc_index::{Idx, IndexSlice, IndexVec};
6262
use rustc_macros::extension;
@@ -756,8 +756,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
756756
res
757757
}
758758

759-
fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> {
760-
hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, None))
759+
fn make_lang_item_qpath(
760+
&mut self,
761+
lang_item: hir::LangItem,
762+
span: Span,
763+
args: Option<&'hir hir::GenericArgs<'hir>>,
764+
) -> hir::QPath<'hir> {
765+
hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, args))
761766
}
762767

763768
fn make_lang_item_path(
@@ -1300,6 +1305,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13001305
let lifetime = self.lower_lifetime(&region);
13011306
hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))
13021307
}
1308+
TyKind::PinnedRef(region, mt) => {
1309+
let region = region.unwrap_or_else(|| {
1310+
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
1311+
self.resolver.get_lifetime_res(t.id)
1312+
{
1313+
debug_assert_eq!(start.plus(1), end);
1314+
start
1315+
} else {
1316+
self.next_node_id()
1317+
};
1318+
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
1319+
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
1320+
});
1321+
let lifetime = self.lower_lifetime(&region);
1322+
let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));
1323+
let span = self.lower_span(t.span);
1324+
let arg = hir::Ty { kind, span, hir_id: self.next_id() };
1325+
let args = self.arena.alloc(hir::GenericArgs {
1326+
args: self.arena.alloc([hir::GenericArg::Type(self.arena.alloc(arg))]),
1327+
constraints: &[],
1328+
parenthesized: hir::GenericArgsParentheses::No,
1329+
span_ext: span,
1330+
});
1331+
let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
1332+
hir::TyKind::Path(path)
1333+
}
13031334
TyKind::BareFn(f) => {
13041335
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
13051336
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
@@ -1882,10 +1913,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
18821913
// Given we are only considering `ImplicitSelf` types, we needn't consider
18831914
// the case where we have a mutable pattern to a reference as that would
18841915
// no longer be an `ImplicitSelf`.
1885-
TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl {
1886-
hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,
1887-
hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,
1888-
},
1916+
TyKind::Ref(_, mt) | TyKind::PinnedRef(_, mt)
1917+
if mt.ty.kind.is_implicit_self() =>
1918+
{
1919+
match mt.mutbl {
1920+
hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,
1921+
hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,
1922+
}
1923+
}
18891924
_ => hir::ImplicitSelfKind::None,
18901925
}
18911926
}),

compiler/rustc_ast_lowering/src/lifetime_collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
9595
visit::walk_ty(self, t);
9696
self.current_binders.pop();
9797
}
98-
TyKind::Ref(None, _) => {
98+
TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
9999
self.record_elided_anchor(t.id, t.span);
100100
visit::walk_ty(self, t);
101101
}

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
545545
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
546546
gate_all!(global_registration, "global registration is experimental");
547547
gate_all!(return_type_notation, "return type notation is experimental");
548+
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
548549

549550
if !visitor.features.never_patterns {
550551
if let Some(spans) = spans.get(&sym::never_patterns) {

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,12 @@ impl<'a> State<'a> {
11631163
self.print_opt_lifetime(lifetime);
11641164
self.print_mt(mt, false);
11651165
}
1166+
ast::TyKind::PinnedRef(lifetime, mt) => {
1167+
self.word("&");
1168+
self.print_opt_lifetime(lifetime);
1169+
self.word("pin ");
1170+
self.print_mt(mt, true);
1171+
}
11661172
ast::TyKind::Never => {
11671173
self.word("!");
11681174
}

0 commit comments

Comments
 (0)