Skip to content

Commit afef083

Browse files
committed
Use !null pattern type in libcore
1 parent 13fb85c commit afef083

File tree

44 files changed

+375
-202
lines changed

Some content is hidden

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

44 files changed

+375
-202
lines changed

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ pub(crate) fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
230230
) -> (Bx::Value, Bx::Value) {
231231
debug!("unsize_ptr: {:?} => {:?}", src_ty, dst_ty);
232232
match (src_ty.kind(), dst_ty.kind()) {
233+
(&ty::Pat(a, _), &ty::Pat(b, _)) => unsize_ptr(bx, src, a, b, old_info),
233234
(&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _))
234235
| (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => {
235236
assert_eq!(bx.cx().type_is_sized(a), old_info.is_none());

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10641064
//
10651065
// This is also relevant for `Pin<&mut Self>`, where we need to peel the
10661066
// `Pin`.
1067+
1068+
loop {
1069+
match *op.layout.ty.kind() {
1070+
ty::Ref(..) | ty::RawPtr(..) => break,
1071+
ty::Pat(inner, _) => op.layout = bx.layout_of(inner),
1072+
_ => {
1073+
let (idx, _) = op.layout.non_1zst_field(bx).expect(
1074+
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
1075+
);
1076+
op = op.extract_field(self, bx, idx);
1077+
}
1078+
}
1079+
}
10671080
while !op.layout.ty.is_raw_ptr() && !op.layout.ty.is_ref() {
10681081
let (idx, _) = op.layout.non_1zst_field(bx).expect(
10691082
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
473473
) -> InterpResult<'tcx> {
474474
trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty);
475475
match (src.layout.ty.kind(), cast_ty.ty.kind()) {
476+
(&ty::Pat(s, s_pat), &ty::Pat(c, c_pat)) if s_pat == c_pat => {
477+
let mut src = src.clone();
478+
src.layout = self.layout_of(s)?;
479+
let mut dest = dest.clone();
480+
dest.layout = self.layout_of(c)?;
481+
let cast_ty = match *cast_ty.ty.kind() {
482+
ty::Pat(base, pat) if pat == c_pat => self.layout_of(base)?,
483+
_ => span_bug!(
484+
self.cur_span(),
485+
"unsize_into: invalid cast ty for pattern type: {cast_ty:#?}"
486+
),
487+
};
488+
self.unsize_into(&src, cast_ty, &dest)
489+
}
476490
(&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _))
477491
| (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, s, c),
478492
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {

compiler/rustc_const_eval/src/interpret/visitor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,12 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
156156
);
157157
// ... that contains a `NonNull`... (gladly, only a single field here)
158158
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
159-
let raw_ptr = self.ecx().project_field(&nonnull_ptr, 0)?; // the actual raw ptr
159+
let pat_ty = self.ecx().project_field(&nonnull_ptr, 0)?; // `*mut T is !null`
160+
let base = match *pat_ty.layout().ty.kind() {
161+
ty::Pat(base, _) => self.ecx().layout_of(base)?,
162+
_ => unreachable!(),
163+
};
164+
let raw_ptr = pat_ty.transmute(base, self.ecx())?; // The actual raw pointer
160165
// ... whose only field finally is a raw ptr we can dereference.
161166
self.visit_box(ty, &raw_ptr)?;
162167

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applica
9999
100100
hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
101101
102+
hir_analysis_coerce_same_pat_kind = only pattern types with the same pattern can be coerced between each other
103+
102104
hir_analysis_coerce_unsized_field_validity = for `{$ty}` to have a valid implementation of `{$trait_name}`, it must be possible to coerce the field of type `{$field_ty}`
103105
.label = `{$field_ty}` must be a pointer, reference, or smart pointer that is allowed to be unsized
104106

compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,18 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
251251
// in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent)
252252
// even if they do not carry that attribute.
253253
match (source.kind(), target.kind()) {
254+
(&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => {
255+
if pat_a != pat_b {
256+
return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
257+
span,
258+
trait_name,
259+
pat_a: pat_a.to_string(),
260+
pat_b: pat_b.to_string(),
261+
}));
262+
}
263+
Ok(())
264+
}
265+
254266
(&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b))
255267
if r_a == *r_b && mutbl_a == *mutbl_b =>
256268
{
@@ -416,6 +428,18 @@ pub(crate) fn coerce_unsized_info<'tcx>(
416428
(mt_a.ty, mt_b.ty, unsize_trait, None, span)
417429
};
418430
let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
431+
(&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => {
432+
if pat_a != pat_b {
433+
return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
434+
span,
435+
trait_name,
436+
pat_a: pat_a.to_string(),
437+
pat_b: pat_b.to_string(),
438+
}));
439+
}
440+
(ty_a, ty_b, coerce_unsized_trait, None, span)
441+
}
442+
419443
(&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
420444
infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
421445
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
@@ -715,13 +739,16 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
715739
let impl_span = tcx.def_span(checker.impl_def_id);
716740
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
717741

718-
let is_permitted_primitive = match *self_ty.kind() {
719-
ty::Adt(def, _) => def.is_box(),
720-
ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true,
721-
_ => false,
722-
};
742+
fn is_permitted_primitive(self_ty: Ty<'_>) -> bool {
743+
match *self_ty.kind() {
744+
ty::Adt(def, _) => def.is_box(),
745+
ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true,
746+
ty::Pat(base, _) => is_permitted_primitive(base),
747+
_ => false,
748+
}
749+
}
723750

724-
if is_permitted_primitive
751+
if is_permitted_primitive(self_ty)
725752
&& let Ok(layout) = tcx.layout_of(typing_env.as_query_input(self_ty))
726753
&& layout.layout.is_pointer_like(&tcx.data_layout)
727754
{

compiler/rustc_hir_analysis/src/coherence/orphan.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,8 @@ pub(crate) fn orphan_check_impl(
206206
(LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
207207
}
208208

209-
ty::Pat(..) => (
210-
LocalImpl::Disallow { problematic_kind: "pattern type" },
211-
NonlocalImpl::DisallowOther,
212-
),
213-
214209
ty::Bool
210+
| ty::Pat(..)
215211
| ty::Char
216212
| ty::Int(..)
217213
| ty::Uint(..)

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,16 @@ pub(crate) struct CoerceUnsizedNonStruct {
12801280
pub trait_name: &'static str,
12811281
}
12821282

1283+
#[derive(Diagnostic)]
1284+
#[diag(hir_analysis_coerce_same_pat_kind)]
1285+
pub(crate) struct CoerceSamePatKind {
1286+
#[primary_span]
1287+
pub span: Span,
1288+
pub trait_name: &'static str,
1289+
pub pat_a: String,
1290+
pub pat_b: String,
1291+
}
1292+
12831293
#[derive(Diagnostic)]
12841294
#[diag(hir_analysis_coerce_unsized_may, code = E0377)]
12851295
pub(crate) struct CoerceSameStruct {

compiler/rustc_middle/src/traits/select.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ pub enum SelectionCandidate<'tcx> {
159159
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
160160
FnPointerCandidate,
161161

162+
/// Builtin impl of the `PointerLike` trait.
163+
PointerLikeCandidate,
164+
162165
TraitAliasCandidate,
163166

164167
/// Matching `dyn Trait` with a supertrait of `Trait`. The index is the

compiler/rustc_mir_transform/src/elaborate_box_derefs.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
77
use rustc_middle::mir::visit::MutVisitor;
88
use rustc_middle::mir::*;
99
use rustc_middle::span_bug;
10-
use rustc_middle::ty::{Ty, TyCtxt};
10+
use rustc_middle::ty::{PatternKind, Ty, TyCtxt};
1111

1212
use crate::patch::MirPatch;
1313

@@ -17,13 +17,14 @@ fn build_ptr_tys<'tcx>(
1717
pointee: Ty<'tcx>,
1818
unique_did: DefId,
1919
nonnull_did: DefId,
20-
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
20+
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
2121
let args = tcx.mk_args(&[pointee.into()]);
2222
let unique_ty = tcx.type_of(unique_did).instantiate(tcx, args);
2323
let nonnull_ty = tcx.type_of(nonnull_did).instantiate(tcx, args);
2424
let ptr_ty = Ty::new_imm_ptr(tcx, pointee);
25+
let pat_ty = Ty::new_pat(tcx, ptr_ty, tcx.mk_pat(PatternKind::NotNull));
2526

26-
(unique_ty, nonnull_ty, ptr_ty)
27+
(unique_ty, nonnull_ty, pat_ty, ptr_ty)
2728
}
2829

2930
/// Constructs the projection needed to access a Box's pointer
@@ -63,7 +64,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
6364
{
6465
let source_info = self.local_decls[place.local].source_info;
6566

66-
let (unique_ty, nonnull_ty, ptr_ty) =
67+
let (unique_ty, nonnull_ty, _pat_ty, ptr_ty) =
6768
build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did);
6869

6970
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
@@ -130,10 +131,11 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
130131
let new_projections =
131132
new_projections.get_or_insert_with(|| base.projection.to_vec());
132133

133-
let (unique_ty, nonnull_ty, ptr_ty) =
134+
let (unique_ty, nonnull_ty, pat_ty, ptr_ty) =
134135
build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did);
135136

136137
new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty));
138+
new_projections.push(PlaceElem::Field(FieldIdx::ZERO, pat_ty));
137139
// While we can't project into `NonNull<_>` in a basic block
138140
// due to MCP#807, this is debug info where it's fine.
139141
new_projections.push(PlaceElem::Field(FieldIdx::ZERO, ptr_ty));

0 commit comments

Comments
 (0)