diff --git a/chalk-solve/src/wf.rs b/chalk-solve/src/wf.rs index b963eebde72..38a30e09e24 100644 --- a/chalk-solve/src/wf.rs +++ b/chalk-solve/src/wf.rs @@ -544,14 +544,19 @@ impl WfWellKnownGoals { let ty = trait_ref.self_type_parameter(interner); let ty_data = ty.data(interner); + // Implementations for scalars, pointer types and never type are provided by libcore. + // User implementations on types other than ADTs are forbidden. let (adt_id, substitution) = match ty_data { - TyData::Apply(ApplicationTy { - name: TypeName::Adt(adt_id), - substitution, - }) => (*adt_id, substitution), - // TODO(areredify) - // when #368 lands, extend this to handle everything accordingly - _ => return None, + TyData::Apply(ApplicationTy { name, substitution }) => match name { + TypeName::Scalar(_) + | TypeName::Raw(_) + | TypeName::Ref(Mutability::Not) + | TypeName::Never => return None, + TypeName::Adt(adt_id) => (*adt_id, substitution), + _ => return Some(GoalData::CannotProve(()).intern(interner)), + }, + + _ => return Some(GoalData::CannotProve(()).intern(interner)), }; // not { Implemented(ImplSelfTy: Drop) } diff --git a/tests/test/wf_lowering.rs b/tests/test/wf_lowering.rs index ab63b7a8700..7d300ec79b5 100644 --- a/tests/test/wf_lowering.rs +++ b/tests/test/wf_lowering.rs @@ -712,7 +712,7 @@ fn struct_sized_constraints() { #[test] fn copy_constraints() { - lowering_error! { + lowering_success! { program { #[lang(copy)] trait Copy { } @@ -720,11 +720,9 @@ fn copy_constraints() { #[lang(drop)] trait Drop { } - struct S { t: T } + struct S { t1: T1, t2: T2 } - impl Copy for S { } - } error_msg { - "trait impl for `Copy` does not meet well-formedness requirements" + impl Copy for S where T1: Copy, T2: Copy { } } } @@ -744,6 +742,34 @@ fn copy_constraints() { } } + // Copy implementations for a struct with non-copy field + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + struct S { t: T } + + impl Copy for S { } + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } + + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + struct S { t1: T1, t2: T2 } + + impl Copy for S where T2: Copy { } + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } + + // Copy implemenation for a Drop type lowering_error! { program { #[lang(copy)] @@ -761,6 +787,95 @@ fn copy_constraints() { "trait impl for `Copy` does not meet well-formedness requirements" } } + + // Tests for Copy impls for builtin types + lowering_success! { + program { + #[lang(copy)] + trait Copy { } + + #[lang(drop)] + trait Drop { } + + impl Copy for u8 {} + impl Copy for f32 {} + impl Copy for char {} + impl Copy for bool {} + impl Copy for *const T {} + impl Copy for *mut T {} + impl<'a, T> Copy for &'a T {} + impl Copy for ! {} + } + } + + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + impl<'a, T> Copy for &'a mut T {} + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } + + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + #[object_safe] + trait Trait {} + + impl<'a> Copy for dyn Trait + 'a {} + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } + + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + impl Copy for fn(u32) {} + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } + + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + impl Copy for str {} + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } + + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + impl Copy for [u32; 4] {} + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } + + lowering_error! { + program { + #[lang(copy)] + trait Copy { } + + impl Copy for [u32] {} + } error_msg { + "trait impl for `Copy` does not meet well-formedness requirements" + } + } } #[test]