Skip to content

Commit 5af9691

Browse files
committed
Handle placeholder assoc types when Chalk produces them
1 parent 9d72b14 commit 5af9691

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

crates/ra_hir/src/ty/tests.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,6 +3181,55 @@ fn test<T: Trait>(t: T) { (*t)<|>; }
31813181
assert_eq!(t, "i128");
31823182
}
31833183

3184+
#[test]
3185+
fn associated_type_placeholder() {
3186+
let t = type_at(
3187+
r#"
3188+
//- /main.rs
3189+
pub trait ApplyL {
3190+
type Out;
3191+
}
3192+
3193+
pub struct RefMutL<T>;
3194+
3195+
impl<T> ApplyL for RefMutL<T> {
3196+
type Out = <T as ApplyL>::Out;
3197+
}
3198+
3199+
fn test<T: ApplyL>() {
3200+
let y: <RefMutL<T> as ApplyL>::Out = no_matter;
3201+
y<|>;
3202+
}
3203+
"#,
3204+
);
3205+
// inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
3206+
// FIXME: fix type parameter names going missing when going through Chalk
3207+
assert_eq!(t, "ApplyL::Out<[missing name]>");
3208+
}
3209+
3210+
#[test]
3211+
fn associated_type_placeholder_2() {
3212+
let t = type_at(
3213+
r#"
3214+
//- /main.rs
3215+
pub trait ApplyL {
3216+
type Out;
3217+
}
3218+
fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
3219+
3220+
fn test<T: ApplyL>(t: T) {
3221+
let y = foo(t);
3222+
y<|>;
3223+
}
3224+
"#,
3225+
);
3226+
// FIXME here Chalk doesn't normalize the type to a placeholder. I think we
3227+
// need to add a rule like Normalize(<T as ApplyL>::Out -> ApplyL::Out<T>)
3228+
// to the trait env ourselves here; probably Chalk can't do this by itself.
3229+
// assert_eq!(t, "ApplyL::Out<[missing name]>");
3230+
assert_eq!(t, "{unknown}");
3231+
}
3232+
31843233
fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
31853234
let file = db.parse(pos.file_id).ok().unwrap();
31863235
let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();

crates/ra_hir/src/ty/traits/chalk.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,17 @@ impl ToChalk for Ty {
4545
fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty {
4646
match self {
4747
Ty::Apply(apply_ty) => {
48-
let struct_id = apply_ty.ctor.to_chalk(db);
49-
let name = TypeName::TypeKindId(struct_id.into());
48+
let name = match apply_ty.ctor {
49+
TypeCtor::AssociatedType(type_alias) => {
50+
let type_id = type_alias.to_chalk(db);
51+
TypeName::AssociatedType(type_id)
52+
}
53+
_ => {
54+
// other TypeCtors get interned and turned into a chalk StructId
55+
let struct_id = apply_ty.ctor.to_chalk(db);
56+
TypeName::TypeKindId(struct_id.into())
57+
}
58+
};
5059
let parameters = apply_ty.parameters.to_chalk(db);
5160
chalk_ir::ApplicationTy { name, parameters }.cast()
5261
}
@@ -79,15 +88,21 @@ impl ToChalk for Ty {
7988
fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self {
8089
match chalk {
8190
chalk_ir::Ty::Apply(apply_ty) => {
91+
// FIXME this is kind of hacky due to the fact that
92+
// TypeName::Placeholder is a Ty::Param on our side
8293
match apply_ty.name {
8394
TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => {
8495
let ctor = from_chalk(db, struct_id);
8596
let parameters = from_chalk(db, apply_ty.parameters);
8697
Ty::Apply(ApplicationTy { ctor, parameters })
8798
}
99+
TypeName::AssociatedType(type_id) => {
100+
let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id));
101+
let parameters = from_chalk(db, apply_ty.parameters);
102+
Ty::Apply(ApplicationTy { ctor, parameters })
103+
}
88104
// FIXME handle TypeKindId::Trait/Type here
89105
TypeName::TypeKindId(_) => unimplemented!(),
90-
TypeName::AssociatedType(_) => unimplemented!(),
91106
TypeName::Placeholder(idx) => {
92107
assert_eq!(idx.ui, UniverseIndex::ROOT);
93108
Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }

0 commit comments

Comments
 (0)