Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Begin to implement type system layer of unsafe binders #134625

Merged
merged 1 commit into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
);
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
| ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Bound(_, _)
Expand Down Expand Up @@ -1654,6 +1655,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
| ty::Dynamic(_, _, _)
| ty::CoroutineWitness(..)
| ty::Never
| ty::UnsafeBinder(_)
| ty::Alias(_, _)
| ty::Param(_)
| ty::Bound(_, _)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(_)
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
}
}

Expand Down Expand Up @@ -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())
}
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_const_eval/src/interpret/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..)
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/util/type_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(_) => {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }))
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..)
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir_analysis/src/variance/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
98 changes: 89 additions & 9 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
Expand Down Expand Up @@ -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);
compiler-errors marked this conversation as resolved.
Show resolved Hide resolved
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(
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..)
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -2295,6 +2296,7 @@ impl<'tcx> TyCtxt<'tcx> {
Ref,
FnDef,
FnPtr,
UnsafeBinder,
Placeholder,
Coroutine,
CoroutineWitness,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, ..) => {
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
})
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/print/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(_)
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))?;
compiler-errors marked this conversation as resolved.
Show resolved Hide resolved
}
ty::Infer(infer_ty) => {
if self.should_print_verbose() {
p!(write("{:?}", ty.kind()));
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
Expand Down
Loading
Loading