Skip to content

Commit eb5401e

Browse files
Use inferred type in SourceAnalyzer::type_of_type
This uses the new InferenceResult::type_of_type_placeholder data to turn type references into completely resolved types instead of just returning the lexical type.
1 parent 09cf067 commit eb5401e

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/infer.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ impl<'db> InferenceResult<'db> {
612612
pub fn placeholder_types(&self) -> impl Iterator<Item = (TypeRefId, &Ty<'db>)> {
613613
self.type_of_type_placeholder.iter()
614614
}
615+
pub fn type_of_type_placeholder(&self, type_ref: TypeRefId) -> Option<Ty<'db>> {
616+
self.type_of_type_placeholder.get(type_ref).copied()
617+
}
615618
pub fn closure_info(&self, closure: InternedClosureId) -> &(Vec<CapturedItem<'db>>, FnTrait) {
616619
self.closure_info.get(&closure).unwrap()
617620
}

src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use hir_def::{
2121
lang_item::LangItem,
2222
nameres::MacroSubNs,
2323
resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
24-
type_ref::{Mutability, TypeRefId},
24+
type_ref::{Mutability, TypeRef, TypeRefId},
2525
};
2626
use hir_expand::{
2727
HirFileId, InFile,
@@ -267,8 +267,11 @@ impl<'db> SourceAnalyzer<'db> {
267267
db: &'db dyn HirDatabase,
268268
ty: &ast::Type,
269269
) -> Option<Type<'db>> {
270+
let interner = DbInterner::new_with(db, None, None);
271+
270272
let type_ref = self.type_id(ty)?;
271-
let ty = TyLoweringContext::new(
273+
274+
let mut ty = TyLoweringContext::new(
272275
db,
273276
&self.resolver,
274277
self.store()?,
@@ -279,6 +282,31 @@ impl<'db> SourceAnalyzer<'db> {
279282
LifetimeElisionKind::Infer,
280283
)
281284
.lower_ty(type_ref);
285+
286+
// Try and substitute unknown types using InferenceResult
287+
if let Some(infer) = self.infer()
288+
&& let Some(store) = self.store()
289+
{
290+
let mut inferred_types = vec![];
291+
TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| {
292+
if matches!(type_ref, TypeRef::Placeholder) {
293+
inferred_types.push(infer.type_of_type_placeholder(type_ref_id));
294+
}
295+
});
296+
let mut inferred_types = inferred_types.into_iter();
297+
298+
let substituted_ty = hir_ty::next_solver::fold::fold_tys(interner, ty, |ty| {
299+
if ty.is_ty_error() { inferred_types.next().flatten().unwrap_or(ty) } else { ty }
300+
});
301+
302+
// Only used the result if the placeholder and unknown type counts matched
303+
let success =
304+
inferred_types.next().is_none() && !substituted_ty.references_non_lt_error();
305+
if success {
306+
ty = substituted_ty;
307+
}
308+
}
309+
282310
Some(Type::new_with_resolver(db, &self.resolver, ty))
283311
}
284312

0 commit comments

Comments
 (0)