Skip to content

Commit 52edea8

Browse files
authored
Unrolled build for rust-lang#134140
Rollup merge of rust-lang#134140 - compiler-errors:unsafe-binders-ast, r=oli-obk Add AST support for unsafe binders I'm splitting up rust-lang#130514 into pieces. It's impossible for me to keep up with a huge PR like that. I'll land type system support for this next, probably w/o MIR lowering, which will come later. r? `@oli-obk` cc `@BoxyUwU` and `@lcnr` who also may want to look at this, though this PR doesn't do too much yet
2 parents 327c7ee + b8c5a0f commit 52edea8

File tree

53 files changed

+616
-18
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+616
-18
lines changed

compiler/rustc_ast/src/ast.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,7 @@ impl Expr {
13821382
| ExprKind::Tup(_)
13831383
| ExprKind::Type(..)
13841384
| ExprKind::Underscore
1385+
| ExprKind::UnsafeBinderCast(..)
13851386
| ExprKind::While(..)
13861387
| ExprKind::Err(_)
13871388
| ExprKind::Dummy => ExprPrecedence::Unambiguous,
@@ -1509,7 +1510,13 @@ pub enum ExprKind {
15091510
/// `'label: for await? pat in iter { block }`
15101511
///
15111512
/// This is desugared to a combination of `loop` and `match` expressions.
1512-
ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind },
1513+
ForLoop {
1514+
pat: P<Pat>,
1515+
iter: P<Expr>,
1516+
body: P<Block>,
1517+
label: Option<Label>,
1518+
kind: ForLoopKind,
1519+
},
15131520
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
15141521
///
15151522
/// `'label: loop { block }`
@@ -1614,6 +1621,8 @@ pub enum ExprKind {
16141621
/// A `format_args!()` expression.
16151622
FormatArgs(P<FormatArgs>),
16161623

1624+
UnsafeBinderCast(UnsafeBinderCastKind, P<Expr>, Option<P<Ty>>),
1625+
16171626
/// Placeholder for an expression that wasn't syntactically well formed in some way.
16181627
Err(ErrorGuaranteed),
16191628

@@ -1652,6 +1661,16 @@ impl GenBlockKind {
16521661
}
16531662
}
16541663

1664+
/// Whether we're unwrapping or wrapping an unsafe binder
1665+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1666+
#[derive(Encodable, Decodable, HashStable_Generic)]
1667+
pub enum UnsafeBinderCastKind {
1668+
// e.g. `&i32` -> `unsafe<'a> &'a i32`
1669+
Wrap,
1670+
// e.g. `unsafe<'a> &'a i32` -> `&i32`
1671+
Unwrap,
1672+
}
1673+
16551674
/// The explicit `Self` type in a "qualified path". The actual
16561675
/// path, including the trait and the associated item, is stored
16571676
/// separately. `position` represents the index of the associated
@@ -2223,6 +2242,12 @@ pub struct BareFnTy {
22232242
pub decl_span: Span,
22242243
}
22252244

2245+
#[derive(Clone, Encodable, Decodable, Debug)]
2246+
pub struct UnsafeBinderTy {
2247+
pub generic_params: ThinVec<GenericParam>,
2248+
pub inner_ty: P<Ty>,
2249+
}
2250+
22262251
/// The various kinds of type recognized by the compiler.
22272252
//
22282253
// Adding a new variant? Please update `test_ty` in `tests/ui/macros/stringify.rs`.
@@ -2242,6 +2267,8 @@ pub enum TyKind {
22422267
PinnedRef(Option<Lifetime>, MutTy),
22432268
/// A bare function (e.g., `fn(usize) -> bool`).
22442269
BareFn(P<BareFnTy>),
2270+
/// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`).
2271+
UnsafeBinder(P<UnsafeBinderTy>),
22452272
/// The never type (`!`).
22462273
Never,
22472274
/// A tuple (`(A, B, C, D,...)`).

compiler/rustc_ast/src/mut_visit.rs

+11
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,11 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
558558
vis.visit_fn_decl(decl);
559559
vis.visit_span(decl_span);
560560
}
561+
TyKind::UnsafeBinder(binder) => {
562+
let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut();
563+
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
564+
vis.visit_ty(inner_ty);
565+
}
561566
TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
562567
TyKind::Paren(ty) => vis.visit_ty(ty),
563568
TyKind::Pat(ty, pat) => {
@@ -1775,6 +1780,12 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
17751780
ExprKind::TryBlock(body) => vis.visit_block(body),
17761781
ExprKind::Lit(_token) => {}
17771782
ExprKind::IncludedBytes(_bytes) => {}
1783+
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
1784+
vis.visit_expr(expr);
1785+
if let Some(ty) = ty {
1786+
vis.visit_ty(ty);
1787+
}
1788+
}
17781789
ExprKind::Err(_guar) => {}
17791790
ExprKind::Dummy => {}
17801791
}

compiler/rustc_ast/src/util/classify.rs

+6
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
152152
| Underscore
153153
| Yeet(..)
154154
| Yield(..)
155+
| UnsafeBinderCast(..)
155156
| Err(..)
156157
| Dummy => return false,
157158
}
@@ -232,6 +233,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
232233
| Paren(_)
233234
| Try(_)
234235
| Yeet(None)
236+
| UnsafeBinderCast(..)
235237
| Err(_)
236238
| Dummy => break None,
237239
}
@@ -253,6 +255,10 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
253255
ty = &mut_ty.ty;
254256
}
255257

258+
ast::TyKind::UnsafeBinder(binder) => {
259+
ty = &binder.inner_ty;
260+
}
261+
256262
ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
257263
ast::FnRetTy::Default(_) => break None,
258264
ast::FnRetTy::Ty(ret) => ty = ret,

compiler/rustc_ast/src/visit.rs

+8
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
522522
walk_list!(visitor, visit_generic_param, generic_params);
523523
try_visit!(visitor.visit_fn_decl(decl));
524524
}
525+
TyKind::UnsafeBinder(binder) => {
526+
walk_list!(visitor, visit_generic_param, &binder.generic_params);
527+
try_visit!(visitor.visit_ty(&binder.inner_ty));
528+
}
525529
TyKind::Path(maybe_qself, path) => {
526530
try_visit!(visitor.visit_qself(maybe_qself));
527531
try_visit!(visitor.visit_path(path, *id));
@@ -1226,6 +1230,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
12261230
ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
12271231
ExprKind::Lit(_token) => {}
12281232
ExprKind::IncludedBytes(_bytes) => {}
1233+
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
1234+
try_visit!(visitor.visit_expr(expr));
1235+
visit_opt!(visitor, visit_ty, ty);
1236+
}
12291237
ExprKind::Err(_guar) => {}
12301238
ExprKind::Dummy => {}
12311239
}

compiler/rustc_ast_lowering/src/expr.rs

+8
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
379379
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
380380
ExprKind::Err(guar) => hir::ExprKind::Err(*guar),
381381

382+
ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(
383+
*kind,
384+
self.lower_expr(expr),
385+
ty.as_ref().map(|ty| {
386+
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast))
387+
}),
388+
),
389+
382390
ExprKind::Dummy => {
383391
span_bug!(e.span, "lowered ExprKind::Dummy")
384392
}

compiler/rustc_ast_lowering/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12281228
param_names: self.lower_fn_params_to_names(&f.decl),
12291229
}))
12301230
}
1231+
TyKind::UnsafeBinder(f) => {
1232+
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
1233+
hir::TyKind::UnsafeBinder(self.arena.alloc(hir::UnsafeBinderTy {
1234+
generic_params,
1235+
inner_ty: self.lower_ty(&f.inner_ty, itctx),
1236+
}))
1237+
}
12311238
TyKind::Never => hir::TyKind::Never,
12321239
TyKind::Tup(tys) => hir::TyKind::Tup(
12331240
self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
560560
gate_all!(return_type_notation, "return type notation is experimental");
561561
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
562562
gate_all!(unsafe_fields, "`unsafe` fields are experimental");
563+
gate_all!(unsafe_binders, "unsafe binder types are experimental");
563564

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

compiler/rustc_ast_pretty/src/pprust/state.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,14 @@ impl<'a> State<'a> {
11981198
ast::TyKind::BareFn(f) => {
11991199
self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params);
12001200
}
1201+
ast::TyKind::UnsafeBinder(f) => {
1202+
self.ibox(INDENT_UNIT);
1203+
self.word("unsafe");
1204+
self.print_generic_params(&f.generic_params);
1205+
self.nbsp();
1206+
self.print_type(&f.inner_ty);
1207+
self.end();
1208+
}
12011209
ast::TyKind::Path(None, path) => {
12021210
self.print_path(path, false, 0);
12031211
}

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+19
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,25 @@ impl<'a> State<'a> {
772772
self.word_nbsp("try");
773773
self.print_block_with_attrs(blk, attrs)
774774
}
775+
ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
776+
self.word("builtin # ");
777+
match kind {
778+
ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"),
779+
ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"),
780+
}
781+
self.popen();
782+
self.ibox(0);
783+
self.print_expr(expr, FixupContext::default());
784+
785+
if let Some(ty) = ty {
786+
self.word(",");
787+
self.space();
788+
self.print_type(ty);
789+
}
790+
791+
self.end();
792+
self.pclose();
793+
}
775794
ast::ExprKind::Err(_) => {
776795
self.popen();
777796
self.word("/*ERROR*/");

compiler/rustc_builtin_macros/src/assert/context.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
323323
| ExprKind::While(_, _, _)
324324
| ExprKind::Yeet(_)
325325
| ExprKind::Become(_)
326-
| ExprKind::Yield(_) => {}
326+
| ExprKind::Yield(_)
327+
| ExprKind::UnsafeBinderCast(..) => {}
327328
}
328329
}
329330

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,8 @@ declare_features! (
636636
/// Allows creation of instances of a struct by moving fields that have
637637
/// not changed from prior instances of the same struct (RFC #2528)
638638
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
639+
/// Allows using `unsafe<'a> &'a T` unsafe binder types.
640+
(incomplete, unsafe_binders, "CURRENT_RUSTC_VERSION", Some(130516)),
639641
/// Allows declaring fields `unsafe`.
640642
(incomplete, unsafe_fields, "CURRENT_RUSTC_VERSION", Some(132922)),
641643
/// Allows const generic parameters to be defined with types that

compiler/rustc_hir/src/hir.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_ast::{
88
};
99
pub use rustc_ast::{
1010
BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
11-
ImplPolarity, IsAuto, Movability, Mutability, UnOp,
11+
ImplPolarity, IsAuto, Movability, Mutability, UnOp, UnsafeBinderCastKind,
1212
};
1313
use rustc_data_structures::fingerprint::Fingerprint;
1414
use rustc_data_structures::sorted_map::SortedMap;
@@ -1740,6 +1740,7 @@ impl Expr<'_> {
17401740
| ExprKind::Struct(..)
17411741
| ExprKind::Tup(_)
17421742
| ExprKind::Type(..)
1743+
| ExprKind::UnsafeBinderCast(..)
17431744
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
17441745

17451746
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
@@ -1769,6 +1770,9 @@ impl Expr<'_> {
17691770
// https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries
17701771
ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
17711772

1773+
// Unsafe binder cast preserves place-ness of the sub-expression.
1774+
ExprKind::UnsafeBinderCast(_, e, _) => e.is_place_expr(allow_projections_from),
1775+
17721776
ExprKind::Unary(UnOp::Deref, _) => true,
17731777

17741778
ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _, _) => {
@@ -1850,7 +1854,8 @@ impl Expr<'_> {
18501854
| ExprKind::Field(base, _)
18511855
| ExprKind::Index(base, _, _)
18521856
| ExprKind::AddrOf(.., base)
1853-
| ExprKind::Cast(base, _) => {
1857+
| ExprKind::Cast(base, _)
1858+
| ExprKind::UnsafeBinderCast(_, base, _) => {
18541859
// This isn't exactly true for `Index` and all `Unary`, but we are using this
18551860
// method exclusively for diagnostics and there's a *cultural* pressure against
18561861
// them being used only for its side-effects.
@@ -2144,6 +2149,10 @@ pub enum ExprKind<'hir> {
21442149
/// A suspension point for coroutines (i.e., `yield <expr>`).
21452150
Yield(&'hir Expr<'hir>, YieldSource),
21462151

2152+
/// Operators which can be used to interconvert `unsafe` binder types.
2153+
/// e.g. `unsafe<'a> &'a i32` <=> `&i32`.
2154+
UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>),
2155+
21472156
/// A placeholder for an expression that wasn't syntactically well formed in some way.
21482157
Err(rustc_span::ErrorGuaranteed),
21492158
}
@@ -2780,6 +2789,12 @@ pub struct BareFnTy<'hir> {
27802789
pub param_names: &'hir [Ident],
27812790
}
27822791

2792+
#[derive(Debug, Clone, Copy, HashStable_Generic)]
2793+
pub struct UnsafeBinderTy<'hir> {
2794+
pub generic_params: &'hir [GenericParam<'hir>],
2795+
pub inner_ty: &'hir Ty<'hir>,
2796+
}
2797+
27832798
#[derive(Debug, Clone, Copy, HashStable_Generic)]
27842799
pub struct OpaqueTy<'hir> {
27852800
pub hir_id: HirId,
@@ -2878,6 +2893,8 @@ pub enum TyKind<'hir> {
28782893
Ref(&'hir Lifetime, MutTy<'hir>),
28792894
/// A bare function (e.g., `fn(usize) -> bool`).
28802895
BareFn(&'hir BareFnTy<'hir>),
2896+
/// An unsafe binder type (e.g. `unsafe<'a> Foo<'a>`).
2897+
UnsafeBinder(&'hir UnsafeBinderTy<'hir>),
28812898
/// The never type (`!`).
28822899
Never,
28832900
/// A tuple (`(A, B, C, D, ...)`).

compiler/rustc_hir/src/intravisit.rs

+8
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
857857
ExprKind::Yield(ref subexpression, _) => {
858858
try_visit!(visitor.visit_expr(subexpression));
859859
}
860+
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
861+
try_visit!(visitor.visit_expr(expr));
862+
visit_opt!(visitor, visit_ty, ty);
863+
}
860864
ExprKind::Lit(_) | ExprKind::Err(_) => {}
861865
}
862866
V::Result::output()
@@ -886,6 +890,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
886890
walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
887891
try_visit!(visitor.visit_fn_decl(function_declaration.decl));
888892
}
893+
TyKind::UnsafeBinder(ref unsafe_binder) => {
894+
walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params);
895+
try_visit!(visitor.visit_ty(unsafe_binder.inner_ty));
896+
}
889897
TyKind::Path(ref qpath) => {
890898
try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
891899
}

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+6
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,12 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
470470
self.outer_index.shift_out(1);
471471
res
472472
}
473+
hir::TyKind::UnsafeBinder(_) => {
474+
self.outer_index.shift_in(1);
475+
let res = intravisit::walk_ty(self, ty);
476+
self.outer_index.shift_out(1);
477+
res
478+
}
473479
_ => intravisit::walk_ty(self, ty),
474480
}
475481
}

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+30
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,36 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
781781
intravisit::walk_ty(this, ty);
782782
});
783783
}
784+
hir::TyKind::UnsafeBinder(binder) => {
785+
let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
786+
binder
787+
.generic_params
788+
.iter()
789+
.enumerate()
790+
.map(|(late_bound_idx, param)| {
791+
(
792+
(param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
793+
late_arg_as_bound_arg(self.tcx, param),
794+
)
795+
})
796+
.unzip();
797+
798+
deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
799+
800+
self.record_late_bound_vars(ty.hir_id, binders);
801+
let scope = Scope::Binder {
802+
hir_id: ty.hir_id,
803+
bound_vars,
804+
s: self.scope,
805+
scope_type: BinderScopeType::Normal,
806+
where_bound_origin: None,
807+
};
808+
self.with(scope, |this| {
809+
// a bare fn has no bounds, so everything
810+
// contained within is scoped within its binder.
811+
intravisit::walk_ty(this, ty);
812+
});
813+
}
784814
hir::TyKind::TraitObject(bounds, lifetime, _) => {
785815
debug!(?bounds, ?lifetime, "TraitObject");
786816
let scope = Scope::TraitRefBoundary { s: self.scope };

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2312,6 +2312,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23122312
self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)),
23132313
)
23142314
}
2315+
hir::TyKind::UnsafeBinder(_binder) => {
2316+
let guar = self
2317+
.dcx()
2318+
.struct_span_err(hir_ty.span, "unsafe binders are not yet implemented")
2319+
.emit();
2320+
Ty::new_error(tcx, guar)
2321+
}
23152322
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
23162323
if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) {
23172324
// Don't continue with type analysis if the `dyn` keyword is missing

0 commit comments

Comments
 (0)