Skip to content

Commit 064f1c7

Browse files
committed
Switch associated_type_shorthand_candidates to lower_nextsolver
1 parent 418f419 commit 064f1c7

File tree

9 files changed

+197
-159
lines changed

9 files changed

+197
-159
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ fn receiver_is_dispatchable<'db>(
564564
// U: Trait<Arg1, ..., ArgN>
565565
let trait_def_id = SolverDefId::TraitId(trait_);
566566
let args = GenericArgs::for_item(interner, trait_def_id, |name, index, kind, _| {
567-
if index == 0 { unsized_self_ty.into() } else { mk_param(index, name, kind) }
567+
if index == 0 { unsized_self_ty.into() } else { mk_param(interner, index, name, kind) }
568568
});
569569
let trait_predicate =
570570
crate::next_solver::TraitRef::new_from_args(interner, trait_def_id, args);
@@ -611,7 +611,7 @@ fn receiver_for_self_ty<'db>(
611611
interner,
612612
SolverDefId::FunctionId(func),
613613
|name, index, kind, _| {
614-
if index == 0 { self_ty.into() } else { mk_param(index, name, kind) }
614+
if index == 0 { self_ty.into() } else { mk_param(interner, index, name, kind) }
615615
},
616616
);
617617

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ pub use infer::{
118118
pub use interner::Interner;
119119
pub use lower::{
120120
ImplTraitLoweringMode, LifetimeElisionKind, ParamLoweringMode, TyDefId, TyLoweringContext,
121-
ValueTyDefId, associated_type_shorthand_candidates, diagnostics::*,
121+
ValueTyDefId, diagnostics::*,
122122
};
123+
pub use lower_nextsolver::associated_type_shorthand_candidates;
123124
pub use mapping::{
124125
ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
125126
lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -804,15 +804,6 @@ pub(crate) fn callable_item_signature_query(db: &dyn HirDatabase, def: CallableD
804804
}
805805
}
806806

807-
pub fn associated_type_shorthand_candidates<R>(
808-
db: &dyn HirDatabase,
809-
def: GenericDefId,
810-
res: TypeNs,
811-
mut cb: impl FnMut(&Name, TypeAliasId) -> Option<R>,
812-
) -> Option<R> {
813-
named_associated_type_shorthand_candidates(db, def, res, None, |name, _, id| cb(name, id))
814-
}
815-
816807
fn named_associated_type_shorthand_candidates<R>(
817808
db: &dyn HirDatabase,
818809
// If the type parameter is defined in an impl and we're in a method, there

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

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ pub(crate) mod path;
1212
use std::{
1313
cell::OnceCell,
1414
iter, mem,
15-
ops::{self, Not as _},
15+
ops::{self, Deref, Not as _},
1616
};
1717

1818
use base_db::Crate;
1919
use either::Either;
2020
use hir_def::{
2121
AdtId, AssocItemId, CallableDefId, ConstParamId, EnumVariantId, FunctionId, GenericDefId,
22-
GenericParamId, ImplId, ItemContainerId, LocalFieldId, Lookup, StructId, TypeAliasId,
22+
GenericParamId, ImplId, ItemContainerId, LocalFieldId, Lookup, StructId, TraitId, TypeAliasId,
2323
TypeOrConstParamId, VariantId,
2424
expr_store::{
2525
ExpressionStore,
@@ -49,6 +49,7 @@ use rustc_type_ir::{
4949
inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _},
5050
};
5151
use salsa::plumbing::AsId;
52+
use smallvec::{SmallVec, smallvec};
5253
use stdx::never;
5354
use triomphe::Arc;
5455

@@ -1607,3 +1608,131 @@ pub(crate) fn associated_type_by_name_including_super_traits<'db>(
16071608
Some((t.skip_binder(), assoc_type))
16081609
})
16091610
}
1611+
1612+
pub fn associated_type_shorthand_candidates(
1613+
db: &dyn HirDatabase,
1614+
def: GenericDefId,
1615+
res: TypeNs,
1616+
mut cb: impl FnMut(&Name, TypeAliasId) -> bool,
1617+
) -> Option<TypeAliasId> {
1618+
let interner = DbInterner::new_with(db, None, None);
1619+
named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| {
1620+
cb(name, id).then_some(id)
1621+
})
1622+
}
1623+
1624+
#[tracing::instrument(skip(interner, check_alias))]
1625+
fn named_associated_type_shorthand_candidates<'db, R>(
1626+
interner: DbInterner<'db>,
1627+
// If the type parameter is defined in an impl and we're in a method, there
1628+
// might be additional where clauses to consider
1629+
def: GenericDefId,
1630+
res: TypeNs,
1631+
assoc_name: Option<Name>,
1632+
mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option<R>,
1633+
) -> Option<R> {
1634+
let db = interner.db;
1635+
let mut search = |t: TraitRef<'db>| -> Option<R> {
1636+
let trait_id = match t.def_id {
1637+
SolverDefId::TraitId(id) => id,
1638+
_ => unreachable!(),
1639+
};
1640+
let mut checked_traits = FxHashSet::default();
1641+
let mut check_trait = |trait_id: TraitId| {
1642+
let name = &db.trait_signature(trait_id).name;
1643+
tracing::debug!(?trait_id, ?name);
1644+
if !checked_traits.insert(trait_id) {
1645+
return None;
1646+
}
1647+
let data = trait_id.trait_items(db);
1648+
1649+
tracing::debug!(?data.items);
1650+
for (name, assoc_id) in &data.items {
1651+
if let &AssocItemId::TypeAliasId(alias) = assoc_id
1652+
&& let Some(ty) = check_alias(name, t, alias)
1653+
{
1654+
return Some(ty);
1655+
}
1656+
}
1657+
None
1658+
};
1659+
let mut stack: SmallVec<[_; 4]> = smallvec![trait_id];
1660+
while let Some(trait_def_id) = stack.pop() {
1661+
if let Some(alias) = check_trait(trait_def_id) {
1662+
return Some(alias);
1663+
}
1664+
for pred in generic_predicates_filtered_by(
1665+
db,
1666+
GenericDefId::TraitId(trait_def_id),
1667+
PredicateFilter::SelfTrait,
1668+
|pred| pred == GenericDefId::TraitId(trait_def_id),
1669+
)
1670+
.0
1671+
.deref()
1672+
{
1673+
tracing::debug!(?pred);
1674+
let trait_id = match pred.kind().skip_binder() {
1675+
rustc_type_ir::ClauseKind::Trait(pred) => pred.def_id(),
1676+
_ => continue,
1677+
};
1678+
let trait_id = match trait_id {
1679+
SolverDefId::TraitId(trait_id) => trait_id,
1680+
_ => continue,
1681+
};
1682+
stack.push(trait_id);
1683+
}
1684+
tracing::debug!(?stack);
1685+
}
1686+
1687+
None
1688+
};
1689+
1690+
match res {
1691+
TypeNs::SelfType(impl_id) => {
1692+
let trait_ref = db.impl_trait_ns(impl_id)?;
1693+
1694+
// we're _in_ the impl -- the binders get added back later. Correct,
1695+
// but it would be nice to make this more explicit
1696+
search(trait_ref.skip_binder())
1697+
}
1698+
TypeNs::GenericParam(param_id) => {
1699+
// Handle `Self::Type` referring to own associated type in trait definitions
1700+
// This *must* be done first to avoid cycles with
1701+
// `generic_predicates_for_param`, but not sure that it's sufficient,
1702+
// see FIXME in `search`.
1703+
if let GenericDefId::TraitId(trait_id) = param_id.parent() {
1704+
let trait_name = &db.trait_signature(trait_id).name;
1705+
tracing::debug!(?trait_name);
1706+
let trait_generics = generics(db, trait_id.into());
1707+
tracing::debug!(?trait_generics);
1708+
if trait_generics[param_id.local_id()].is_trait_self() {
1709+
let args = crate::next_solver::GenericArgs::identity_for_item(
1710+
interner,
1711+
trait_id.into(),
1712+
);
1713+
let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
1714+
tracing::debug!(?args, ?trait_ref);
1715+
return search(trait_ref);
1716+
}
1717+
}
1718+
1719+
let predicates =
1720+
db.generic_predicates_for_param_ns(def, param_id.into(), assoc_name.clone());
1721+
predicates
1722+
.iter()
1723+
.find_map(|pred| match (*pred).kind().skip_binder() {
1724+
rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate),
1725+
_ => None,
1726+
})
1727+
.and_then(|trait_predicate| {
1728+
let trait_ref = trait_predicate.trait_ref;
1729+
assert!(
1730+
!trait_ref.has_escaping_bound_vars(),
1731+
"FIXME unexpected higher-ranked trait bound"
1732+
);
1733+
search(trait_ref)
1734+
})
1735+
}
1736+
_ => None,
1737+
}
1738+
}

src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs

Lines changed: 35 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::ops::Deref;
44

55
use either::Either;
66
use hir_def::{
7-
AssocItemId, GenericDefId, GenericParamId, Lookup, TraitId,
7+
AssocItemId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId,
88
builtin_type::BuiltinType,
99
expr_store::{
1010
ExpressionStore, HygieneId,
@@ -17,6 +17,7 @@ use hir_def::{
1717
signatures::TraitFlags,
1818
type_ref::{TypeRef, TypeRefId},
1919
};
20+
use hir_expand::name::Name;
2021
use intern::sym;
2122
use rustc_hash::FxHashSet;
2223
use rustc_type_ir::{
@@ -33,7 +34,10 @@ use crate::{
3334
db::HirDatabase,
3435
generics::{Generics, generics},
3536
lower::PathDiagnosticCallbackData,
36-
lower_nextsolver::{LifetimeElisionKind, PredicateFilter, generic_predicates_filtered_by},
37+
lower_nextsolver::{
38+
LifetimeElisionKind, PredicateFilter, generic_predicates_filtered_by,
39+
named_associated_type_shorthand_candidates,
40+
},
3741
next_solver::{
3842
AdtDef, Binder, Clause, Const, DbInterner, ErrorGuaranteed, Predicate, ProjectionPredicate,
3943
Region, SolverDefId, TraitRef, Ty,
@@ -501,137 +505,40 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
501505
let Some(res) = res else {
502506
return Ty::new_error(self.ctx.interner, ErrorGuaranteed);
503507
};
504-
let segment = self.current_or_prev_segment;
505-
let assoc_name = segment.name;
506508
let db = self.ctx.db;
507509
let def = self.ctx.def;
508-
let mut search = |t: TraitRef<'db>| {
509-
let trait_id = match t.def_id {
510-
SolverDefId::TraitId(id) => id,
511-
_ => unreachable!(),
512-
};
513-
let mut checked_traits = FxHashSet::default();
514-
let mut check_trait = |trait_id: TraitId| {
515-
let name = &db.trait_signature(trait_id).name;
516-
tracing::debug!(?trait_id, ?name);
517-
if !checked_traits.insert(trait_id) {
518-
return None;
519-
}
520-
let data = trait_id.trait_items(db);
521-
522-
tracing::debug!(?data.items);
523-
for (name, assoc_id) in &data.items {
524-
if let &AssocItemId::TypeAliasId(alias) = assoc_id {
525-
if name != assoc_name {
526-
continue;
527-
}
528-
529-
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
530-
// generic params. It's inefficient to splice the `Substitution`s, so we may want
531-
// that method to optionally take parent `Substitution` as we already know them at
532-
// this point (`t.substitution`).
533-
let substs = self.substs_from_path_segment(alias.into(), false, None, true);
534-
535-
let substs = crate::next_solver::GenericArgs::new_from_iter(
536-
interner,
537-
t.args.iter().chain(substs.iter().skip(t.args.len())),
538-
);
539-
540-
return Some(Ty::new_alias(
541-
interner,
542-
AliasTyKind::Projection,
543-
AliasTy::new(interner, alias.into(), substs),
544-
));
545-
}
546-
}
547-
None
548-
};
549-
let mut stack: SmallVec<[_; 4]> = smallvec![trait_id];
550-
while let Some(trait_def_id) = stack.pop() {
551-
if let Some(alias) = check_trait(trait_def_id) {
552-
return alias;
553-
}
554-
for pred in generic_predicates_filtered_by(
555-
db,
556-
GenericDefId::TraitId(trait_def_id),
557-
PredicateFilter::SelfTrait,
558-
|pred| pred == GenericDefId::TraitId(trait_def_id),
559-
)
560-
.0
561-
.deref()
562-
{
563-
tracing::debug!(?pred);
564-
let trait_id = match pred.kind().skip_binder() {
565-
rustc_type_ir::ClauseKind::Trait(pred) => pred.def_id(),
566-
_ => continue,
567-
};
568-
let trait_id = match trait_id {
569-
SolverDefId::TraitId(trait_id) => trait_id,
570-
_ => continue,
571-
};
572-
stack.push(trait_id);
573-
}
574-
tracing::debug!(?stack);
510+
let segment = self.current_or_prev_segment;
511+
let assoc_name = segment.name;
512+
let mut check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| {
513+
if name != assoc_name {
514+
return None;
575515
}
576516

577-
Ty::new_error(interner, ErrorGuaranteed)
517+
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
518+
// generic params. It's inefficient to splice the `Substitution`s, so we may want
519+
// that method to optionally take parent `Substitution` as we already know them at
520+
// this point (`t.substitution`).
521+
let substs = self.substs_from_path_segment(associated_ty.into(), false, None, true);
522+
523+
let substs = crate::next_solver::GenericArgs::new_from_iter(
524+
interner,
525+
t.args.iter().chain(substs.iter().skip(t.args.len())),
526+
);
527+
528+
Some(Ty::new_alias(
529+
interner,
530+
AliasTyKind::Projection,
531+
AliasTy::new(interner, associated_ty.into(), substs),
532+
))
578533
};
579-
580-
match res {
581-
TypeNs::SelfType(impl_id) => {
582-
let trait_ref = db.impl_trait_ns(impl_id);
583-
let Some(trait_ref) = trait_ref else {
584-
return Ty::new_error(interner, ErrorGuaranteed);
585-
};
586-
587-
// we're _in_ the impl -- the binders get added back later. Correct,
588-
// but it would be nice to make this more explicit
589-
search(trait_ref.skip_binder())
590-
}
591-
TypeNs::GenericParam(param_id) => {
592-
// Handle `Self::Type` referring to own associated type in trait definitions
593-
// This *must* be done first to avoid cycles with
594-
// `generic_predicates_for_param`, but not sure that it's sufficient,
595-
// see FIXME in `search`.
596-
if let GenericDefId::TraitId(trait_id) = param_id.parent() {
597-
let trait_name = &db.trait_signature(trait_id).name;
598-
tracing::debug!(?trait_name);
599-
let trait_generics = generics(db, trait_id.into());
600-
tracing::debug!(?trait_generics);
601-
if trait_generics[param_id.local_id()].is_trait_self() {
602-
let args = crate::next_solver::GenericArgs::identity_for_item(
603-
interner,
604-
trait_id.into(),
605-
);
606-
let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
607-
tracing::debug!(?args, ?trait_ref);
608-
return search(trait_ref);
609-
}
610-
}
611-
612-
let predicates = db.generic_predicates_for_param_ns(
613-
def,
614-
param_id.into(),
615-
Some(segment.name.clone()),
616-
);
617-
predicates
618-
.iter()
619-
.find_map(|pred| match (*pred).kind().skip_binder() {
620-
rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate),
621-
_ => None,
622-
})
623-
.map(|trait_predicate| {
624-
let trait_ref = trait_predicate.trait_ref;
625-
assert!(
626-
!trait_ref.has_escaping_bound_vars(),
627-
"FIXME unexpected higher-ranked trait bound"
628-
);
629-
search(trait_ref)
630-
})
631-
.unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
632-
}
633-
_ => Ty::new_error(interner, ErrorGuaranteed),
634-
}
534+
named_associated_type_shorthand_candidates(
535+
interner,
536+
def,
537+
res,
538+
Some(assoc_name.clone()),
539+
check_alias,
540+
)
541+
.unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
635542
}
636543

637544
fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> {

0 commit comments

Comments
 (0)