diff options
| author | jackh726 <jack.huey@umassmed.edu> | 2021-08-23 16:39:11 -0400 |
|---|---|---|
| committer | jackh726 <jack.huey@umassmed.edu> | 2021-08-23 17:53:16 -0400 |
| commit | b0170779f5c6e9705658cda1b02cf1fd1a925205 (patch) | |
| tree | 18c8d16c0ba375ae93e436bb973ae44473785ce9 | |
| parent | 6df6eb8ae8358ebab76fcfa35ac7cc41e18a2560 (diff) | |
| download | rust-b0170779f5c6e9705658cda1b02cf1fd1a925205.tar.gz rust-b0170779f5c6e9705658cda1b02cf1fd1a925205.zip | |
Add comment and extra test
4 files changed, 58 insertions, 8 deletions
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index b95cbd9025c..c384e0dcb2c 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1240,9 +1240,35 @@ pub fn check_type_bounds<'tcx>( // } // // - `impl_trait_ref` would be `<(A, B) as Foo<u32>> - // - `impl_ty_substs` would be `[A, B, ^0.0]` + // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0) // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from // the *trait* with the generic associated type parameters (as bound vars). + // + // A note regarding the use of bound vars here: + // Imagine as an example + // ``` + // trait Family { + // type Member<C: Eq>; + // } + // + // impl Family for VecFamily { + // type Member<C: Eq> = i32; + // } + // ``` + // Here, we would generate + // ```notrust + // forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) } + // ``` + // when we really would like to generate + // ```notrust + // forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) } + // ``` + // But, this is probably fine, because although the first clause can be used with types C that + // do not implement Eq, for it to cause some kind of problem, there would have to be a + // VecFamily::Member<X> for some type X where !(X: Eq), that appears in the value of type + // Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing + // elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in + // the trait (notably, that X: Eq and T: Family). let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id); let mut substs = smallvec::SmallVec::with_capacity(defs.count()); if let Some(def_id) = defs.parent { diff --git a/src/test/ui/generic-associated-types/issue-87429-2.rs b/src/test/ui/generic-associated-types/issue-87429-2.rs new file mode 100644 index 00000000000..d35bb098abd --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87429-2.rs @@ -0,0 +1,20 @@ +// Derived from `issue-87429`. A test that ensures that using bound vars in the +// predicates in the param env when checking that an associated type satisfies +// its bounds does not cause us to not be able to use the bounds on the parameters. + +// check-pass + +#![feature(generic_associated_types)] + +trait Family { + type Member<'a, C: Eq>: for<'b> MyBound<'b, C>; +} + +trait MyBound<'a, C> { } +impl<'a, C: Eq> MyBound<'a, C> for i32 { } + +impl Family for () { + type Member<'a, C: Eq> = i32; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr index 8f031c76183..01cb0bfc72c 100644 --- a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr +++ b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr @@ -2,12 +2,14 @@ error[E0277]: can't compare `Foo` with `Foo` --> $DIR/issue-87429-associated-type-default.rs:14:5 | LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo; - | ^^^^^^^^^^^^^^^^^-----------------------------------^^^^^^^ - | | | - | | required by this bound in `Family2::Member` - | no implementation for `Foo == Foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Foo == Foo` | = help: the trait `PartialEq` is not implemented for `Foo` +note: required by a bound in `Family2::Member` + --> $DIR/issue-87429-associated-type-default.rs:14:22 + | +LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family2::Member` error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr index 05d40f9e7cc..87bd35f5878 100644 --- a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr +++ b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr @@ -11,13 +11,15 @@ LL | #![feature(specialization)] error[E0277]: can't compare `Foo` with `Foo` --> $DIR/issue-87429-specialization.rs:21:5 | -LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>>; - | ----------------------------------- required by this bound in `Family::Member` -... LL | default type Member<'a> = Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Foo == Foo` | = help: the trait `PartialEq` is not implemented for `Foo` +note: required by a bound in `Family::Member` + --> $DIR/issue-87429-specialization.rs:8:22 + | +LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member` error: aborting due to previous error; 1 warning emitted |
