mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Fix inference of indexing argument (partly)
We need to add the `T: Index<Arg>` obligation to be resolved later as well, otherwise we can't make inferences about `Arg` later based on the `Index` impls. This still doesn't fix indexing with integer variables though; there's a further problem with Chalk floundering because of the variable, I think.
This commit is contained in:
parent
dceec6176b
commit
57feb323f7
2 changed files with 48 additions and 8 deletions
|
@ -28,8 +28,8 @@ use hir_def::{
|
||||||
path::{path, Path},
|
path::{path, Path},
|
||||||
resolver::{HasResolver, Resolver, TypeNs},
|
resolver::{HasResolver, Resolver, TypeNs},
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, TraitId, TypeAliasId,
|
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId,
|
||||||
VariantId,
|
TypeAliasId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::{diagnostics::DiagnosticSink, name::name};
|
use hir_expand::{diagnostics::DiagnosticSink, name::name};
|
||||||
use ra_arena::map::ArenaMap;
|
use ra_arena::map::ArenaMap;
|
||||||
|
@ -376,17 +376,21 @@ impl<'a> InferenceContext<'a> {
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
match assoc_ty {
|
match assoc_ty {
|
||||||
Some(res_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 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)
|
.push(inner_ty)
|
||||||
.fill(params.iter().cloned());
|
.fill(params.iter().cloned())
|
||||||
|
.build();
|
||||||
|
let trait_ref = TraitRef { trait_, substs: substs.clone() };
|
||||||
let projection = ProjectionPredicate {
|
let projection = ProjectionPredicate {
|
||||||
ty: ty.clone(),
|
ty: ty.clone(),
|
||||||
projection_ty: ProjectionTy {
|
projection_ty: ProjectionTy { associated_ty: res_assoc_ty, parameters: substs },
|
||||||
associated_ty: res_assoc_ty,
|
|
||||||
parameters: builder.build(),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
self.obligations.push(Obligation::Trait(trait_ref));
|
||||||
self.obligations.push(Obligation::Projection(projection));
|
self.obligations.push(Obligation::Projection(projection));
|
||||||
self.resolve_ty_as_possible(ty)
|
self.resolve_ty_as_possible(ty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_ops_index_autoderef() {
|
fn infer_ops_index_autoderef() {
|
||||||
check_types(
|
check_types(
|
||||||
|
|
Loading…
Reference in a new issue