Skip to content

Commit 9bdba7b

Browse files
Parsing unsafe binders
1 parent 648d024 commit 9bdba7b

File tree

6 files changed

+41
-0
lines changed

6 files changed

+41
-0
lines changed

compiler/rustc_ast/src/ast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2148,6 +2148,12 @@ pub struct BareFnTy {
21482148
pub decl_span: Span,
21492149
}
21502150

2151+
#[derive(Clone, Encodable, Decodable, Debug)]
2152+
pub struct UnsafeBinderTy {
2153+
pub generic_params: ThinVec<GenericParam>,
2154+
pub inner_ty: P<Ty>,
2155+
}
2156+
21512157
/// The various kinds of type recognized by the compiler.
21522158
//
21532159
// Adding a new variant? Please update `test_ty` in `tests/ui/macros/stringify.rs`.
@@ -2163,6 +2169,8 @@ pub enum TyKind {
21632169
Ref(Option<Lifetime>, MutTy),
21642170
/// A bare function (e.g., `fn(usize) -> bool`).
21652171
BareFn(P<BareFnTy>),
2172+
/// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`).
2173+
UnsafeBinder(P<UnsafeBinderTy>),
21662174
/// The never type (`!`).
21672175
Never,
21682176
/// A tuple (`(A, B, C, D,...)`).

compiler/rustc_ast/src/mut_visit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,11 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
496496
vis.visit_fn_decl(decl);
497497
vis.visit_span(decl_span);
498498
}
499+
TyKind::UnsafeBinder(binder) => {
500+
let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut();
501+
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
502+
vis.visit_ty(inner_ty);
503+
}
499504
TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
500505
TyKind::Paren(ty) => vis.visit_ty(ty),
501506
TyKind::Pat(ty, pat) => {

compiler/rustc_ast/src/util/classify.rs

+4
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,10 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
251251
ty = &mut_ty.ty;
252252
}
253253

254+
ast::TyKind::UnsafeBinder(binder) => {
255+
ty = &binder.inner_ty;
256+
}
257+
254258
ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
255259
ast::FnRetTy::Default(_) => break None,
256260
ast::FnRetTy::Ty(ret) => ty = ret,

compiler/rustc_ast/src/visit.rs

+4
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
512512
walk_list!(visitor, visit_generic_param, generic_params);
513513
try_visit!(walk_fn_decl(visitor, decl));
514514
}
515+
TyKind::UnsafeBinder(binder) => {
516+
walk_list!(visitor, visit_generic_param, &binder.generic_params);
517+
try_visit!(visitor.visit_ty(&binder.inner_ty));
518+
}
515519
TyKind::Path(maybe_qself, path) => {
516520
try_visit!(walk_qself(visitor, maybe_qself));
517521
try_visit!(visitor.visit_path(path, *id));

compiler/rustc_ast_pretty/src/pprust/state.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,14 @@ impl<'a> State<'a> {
11901190
ast::TyKind::BareFn(f) => {
11911191
self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params);
11921192
}
1193+
ast::TyKind::UnsafeBinder(f) => {
1194+
self.ibox(INDENT_UNIT);
1195+
self.word("unsafe");
1196+
self.print_generic_params(&f.generic_params);
1197+
self.nbsp();
1198+
self.print_type(&f.inner_ty);
1199+
self.end();
1200+
}
11931201
ast::TyKind::Path(None, path) => {
11941202
self.print_path(path, false, 0);
11951203
}

compiler/rustc_parse/src/parser/ty.rs

+12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_ast::{
55
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
66
GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
77
PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind,
8+
UnsafeBinderTy,
89
};
910
use rustc_errors::{Applicability, PResult};
1011
use rustc_span::symbol::{Ident, kw, sym};
@@ -361,6 +362,8 @@ impl<'a> Parser<'a> {
361362
TyKind::Err(guar)
362363
}
363364
}
365+
} else if self.check_keyword(kw::Unsafe) {
366+
self.parse_unsafe_binder_ty()?
364367
} else {
365368
let msg = format!("expected type, found {}", super::token_descr(&self.token));
366369
let mut err = self.dcx().struct_span_err(self.token.span, msg);
@@ -382,6 +385,15 @@ impl<'a> Parser<'a> {
382385
if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
383386
}
384387

388+
fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
389+
assert!(self.eat_keyword(kw::Unsafe));
390+
self.expect_lt()?;
391+
let generic_params = self.parse_generic_params()?;
392+
self.expect_gt()?;
393+
394+
Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty: self.parse_ty()? })))
395+
}
396+
385397
/// Parse an anonymous struct or union (only for field definitions):
386398
/// ```ignore (feature-not-ready)
387399
/// #[repr(C)]

0 commit comments

Comments
 (0)