Skip to content

Commit 60593cc

Browse files
committed
More work on DispatchFromDyn
Signed-off-by: Nick Cameron <nrc@ncameron.org>
1 parent 9f84704 commit 60593cc

File tree

2 files changed

+206
-9
lines changed

2 files changed

+206
-9
lines changed

chalk-solve/src/wf.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,9 +1069,9 @@ impl WfWellKnownConstraints {
10691069
}
10701070
}
10711071

1072-
/// Verify constraints ofa DispatchForDyn impl.
1072+
/// Verify constraints of a DispatchFromDyn impl.
10731073
///
1074-
/// Rules for DispatchForDyn impl to be considered well-formed:
1074+
/// Rules for DispatchFromDyn impl to be considered well-formed:
10751075
///
10761076
/// * Self and the type parameter must both be references or raw pointers with the same mutabilty
10771077
/// * OR all the following hold:
@@ -1080,7 +1080,7 @@ impl WfWellKnownConstraints {
10801080
/// - Self must not be `#[repr(packed)]` or `#[repr(C)]`
10811081
/// - Self must have exactly one field which is not a 1-ZST, and that field must have a
10821082
/// different type in the type parameter (i.e., it is a field being coerced)
1083-
/// - `DispatchForDyn` is implemented for the type of the field being coerced.
1083+
/// - `DispatchFromDyn` is implemented for the type of the field being coerced.
10841084
fn dispatch_from_dyn_constraint<I: Interner>(
10851085
solver: &mut dyn Solver<I>,
10861086
db: &dyn RustIrDatabase<I>,
@@ -1093,7 +1093,7 @@ impl WfWellKnownConstraints {
10931093

10941094
let trait_ref: &TraitRef<I> = &impl_datum.trait_ref;
10951095

1096-
// DispatchForDyn specifies that Self (source) can be coerced to T (target; its single type parameter).
1096+
// DispatchFromDyn specifies that Self (source) can be coerced to T (target; its single type parameter).
10971097
let source = trait_ref.self_type_parameter(interner);
10981098
let target = trait_ref
10991099
.substitution
@@ -1121,7 +1121,7 @@ impl WfWellKnownConstraints {
11211121
match (source.kind(interner), target.kind(interner)) {
11221122
(TyKind::Ref(s_m, _, _), TyKind::Ref(t_m, _, _))
11231123
| (TyKind::Raw(s_m, _), TyKind::Raw(t_m, _))
1124-
if s_m != t_m =>
1124+
if s_m == t_m =>
11251125
{
11261126
true
11271127
}
@@ -1153,9 +1153,9 @@ impl WfWellKnownConstraints {
11531153
let mut non_zst_fields: Vec<_> = source_fields
11541154
.iter()
11551155
.zip(target_fields.iter())
1156-
.filter(|(sf, tf)| {
1157-
// TODO ignore 1-ZST fields
1158-
true
1156+
.filter(|(sf, _)| match sf.adt_id(interner) {
1157+
Some(adt) => !db.adt_size_align(adt).one_zst(),
1158+
None => true,
11591159
})
11601160
.collect();
11611161

@@ -1177,7 +1177,7 @@ impl WfWellKnownConstraints {
11771177
return false;
11781178
}
11791179

1180-
// Type(field_src): DispatchForDyn<Type(field_tgt)>
1180+
// Type(field_src): DispatchFromDyn<Type(field_tgt)>
11811181
let field_dispatch_goal: Goal<I> = TraitRef {
11821182
trait_id: trait_ref.trait_id,
11831183
substitution: Substitution::from_iter(

tests/test/unsize.rs

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,200 @@ fn struct_unsizing() {
586586
}
587587
}
588588
}
589+
590+
#[test]
591+
fn dispatch_from_dyn() {
592+
test! {
593+
program {
594+
#[lang(dispatch_from_dyn)]
595+
trait DispatchFromDyn<T> {}
596+
597+
impl<'a, T, U> DispatchFromDyn<&'a U> for &'a T {}
598+
}
599+
600+
// Smoke test that DispatchFromDyn works just like any other impl.
601+
goal {
602+
forall<'a> {
603+
&'a u8: DispatchFromDyn<&'a u8>
604+
}
605+
} yields {
606+
"Unique"
607+
}
608+
}
609+
}
610+
611+
#[test]
612+
fn dispatch_from_dyn_wf() {
613+
lowering_success! {
614+
program {
615+
#[lang(dispatch_from_dyn)]
616+
trait DispatchFromDyn<T> {}
617+
618+
#[one_zst]
619+
struct PhantomData<T> {}
620+
621+
struct Foo<T> {
622+
f: *mut T,
623+
f2: PhantomData<u8>,
624+
}
625+
626+
// References and pointers
627+
impl<'a, T, U> DispatchFromDyn<&'a U> for &'a T {}
628+
impl<'a, T, U> DispatchFromDyn<&'a mut U> for &'a mut T {}
629+
impl<T, U> DispatchFromDyn<*const U> for *const T {}
630+
impl<T, U> DispatchFromDyn<*mut U> for *mut T {}
631+
632+
// Struct
633+
impl<T, U> DispatchFromDyn<Foo<U>> for Foo<T> {}
634+
}
635+
}
636+
637+
// Reference: mutability mismatch
638+
lowering_error! {
639+
program {
640+
#[lang(dispatch_from_dyn)]
641+
trait DispatchFromDyn<T> {}
642+
643+
impl<'a, T, U> DispatchFromDyn<&'a U> for &'a mut T {}
644+
} error_msg {
645+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
646+
}
647+
}
648+
649+
// Raw pointer: mutability mismatch
650+
lowering_error! {
651+
program {
652+
#[lang(dispatch_from_dyn)]
653+
trait DispatchFromDyn<T> {}
654+
655+
impl<'a, T, U> DispatchFromDyn<*mut U> for *const T {}
656+
} error_msg {
657+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
658+
}
659+
}
660+
661+
// No non-ZST fields
662+
lowering_error! {
663+
program {
664+
#[lang(dispatch_from_dyn)]
665+
trait DispatchFromDyn<T> {}
666+
667+
#[one_zst]
668+
struct PhantomData<T> {}
669+
670+
struct Foo<T> {
671+
f: PhantomData<T>,
672+
}
673+
674+
impl<T, U> DispatchFromDyn<Foo<U>> for Foo<T> {}
675+
} error_msg {
676+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
677+
}
678+
}
679+
680+
// Too many fields
681+
lowering_error! {
682+
program {
683+
#[lang(dispatch_from_dyn)]
684+
trait DispatchFromDyn<T> {}
685+
686+
struct Foo<T> {
687+
f: *mut T,
688+
f2: u8,
689+
}
690+
691+
impl<T, U> DispatchFromDyn<Foo<U>> for Foo<T> {}
692+
} error_msg {
693+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
694+
}
695+
}
696+
697+
// Field does not impl DispatchFromDyn
698+
lowering_error! {
699+
program {
700+
#[lang(dispatch_from_dyn)]
701+
trait DispatchFromDyn<T> {}
702+
703+
struct Foo<T> {
704+
f: T,
705+
}
706+
707+
impl<T, U> DispatchFromDyn<Foo<U>> for Foo<T> {}
708+
} error_msg {
709+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
710+
}
711+
}
712+
713+
// Field type does not change
714+
lowering_error! {
715+
program {
716+
#[lang(dispatch_from_dyn)]
717+
trait DispatchFromDyn<T> {}
718+
719+
#[one_zst]
720+
struct PhantomData<T> {}
721+
722+
struct Foo<T> {
723+
f: *const u8,
724+
f2: PhantomData<T>,
725+
}
726+
727+
impl<T, U> DispatchFromDyn<Foo<U>> for Foo<T> {}
728+
} error_msg {
729+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
730+
}
731+
}
732+
733+
// Different definitions
734+
lowering_error! {
735+
program {
736+
#[lang(dispatch_from_dyn)]
737+
trait DispatchFromDyn<T> {}
738+
739+
struct Foo<T> {
740+
f: *const T,
741+
}
742+
743+
struct Bar<T> {
744+
f: *const T,
745+
}
746+
747+
impl<T, U> DispatchFromDyn<Bar<U>> for Foo<T> {}
748+
} error_msg {
749+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
750+
}
751+
}
752+
753+
// Not a struct
754+
lowering_error! {
755+
program {
756+
#[lang(dispatch_from_dyn)]
757+
trait DispatchFromDyn<T> {}
758+
759+
enum Foo<T> {
760+
Bar(*const T),
761+
}
762+
763+
impl<T, U> DispatchFromDyn<Foo<U>> for Foo<T> {}
764+
} error_msg {
765+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
766+
}
767+
}
768+
769+
// repr(C)
770+
lowering_error! {
771+
program {
772+
#[lang(dispatch_from_dyn)]
773+
trait DispatchFromDyn<T> {}
774+
775+
#[repr(C)]
776+
struct Foo<T> {
777+
f: *mut T,
778+
}
779+
780+
impl<T, U> DispatchFromDyn<Foo<U>> for Foo<T> {}
781+
} error_msg {
782+
"trait impl for `DispatchFromDyn` does not meet well-formedness requirements"
783+
}
784+
}
785+
}

0 commit comments

Comments
 (0)