Skip to content

Commit e219999

Browse files
committed
Auto merge of rust-lang#15211 - lowr:patch/gats-in-bounds-for-assoc, r=flodiebold
Support GATs in bounds for associated types Chalk has a dedicated IR for bounds on trait associated type: `rust_ir::InlineBound`. We have been failing to convert GATs inside those bounds from our IR to chalk IR. This PR provides an easy fix for it: properly take GATs into account during the conversion.
2 parents 45d4ebc + 9fd5f8c commit e219999

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

crates/hir-ty/src/chalk_db.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{iter, sync::Arc};
55

66
use tracing::debug;
77

8-
use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
8+
use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds};
99
use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
1010

1111
use base_db::CrateId;
@@ -846,28 +846,34 @@ pub(super) fn generic_predicate_to_inline_bound(
846846
}
847847
let args_no_self = trait_ref.substitution.as_slice(Interner)[1..]
848848
.iter()
849-
.map(|ty| ty.clone().cast(Interner))
849+
.cloned()
850+
.casted(Interner)
850851
.collect();
851852
let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
852853
Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
853854
}
854855
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
855-
let trait_ = projection_ty.trait_(db);
856-
if projection_ty.self_type_parameter(db) != self_ty_shifted_in {
856+
let generics =
857+
generics(db.upcast(), from_assoc_type_id(projection_ty.associated_ty_id).into());
858+
let (assoc_args, trait_args) =
859+
projection_ty.substitution.as_slice(Interner).split_at(generics.len_self());
860+
let (self_ty, args_no_self) =
861+
trait_args.split_first().expect("projection without trait self type");
862+
if self_ty.assert_ty_ref(Interner) != &self_ty_shifted_in {
857863
return None;
858864
}
859-
let args_no_self = projection_ty.substitution.as_slice(Interner)[1..]
860-
.iter()
861-
.map(|ty| ty.clone().cast(Interner))
862-
.collect();
865+
866+
let args_no_self = args_no_self.iter().cloned().casted(Interner).collect();
867+
let parameters = assoc_args.to_vec();
868+
863869
let alias_eq_bound = rust_ir::AliasEqBound {
864870
value: ty.clone(),
865871
trait_bound: rust_ir::TraitBound {
866-
trait_id: to_chalk_trait_id(trait_),
872+
trait_id: to_chalk_trait_id(projection_ty.trait_(db)),
867873
args_no_self,
868874
},
869875
associated_ty_id: projection_ty.associated_ty_id,
870-
parameters: Vec::new(), // FIXME we don't support generic associated types yet
876+
parameters,
871877
};
872878
Some(chalk_ir::Binders::new(
873879
binders,

crates/hir-ty/src/tests/traits.rs

+24
Original file line numberDiff line numberDiff line change
@@ -4148,6 +4148,30 @@ where
41484148
);
41494149
}
41504150

4151+
#[test]
4152+
fn gats_in_bounds_for_assoc() {
4153+
check_types(
4154+
r#"
4155+
trait Trait {
4156+
type Assoc: Another<Gat<i32> = usize>;
4157+
type Assoc2<T>: Another<Gat<T> = T>;
4158+
}
4159+
trait Another {
4160+
type Gat<T>;
4161+
fn foo(&self) -> Self::Gat<i32>;
4162+
fn bar<T>(&self) -> Self::Gat<T>;
4163+
}
4164+
4165+
fn test<T: Trait>(a: T::Assoc, b: T::Assoc2<isize>) {
4166+
let v = a.foo();
4167+
//^ usize
4168+
let v = b.bar::<isize>();
4169+
//^ isize
4170+
}
4171+
"#,
4172+
);
4173+
}
4174+
41514175
#[test]
41524176
fn bin_op_with_scalar_fallback() {
41534177
// Extra impls are significant so that chalk doesn't give us definite guidances.

0 commit comments

Comments
 (0)