Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix inference of indexing argument (partly) #5211

Merged
merged 1 commit into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 12 additions & 8 deletions crates/ra_hir_ty/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use hir_def::{
path::{path, Path},
resolver::{HasResolver, Resolver, TypeNs},
type_ref::{Mutability, TypeRef},
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, TraitId, TypeAliasId,
VariantId,
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId,
TypeAliasId, VariantId,
};
use hir_expand::{diagnostics::DiagnosticSink, name::name};
use ra_arena::map::ArenaMap;
Expand Down Expand Up @@ -376,17 +376,21 @@ impl<'a> InferenceContext<'a> {
) -> Ty {
match assoc_ty {
Some(res_assoc_ty) => {
let trait_ = match res_assoc_ty.lookup(self.db.upcast()).container {
hir_def::AssocContainerId::TraitId(trait_) => trait_,
_ => panic!("resolve_associated_type called with non-associated type"),
};
let ty = self.table.new_type_var();
let builder = Substs::build_for_def(self.db, res_assoc_ty)
let substs = Substs::build_for_def(self.db, res_assoc_ty)
.push(inner_ty)
.fill(params.iter().cloned());
.fill(params.iter().cloned())
.build();
let trait_ref = TraitRef { trait_, substs: substs.clone() };
let projection = ProjectionPredicate {
ty: ty.clone(),
projection_ty: ProjectionTy {
associated_ty: res_assoc_ty,
parameters: builder.build(),
},
projection_ty: ProjectionTy { associated_ty: res_assoc_ty, parameters: substs },
};
self.obligations.push(Obligation::Trait(trait_ref));
self.obligations.push(Obligation::Projection(projection));
self.resolve_ty_as_possible(ty)
}
Expand Down
36 changes: 36 additions & 0 deletions crates/ra_hir_ty/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,42 @@ mod ops {
);
}

#[test]
fn infer_ops_index_int() {
check_types(
r#"
//- /main.rs crate:main deps:std
struct Bar;
struct Foo;

impl std::ops::Index<u32> for Bar {
type Output = Foo;
}

struct Range;
impl std::ops::Index<Range> for Bar {
type Output = Bar;
}

fn test() {
let a = Bar;
let b = a[1];
b;
//^ Foo
}

//- /std.rs crate:std
#[prelude_import] use ops::*;
mod ops {
#[lang = "index"]
pub trait Index<Idx> {
type Output;
}
}
Copy link
Member

@matklad matklad Jul 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at some point we need to figure a better way to specify such preludes...

I guess, we can do //- core, and have that auto-magically insert everything, but I wonder if it makes sense to keep stuff more granular?

LGTM!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do kind of like having it explicit what types/traits are actually needed by the test. Also, keeping it small helps when debugging tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's true. But we might do something granular, but still with only one trait Index written down

//- include(std::core::Index, std::result::Result)

but that won't you see at a glance what's going on...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be nice. Maybe there should just be std/core "snippets" that the tests can include.

"#,
);
}

#[test]
fn infer_ops_index_autoderef() {
check_types(
Expand Down