diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index afac92b2662..b61febe3a68 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -997,33 +997,38 @@ pub fn resolve_indexing_op( struct Valid; impl Valid { fn valid_impl( - impls: impl Iterator, + mut impls: impl Iterator, table: &mut InferenceTable, self_ty: &Ty, ) -> Option> { let db = table.db; - for impl_ in impls { - let impl_data = db.impl_data(impl_); - let substs = - TyBuilder::subst_for_def(db, impl_).fill_with_inference_vars(table).build(); - let impl_ty = - substs.apply(db.impl_self_ty(impl_).into_value_and_skipped_binders().0, Interner); + loop { + let impl_ = impls.next()?; + let r = table.run_in_snapshot(|table| { + let impl_data = db.impl_data(impl_); + let substs = + TyBuilder::subst_for_def(db, impl_).fill_with_inference_vars(table).build(); + let impl_ty = substs + .apply(db.impl_self_ty(impl_).into_value_and_skipped_binders().0, Interner); - if !table.unify(self_ty, &impl_ty) { - continue; - } + table + .unify(self_ty, &impl_ty) + .then(|| { + let wh_goals = + crate::chalk_db::convert_where_clauses(db, impl_.into(), &substs) + .into_iter() + .map(|b| b.into_well_formed_goal(Interner).cast(Interner)); - let wh_goals = crate::chalk_db::convert_where_clauses(db, impl_.into(), &substs) - .into_iter() - .map(|b| b.into_well_formed_goal(Interner).cast(Interner)); + let goal = crate::Goal::all(Interner, wh_goals); - let goal = crate::Goal::all(Interner, wh_goals); - - if table.try_obligation(goal).is_some() { - return Some(impl_data); + table.try_obligation(goal).map(|_| impl_data) + }) + .flatten() + }); + if r.is_some() { + break r; } } - None } fn is_valid_item( diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index e5390eeb326..2b1e8e325e4 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -438,29 +438,23 @@ impl NameRefClass { name_ref: ast::NameRef, ) -> Option { let parent = name_ref.syntax().parent()?; - match_ast! { - match parent { - ast::MethodCallExpr(method_call) => { - sema.resolve_impl_method(&ast::Expr::MethodCallExpr(method_call)) - .map(Definition::Function) - .map(NameRefClass::Definition) - }, - ast::PathSegment(ps) => { - ps.syntax().parent().and_then(ast::Path::cast) - .map(|p| - p.syntax() - .parent() - .and_then(ast::PathExpr::cast) - .map(|pe| - sema.resolve_impl_method(&ast::Expr::PathExpr(pe)) - .map(Definition::Function) - .map(NameRefClass::Definition) - ).flatten() - ).flatten() - }, - _=> None - } - } + let expr = match_ast! { + match parent { + ast::MethodCallExpr(method_call) => { + Some(ast::Expr::MethodCallExpr(method_call)) + }, + ast::PathSegment(..) => { + parent.ancestors() + .find_map(ast::PathExpr::cast) + .map(ast::Expr::PathExpr) + }, + _=> None + } + }; + expr.as_ref() + .and_then(|e| sema.resolve_impl_method(e)) + .map(Definition::Function) + .map(NameRefClass::Definition) } pub fn classify_lifetime( sema: &Semantics,