Skip to content

Commit d9ef8d8

Browse files
committed
view-types: store borrows of view types in the AST
1 parent 82a8e58 commit d9ef8d8

35 files changed

Lines changed: 431 additions & 191 deletions

File tree

compiler/rustc_ast/src/ast.rs

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -646,8 +646,10 @@ impl Pat {
646646
PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
647647
// `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
648648
PatKind::Ref(pat, pinned, mutbl) => pat.to_ty().map(|ty| match pinned {
649-
Pinnedness::Not => TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }),
650-
Pinnedness::Pinned => TyKind::PinnedRef(None, MutTy { ty, mutbl: *mutbl }),
649+
Pinnedness::Not => TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }, ViewKind::Full),
650+
Pinnedness::Pinned => {
651+
TyKind::PinnedRef(None, MutTy { ty, mutbl: *mutbl }, ViewKind::Full)
652+
}
651653
})?,
652654
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
653655
// when `P` can be reparsed as a type `T`.
@@ -1510,9 +1512,9 @@ impl Expr {
15101512

15111513
ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
15121514

1513-
ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => {
1514-
expr.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))?
1515-
}
1515+
ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => expr
1516+
.to_ty()
1517+
.map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }, ViewKind::Full))?,
15161518

15171519
ExprKind::Repeat(expr, expr_len) => {
15181520
expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?
@@ -2473,7 +2475,8 @@ impl From<Box<Ty>> for Ty {
24732475
impl Ty {
24742476
pub fn peel_refs(&self) -> &Self {
24752477
let mut final_ty = self;
2476-
while let TyKind::Ref(_, MutTy { ty, .. }) | TyKind::Ptr(MutTy { ty, .. }) = &final_ty.kind
2478+
while let TyKind::Ref(_, MutTy { ty, .. }, _) | TyKind::Ptr(MutTy { ty, .. }) =
2479+
&final_ty.kind
24772480
{
24782481
final_ty = ty;
24792482
}
@@ -2518,11 +2521,11 @@ pub enum TyKind {
25182521
/// A raw pointer (`*const T` or `*mut T`).
25192522
Ptr(MutTy),
25202523
/// A reference (`&'a T` or `&'a mut T`).
2521-
Ref(#[visitable(extra = LifetimeCtxt::Ref)] Option<Lifetime>, MutTy),
2524+
Ref(#[visitable(extra = LifetimeCtxt::Ref)] Option<Lifetime>, MutTy, ViewKind),
25222525
/// A pinned reference (`&'a pin const T` or `&'a pin mut T`).
25232526
///
25242527
/// Desugars into `Pin<&'a T>` or `Pin<&'a mut T>`.
2525-
PinnedRef(#[visitable(extra = LifetimeCtxt::Ref)] Option<Lifetime>, MutTy),
2528+
PinnedRef(#[visitable(extra = LifetimeCtxt::Ref)] Option<Lifetime>, MutTy, ViewKind),
25262529
/// A function pointer type (e.g., `fn(usize) -> bool`).
25272530
FnPtr(Box<FnPtrTy>),
25282531
/// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`).
@@ -2660,6 +2663,21 @@ pub enum TraitObjectSyntax {
26602663
None = 1,
26612664
}
26622665

2666+
/// Represents how a reference is viewed.
2667+
// FIXME(scrabsha): move this to a new variant of `Mutabiliy` when viewing of non-reference types
2668+
// is implemented.
2669+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
2670+
pub enum ViewKind {
2671+
/// `&mut T`. All the fields can be observed.
2672+
Full,
2673+
/// `&mut T.{ foo, bar }`. Only `foo` and `bar` can be observed.
2674+
Partial {
2675+
span: Span,
2676+
#[visitable(ignore)]
2677+
fields: ThinVec<Ident>,
2678+
},
2679+
}
2680+
26632681
/// SAFETY: `TraitObjectSyntax` only has 3 data-less variants which means
26642682
/// it can be represented with a `u2`. We use `repr(u8)` to guarantee the
26652683
/// discriminants of the variants are no greater than `3`.
@@ -2933,21 +2951,21 @@ pub struct Param {
29332951
pub enum SelfKind {
29342952
/// `self`, `mut self`
29352953
Value(Mutability),
2936-
/// `&'lt self`, `&'lt mut self`
2937-
Region(Option<Lifetime>, Mutability),
2938-
/// `&'lt pin const self`, `&'lt pin mut self`
2939-
Pinned(Option<Lifetime>, Mutability),
2954+
/// `&'lt self`, `&'lt mut self`, `&'lt mut self.{ a, b }`
2955+
Region(Option<Lifetime>, Mutability, ViewKind),
2956+
/// `&'lt pin const self`, `&'lt pin mut self`, `&'lt pin mut self.{ a, b }`.
2957+
Pinned(Option<Lifetime>, Mutability, ViewKind),
29402958
/// `self: TYPE`, `mut self: TYPE`
29412959
Explicit(Box<Ty>, Mutability),
29422960
}
29432961

29442962
impl SelfKind {
29452963
pub fn to_ref_suggestion(&self) -> String {
29462964
match self {
2947-
SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(),
2948-
SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()),
2949-
SelfKind::Pinned(None, mutbl) => format!("&pin {}", mutbl.ptr_str()),
2950-
SelfKind::Pinned(Some(lt), mutbl) => format!("&{lt} pin {}", mutbl.ptr_str()),
2965+
SelfKind::Region(None, mutbl, _) => mutbl.ref_prefix_str().to_string(),
2966+
SelfKind::Region(Some(lt), mutbl, _) => format!("&{lt} {}", mutbl.prefix_str()),
2967+
SelfKind::Pinned(None, mutbl, _) => format!("&pin {}", mutbl.ptr_str()),
2968+
SelfKind::Pinned(Some(lt), mutbl, _) => format!("&{lt} pin {}", mutbl.ptr_str()),
29512969
SelfKind::Value(_) | SelfKind::Explicit(_, _) => {
29522970
unreachable!("if we had an explicit self, we wouldn't be here")
29532971
}
@@ -2964,13 +2982,15 @@ impl Param {
29642982
if ident.name == kw::SelfLower {
29652983
return match self.ty.kind {
29662984
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
2967-
TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
2968-
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
2985+
TyKind::Ref(lt, MutTy { ref ty, mutbl }, ref view)
2986+
if ty.kind.is_implicit_self() =>
2987+
{
2988+
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl, view.clone())))
29692989
}
2970-
TyKind::PinnedRef(lt, MutTy { ref ty, mutbl })
2990+
TyKind::PinnedRef(lt, MutTy { ref ty, mutbl }, ref view)
29712991
if ty.kind.is_implicit_self() =>
29722992
{
2973-
Some(respan(self.pat.span, SelfKind::Pinned(lt, mutbl)))
2993+
Some(respan(self.pat.span, SelfKind::Pinned(lt, mutbl, view.clone())))
29742994
}
29752995
_ => Some(respan(
29762996
self.pat.span.to(self.ty.span),
@@ -3003,20 +3023,20 @@ impl Param {
30033023
let (mutbl, ty) = match eself.node {
30043024
SelfKind::Explicit(ty, mutbl) => (mutbl, ty),
30053025
SelfKind::Value(mutbl) => (mutbl, infer_ty),
3006-
SelfKind::Region(lt, mutbl) => (
3026+
SelfKind::Region(lt, mutbl, views) => (
30073027
Mutability::Not,
30083028
Box::new(Ty {
30093029
id: DUMMY_NODE_ID,
3010-
kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }),
3030+
kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }, views),
30113031
span,
30123032
tokens: None,
30133033
}),
30143034
),
3015-
SelfKind::Pinned(lt, mutbl) => (
3035+
SelfKind::Pinned(lt, mutbl, view) => (
30163036
mutbl,
30173037
Box::new(Ty {
30183038
id: DUMMY_NODE_ID,
3019-
kind: TyKind::PinnedRef(lt, MutTy { ty: infer_ty, mutbl }),
3039+
kind: TyKind::PinnedRef(lt, MutTy { ty: infer_ty, mutbl }, view),
30203040
span,
30213041
tokens: None,
30223042
}),
@@ -4340,7 +4360,7 @@ mod size_asserts {
43404360
static_assert_size!(Stmt, 32);
43414361
static_assert_size!(StmtKind, 16);
43424362
static_assert_size!(TraitImplHeader, 72);
4343-
static_assert_size!(Ty, 64);
4344-
static_assert_size!(TyKind, 40);
4363+
static_assert_size!(Ty, 80);
4364+
static_assert_size!(TyKind, 56);
43454365
// tidy-alphabetical-end
43464366
}

compiler/rustc_ast/src/util/classify.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Routines the parser and pretty-printer use to classify AST nodes.
22
3+
use crate::ViewKind;
34
use crate::ast::ExprKind::*;
45
use crate::ast::{self, MatchKind};
56
use crate::token::Delimiter;
@@ -167,6 +168,8 @@ pub enum TrailingBrace<'a> {
167168
/// Trailing brace in any other expression, such as `a + B {}`. We will
168169
/// suggest wrapping the innermost expression in parentheses: `a + (B {})`.
169170
Expr(&'a ast::Expr),
171+
/// Trailing brace in a type, like the one in `&Foo. { bar }`
172+
Type(&'a ast::Ty),
170173
}
171174

172175
/// If an expression ends with `}`, returns the innermost expression ending in the `}`
@@ -205,7 +208,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
205208
| ConstBlock(_) => break Some(TrailingBrace::Expr(expr)),
206209

207210
Cast(_, ty) => {
208-
break type_trailing_braced_mac_call(ty).map(TrailingBrace::MacCall);
211+
break type_trailing_brace(ty);
209212
}
210213

211214
MacCall(mac) => {
@@ -246,21 +249,30 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
246249
}
247250
}
248251

249-
/// If the type's last token is `}`, it must be due to a braced macro call, such
250-
/// as in `*const brace! { ... }`. Returns that trailing macro call.
251-
fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
252+
/// If a type ends with `}`, return the innermost node ending with the `}`.
253+
///
254+
/// This may be caused by a macro call (`*const brace! { ... }`) or a view type
255+
/// (`&Foo.{ bar }`).
256+
fn type_trailing_brace(mut ty: &ast::Ty) -> Option<TrailingBrace<'_>> {
252257
loop {
253258
match &ty.kind {
254259
ast::TyKind::MacCall(mac) => {
255-
break (mac.args.delim == Delimiter::Brace).then_some(mac);
260+
break (mac.args.delim == Delimiter::Brace)
261+
.then_some(mac.as_ref())
262+
.map(TrailingBrace::MacCall);
256263
}
257264

258265
ast::TyKind::Ptr(mut_ty)
259-
| ast::TyKind::Ref(_, mut_ty)
260-
| ast::TyKind::PinnedRef(_, mut_ty) => {
266+
| ast::TyKind::Ref(_, mut_ty, ViewKind::Full)
267+
| ast::TyKind::PinnedRef(_, mut_ty, ViewKind::Full) => {
261268
ty = &mut_ty.ty;
262269
}
263270

271+
ast::TyKind::Ref(_, _, ViewKind::Partial { .. })
272+
| ast::TyKind::PinnedRef(_, _, ViewKind::Partial { .. }) => {
273+
break Some(TrailingBrace::Type(ty));
274+
}
275+
264276
ast::TyKind::UnsafeBinder(binder) => {
265277
ty = &binder.inner_ty;
266278
}

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ macro_rules! common_visitor_and_walkers {
486486
UnsafeBinderTy,
487487
UnsafeSource,
488488
UseTreeKind,
489+
ViewKind,
489490
VisibilityKind,
490491
WhereBoundPredicate,
491492
WhereClause,

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,11 +1413,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
14131413
TyKind::Err(guar) => hir::TyKind::Err(*guar),
14141414
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty_alloc(ty, itctx)),
14151415
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
1416-
TyKind::Ref(region, mt) => {
1416+
TyKind::Ref(region, mt, _) => {
14171417
let lifetime = self.lower_ty_direct_lifetime(t, *region);
14181418
hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))
14191419
}
1420-
TyKind::PinnedRef(region, mt) => {
1420+
TyKind::PinnedRef(region, mt, _) => {
14211421
let lifetime = self.lower_ty_direct_lifetime(t, *region);
14221422
let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));
14231423
let span = self.lower_span(t.span);
@@ -1841,7 +1841,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
18411841
// Given we are only considering `ImplicitSelf` types, we needn't consider
18421842
// the case where we have a mutable pattern to a reference as that would
18431843
// no longer be an `ImplicitSelf`.
1844-
TyKind::Ref(_, mt) | TyKind::PinnedRef(_, mt)
1844+
TyKind::Ref(_, mt, _) | TyKind::PinnedRef(_, mt, _)
18451845
if mt.ty.kind.is_implicit_self() =>
18461846
{
18471847
match mt.mutbl {

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_ast::util::comments::{Comment, CommentStyle};
1717
use rustc_ast::{
1818
self as ast, AttrArgs, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg, GenericBound,
1919
InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, PatKind,
20-
RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
20+
RangeEnd, RangeSyntax, Safety, SelfKind, Term, ViewKind, attr,
2121
};
2222
use rustc_span::edition::Edition;
2323
use rustc_span::source_map::SourceMap;
@@ -1255,6 +1255,16 @@ impl<'a> State<'a> {
12551255
}
12561256
}
12571257

1258+
fn print_view(&mut self, view: &ViewKind) {
1259+
if let ViewKind::Partial { fields, .. } = view {
1260+
self.word_space(".{");
1261+
self.commasep(Breaks::Inconsistent, fields, |s, field| {
1262+
s.print_ident(*field);
1263+
});
1264+
self.word_space(" }");
1265+
}
1266+
}
1267+
12581268
pub fn print_assoc_item_constraint(&mut self, constraint: &ast::AssocItemConstraint) {
12591269
self.print_ident(constraint.ident);
12601270
if let Some(args) = constraint.gen_args.as_ref() {
@@ -1333,16 +1343,18 @@ impl<'a> State<'a> {
13331343
self.word("*");
13341344
self.print_mt(mt, true);
13351345
}
1336-
ast::TyKind::Ref(lifetime, mt) => {
1346+
ast::TyKind::Ref(lifetime, mt, view) => {
13371347
self.word("&");
13381348
self.print_opt_lifetime(lifetime);
13391349
self.print_mt(mt, false);
1350+
self.print_view(view);
13401351
}
1341-
ast::TyKind::PinnedRef(lifetime, mt) => {
1352+
ast::TyKind::PinnedRef(lifetime, mt, view) => {
13421353
self.word("&");
13431354
self.print_opt_lifetime(lifetime);
13441355
self.word("pin ");
13451356
self.print_mt(mt, true);
1357+
self.print_view(view);
13461358
}
13471359
ast::TyKind::Never => {
13481360
self.word("!");
@@ -2056,26 +2068,28 @@ impl<'a> State<'a> {
20562068
match &explicit_self.node {
20572069
SelfKind::Value(m) => {
20582070
self.print_mutability(*m, false);
2059-
self.word("self")
2071+
self.word("self");
20602072
}
2061-
SelfKind::Region(lt, m) => {
2073+
SelfKind::Region(lt, m, view) => {
20622074
self.word("&");
20632075
self.print_opt_lifetime(lt);
20642076
self.print_mutability(*m, false);
2065-
self.word("self")
2077+
self.word("self");
2078+
self.print_view(view);
20662079
}
2067-
SelfKind::Pinned(lt, m) => {
2080+
SelfKind::Pinned(lt, m, view) => {
20682081
self.word("&");
20692082
self.print_opt_lifetime(lt);
20702083
self.word("pin ");
20712084
self.print_mutability(*m, true);
2072-
self.word("self")
2085+
self.word("self");
2086+
self.print_view(view);
20732087
}
20742088
SelfKind::Explicit(typ, m) => {
20752089
self.print_mutability(*m, false);
20762090
self.word("self");
20772091
self.word_space(":");
2078-
self.print_type(typ)
2092+
self.print_type(typ);
20792093
}
20802094
}
20812095
}

compiler/rustc_ast_pretty/src/pprust/tests.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ fn variant_to_string(var: &ast::Variant) -> String {
2222
to_string(|s| s.print_variant(var))
2323
}
2424

25+
fn ty_to_string(ty: &ast::Ty) -> String {
26+
to_string(|s| {
27+
s.print_type(ty);
28+
})
29+
}
30+
2531
#[test]
2632
fn test_fun_to_string() {
2733
create_default_session_globals_then(|| {
@@ -60,3 +66,36 @@ fn test_variant_to_string() {
6066
assert_eq!(varstr, "principal_skinner");
6167
})
6268
}
69+
70+
#[test]
71+
fn test_field_view() {
72+
create_default_session_globals_then(|| {
73+
let ty = ast::Ty {
74+
id: ast::DUMMY_NODE_ID,
75+
kind: ast::TyKind::Ref(
76+
None,
77+
ast::MutTy {
78+
ty: Box::new(ast::Ty {
79+
id: ast::DUMMY_NODE_ID,
80+
kind: ast::TyKind::Dummy,
81+
span: DUMMY_SP,
82+
tokens: None,
83+
}),
84+
mutbl: ast::Mutability::Mut,
85+
},
86+
ast::ViewKind::Partial {
87+
span: DUMMY_SP,
88+
fields: thin_vec::thin_vec![
89+
Ident::from_str("milhouse"),
90+
Ident::from_str("apu")
91+
],
92+
},
93+
),
94+
span: DUMMY_SP,
95+
tokens: None,
96+
};
97+
98+
let ty_str = ty_to_string(&ty);
99+
assert_eq!(ty_str, "&mut (/*DUMMY*/).{ milhouse, apu }");
100+
});
101+
}

0 commit comments

Comments
 (0)