From c5914753ad438fe53c3b97a079b595136dc862c9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 21 Sep 2024 14:32:36 -0400 Subject: [PATCH] Add a few more tests, comments --- .../src/collect/item_bounds.rs | 6 ++++ ...ed-associated-type-bound-incompleteness.rs | 28 +++++++++++++++++ ...ssociated-type-bound-incompleteness.stderr | 16 ++++++++++ .../nested-gat-projection.rs | 31 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.rs create mode 100644 tests/ui/associated-type-bounds/nested-associated-type-bound-incompleteness.stderr create mode 100644 tests/ui/associated-type-bounds/nested-gat-projection.rs diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 39b697bbfc1b2..7557219aaa693 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> >::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> >::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 0000000000000..eb616631d1dc8 --- /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 {} +impl Bound for U {} + +trait Trait +where + <::Assoc as Other>::Assoc: Bound, +{ + type Assoc: Other; +} + +trait Other { + type Assoc; +} + +fn impls_trait, U>() -> Vec { vec![] } + +fn foo() { + let mut vec_u = impls_trait::<<::Assoc as Other>::Assoc, _>(); + vec_u.sort(); + drop::>(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 0000000000000..c77400f382280 --- /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_u); + | --------------- ^^^^^ expected `Vec`, found `Vec` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec` +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 0000000000000..ad37da9ed1948 --- /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> as OtherTrait>::OtherGat<'b>: HigherRanked<'c>, +{ + type Gat<'a>; +} + +trait OtherTrait { + type OtherGat<'b>; +} + +trait HigherRanked<'c> {} + +fn lower_ranked OtherTrait: HigherRanked<'c>>>() {} + +fn higher_ranked() +where + for<'a> T::Gat<'a>: OtherTrait, + for<'a, 'b, 'c> as OtherTrait>::OtherGat<'b>: HigherRanked<'c>, +{ +} + +fn test() { + lower_ranked::>(); + higher_ranked::(); +} + +fn main() {}