Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,8 @@ pub enum TyKind {
/// Usually not written directly in user code but indirectly via the macro
/// `core::field::field_of!(...)`.
FieldOf(Box<Ty>, Option<Ident>, Ident),
/// A view of a type. `T.{ field_1, field_2 }`.
View(Box<Ty>, #[visitable(ignore)] ThinVec<Ident>),
/// Sometimes we need a dummy value when no error has occurred.
Dummy,
/// Placeholder for a kind that has failed to be defined.
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
| ast::TyKind::Pat(..)
| ast::TyKind::FieldOf(..)
| ast::TyKind::Dummy
| ast::TyKind::Err(..) => break None,
| ast::TyKind::Err(..)
| ast::TyKind::View(..) => break None,
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
hir::TyKind::Err(guar)
}
TyKind::View(ty, _) => {
// FIXME(scrabsha): lower view types to HIR.
return self.lower_ty(ty, itctx);
}
TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"),
};

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::TyKind::Pat(..) => {
gate!(self, pattern_types, ty.span, "pattern types are unstable");
}
ast::TyKind::View(..) => {
gate!(self, view_types, ty.span, "view types are unstable");
}
_ => {}
}
visit::walk_ty(self, ty)
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,20 @@ impl<'a> State<'a> {
}
}

fn print_view(&mut self, fields: &[Ident]) {
self.word(".{");

if !fields.is_empty() {
self.space();
self.commasep(Consistent, fields, |s, field| {
s.print_ident(*field);
});
self.space();
}

self.word("}");
}
Comment thread
scrabsha marked this conversation as resolved.

pub fn print_assoc_item_constraint(&mut self, constraint: &ast::AssocItemConstraint) {
self.print_ident(constraint.ident);
if let Some(args) = constraint.gen_args.as_ref() {
Expand Down Expand Up @@ -1441,6 +1455,10 @@ impl<'a> State<'a> {
self.end(ib);
self.pclose();
}
ast::TyKind::View(ty, fields) => {
self.print_type(ty);
self.print_view(fields);
}
}
self.end(ib);
}
Expand Down
31 changes: 30 additions & 1 deletion compiler/rustc_ast_pretty/src/pprust/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_ast as ast;
use rustc_span::{DUMMY_SP, Ident, create_default_session_globals_then};
use thin_vec::ThinVec;
use thin_vec::{ThinVec, thin_vec};

use super::*;

Expand All @@ -22,6 +22,12 @@ fn variant_to_string(var: &ast::Variant) -> String {
to_string(|s| s.print_variant(var))
}

fn ty_to_string(ty: &ast::Ty) -> String {
to_string(|s| {
s.print_type(ty);
})
}

#[test]
fn test_fun_to_string() {
create_default_session_globals_then(|| {
Expand Down Expand Up @@ -60,3 +66,26 @@ fn test_variant_to_string() {
assert_eq!(varstr, "principal_skinner");
})
}

#[test]
fn test_field_view() {
create_default_session_globals_then(|| {
let ty = ast::Ty {
id: ast::DUMMY_NODE_ID,
kind: ast::TyKind::View(
Box::new(ast::Ty {
id: ast::DUMMY_NODE_ID,
kind: ast::TyKind::Dummy,
span: DUMMY_SP,
tokens: None,
}),
thin_vec![Ident::from_str("milhouse"), Ident::from_str("apu")],
),
span: DUMMY_SP,
tokens: None,
};

let ty_str = ty_to_string(&ty);
assert_eq!(ty_str, "(/*DUMMY*/).{ milhouse, apu }");
});
}
2 changes: 2 additions & 0 deletions compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ mod pattern_type;
mod source_util;
mod test;
mod trace_macros;
mod view_type;

pub mod asm;
pub mod cmdline_attrs;
Expand Down Expand Up @@ -99,6 +100,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
stringify: source_util::expand_stringify,
trace_macros: trace_macros::expand_trace_macros,
unreachable: edition_panic::expand_unreachable,
view_type: view_type::expand,
// tidy-alphabetical-end
}

Expand Down
47 changes: 47 additions & 0 deletions compiler/rustc_builtin_macros/src/view_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use rustc_ast::token::TokenKind;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{Ty, ast};
use rustc_errors::PResult;
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_parse::parser::{ExpTokenPair, TokenType};
use rustc_span::{Ident, Span};
use thin_vec::ThinVec;

pub(crate) fn expand<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'cx> {
let (ty, pat) = match parse_view_ty(cx, tts) {
Ok(parsed) => parsed,
Err(err) => {
return ExpandResult::Ready(DummyResult::any(sp, err.emit()));
}
};

ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::View(ty, pat))))
}

fn parse_view_ty<'a>(
cx: &mut ExtCtxt<'a>,
stream: TokenStream,
) -> PResult<'a, (Box<Ty>, ThinVec<Ident>)> {
let mut parser = cx.new_parser_from_tts(stream);

let ty = parser.parse_ty()?;

parser.expect(ExpTokenPair { tok: TokenKind::Dot, token_type: TokenType::Dot })?;

let fields = match parser.parse_delim_comma_seq(
ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace },
ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace },
|p| p.parse_field_name(),
) {
Ok((fields, _)) => fields,
Err(diag) => {
return Err(diag);
}
};

Ok((ty, fields))
}
4 changes: 2 additions & 2 deletions compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ impl<'a> Parser<'a> {
/// Parses a comma-separated sequence, including both delimiters.
/// The function `f` must consume tokens until reaching the next separator or
/// closing bracket.
fn parse_delim_comma_seq<T>(
pub fn parse_delim_comma_seq<T>(
&mut self,
open: ExpTokenPair,
close: ExpTokenPair,
Expand Down Expand Up @@ -1355,7 +1355,7 @@ impl<'a> Parser<'a> {
/// ```enbf
/// FieldName = IntLit | Ident
/// ```
fn parse_field_name(&mut self) -> PResult<'a, Ident> {
pub fn parse_field_name(&mut self) -> PResult<'a, Ident> {
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind
{
if let Some(suffix) = suffix {
Expand Down
21 changes: 1 addition & 20 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::errors::{
NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
};
use crate::parser::item::FrontMatterParsingMode;
use crate::parser::{ExpTokenPair, FnContext, FnParseMode};
use crate::parser::{FnContext, FnParseMode};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};

/// Signals whether parsing a type should allow `+`.
Expand Down Expand Up @@ -768,25 +768,6 @@ impl<'a> Parser<'a> {
self.bump_with((dyn_tok, dyn_tok_sp));
}
let ty = self.parse_ty_no_plus()?;
if self.token == TokenKind::Dot && self.look_ahead(1, |t| t.kind == TokenKind::OpenBrace) {
// & [mut] <type> . { <fields> }
// ^
// we are here
let view_start_span = self.token.span;
self.bump();
let fields = self
.parse_delim_comma_seq(
ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace },
ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace },
|p| p.parse_ident(),
)?
.0;
// FIXME(scrabsha): actually propagate field view in the AST.
let _ = fields;
let view_end_span = self.prev_token.span;
let span = view_start_span.to(view_end_span);
self.psess.gated_spans.gate(sym::view_types, span);
}
Ok(match pinned {
Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/input_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
CVarArgs,
Dummy,
FieldOf,
View,
Err
]
);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2306,6 +2306,7 @@ symbols! {
vgpr384,
vgpr512,
vgpr1024,
view_type,
view_types,
vis,
visible_private_types,
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,9 @@ mod bool;
mod escape;
mod tuple;
mod unit;
#[cfg_attr(feature = "nightly", not(bootstrap))]
#[unstable(feature = "view_type_macro", issue = "155938")]
pub mod view;

#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;
Expand Down
21 changes: 21 additions & 0 deletions library/core/src/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Helpers module for exporting the `view_types` macro.

/// Creates a view type.
/// ```
/// #![feature(view_types, view_type_macro)]
//
/// struct Foo {
/// bar: usize,
/// baz: u32,
/// }
///
/// type FooBar = std::view::view_type!(Foo.{ bar });
/// ```
#[macro_export]
#[rustc_builtin_macro(view_type)]
#[unstable(feature = "view_type_macro", issue = "155938")]
macro_rules! view_type {
($($arg:tt)*) => {
/* compiler built-in */
};
}
3 changes: 3 additions & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,9 @@ pub mod process;
pub mod random;
pub mod sync;
pub mod time;
#[cfg_attr(feature = "nightly", not(bootstrap))]
#[unstable(feature = "view_type_macro", issue = "155938")]
pub mod view;

// Pull in `std_float` crate into std. The contents of
// `std_float` are in a different repository: rust-lang/portable-simd.
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! Helper module for exporting the `view_types` macro.

pub use core::view_type;
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_utils/src/check_proc_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) {
// experimental
| TyKind::Pat(..)
| TyKind::FieldOf(..)
| TyKind::View(..)

// unused
| TyKind::CVarArgs
Expand Down
8 changes: 8 additions & 0 deletions src/tools/rustfmt/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,14 @@ impl Rewrite for ast::Ty {
result.push_str(&rewrite);
Ok(result)
}

ast::TyKind::View(..) => {
// This doesn't normally occur in the AST because macros aren't expanded. However,
// rustfmt tries to parse macro arguments when formatting macros, so it's not
// totally impossible for rustfmt to come across this node when formatting a file.
// Also, rustfmt might get passed the output from `-Zunpretty=expanded`.
Err(RewriteError::Unknown)
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1579,6 +1579,13 @@ Tests on `enum` variants.

**FIXME**: Should be rehomed with `tests/ui/enum/`.

## `tests/ui/view-types`

Anything related to view types.

See
[Tracking Issue for view types](https://github.com/rust-lang/rust/issues/155938).

## `tests/ui/wasm/`

These tests target the `wasm32` architecture specifically. They are usually regression tests for WASM-specific bugs which were observed in the past.
Expand Down
17 changes: 0 additions & 17 deletions tests/ui/feature-gates/feature-gate-view-types.rs

This file was deleted.

33 changes: 0 additions & 33 deletions tests/ui/feature-gates/feature-gate-view-types.stderr

This file was deleted.

Loading
Loading