Skip to content

Commit 9a1c5eb

Browse files
Begin to implement type system layer of unsafe binders
1 parent b22856d commit 9a1c5eb

File tree

79 files changed

+536
-305
lines changed

Some content is hidden

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

79 files changed

+536
-305
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
263263
&self,
264264
negative_impls,
265265
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
266-
"negative trait bounds are not yet fully implemented; \
266+
"negative trait bounds are not fully implemented; \
267267
use marker types for now"
268268
);
269269
}

compiler/rustc_borrowck/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
16131613
| ty::CoroutineWitness(..)
16141614
| ty::Never
16151615
| ty::Tuple(_)
1616+
| ty::UnsafeBinder(_)
16161617
| ty::Alias(_, _)
16171618
| ty::Param(_)
16181619
| ty::Bound(_, _)
@@ -1654,6 +1655,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
16541655
| ty::Dynamic(_, _, _)
16551656
| ty::CoroutineWitness(..)
16561657
| ty::Never
1658+
| ty::UnsafeBinder(_)
16571659
| ty::Alias(_, _)
16581660
| ty::Param(_)
16591661
| ty::Bound(_, _)

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+1
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ fn push_debuginfo_type_name<'tcx>(
432432
push_closure_or_coroutine_name(tcx, def_id, args, qualified, output, visited);
433433
}
434434
}
435+
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binders)"),
435436
ty::Param(_)
436437
| ty::Error(_)
437438
| ty::Infer(_)

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ fn const_to_valtree_inner<'tcx>(
178178
| ty::Closure(..)
179179
| ty::CoroutineClosure(..)
180180
| ty::Coroutine(..)
181-
| ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType(ty)),
181+
| ty::CoroutineWitness(..)
182+
| ty::UnsafeBinder(_) => Err(ValTreeCreationError::NonSupportedType(ty)),
182183
}
183184
}
184185

@@ -358,7 +359,10 @@ pub fn valtree_to_const_value<'tcx>(
358359
| ty::FnPtr(..)
359360
| ty::Str
360361
| ty::Slice(_)
361-
| ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()),
362+
| ty::Dynamic(..)
363+
| ty::UnsafeBinder(_) => {
364+
bug!("no ValTree should have been created for type {:?}", ty.kind())
365+
}
362366
}
363367
}
364368

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
9090
| ty::CoroutineClosure(_, _)
9191
| ty::Coroutine(_, _)
9292
| ty::CoroutineWitness(..)
93+
| ty::UnsafeBinder(_)
9394
| ty::Never
9495
| ty::Tuple(_)
9596
| ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),

compiler/rustc_const_eval/src/interpret/stack.rs

+2
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
505505
// We don't want to do any queries, so there is not much we can do with ADTs.
506506
ty::Adt(..) => false,
507507

508+
ty::UnsafeBinder(ty) => is_very_trivially_sized(ty.skip_binder()),
509+
508510
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
509511

510512
ty::Infer(ty::TyVar(_)) => false,

compiler/rustc_const_eval/src/interpret/validity.rs

+1
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
768768
// Nothing to check.
769769
interp_ok(true)
770770
}
771+
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
771772
// The above should be all the primitive types. The rest is compound, we
772773
// check them by visiting their fields/variants.
773774
ty::Adt(..)

compiler/rustc_const_eval/src/util/type_name.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
3838
| ty::FnPtr(..)
3939
| ty::Never
4040
| ty::Tuple(_)
41-
| ty::Dynamic(_, _, _) => self.pretty_print_type(ty),
41+
| ty::Dynamic(_, _, _)
42+
| ty::UnsafeBinder(_) => self.pretty_print_type(ty),
4243

4344
// Placeholders (all printed as `_` to uniformize them).
4445
ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {

compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ impl<'tcx> InherentCollect<'tcx> {
178178
| ty::Ref(..)
179179
| ty::Never
180180
| ty::FnPtr(..)
181-
| ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
181+
| ty::Tuple(..)
182+
| ty::UnsafeBinder(_) => self.check_primitive_impl(id, self_ty),
182183
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) | ty::Param(_) => {
183184
Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }))
184185
}

compiler/rustc_hir_analysis/src/coherence/orphan.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ pub(crate) fn orphan_check_impl(
225225
| ty::FnDef(..)
226226
| ty::FnPtr(..)
227227
| ty::Never
228-
| ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
228+
| ty::Tuple(..)
229+
| ty::UnsafeBinder(_) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
229230

230231
ty::Closure(..)
231232
| ty::CoroutineClosure(..)

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -2318,13 +2318,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23182318
self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)),
23192319
)
23202320
}
2321-
hir::TyKind::UnsafeBinder(_binder) => {
2322-
let guar = self
2323-
.dcx()
2324-
.struct_span_err(hir_ty.span, "unsafe binders are not yet implemented")
2325-
.emit();
2326-
Ty::new_error(tcx, guar)
2327-
}
2321+
hir::TyKind::UnsafeBinder(binder) => Ty::new_unsafe_binder(
2322+
tcx,
2323+
ty::Binder::bind_with_vars(
2324+
self.lower_ty(binder.inner_ty),
2325+
tcx.late_bound_vars(hir_ty.hir_id),
2326+
),
2327+
),
23282328
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
23292329
if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) {
23302330
// Don't continue with type analysis if the `dyn` keyword is missing

compiler/rustc_hir_analysis/src/variance/constraints.rs

+5
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
322322
self.add_constraints_from_sig(current, sig_tys.with(hdr), variance);
323323
}
324324

325+
ty::UnsafeBinder(ty) => {
326+
// FIXME(unsafe_binders): This is covariant, right?
327+
self.add_constraints_from_ty(current, ty.skip_binder(), variance);
328+
}
329+
325330
ty::Error(_) => {
326331
// we encounter this when walking the trait references for object
327332
// types, where we use Error as the Self type

compiler/rustc_hir_typeck/src/cast.rs

+2
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
116116
Some(&f) => self.pointer_kind(f, span)?,
117117
},
118118

119+
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
120+
119121
// Pointers to foreign types are thin, despite being unsized
120122
ty::Foreign(..) => Some(PointerKind::Thin),
121123
// We should really try to normalize here.

compiler/rustc_hir_typeck/src/expr.rs

+89-9
Original file line numberDiff line numberDiff line change
@@ -574,8 +574,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
574574
self.check_expr_index(base, idx, expr, brackets_span)
575575
}
576576
ExprKind::Yield(value, _) => self.check_expr_yield(value, expr),
577-
ExprKind::UnsafeBinderCast(kind, expr, ty) => {
578-
self.check_expr_unsafe_binder_cast(kind, expr, ty, expected)
577+
ExprKind::UnsafeBinderCast(kind, inner_expr, ty) => {
578+
self.check_expr_unsafe_binder_cast(expr.span, kind, inner_expr, ty, expected)
579579
}
580580
ExprKind::Err(guar) => Ty::new_error(tcx, guar),
581581
}
@@ -1649,14 +1649,94 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16491649

16501650
fn check_expr_unsafe_binder_cast(
16511651
&self,
1652-
_kind: hir::UnsafeBinderCastKind,
1653-
expr: &'tcx hir::Expr<'tcx>,
1654-
_hir_ty: Option<&'tcx hir::Ty<'tcx>>,
1655-
_expected: Expectation<'tcx>,
1652+
span: Span,
1653+
kind: hir::UnsafeBinderCastKind,
1654+
inner_expr: &'tcx hir::Expr<'tcx>,
1655+
hir_ty: Option<&'tcx hir::Ty<'tcx>>,
1656+
expected: Expectation<'tcx>,
16561657
) -> Ty<'tcx> {
1657-
let guar =
1658-
self.dcx().struct_span_err(expr.span, "unsafe binders are not yet implemented").emit();
1659-
Ty::new_error(self.tcx, guar)
1658+
self.dcx().span_err(inner_expr.span, "unsafe binder casts are not fully implemented");
1659+
1660+
match kind {
1661+
hir::UnsafeBinderCastKind::Wrap => {
1662+
let ascribed_ty =
1663+
hir_ty.map(|hir_ty| self.lower_ty_saving_user_provided_ty(hir_ty));
1664+
let expected_ty = expected.only_has_type(self);
1665+
let binder_ty = match (ascribed_ty, expected_ty) {
1666+
(Some(ascribed_ty), Some(expected_ty)) => {
1667+
self.demand_eqtype(inner_expr.span, expected_ty, ascribed_ty);
1668+
expected_ty
1669+
}
1670+
(Some(ty), None) | (None, Some(ty)) => ty,
1671+
// This will always cause a structural resolve error, but we do it
1672+
// so we don't need to manually report an E0282 both on this codepath
1673+
// and in the others; it all happens in `structurally_resolve_type`.
1674+
(None, None) => self.next_ty_var(inner_expr.span),
1675+
};
1676+
1677+
let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty);
1678+
let hint_ty = match *binder_ty.kind() {
1679+
ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars(
1680+
inner_expr.span,
1681+
infer::BoundRegionConversionTime::HigherRankedType,
1682+
binder.into(),
1683+
),
1684+
ty::Error(e) => Ty::new_error(self.tcx, e),
1685+
_ => {
1686+
let guar = self
1687+
.dcx()
1688+
.struct_span_err(
1689+
hir_ty.map_or(span, |hir_ty| hir_ty.span),
1690+
format!(
1691+
"`wrap_binder!()` can only wrap into unsafe binder, not {}",
1692+
binder_ty.sort_string(self.tcx)
1693+
),
1694+
)
1695+
.with_note("unsafe binders are the only valid output of wrap")
1696+
.emit();
1697+
Ty::new_error(self.tcx, guar)
1698+
}
1699+
};
1700+
1701+
self.check_expr_has_type_or_error(inner_expr, hint_ty, |_| {});
1702+
1703+
binder_ty
1704+
}
1705+
hir::UnsafeBinderCastKind::Unwrap => {
1706+
let ascribed_ty =
1707+
hir_ty.map(|hir_ty| self.lower_ty_saving_user_provided_ty(hir_ty));
1708+
let hint_ty = ascribed_ty.unwrap_or_else(|| self.next_ty_var(inner_expr.span));
1709+
// FIXME(unsafe_binders): coerce here if needed?
1710+
let binder_ty = self.check_expr_has_type_or_error(inner_expr, hint_ty, |_| {});
1711+
1712+
// Unwrap the binder. This will be ambiguous if it's an infer var, and will error
1713+
// if it's not an unsafe binder.
1714+
let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty);
1715+
match *binder_ty.kind() {
1716+
ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars(
1717+
inner_expr.span,
1718+
infer::BoundRegionConversionTime::HigherRankedType,
1719+
binder.into(),
1720+
),
1721+
ty::Error(e) => Ty::new_error(self.tcx, e),
1722+
_ => {
1723+
let guar = self
1724+
.dcx()
1725+
.struct_span_err(
1726+
hir_ty.map_or(inner_expr.span, |hir_ty| hir_ty.span),
1727+
format!(
1728+
"expected unsafe binder, found {} as input of \
1729+
`unwrap_binder!()`",
1730+
binder_ty.sort_string(self.tcx)
1731+
),
1732+
)
1733+
.with_note("only an unsafe binder type can be unwrapped")
1734+
.emit();
1735+
Ty::new_error(self.tcx, guar)
1736+
}
1737+
}
1738+
}
1739+
}
16601740
}
16611741

16621742
fn check_expr_array(

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

+1
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
441441
| ty::FnDef(..)
442442
| ty::FnPtr(..)
443443
| ty::Dynamic(..)
444+
| ty::UnsafeBinder(_)
444445
| ty::Never
445446
| ty::Tuple(..)
446447
| ty::Alias(..)

compiler/rustc_lint/src/types.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12841284
FfiSafe
12851285
}
12861286

1287+
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
1288+
12871289
ty::Param(..)
12881290
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
12891291
| ty::Infer(..)

compiler/rustc_middle/src/ty/context.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
471471
| ty::CoroutineClosure(..)
472472
| ty::Coroutine(_, _)
473473
| ty::Never
474-
| ty::Tuple(_) => {
474+
| ty::Tuple(_)
475+
| ty::UnsafeBinder(_) => {
475476
let simp = ty::fast_reject::simplify_type(
476477
tcx,
477478
self_ty,
@@ -2295,6 +2296,7 @@ impl<'tcx> TyCtxt<'tcx> {
22952296
Ref,
22962297
FnDef,
22972298
FnPtr,
2299+
UnsafeBinder,
22982300
Placeholder,
22992301
Coroutine,
23002302
CoroutineWitness,

compiler/rustc_middle/src/ty/error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ impl<'tcx> Ty<'tcx> {
191191
_ => "fn item".into(),
192192
},
193193
ty::FnPtr(..) => "fn pointer".into(),
194+
ty::UnsafeBinder(_) => "unsafe binder".into(),
194195
ty::Dynamic(..) => "trait object".into(),
195196
ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(),
196197
ty::Coroutine(def_id, ..) => {

compiler/rustc_middle/src/ty/flags.rs

+6
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ impl FlagComputation {
253253
&ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| {
254254
computation.add_tys(sig_tys.inputs_and_output);
255255
}),
256+
257+
&ty::UnsafeBinder(bound_ty) => {
258+
self.bound_computation(bound_ty.into(), |computation, ty| {
259+
computation.add_ty(ty);
260+
})
261+
}
256262
}
257263
}
258264

compiler/rustc_middle/src/ty/layout.rs

+5
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,11 @@ where
816816
bug!("TyAndLayout::field({:?}): not applicable", this)
817817
}
818818

819+
ty::UnsafeBinder(bound_ty) => {
820+
let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into());
821+
field_ty_or_layout(TyAndLayout { ty, ..this }, cx, i)
822+
}
823+
819824
// Potentially-wide pointers.
820825
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
821826
assert!(i < this.fields.count());

compiler/rustc_middle/src/ty/print/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ fn characteristic_def_id_of_type_cached<'a>(
291291
| ty::Uint(_)
292292
| ty::Str
293293
| ty::FnPtr(..)
294+
| ty::UnsafeBinder(_)
294295
| ty::Alias(..)
295296
| ty::Placeholder(..)
296297
| ty::Param(_)

compiler/rustc_middle/src/ty/print/pretty.rs

+4
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
695695
}
696696
}
697697
ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))),
698+
ty::UnsafeBinder(ref bound_ty) => {
699+
// FIXME(unsafe_binders): Make this print `unsafe<>` rather than `for<>`.
700+
self.wrap_binder(bound_ty, |ty, cx| cx.pretty_print_type(*ty))?;
701+
}
698702
ty::Infer(infer_ty) => {
699703
if self.should_print_verbose() {
700704
p!(write("{:?}", ty.kind()));

compiler/rustc_middle/src/ty/structural_impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
393393
ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
394394
ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?),
395395
ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr),
396+
ty::UnsafeBinder(f) => ty::UnsafeBinder(f.try_fold_with(folder)?),
396397
ty::Ref(r, ty, mutbl) => {
397398
ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
398399
}
@@ -443,6 +444,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
443444
ty::Tuple(ts) => ts.visit_with(visitor),
444445
ty::FnDef(_, args) => args.visit_with(visitor),
445446
ty::FnPtr(ref sig_tys, _) => sig_tys.visit_with(visitor),
447+
ty::UnsafeBinder(ref f) => f.visit_with(visitor),
446448
ty::Ref(r, ty, _) => {
447449
try_visit!(r.visit_with(visitor));
448450
ty.visit_with(visitor)

0 commit comments

Comments
 (0)