Begin to implement type system layer of unsafe binders

This commit is contained in:
Michael Goulet 2024-12-21 17:05:40 +00:00
parent b22856d192
commit 9a1c5eb5b3
79 changed files with 536 additions and 305 deletions

View file

@ -263,7 +263,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
&self,
negative_impls,
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
"negative trait bounds are not yet fully implemented; \
"negative trait bounds are not fully implemented; \
use marker types for now"
);
}

View file

@ -1613,6 +1613,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
| ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Bound(_, _)
@ -1654,6 +1655,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
| ty::Dynamic(_, _, _)
| ty::CoroutineWitness(..)
| ty::Never
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Bound(_, _)

View file

@ -432,6 +432,7 @@ fn push_debuginfo_type_name<'tcx>(
push_closure_or_coroutine_name(tcx, def_id, args, qualified, output, visited);
}
}
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binders)"),
ty::Param(_)
| ty::Error(_)
| ty::Infer(_)

View file

@ -178,7 +178,8 @@ fn const_to_valtree_inner<'tcx>(
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType(ty)),
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_) => Err(ValTreeCreationError::NonSupportedType(ty)),
}
}
@ -358,7 +359,10 @@ pub fn valtree_to_const_value<'tcx>(
| ty::FnPtr(..)
| ty::Str
| ty::Slice(_)
| ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()),
| ty::Dynamic(..)
| ty::UnsafeBinder(_) => {
bug!("no ValTree should have been created for type {:?}", ty.kind())
}
}
}

View file

@ -90,6 +90,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
| ty::CoroutineClosure(_, _)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_)
| ty::Never
| ty::Tuple(_)
| ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),

View file

@ -505,6 +505,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// We don't want to do any queries, so there is not much we can do with ADTs.
ty::Adt(..) => false,
ty::UnsafeBinder(ty) => is_very_trivially_sized(ty.skip_binder()),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
ty::Infer(ty::TyVar(_)) => false,

View file

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

View file

@ -38,7 +38,8 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
| ty::FnPtr(..)
| ty::Never
| ty::Tuple(_)
| ty::Dynamic(_, _, _) => self.pretty_print_type(ty),
| ty::Dynamic(_, _, _)
| ty::UnsafeBinder(_) => self.pretty_print_type(ty),
// Placeholders (all printed as `_` to uniformize them).
ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {

View file

@ -178,7 +178,8 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Ref(..)
| ty::Never
| ty::FnPtr(..)
| ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
| ty::Tuple(..)
| ty::UnsafeBinder(_) => self.check_primitive_impl(id, self_ty),
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) | ty::Param(_) => {
Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }))
}

View file

@ -225,7 +225,8 @@ pub(crate) fn orphan_check_impl(
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Never
| ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
| ty::Tuple(..)
| ty::UnsafeBinder(_) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
ty::Closure(..)
| ty::CoroutineClosure(..)

View file

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

View file

@ -322,6 +322,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_sig(current, sig_tys.with(hdr), variance);
}
ty::UnsafeBinder(ty) => {
// FIXME(unsafe_binders): This is covariant, right?
self.add_constraints_from_ty(current, ty.skip_binder(), variance);
}
ty::Error(_) => {
// we encounter this when walking the trait references for object
// types, where we use Error as the Self type

View file

@ -116,6 +116,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(&f) => self.pointer_kind(f, span)?,
},
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
// Pointers to foreign types are thin, despite being unsized
ty::Foreign(..) => Some(PointerKind::Thin),
// We should really try to normalize here.

View file

@ -574,8 +574,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_index(base, idx, expr, brackets_span)
}
ExprKind::Yield(value, _) => self.check_expr_yield(value, expr),
ExprKind::UnsafeBinderCast(kind, expr, ty) => {
self.check_expr_unsafe_binder_cast(kind, expr, ty, expected)
ExprKind::UnsafeBinderCast(kind, inner_expr, ty) => {
self.check_expr_unsafe_binder_cast(expr.span, kind, inner_expr, ty, expected)
}
ExprKind::Err(guar) => Ty::new_error(tcx, guar),
}
@ -1649,14 +1649,94 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_expr_unsafe_binder_cast(
&self,
_kind: hir::UnsafeBinderCastKind,
expr: &'tcx hir::Expr<'tcx>,
_hir_ty: Option<&'tcx hir::Ty<'tcx>>,
_expected: Expectation<'tcx>,
span: Span,
kind: hir::UnsafeBinderCastKind,
inner_expr: &'tcx hir::Expr<'tcx>,
hir_ty: Option<&'tcx hir::Ty<'tcx>>,
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
let guar =
self.dcx().struct_span_err(expr.span, "unsafe binders are not yet implemented").emit();
Ty::new_error(self.tcx, guar)
self.dcx().span_err(inner_expr.span, "unsafe binder casts are not fully implemented");
match kind {
hir::UnsafeBinderCastKind::Wrap => {
let ascribed_ty =
hir_ty.map(|hir_ty| self.lower_ty_saving_user_provided_ty(hir_ty));
let expected_ty = expected.only_has_type(self);
let binder_ty = match (ascribed_ty, expected_ty) {
(Some(ascribed_ty), Some(expected_ty)) => {
self.demand_eqtype(inner_expr.span, expected_ty, ascribed_ty);
expected_ty
}
(Some(ty), None) | (None, Some(ty)) => ty,
// This will always cause a structural resolve error, but we do it
// so we don't need to manually report an E0282 both on this codepath
// and in the others; it all happens in `structurally_resolve_type`.
(None, None) => self.next_ty_var(inner_expr.span),
};
let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty);
let hint_ty = match *binder_ty.kind() {
ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars(
inner_expr.span,
infer::BoundRegionConversionTime::HigherRankedType,
binder.into(),
),
ty::Error(e) => Ty::new_error(self.tcx, e),
_ => {
let guar = self
.dcx()
.struct_span_err(
hir_ty.map_or(span, |hir_ty| hir_ty.span),
format!(
"`wrap_binder!()` can only wrap into unsafe binder, not {}",
binder_ty.sort_string(self.tcx)
),
)
.with_note("unsafe binders are the only valid output of wrap")
.emit();
Ty::new_error(self.tcx, guar)
}
};
self.check_expr_has_type_or_error(inner_expr, hint_ty, |_| {});
binder_ty
}
hir::UnsafeBinderCastKind::Unwrap => {
let ascribed_ty =
hir_ty.map(|hir_ty| self.lower_ty_saving_user_provided_ty(hir_ty));
let hint_ty = ascribed_ty.unwrap_or_else(|| self.next_ty_var(inner_expr.span));
// FIXME(unsafe_binders): coerce here if needed?
let binder_ty = self.check_expr_has_type_or_error(inner_expr, hint_ty, |_| {});
// Unwrap the binder. This will be ambiguous if it's an infer var, and will error
// if it's not an unsafe binder.
let binder_ty = self.structurally_resolve_type(inner_expr.span, binder_ty);
match *binder_ty.kind() {
ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars(
inner_expr.span,
infer::BoundRegionConversionTime::HigherRankedType,
binder.into(),
),
ty::Error(e) => Ty::new_error(self.tcx, e),
_ => {
let guar = self
.dcx()
.struct_span_err(
hir_ty.map_or(inner_expr.span, |hir_ty| hir_ty.span),
format!(
"expected unsafe binder, found {} as input of \
`unwrap_binder!()`",
binder_ty.sort_string(self.tcx)
),
)
.with_note("only an unsafe binder type can be unwrapped")
.emit();
Ty::new_error(self.tcx, guar)
}
}
}
}
}
fn check_expr_array(

View file

@ -441,6 +441,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Dynamic(..)
| ty::UnsafeBinder(_)
| ty::Never
| ty::Tuple(..)
| ty::Alias(..)

View file

@ -1284,6 +1284,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
FfiSafe
}
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
ty::Param(..)
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
| ty::Infer(..)

View file

@ -471,7 +471,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::Never
| ty::Tuple(_) => {
| ty::Tuple(_)
| ty::UnsafeBinder(_) => {
let simp = ty::fast_reject::simplify_type(
tcx,
self_ty,
@ -2295,6 +2296,7 @@ impl<'tcx> TyCtxt<'tcx> {
Ref,
FnDef,
FnPtr,
UnsafeBinder,
Placeholder,
Coroutine,
CoroutineWitness,

View file

@ -191,6 +191,7 @@ impl<'tcx> Ty<'tcx> {
_ => "fn item".into(),
},
ty::FnPtr(..) => "fn pointer".into(),
ty::UnsafeBinder(_) => "unsafe binder".into(),
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(),
ty::Coroutine(def_id, ..) => {

View file

@ -253,6 +253,12 @@ impl FlagComputation {
&ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| {
computation.add_tys(sig_tys.inputs_and_output);
}),
&ty::UnsafeBinder(bound_ty) => {
self.bound_computation(bound_ty.into(), |computation, ty| {
computation.add_ty(ty);
})
}
}
}

View file

@ -816,6 +816,11 @@ where
bug!("TyAndLayout::field({:?}): not applicable", this)
}
ty::UnsafeBinder(bound_ty) => {
let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into());
field_ty_or_layout(TyAndLayout { ty, ..this }, cx, i)
}
// Potentially-wide pointers.
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
assert!(i < this.fields.count());

View file

@ -291,6 +291,7 @@ fn characteristic_def_id_of_type_cached<'a>(
| ty::Uint(_)
| ty::Str
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Alias(..)
| ty::Placeholder(..)
| ty::Param(_)

View file

@ -695,6 +695,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
}
ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))),
ty::UnsafeBinder(ref bound_ty) => {
// FIXME(unsafe_binders): Make this print `unsafe<>` rather than `for<>`.
self.wrap_binder(bound_ty, |ty, cx| cx.pretty_print_type(*ty))?;
}
ty::Infer(infer_ty) => {
if self.should_print_verbose() {
p!(write("{:?}", ty.kind()));

View file

@ -393,6 +393,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?),
ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr),
ty::UnsafeBinder(f) => ty::UnsafeBinder(f.try_fold_with(folder)?),
ty::Ref(r, ty, mutbl) => {
ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
}
@ -443,6 +444,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
ty::Tuple(ts) => ts.visit_with(visitor),
ty::FnDef(_, args) => args.visit_with(visitor),
ty::FnPtr(ref sig_tys, _) => sig_tys.visit_with(visitor),
ty::UnsafeBinder(ref f) => f.visit_with(visitor),
ty::Ref(r, ty, _) => {
try_visit!(r.visit_with(visitor));
ty.visit_with(visitor)

View file

@ -673,6 +673,11 @@ impl<'tcx> Ty<'tcx> {
Ty::new(tcx, FnPtr(sig_tys, hdr))
}
#[inline]
pub fn new_unsafe_binder(tcx: TyCtxt<'tcx>, b: Binder<'tcx, Ty<'tcx>>) -> Ty<'tcx> {
Ty::new(tcx, UnsafeBinder(b.into()))
}
#[inline]
pub fn new_dynamic(
tcx: TyCtxt<'tcx>,
@ -962,6 +967,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
Ty::new_pat(interner, ty, pat)
}
fn new_unsafe_binder(interner: TyCtxt<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>) -> Self {
Ty::new_unsafe_binder(interner, ty)
}
fn new_unit(interner: TyCtxt<'tcx>) -> Self {
interner.types.unit
}
@ -1480,6 +1489,7 @@ impl<'tcx> Ty<'tcx> {
| ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::UnsafeBinder(_)
| ty::Error(_)
| ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8,
@ -1659,6 +1669,8 @@ impl<'tcx> Ty<'tcx> {
// metadata of `tail`.
ty::Param(_) | ty::Alias(..) => Err(tail),
| ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
ty::Infer(ty::TyVar(_))
| ty::Pat(..)
| ty::Bound(..)
@ -1819,6 +1831,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::RawPtr(..)
| ty::Char
| ty::Ref(..)
@ -1898,6 +1911,8 @@ impl<'tcx> Ty<'tcx> {
// Might be, but not "trivial" so just giving the safe answer.
ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false,
ty::UnsafeBinder(_) => false,
// Needs normalization or revealing to determine, so no is the safe answer.
ty::Alias(..) => false,
@ -1976,7 +1991,8 @@ impl<'tcx> Ty<'tcx> {
| Coroutine(_, _)
| CoroutineWitness(..)
| Never
| Tuple(_) => true,
| Tuple(_)
| UnsafeBinder(_) => true,
Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false,
}
}

View file

@ -1241,6 +1241,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Foreign(_)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_)
| ty::Infer(_)
| ty::Alias(..)
| ty::Param(_)
@ -1281,6 +1282,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Foreign(_)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_)
| ty::Infer(_)
| ty::Alias(..)
| ty::Param(_)
@ -1322,6 +1324,9 @@ impl<'tcx> Ty<'tcx> {
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => AsyncDropGlueMorphology::Noop,
// FIXME(unsafe_binders):
ty::UnsafeBinder(_) => todo!(),
ty::Tuple(tys) if tys.is_empty() => AsyncDropGlueMorphology::Noop,
ty::Adt(adt_def, _) if adt_def.is_manually_drop() => AsyncDropGlueMorphology::Noop,
@ -1522,7 +1527,7 @@ impl<'tcx> Ty<'tcx> {
false
}
ty::Foreign(_) | ty::CoroutineWitness(..) | ty::Error(_) => false,
ty::Foreign(_) | ty::CoroutineWitness(..) | ty::Error(_) | ty::UnsafeBinder(_) => false,
}
}
@ -1681,7 +1686,8 @@ pub fn needs_drop_components_with_async<'tcx>(
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => Ok(smallvec![ty]),
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_) => Ok(smallvec![ty]),
}
}

View file

@ -194,6 +194,9 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
sig_tys.skip_binder().inputs_and_output.iter().rev().map(|ty| ty.into()),
);
}
ty::UnsafeBinder(bound_ty) => {
stack.push(bound_ty.skip_binder().into());
}
},
GenericArgKind::Lifetime(_) => {}
GenericArgKind::Const(parent_ct) => match parent_ct.kind() {

View file

@ -161,6 +161,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
| ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Bound(_, _)
@ -200,6 +201,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
| ty::Dynamic(_, _, _)
| ty::CoroutineWitness(..)
| ty::Never
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Bound(_, _)

View file

@ -944,7 +944,8 @@ fn try_write_constant<'tcx>(
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"),
| ty::Dynamic(..)
| ty::UnsafeBinder(_) => throw_machine_stop_str!("unsupported type"),
ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(),
}

View file

@ -285,7 +285,9 @@ fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Span> {
| ty::Placeholder(_)
| ty::Infer(_)
| ty::Slice(_)
| ty::Array(_, _) => None,
| ty::Array(_, _)
| ty::UnsafeBinder(_) => None,
ty::Adt(adt_def, _) => {
let did = adt_def.did();
let try_local_did_span = |did: DefId| {

View file

@ -378,6 +378,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
| ty::Pat(_, _)
| ty::FnDef(_, _)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Dynamic(_, _, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)

View file

@ -339,7 +339,9 @@ where
| ty::Slice(..)
| ty::RawPtr(..)
| ty::Never
| ty::Tuple(..) => self.found_non_local_ty(ty),
| ty::Tuple(..)
// FIXME(unsafe_binders): Non-local?
| ty::UnsafeBinder(_) => self.found_non_local_ty(ty),
ty::Param(..) => panic!("unexpected ty param"),

View file

@ -545,6 +545,7 @@ where
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
@ -634,6 +635,7 @@ where
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Alias(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)

View file

@ -83,6 +83,8 @@ where
.map(|bty| bty.instantiate(cx, args))
.collect()),
ty::UnsafeBinder(bound_ty) => Ok(vec![bound_ty.into()]),
// For `PhantomData<T>`, we pass `T`.
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]),
@ -144,6 +146,8 @@ where
panic!("unexpected type `{ty:?}`")
}
ty::UnsafeBinder(bound_ty) => Ok(vec![bound_ty.into()]),
// impl Sized for ()
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |ty| vec![ty::Binder::dummy(ty)])),
@ -239,6 +243,8 @@ where
}
},
ty::UnsafeBinder(_) => Err(NoSolution),
// impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types
ty::CoroutineWitness(def_id, args) => Ok(ecx
.cx()
@ -374,6 +380,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
| ty::Never
| ty::Tuple(_)
| ty::Pat(_, _)
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Placeholder(..)
@ -544,6 +551,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never
| ty::UnsafeBinder(_)
| ty::Tuple(_)
| ty::Alias(_, _)
| ty::Param(_)
@ -694,7 +702,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
| ty::Param(_)
| ty::Placeholder(..)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Error(_) => return Err(NoSolution),
| ty::Error(_)
| ty::UnsafeBinder(_) => return Err(NoSolution),
ty::Bound(..)
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
@ -764,6 +773,10 @@ pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
| ty::Coroutine(_, _)
| ty::CoroutineWitness(_, _) => Err(NoSolution),
// FIXME(unsafe_binders): Unsafe binders could implement `~const Drop`
// if their inner type implements it.
ty::UnsafeBinder(_) => Err(NoSolution),
ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
Err(NoSolution)
}

View file

@ -619,6 +619,11 @@ where
Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]),
},
ty::UnsafeBinder(_) => {
// FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders.
todo!()
}
ty::Infer(
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
)
@ -822,6 +827,11 @@ where
| ty::Tuple(_)
| ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
ty::UnsafeBinder(_) => {
// FIXME(unsafe_binders): instantiate this with placeholders?? i guess??
todo!("discr subgoal...")
}
// We do not call `Ty::discriminant_ty` on alias, param, or placeholder
// types, which return `<self_ty as DiscriminantKind>::Discriminant`
// (or ICE in the case of placeholders). Projecting a type to itself
@ -869,6 +879,11 @@ where
| ty::Tuple(_)
| ty::Error(_) => self_ty.async_destructor_ty(ecx.cx()),
ty::UnsafeBinder(_) => {
// FIXME(unsafe_binders): Instantiate the binder with placeholders I guess.
todo!()
}
// We do not call `Ty::async_destructor_ty` on alias, param, or placeholder
// types, which return `<self_ty as AsyncDestruct>::AsyncDestructor`
// (or ICE in the case of placeholders). Projecting a type to itself

View file

@ -1100,7 +1100,8 @@ where
| ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Adt(_, _) => {
| ty::Adt(_, _)
| ty::UnsafeBinder(_) => {
let mut disqualifying_impl = None;
self.cx().for_each_relevant_impl(
goal.predicate.def_id(),

View file

@ -415,6 +415,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Error(_) => ConstructorSet::Unlistable,

View file

@ -285,6 +285,7 @@ where
| ty::Ref(..)
| ty::Pat(..)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Param(..)
| ty::Bound(..)
| ty::Error(_)

View file

@ -621,6 +621,11 @@ pub(crate) fn encode_ty<'tcx>(
typeid.push_str(&s);
}
// FIXME(unsafe_binders): Implement this.
ty::UnsafeBinder(_) => {
todo!()
}
// Trait types
ty::Dynamic(predicates, region, kind) => {
// u3dynI<element-type1[..element-typeN]>E, where <element-type> is <predicate>, as

View file

@ -64,7 +64,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
| ty::Pat(..)
| ty::Slice(..)
| ty::Str
| ty::Tuple(..) => t.super_fold_with(self),
| ty::Tuple(..)
| ty::UnsafeBinder(_) => t.super_fold_with(self),
ty::Bool => {
if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {

View file

@ -356,6 +356,8 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
ty::FnPtr(sig_tys, hdr) => {
TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables)))
}
// FIXME(unsafe_binders):
ty::UnsafeBinder(_) => todo!(),
ty::Dynamic(existential_predicates, region, dyn_kind) => {
TyKind::RigidTy(RigidTy::Dynamic(
existential_predicates

View file

@ -2149,6 +2149,7 @@ symbols! {
unwrap,
unwrap_binder,
unwrap_or,
unwrap_unsafe_binder,
use_extern_macros,
use_nested_groups,
used,

View file

@ -466,6 +466,9 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
})?;
}
// FIXME(unsafe_binder):
ty::UnsafeBinder(..) => todo!(),
ty::Dynamic(predicates, r, kind) => {
self.push(match kind {
ty::Dyn => "D",

View file

@ -1532,6 +1532,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
ty::CoroutineWitness(..) => Some(20),
ty::CoroutineClosure(..) => Some(21),
ty::Pat(..) => Some(22),
ty::UnsafeBinder(..) => Some(23),
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
}
}

View file

@ -1047,6 +1047,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// Integers and floats always have `u8` as their discriminant.
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
// type parameters, opaques, and unnormalized projections don't have
// a known discriminant and may need to be normalized further or rely
// on param env for discriminant projections
@ -1072,6 +1074,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
@ -1163,6 +1166,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
true
}
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
// FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
ty::Param(_)
| ty::Alias(..)

View file

@ -83,7 +83,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
| ty::Placeholder(..)
| ty::Infer(_)
| ty::Bound(..)
| ty::Coroutine(..) => false,
| ty::Coroutine(..)
| ty::UnsafeBinder(_) => false,
}
}
@ -336,6 +337,11 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
constraints.dtorck_types.push(ty);
}
// Can't instantiate binder here.
ty::UnsafeBinder(_) => {
constraints.dtorck_types.push(ty);
}
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
// By the time this code runs, all type variables ought to
// be fully resolved.

View file

@ -619,7 +619,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
continue;
}
match obligation.self_ty().skip_binder().kind() {
let self_ty = obligation.self_ty().skip_binder();
match self_ty.kind() {
// Fast path to avoid evaluating an obligation that trivially holds.
// There may be more bounds, but these are checked by the regular path.
ty::FnPtr(..) => return false,
@ -651,6 +652,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_)
| ty::Never
| ty::Tuple(_)
| ty::Error(_) => return true,
@ -794,7 +796,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Coroutine(..)
| ty::Never
| ty::Tuple(_)
| ty::CoroutineWitness(..) => {
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_) => {
// Only consider auto impls of unsafe traits when there are
// no unsafe fields.
if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
@ -1176,6 +1179,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::FnDef(_, _)
| ty::Pat(_, _)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Dynamic(_, _, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
@ -1220,6 +1224,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::UnsafeBinder(_)
| ty::Never
| ty::Tuple(..)
| ty::Alias(..)

View file

@ -2095,6 +2095,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
}
// FIXME(unsafe_binders): This binder needs to be squashed
ty::UnsafeBinder(binder_ty) => Where(binder_ty.map_bound(|ty| vec![ty])),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => None,
ty::Infer(ty::TyVar(_)) => Ambiguous,
@ -2133,6 +2136,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
None
}
// FIXME(unsafe_binder): Should we conditionally
// (i.e. universally) implement copy/clone?
ty::UnsafeBinder(_) => None,
ty::Dynamic(..)
| ty::Str
| ty::Slice(..)
@ -2285,6 +2292,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| ty::Never
| ty::Char => ty::Binder::dummy(Vec::new()),
// FIXME(unsafe_binders): Squash the double binder for now, I guess.
ty::UnsafeBinder(_) => return Err(SelectionError::Unimplemented),
// Treat this like `struct str([u8]);`
ty::Str => ty::Binder::dummy(vec![Ty::new_slice(self.tcx(), self.tcx().types.u8)]),

View file

@ -828,6 +828,9 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
// Let the visitor iterate into the argument/return
// types appearing in the fn signature.
}
ty::UnsafeBinder(_) => {
// FIXME(unsafe_binders): We should also recurse into the binder here.
}
ty::Dynamic(data, r, _) => {
// WfObject

View file

@ -49,7 +49,8 @@ fn resolve_instance_raw<'tcx>(
| ty::Adt(..)
| ty::Dynamic(..)
| ty::Array(..)
| ty::Slice(..) => {}
| ty::Slice(..)
| ty::UnsafeBinder(..) => {}
// Drop shims can only be built from ADTs.
_ => return Ok(None),
}

View file

@ -666,6 +666,11 @@ fn layout_of_uncached<'tcx>(
tcx.mk_layout(layout)
}
ty::UnsafeBinder(bound_ty) => {
let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into());
cx.layout_of(ty)?.layout
}
// Types with no meaningful known layout.
ty::Alias(..) => {
// NOTE(eddyb) `layout_of` query should've normalized these away,

View file

@ -202,6 +202,11 @@ where
}
}
ty::UnsafeBinder(bound_ty) => {
let ty = self.tcx.instantiate_bound_regions_with_erased(bound_ty.into());
queue_type(self, ty);
}
_ if tcx.type_is_copy_modulo_regions(self.typing_env, component) => {}
ty::Closure(_, args) => {

View file

@ -37,6 +37,8 @@ fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'
| Never
| Dynamic(_, _, ty::DynStar) => None,
UnsafeBinder(_) => todo!(),
// these are never sized
Str | Slice(..) | Dynamic(_, _, ty::Dyn) | Foreign(..) => Some(ty),

View file

@ -6,8 +6,6 @@ use std::ops::{ControlFlow, Deref};
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
#[cfg(feature = "nightly")]
use rustc_serialize::Decodable;
use tracing::instrument;
use crate::data_structures::SsoHashSet;
@ -69,14 +67,14 @@ macro_rules! impl_binder_encode_decode {
self.as_ref().skip_binder().encode(e);
}
}
impl<I: Interner, D: crate::TyDecoder<I = I>> Decodable<D> for ty::Binder<I, $t>
impl<I: Interner, D: crate::TyDecoder<I = I>> rustc_serialize::Decodable<D> for ty::Binder<I, $t>
where
$t: TypeVisitable<I> + rustc_serialize::Decodable<D>,
I::BoundVarKinds: rustc_serialize::Decodable<D>,
{
fn decode(decoder: &mut D) -> Self {
let bound_vars = Decodable::decode(decoder);
ty::Binder::bind_with_vars(<$t>::decode(decoder), bound_vars)
let bound_vars = rustc_serialize::Decodable::decode(decoder);
ty::Binder::bind_with_vars(rustc_serialize::Decodable::decode(decoder), bound_vars)
}
}
)*

View file

@ -41,6 +41,7 @@ pub enum SimplifiedType<DefId> {
Coroutine(DefId),
CoroutineWitness(DefId),
Function(usize),
UnsafeBinder,
Placeholder,
Error,
}
@ -138,6 +139,7 @@ pub fn simplify_type<I: Interner>(
ty::FnPtr(sig_tys, _hdr) => {
Some(SimplifiedType::Function(sig_tys.skip_binder().inputs().len()))
}
ty::UnsafeBinder(_) => Some(SimplifiedType::UnsafeBinder),
ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
ty::Param(_) => match treat_params {
TreatParams::AsRigid => Some(SimplifiedType::Placeholder),
@ -290,7 +292,8 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Foreign(_)
| ty::Placeholder(_) => {}
| ty::Placeholder(_)
| ty::UnsafeBinder(_) => {}
};
// The type system needs to support exponentially large types
@ -447,6 +450,13 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth))
}
ty::UnsafeBinder(lhs_ty) => match rhs.kind() {
ty::UnsafeBinder(rhs_ty) => {
self.types_may_unify(lhs_ty.skip_binder(), rhs_ty.skip_binder())
}
_ => false,
},
ty::Error(..) => true,
}
}

View file

@ -112,6 +112,8 @@ pub trait Ty<I: Interner<Ty = Self>>:
fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self;
fn new_unsafe_binder(interner: I, ty: ty::Binder<I, I::Ty>) -> Self;
fn tuple_fields(self) -> I::Tys;
fn to_opt_closure_kind(self) -> Option<ty::ClosureKind>;
@ -185,6 +187,7 @@ pub trait Ty<I: Interner<Ty = Self>>:
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::CoroutineClosure(_, _)

View file

@ -202,6 +202,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnPtr(..)
| ty::UnsafeBinder(_)
| ty::Dynamic(_, _, _)
| ty::Tuple(_) => {
ty.super_visit_with(self);

View file

@ -549,6 +549,10 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
Ok(Ty::new_pat(cx, ty, pat))
}
(ty::UnsafeBinder(a_binder), ty::UnsafeBinder(b_binder)) => {
Ok(Ty::new_unsafe_binder(cx, relation.binders(*a_binder, *b_binder)?))
}
_ => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
}
}

View file

@ -1,4 +1,5 @@
use std::fmt;
use std::ops::Deref;
use derive_where::derive_where;
use rustc_ast_ir::Mutability;
@ -13,6 +14,7 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
use self::TyKind::*;
pub use self::closure::*;
use crate::inherent::*;
use crate::visit::TypeVisitable;
use crate::{self as ty, DebruijnIndex, Interner};
mod closure;
@ -150,6 +152,13 @@ pub enum TyKind<I: Interner> {
/// worth the mild inconvenience.
FnPtr(ty::Binder<I, FnSigTys<I>>, FnHeader<I>),
/// An unsafe binder type.
///
/// A higher-ranked type used to represent a type which has had some of its
/// lifetimes erased. This can be used to represent types in positions where
/// a lifetime is literally inexpressible, such as self-referential types.
UnsafeBinder(UnsafeBinderInner<I>),
/// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
Dynamic(I::BoundExistentialPredicates, I::Region, DynKind),
@ -287,6 +296,8 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t),
FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(),
FnPtr(sig_tys, hdr) => write!(f, "{:?}", sig_tys.with(*hdr)),
// FIXME(unsafe_binder): print this like `unsafe<'a> T<'a>`.
UnsafeBinder(binder) => write!(f, "{:?}", binder),
Dynamic(p, r, repr) => match repr {
DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
@ -964,6 +975,66 @@ impl<I: Interner> fmt::Debug for FnSig<I> {
}
}
// FIXME: this is a distinct type because we need to define `Encode`/`Decode`
// impls in this crate for `Binder<I, I::Ty>`.
#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
pub struct UnsafeBinderInner<I: Interner>(ty::Binder<I, I::Ty>);
impl<I: Interner> From<ty::Binder<I, I::Ty>> for UnsafeBinderInner<I> {
fn from(value: ty::Binder<I, I::Ty>) -> Self {
UnsafeBinderInner(value)
}
}
impl<I: Interner> From<UnsafeBinderInner<I>> for ty::Binder<I, I::Ty> {
fn from(value: UnsafeBinderInner<I>) -> Self {
value.0
}
}
impl<I: Interner> fmt::Debug for UnsafeBinderInner<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<I: Interner> Deref for UnsafeBinderInner<I> {
type Target = ty::Binder<I, I::Ty>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(feature = "nightly")]
impl<I: Interner, E: crate::TyEncoder<I = I>> rustc_serialize::Encodable<E> for UnsafeBinderInner<I>
where
I::Ty: rustc_serialize::Encodable<E>,
I::BoundVarKinds: rustc_serialize::Encodable<E>,
{
fn encode(&self, e: &mut E) {
self.bound_vars().encode(e);
self.as_ref().skip_binder().encode(e);
}
}
#[cfg(feature = "nightly")]
impl<I: Interner, D: crate::TyDecoder<I = I>> rustc_serialize::Decodable<D> for UnsafeBinderInner<I>
where
I::Ty: TypeVisitable<I> + rustc_serialize::Decodable<D>,
I::BoundVarKinds: rustc_serialize::Decodable<D>,
{
fn decode(decoder: &mut D) -> Self {
let bound_vars = rustc_serialize::Decodable::decode(decoder);
UnsafeBinderInner(ty::Binder::bind_with_vars(
rustc_serialize::Decodable::decode(decoder),
bound_vars,
))
}
}
// This is just a `FnSig` without the `FnHeader` fields.
#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]

View file

@ -2255,12 +2255,14 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
}
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binders)"),
ty::Closure(..) => panic!("Closure"),
ty::CoroutineClosure(..) => panic!("CoroutineClosure"),
ty::Coroutine(..) => panic!("Coroutine"),
ty::Placeholder(..) => panic!("Placeholder"),
ty::CoroutineWitness(..) => panic!("CoroutineWitness"),
ty::Infer(..) => panic!("Infer"),
ty::Error(_) => FatalError.raise(),
}
}

View file

@ -559,6 +559,7 @@ impl<'tcx> LinkCollector<'_, 'tcx> {
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Dynamic(..)
| ty::UnsafeBinder(_)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(_)

View file

@ -877,7 +877,8 @@ impl TyCoercionStability {
| ty::CoroutineClosure(..)
| ty::Never
| ty::Tuple(_)
| ty::Alias(ty::Projection, _) => Self::Deref,
| ty::Alias(ty::Projection, _)
| ty::UnsafeBinder(_) => Self::Deref,
};
}
}

View file

@ -677,6 +677,9 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
ExprKind::Type(e, _) => {
helper(typeck, consume, e, f)?;
},
ExprKind::UnsafeBinderCast(_, e, _) => {
helper(typeck, consume, e, f)?;
},
// Either drops temporaries, jumps out of the current expression, or has no sub expression.
ExprKind::DropTemps(_)
@ -694,7 +697,6 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
| ExprKind::Continue(_)
| ExprKind::InlineAsm(_)
| ExprKind::OffsetOf(..)
| ExprKind::UnsafeBinderCast(..)
| ExprKind::Err(_) => (),
}
ControlFlow::Continue(())

View file

@ -37,7 +37,7 @@
// Const generic parameter
// gdb-command:info functions -q function_names::const_generic_fn.*
// gdb-check:[...]static fn function_names::const_generic_fn_bool<false>();
// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#a70c39591cb5f53d}>();
// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#ffa3db4ca1d52dce}>();
// gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>();
// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>();

View file

@ -13,34 +13,8 @@ fn main() {
let kind = TyKind::Bool; //~ ERROR usage of `ty::TyKind::<kind>`
match kind {
TyKind::Bool => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Char => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Int(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Uint(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Float(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Adt(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Foreign(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Str => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Array(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Pat(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Slice(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::RawPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Ref(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::FnDef(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::FnPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Dynamic(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::CoroutineClosure(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Coroutine(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::CoroutineWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Never => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Tuple(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Alias(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Param(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Bound(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Placeholder(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Infer(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Error(_) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Bool => {}, //~ ERROR usage of `ty::TyKind::<kind>`
_ => {}
}
if let ty::Int(int_ty) = kind {}

View file

@ -13,179 +13,17 @@ LL | #[deny(rustc::usage_of_ty_tykind)]
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:16:9
|
LL | TyKind::Bool => (),
LL | TyKind::Bool => {},
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:17:9
|
LL | TyKind::Char => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:18:9
|
LL | TyKind::Int(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:19:9
|
LL | TyKind::Uint(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:20:9
|
LL | TyKind::Float(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:21:9
|
LL | TyKind::Adt(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:22:9
|
LL | TyKind::Foreign(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:23:9
|
LL | TyKind::Str => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:24:9
|
LL | TyKind::Array(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:25:9
|
LL | TyKind::Pat(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:26:9
|
LL | TyKind::Slice(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:27:9
|
LL | TyKind::RawPtr(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:28:9
|
LL | TyKind::Ref(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:29:9
|
LL | TyKind::FnDef(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:30:9
|
LL | TyKind::FnPtr(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:31:9
|
LL | TyKind::Dynamic(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:32:9
|
LL | TyKind::Closure(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:33:9
|
LL | TyKind::CoroutineClosure(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:34:9
|
LL | TyKind::Coroutine(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:35:9
|
LL | TyKind::CoroutineWitness(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:36:9
|
LL | TyKind::Never => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:37:9
|
LL | TyKind::Tuple(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:38:9
|
LL | TyKind::Alias(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:39:9
|
LL | TyKind::Param(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:40:9
|
LL | TyKind::Bound(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:41:9
|
LL | TyKind::Placeholder(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:42:9
|
LL | TyKind::Infer(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:43:9
|
LL | TyKind::Error(_) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:48:12
--> $DIR/ty_tykind_usage.rs:22:12
|
LL | if let TyKind::Int(int_ty) = kind {}
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind`
--> $DIR/ty_tykind_usage.rs:50:24
--> $DIR/ty_tykind_usage.rs:24:24
|
LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
| ^^^^^^^^^^
@ -193,7 +31,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
= help: try using `Ty` instead
error: usage of `ty::TyKind`
--> $DIR/ty_tykind_usage.rs:52:37
--> $DIR/ty_tykind_usage.rs:26:37
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
@ -201,7 +39,7 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
= help: try using `Ty` instead
error: usage of `ty::TyKind`
--> $DIR/ty_tykind_usage.rs:52:53
--> $DIR/ty_tykind_usage.rs:26:53
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
@ -209,12 +47,12 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
= help: try using `Ty` instead
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:55:9
--> $DIR/ty_tykind_usage.rs:29:9
|
LL | IrTyKind::Bool
| --------^^^^^^
| |
| help: try using `ty::<kind>` directly: `ty`
error: aborting due to 34 previous errors
error: aborting due to 7 previous errors

View file

@ -7,6 +7,6 @@ auto trait AutoDummyTrait {}
//~^ ERROR auto traits are experimental and possibly buggy
impl !AutoDummyTrait for DummyStruct {}
//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
//~^ ERROR negative trait bounds are not fully implemented; use marker types for now
fn main() {}

View file

@ -8,7 +8,7 @@ LL | auto trait AutoDummyTrait {}
= help: add `#![feature(auto_traits)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
error[E0658]: negative trait bounds are not fully implemented; use marker types for now
--> $DIR/feature-gate-auto-traits.rs:9:6
|
LL | impl !AutoDummyTrait for DummyStruct {}

View file

@ -1,10 +1,10 @@
error: symbol-name(_ZN5basic4main17had874e876c8b1028E)
error: symbol-name(_ZN5basic4main17h144191e1523a280eE)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
error: demangling(basic::main::had874e876c8b1028)
error: demangling(basic::main::h144191e1523a280e)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]

View file

@ -1,10 +1,10 @@
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17haf0d0ad2255e29c6E)
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h71f988fda3b6b180E)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::haf0d0ad2255e29c6)
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h71f988fda3b6b180)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]

View file

@ -1,3 +1,3 @@
trait MyTrait {}
impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not yet fully implemented
impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not fully implemented
fn main() {}

View file

@ -1,4 +1,4 @@
error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
error[E0658]: negative trait bounds are not fully implemented; use marker types for now
--> $DIR/feature-gate-negative_impls.rs:2:6
|
LL | impl !MyTrait for u32 {}

View file

@ -4,10 +4,11 @@
use std::unsafe_binder::{wrap_binder, unwrap_binder};
fn main() {
unsafe {
let x = 1;
let binder: unsafe<'a> &'a i32 = wrap_binder!(x);
//~^ ERROR unsafe binders are not yet implemented
//~| ERROR unsafe binders are not yet implemented
let rx = *unwrap_binder!(binder);
//~^ ERROR unsafe binders are not yet implemented
let binder: unsafe<'a> &'a i32 = wrap_binder!(&x);
//~^ ERROR unsafe binder casts are not fully implemented
let rx = *unwrap_binder!(binder);
//~^ ERROR unsafe binder casts are not fully implemented
}
}

View file

@ -7,23 +7,17 @@ LL | #![feature(unsafe_binders)]
= note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
= note: `#[warn(incomplete_features)]` on by default
error: unsafe binders are not yet implemented
--> $DIR/expr.rs:8:17
error: unsafe binder casts are not fully implemented
--> $DIR/expr.rs:9:55
|
LL | let binder: unsafe<'a> &'a i32 = wrap_binder!(x);
| ^^^^^^^^^^^^^^^^^^
LL | let binder: unsafe<'a> &'a i32 = wrap_binder!(&x);
| ^^
error: unsafe binders are not yet implemented
--> $DIR/expr.rs:8:51
error: unsafe binder casts are not fully implemented
--> $DIR/expr.rs:11:34
|
LL | let binder: unsafe<'a> &'a i32 = wrap_binder!(x);
| ^
LL | let rx = *unwrap_binder!(binder);
| ^^^^^^
error: unsafe binders are not yet implemented
--> $DIR/expr.rs:11:30
|
LL | let rx = *unwrap_binder!(binder);
| ^^^^^^
error: aborting due to 3 previous errors; 1 warning emitted
error: aborting due to 2 previous errors; 1 warning emitted

View file

@ -3,16 +3,13 @@
fn foo<'a>() {
let good: unsafe<'b> &'a &'b ();
//~^ ERROR unsafe binders are not yet implemented
let missing: unsafe<> &'missing ();
//~^ ERROR unsafe binders are not yet implemented
//~| ERROR use of undeclared lifetime name `'missing`
//~^ ERROR use of undeclared lifetime name `'missing`
fn inner<'b>() {
let outer: unsafe<> &'a &'b ();
//~^ ERROR unsafe binders are not yet implemented
//~| can't use generic parameters from outer item
//~^ can't use generic parameters from outer item
}
}

View file

@ -1,5 +1,5 @@
error[E0261]: use of undeclared lifetime name `'missing`
--> $DIR/lifetime-resolution.rs:8:28
--> $DIR/lifetime-resolution.rs:7:28
|
LL | let missing: unsafe<> &'missing ();
| ^^^^^^^^ undeclared lifetime
@ -15,7 +15,7 @@ LL | fn foo<'missing, 'a>() {
| +++++++++
error[E0401]: can't use generic parameters from outer item
--> $DIR/lifetime-resolution.rs:13:30
--> $DIR/lifetime-resolution.rs:11:30
|
LL | fn foo<'a>() {
| -- lifetime parameter from outer item
@ -41,25 +41,7 @@ LL | #![feature(unsafe_binders)]
= note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
= note: `#[warn(incomplete_features)]` on by default
error: unsafe binders are not yet implemented
--> $DIR/lifetime-resolution.rs:5:15
|
LL | let good: unsafe<'b> &'a &'b ();
| ^^^^^^^^^^^^^^^^^^^^^
error: unsafe binders are not yet implemented
--> $DIR/lifetime-resolution.rs:8:18
|
LL | let missing: unsafe<> &'missing ();
| ^^^^^^^^^^^^^^^^^^^^^
error: unsafe binders are not yet implemented
--> $DIR/lifetime-resolution.rs:13:20
|
LL | let outer: unsafe<> &'a &'b ();
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors; 1 warning emitted
error: aborting due to 2 previous errors; 1 warning emitted
Some errors have detailed explanations: E0261, E0401.
For more information about an error, try `rustc --explain E0261`.

View file

@ -0,0 +1,43 @@
#![feature(unsafe_binders)]
//~^ WARN the feature `unsafe_binders` is incomplete
use std::unsafe_binder::{wrap_binder, unwrap_binder};
fn a() {
let _: unsafe<'a> &'a i32 = wrap_binder!(&());
//~^ ERROR unsafe binder casts are not fully implemented
//~| ERROR mismatched types
}
fn b() {
let _: i32 = wrap_binder!(&());
//~^ ERROR unsafe binder casts are not fully implemented
//~| ERROR `wrap_binder!()` can only wrap into unsafe binder
}
fn c() {
let y = 1;
unwrap_binder!(y);
//~^ ERROR unsafe binder casts are not fully implemented
//~| ERROR expected unsafe binder, found integer as input
}
fn d() {
let unknown = Default::default();
unwrap_binder!(unknown);
//~^ ERROR unsafe binder casts are not fully implemented
// FIXME(unsafe_binders): This should report ambiguity once we've removed
// the error above which taints the infcx.
}
fn e() {
let x = wrap_binder!(&42);
//~^ ERROR unsafe binder casts are not fully implemented
// Currently, type inference doesn't flow backwards for unsafe binders.
// It could, perhaps, but that may cause even more surprising corners.
// FIXME(unsafe_binders): This should report ambiguity once we've removed
// the error above which taints the infcx.
let _: unsafe<'a> &'a i32 = x;
}
fn main() {}

View file

@ -0,0 +1,68 @@
warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/mismatch.rs:1:12
|
LL | #![feature(unsafe_binders)]
| ^^^^^^^^^^^^^^
|
= note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
= note: `#[warn(incomplete_features)]` on by default
error: unsafe binder casts are not fully implemented
--> $DIR/mismatch.rs:7:46
|
LL | let _: unsafe<'a> &'a i32 = wrap_binder!(&());
| ^^^
error[E0308]: mismatched types
--> $DIR/mismatch.rs:7:46
|
LL | let _: unsafe<'a> &'a i32 = wrap_binder!(&());
| ^^^ expected `&i32`, found `&()`
|
= note: expected reference `&i32`
found reference `&()`
error: unsafe binder casts are not fully implemented
--> $DIR/mismatch.rs:13:31
|
LL | let _: i32 = wrap_binder!(&());
| ^^^
error: `wrap_binder!()` can only wrap into unsafe binder, not `i32`
--> $DIR/mismatch.rs:13:18
|
LL | let _: i32 = wrap_binder!(&());
| ^^^^^^^^^^^^^^^^^
|
= note: unsafe binders are the only valid output of wrap
= note: this error originates in the macro `wrap_binder` (in Nightly builds, run with -Z macro-backtrace for more info)
error: unsafe binder casts are not fully implemented
--> $DIR/mismatch.rs:20:20
|
LL | unwrap_binder!(y);
| ^
error: expected unsafe binder, found integer as input of `unwrap_binder!()`
--> $DIR/mismatch.rs:20:20
|
LL | unwrap_binder!(y);
| ^
|
= note: only an unsafe binder type can be unwrapped
error: unsafe binder casts are not fully implemented
--> $DIR/mismatch.rs:27:20
|
LL | unwrap_binder!(unknown);
| ^^^^^^^
error: unsafe binder casts are not fully implemented
--> $DIR/mismatch.rs:34:26
|
LL | let x = wrap_binder!(&42);
| ^^^
error: aborting due to 8 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,7 +1,8 @@
//@ check-pass
#![feature(unsafe_binders)]
//~^ WARN the feature `unsafe_binders` is incomplete
fn main() {
let x: unsafe<'a> &'a ();
//~^ ERROR unsafe binders are not yet implemented
}

View file

@ -1,5 +1,5 @@
warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/simple.rs:1:12
--> $DIR/simple.rs:3:12
|
LL | #![feature(unsafe_binders)]
| ^^^^^^^^^^^^^^
@ -7,11 +7,5 @@ LL | #![feature(unsafe_binders)]
= note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
= note: `#[warn(incomplete_features)]` on by default
error: unsafe binders are not yet implemented
--> $DIR/simple.rs:5:12
|
LL | let x: unsafe<'a> &'a ();
| ^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error; 1 warning emitted
warning: 1 warning emitted