about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-09-21 14:32:36 -0400
committerMichael Goulet <michael@errs.io>2024-09-25 13:13:04 -0400
commitc5914753ad438fe53c3b97a079b595136dc862c9 (patch)
tree811e417bea4339564c4479a8113e84fb48db9ff7
parent149bd877de8c84870c303399e62770cf2a72fcf7 (diff)
downloadrust-c5914753ad438fe53c3b97a079b595136dc862c9.tar.gz
rust-c5914753ad438fe53c3b97a079b595136dc862c9.zip
Add a few more tests, comments
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs6
-rw-r--r--tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.rs28
-rw-r--r--tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.stderr16
-rw-r--r--tests/ui/associated-type-bounds/nested-gat-projection.rs31
4 files changed, 81 insertions, 0 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 39b697bbfc1..7557219aaa6 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -173,6 +173,12 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
     ))
 }
 
+/// Given some where clause like `for<'b, 'c> <Self as Trait<'a_identity>>::Gat<'b>: Bound<'c>`,
+/// the mapping will map `'b` back to the GAT's `'b_identity`. Then we need to compress the
+/// remaining bound var `'c` to index 0.
+///
+/// This folder gives us: `for<'c> <Self as Trait<'a_identity>>::Gat<'b_identity>: Bound<'c>`,
+/// which is sufficient for an item bound for `Gat`, since all of the GAT's args are identity.
 struct MapAndCompressBoundVars<'tcx> {
     tcx: TyCtxt<'tcx>,
     /// How deep are we? Makes sure we don't touch the vars of nested binders.
diff --git a/tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.rs b/tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.rs
new file mode 100644
index 00000000000..eb616631d1d
--- /dev/null
+++ b/tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.rs
@@ -0,0 +1,28 @@
+// Demonstrates a mostly-theoretical inference guidance now that we turn the where
+// clause on `Trait` into an item bound, given that we prefer item bounds somewhat
+// greedily in trait selection.
+
+trait Bound<T> {}
+impl<T, U> Bound<T> for U {}
+
+trait Trait
+where
+    <<Self as Trait>::Assoc as Other>::Assoc: Bound<u32>,
+{
+    type Assoc: Other;
+}
+
+trait Other {
+    type Assoc;
+}
+
+fn impls_trait<T: Bound<U>, U>() -> Vec<U> { vec![] }
+
+fn foo<T: Trait>() {
+    let mut vec_u = impls_trait::<<<T as Trait>::Assoc as Other>::Assoc, _>();
+    vec_u.sort();
+    drop::<Vec<u8>>(vec_u);
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.stderr b/tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.stderr
new file mode 100644
index 00000000000..c77400f3822
--- /dev/null
+++ b/tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/nested-associated-type-bound-incompleteness.rs:24:21
+   |
+LL |     drop::<Vec<u8>>(vec_u);
+   |     --------------- ^^^^^ expected `Vec<u8>`, found `Vec<u32>`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Vec<u8>`
+              found struct `Vec<u32>`
+note: function defined here
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/associated-type-bounds/nested-gat-projection.rs b/tests/ui/associated-type-bounds/nested-gat-projection.rs
new file mode 100644
index 00000000000..ad37da9ed19
--- /dev/null
+++ b/tests/ui/associated-type-bounds/nested-gat-projection.rs
@@ -0,0 +1,31 @@
+//@ check-pass
+
+trait Trait
+where
+    for<'a> Self::Gat<'a>: OtherTrait,
+    for<'a, 'b, 'c> <Self::Gat<'a> as OtherTrait>::OtherGat<'b>: HigherRanked<'c>,
+{
+    type Gat<'a>;
+}
+
+trait OtherTrait {
+    type OtherGat<'b>;
+}
+
+trait HigherRanked<'c> {}
+
+fn lower_ranked<T: for<'b, 'c> OtherTrait<OtherGat<'b>: HigherRanked<'c>>>() {}
+
+fn higher_ranked<T: Trait>()
+where
+    for<'a> T::Gat<'a>: OtherTrait,
+    for<'a, 'b, 'c> <T::Gat<'a> as OtherTrait>::OtherGat<'b>: HigherRanked<'c>,
+{
+}
+
+fn test<T: Trait>() {
+    lower_ranked::<T::Gat<'_>>();
+    higher_ranked::<T>();
+}
+
+fn main() {}