aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-08-11 14:54:31 +0100
committerFlorian Diebold <[email protected]>2019-08-12 20:43:00 +0100
commit5af9691dc9132db61b50c4e90cdeda6fea0c5dd9 (patch)
treefa1f8c46158271eb859928ed9da3eb389f861c09 /crates/ra_hir/src
parent9d72b14cfe3606e9c55e488d74568471f981bb3d (diff)
Handle placeholder assoc types when Chalk produces them
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty/tests.rs49
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs21
2 files changed, 67 insertions, 3 deletions
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index e6a09cc67..28727bb18 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3181,6 +3181,55 @@ fn test<T: Trait>(t: T) { (*t)<|>; }
3181 assert_eq!(t, "i128"); 3181 assert_eq!(t, "i128");
3182} 3182}
3183 3183
3184#[test]
3185fn associated_type_placeholder() {
3186 let t = type_at(
3187 r#"
3188//- /main.rs
3189pub trait ApplyL {
3190 type Out;
3191}
3192
3193pub struct RefMutL<T>;
3194
3195impl<T> ApplyL for RefMutL<T> {
3196 type Out = <T as ApplyL>::Out;
3197}
3198
3199fn 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]
3211fn associated_type_placeholder_2() {
3212 let t = type_at(
3213 r#"
3214//- /main.rs
3215pub trait ApplyL {
3216 type Out;
3217}
3218fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
3219
3220fn 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
3184fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 3233fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
3185 let file = db.parse(pos.file_id).ok().unwrap(); 3234 let file = db.parse(pos.file_id).ok().unwrap();
3186 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 3235 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index e669f835b..6df7094c5 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -45,8 +45,17 @@ impl ToChalk for Ty {
45 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { 45 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty {
46 match self { 46 match self {
47 Ty::Apply(apply_ty) => { 47 Ty::Apply(apply_ty) => {
48 let struct_id = apply_ty.ctor.to_chalk(db); 48 let name = match apply_ty.ctor {
49 let name = TypeName::TypeKindId(struct_id.into()); 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 };
50 let parameters = apply_ty.parameters.to_chalk(db); 59 let parameters = apply_ty.parameters.to_chalk(db);
51 chalk_ir::ApplicationTy { name, parameters }.cast() 60 chalk_ir::ApplicationTy { name, parameters }.cast()
52 } 61 }
@@ -79,15 +88,21 @@ impl ToChalk for Ty {
79 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { 88 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self {
80 match chalk { 89 match chalk {
81 chalk_ir::Ty::Apply(apply_ty) => { 90 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
82 match apply_ty.name { 93 match apply_ty.name {
83 TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { 94 TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => {
84 let ctor = from_chalk(db, struct_id); 95 let ctor = from_chalk(db, struct_id);
85 let parameters = from_chalk(db, apply_ty.parameters); 96 let parameters = from_chalk(db, apply_ty.parameters);
86 Ty::Apply(ApplicationTy { ctor, parameters }) 97 Ty::Apply(ApplicationTy { ctor, parameters })
87 } 98 }
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 }
88 // FIXME handle TypeKindId::Trait/Type here 104 // FIXME handle TypeKindId::Trait/Type here
89 TypeName::TypeKindId(_) => unimplemented!(), 105 TypeName::TypeKindId(_) => unimplemented!(),
90 TypeName::AssociatedType(_) => unimplemented!(),
91 TypeName::Placeholder(idx) => { 106 TypeName::Placeholder(idx) => {
92 assert_eq!(idx.ui, UniverseIndex::ROOT); 107 assert_eq!(idx.ui, UniverseIndex::ROOT);
93 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } 108 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }