Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8c271d9

Browse files
committed
Allow unsizing pattern types with pointer base
1 parent 4baed81 commit 8c271d9

File tree

18 files changed

+164
-11
lines changed

18 files changed

+164
-11
lines changed

‎compiler/rustc_codegen_cranelift/src/unsize.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ pub(crate) fn coerce_unsized_into<'tcx>(
148148
dst.write_cvalue(fx, CValue::by_val_pair(base, info, dst.layout()));
149149
};
150150
match (&src_ty.kind(), &dst_ty.kind()) {
151+
(ty::Pat(a, _), ty::Pat(b, _)) => {
152+
let src = src.cast_pat_ty_to_base(fx.layout_of(*a));
153+
let dst = dst.place_transmute_type(fx, *b);
154+
return coerce_unsized_into(fx, src, dst);
155+
}
151156
(&ty::Ref(..), &ty::Ref(..))
152157
| (&ty::Ref(..), &ty::RawPtr(..))
153158
| (&ty::RawPtr(..), &ty::RawPtr(..)) => coerce_ptr(),

‎compiler/rustc_codegen_cranelift/src/value_and_place.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,14 @@ impl<'tcx> CValue<'tcx> {
379379
assert_eq!(self.layout().backend_repr, layout.backend_repr);
380380
CValue(self.0, layout)
381381
}
382+
383+
pub(crate) fn cast_pat_ty_to_base(self, layout: TyAndLayout<'tcx>) -> Self {
384+
let ty::Pat(base, _) = *self.layout().ty.kind() else {
385+
panic!("not a pattern type: {:#?}", self.layout())
386+
};
387+
assert_eq!(layout.ty, base);
388+
CValue(self.0, layout)
389+
}
382390
}
383391

384392
/// A place where you can write a value to or read a value from

‎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_const_eval/src/interpret/cast.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,12 @@ 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_pat), &ty::Pat(cast_ty, c_pat)) if s_pat == c_pat => {
477+
let src = self.project_field(src, FieldIdx::ZERO)?;
478+
let dest = self.project_field(dest, FieldIdx::ZERO)?;
479+
let cast_ty = self.layout_of(cast_ty)?;
480+
self.unsize_into(&src, cast_ty, &dest)
481+
}
476482
(&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _))
477483
| (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, s, c),
478484
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {

‎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
@@ -249,6 +249,18 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
249249
// in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent)
250250
// even if they do not carry that attribute.
251251
match (source.kind(), target.kind()) {
252+
(&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => {
253+
if pat_a != pat_b {
254+
return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
255+
span,
256+
trait_name,
257+
pat_a: pat_a.to_string(),
258+
pat_b: pat_b.to_string(),
259+
}));
260+
}
261+
Ok(())
262+
}
263+
252264
(&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b))
253265
if r_a == *r_b && mutbl_a == *mutbl_b =>
254266
{
@@ -414,6 +426,18 @@ pub(crate) fn coerce_unsized_info<'tcx>(
414426
(mt_a.ty, mt_b.ty, unsize_trait, None, span)
415427
};
416428
let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
429+
(&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => {
430+
if pat_a != pat_b {
431+
return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
432+
span,
433+
trait_name,
434+
pat_a: pat_a.to_string(),
435+
pat_b: pat_b.to_string(),
436+
}));
437+
}
438+
(ty_a, ty_b, coerce_unsized_trait, None, span)
439+
}
440+
417441
(&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
418442
infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
419443
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
@@ -713,13 +737,16 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
713737
let impl_span = tcx.def_span(checker.impl_def_id);
714738
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
715739

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

722-
if is_permitted_primitive
749+
if is_permitted_primitive(self_ty)
723750
&& let Ok(layout) = tcx.layout_of(typing_env.as_query_input(self_ty))
724751
&& layout.layout.is_pointer_like(&tcx.data_layout)
725752
{

‎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
@@ -1271,6 +1271,16 @@ pub(crate) struct CoerceUnsizedNonStruct {
12711271
pub trait_name: &'static str,
12721272
}
12731273

1274+
#[derive(Diagnostic)]
1275+
#[diag(hir_analysis_coerce_same_pat_kind)]
1276+
pub(crate) struct CoerceSamePatKind {
1277+
#[primary_span]
1278+
pub span: Span,
1279+
pub trait_name: &'static str,
1280+
pub pat_a: String,
1281+
pub pat_b: String,
1282+
}
1283+
12741284
#[derive(Diagnostic)]
12751285
#[diag(hir_analysis_coerce_unsized_may, code = E0377)]
12761286
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/validate.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
707707
};
708708
check_equal(self, location, *f_ty);
709709
}
710+
// Debug info is allowed to project into pattern types
711+
ty::Pat(base, _) => check_equal(self, location, *base),
710712
ty::Adt(adt_def, args) => {
711713
// see <https://github.com/rust-lang/rust/blob/7601adcc764d42c9f2984082b49948af652df986/compiler/rustc_middle/src/ty/layout.rs#L861-L864>
712714
if self.tcx.is_lang_item(adt_def.did(), LangItem::DynMetadata) {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /