Skip to content

Commit dcdf133

Browse files
committed
view-types: store view types in the AST
1 parent 0e252df commit dcdf133

34 files changed

Lines changed: 243 additions & 204 deletions

File tree

compiler/rustc_ast/src/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2564,6 +2564,8 @@ pub enum TyKind {
25642564
/// Usually not written directly in user code but indirectly via the macro
25652565
/// `core::field::field_of!(...)`.
25662566
FieldOf(Box<Ty>, Option<Ident>, Ident),
2567+
/// A view of a type. `T.{ field_1, field_2 }`.
2568+
View(Box<Ty>, #[visitable(ignore)] ThinVec<Ident>),
25672569
/// Sometimes we need a dummy value when no error has occurred.
25682570
Dummy,
25692571
/// Placeholder for a kind that has failed to be defined.

compiler/rustc_ast/src/util/classify.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
302302
| ast::TyKind::Pat(..)
303303
| ast::TyKind::FieldOf(..)
304304
| ast::TyKind::Dummy
305-
| ast::TyKind::Err(..) => break None,
305+
| ast::TyKind::Err(..)
306+
| ast::TyKind::View(..) => break None,
306307
}
307308
}
308309
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
17071707
);
17081708
hir::TyKind::Err(guar)
17091709
}
1710+
TyKind::View(ty, _) => {
1711+
// FIXME(scrabsha): lower view types to HIR.
1712+
return self.lower_ty(ty, itctx);
1713+
}
17101714
TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"),
17111715
};
17121716

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
285285
ast::TyKind::Pat(..) => {
286286
gate!(self, pattern_types, ty.span, "pattern types are unstable");
287287
}
288+
ast::TyKind::View(..) => {
289+
gate!(self, view_types, ty.span, "view types are unstable");
290+
}
288291
_ => {}
289292
}
290293
visit::walk_ty(self, ty)

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,20 @@ impl<'a> State<'a> {
12591259
}
12601260
}
12611261

1262+
fn print_view(&mut self, fields: &[Ident]) {
1263+
self.word(".{");
1264+
1265+
if !fields.is_empty() {
1266+
self.space();
1267+
self.commasep(Consistent, fields, |s, field| {
1268+
s.print_ident(*field);
1269+
});
1270+
self.space();
1271+
}
1272+
1273+
self.word("}");
1274+
}
1275+
12621276
pub fn print_assoc_item_constraint(&mut self, constraint: &ast::AssocItemConstraint) {
12631277
self.print_ident(constraint.ident);
12641278
if let Some(args) = constraint.gen_args.as_ref() {
@@ -1441,6 +1455,10 @@ impl<'a> State<'a> {
14411455
self.end(ib);
14421456
self.pclose();
14431457
}
1458+
ast::TyKind::View(ty, fields) => {
1459+
self.print_type(ty);
1460+
self.print_view(fields);
1461+
}
14441462
}
14451463
self.end(ib);
14461464
}

compiler/rustc_ast_pretty/src/pprust/tests.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_ast as ast;
22
use rustc_span::{DUMMY_SP, Ident, create_default_session_globals_then};
3-
use thin_vec::ThinVec;
3+
use thin_vec::{ThinVec, thin_vec};
44

55
use super::*;
66

@@ -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,26 @@ 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::View(
76+
Box::new(ast::Ty {
77+
id: ast::DUMMY_NODE_ID,
78+
kind: ast::TyKind::Dummy,
79+
span: DUMMY_SP,
80+
tokens: None,
81+
}),
82+
thin_vec![Ident::from_str("milhouse"), Ident::from_str("apu")],
83+
),
84+
span: DUMMY_SP,
85+
tokens: None,
86+
};
87+
88+
let ty_str = ty_to_string(&ty);
89+
assert_eq!(ty_str, "(/*DUMMY*/).{ milhouse, apu }");
90+
});
91+
}

compiler/rustc_builtin_macros/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ mod pattern_type;
4747
mod source_util;
4848
mod test;
4949
mod trace_macros;
50+
mod view_type;
5051

5152
pub mod asm;
5253
pub mod cmdline_attrs;
@@ -99,6 +100,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
99100
stringify: source_util::expand_stringify,
100101
trace_macros: trace_macros::expand_trace_macros,
101102
unreachable: edition_panic::expand_unreachable,
103+
view_type: view_type::expand,
102104
// tidy-alphabetical-end
103105
}
104106

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use rustc_ast::token::TokenKind;
2+
use rustc_ast::tokenstream::TokenStream;
3+
use rustc_ast::{Ty, ast};
4+
use rustc_errors::PResult;
5+
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
6+
use rustc_parse::parser::{ExpTokenPair, TokenType};
7+
use rustc_span::{Ident, Span};
8+
use thin_vec::ThinVec;
9+
10+
pub(crate) fn expand<'cx>(
11+
cx: &'cx mut ExtCtxt<'_>,
12+
sp: Span,
13+
tts: TokenStream,
14+
) -> MacroExpanderResult<'cx> {
15+
let (ty, pat) = match parse_view_ty(cx, tts) {
16+
Ok(parsed) => parsed,
17+
Err(err) => {
18+
return ExpandResult::Ready(DummyResult::any(sp, err.emit()));
19+
}
20+
};
21+
22+
ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::View(ty, pat))))
23+
}
24+
25+
fn parse_view_ty<'a>(
26+
cx: &mut ExtCtxt<'a>,
27+
stream: TokenStream,
28+
) -> PResult<'a, (Box<Ty>, ThinVec<Ident>)> {
29+
let mut parser = cx.new_parser_from_tts(stream);
30+
31+
let ty = parser.parse_ty()?;
32+
33+
parser.expect(ExpTokenPair { tok: TokenKind::Dot, token_type: TokenType::Dot })?;
34+
35+
let fields = match parser.parse_delim_comma_seq(
36+
ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace },
37+
ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace },
38+
|p| p.parse_field_name(),
39+
) {
40+
Ok((fields, _)) => fields,
41+
Err(diag) => {
42+
return Err(diag);
43+
}
44+
};
45+
46+
Ok((ty, fields))
47+
}

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,7 @@ impl<'a> Parser<'a> {
10901090
/// Parses a comma-separated sequence, including both delimiters.
10911091
/// The function `f` must consume tokens until reaching the next separator or
10921092
/// closing bracket.
1093-
fn parse_delim_comma_seq<T>(
1093+
pub fn parse_delim_comma_seq<T>(
10941094
&mut self,
10951095
open: ExpTokenPair,
10961096
close: ExpTokenPair,
@@ -1355,7 +1355,7 @@ impl<'a> Parser<'a> {
13551355
/// ```enbf
13561356
/// FieldName = IntLit | Ident
13571357
/// ```
1358-
fn parse_field_name(&mut self) -> PResult<'a, Ident> {
1358+
pub fn parse_field_name(&mut self) -> PResult<'a, Ident> {
13591359
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind
13601360
{
13611361
if let Some(suffix) = suffix {

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::errors::{
1919
NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
2020
};
2121
use crate::parser::item::FrontMatterParsingMode;
22-
use crate::parser::{ExpTokenPair, FnContext, FnParseMode};
22+
use crate::parser::{FnContext, FnParseMode};
2323
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
2424

2525
/// Signals whether parsing a type should allow `+`.
@@ -768,25 +768,6 @@ impl<'a> Parser<'a> {
768768
self.bump_with((dyn_tok, dyn_tok_sp));
769769
}
770770
let ty = self.parse_ty_no_plus()?;
771-
if self.token == TokenKind::Dot && self.look_ahead(1, |t| t.kind == TokenKind::OpenBrace) {
772-
// & [mut] <type> . { <fields> }
773-
// ^
774-
// we are here
775-
let view_start_span = self.token.span;
776-
self.bump();
777-
let fields = self
778-
.parse_delim_comma_seq(
779-
ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace },
780-
ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace },
781-
|p| p.parse_ident(),
782-
)?
783-
.0;
784-
// FIXME(scrabsha): actually propagate field view in the AST.
785-
let _ = fields;
786-
let view_end_span = self.prev_token.span;
787-
let span = view_start_span.to(view_end_span);
788-
self.psess.gated_spans.gate(sym::view_types, span);
789-
}
790771
Ok(match pinned {
791772
Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
792773
Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),

0 commit comments

Comments
 (0)