Skip to content

Commit efb5616

Browse files
committed
fix: handle lifetime variables in projection normalization
1 parent 2e9f120 commit efb5616

File tree

5 files changed

+94
-42
lines changed

5 files changed

+94
-42
lines changed

crates/hir-ty/src/db.rs

+8
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
150150
id: chalk_db::AssociatedTyValueId,
151151
) -> Arc<chalk_db::AssociatedTyValue>;
152152

153+
#[salsa::invoke(crate::traits::normalize_projection_query)]
154+
#[salsa::transparent]
155+
fn normalize_projection(
156+
&self,
157+
projection: crate::ProjectionTy,
158+
env: Arc<crate::TraitEnvironment>,
159+
) -> Option<crate::Ty>;
160+
153161
#[salsa::invoke(trait_solve_wait)]
154162
#[salsa::transparent]
155163
fn trait_solve(

crates/hir-ty/src/lib.rs

-14
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,6 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
196196
make_binders_with_count(db, usize::MAX, generics, value)
197197
}
198198

199-
// FIXME: get rid of this
200-
pub fn make_canonical<T: HasInterner<Interner = Interner>>(
201-
value: T,
202-
kinds: impl IntoIterator<Item = TyVariableKind>,
203-
) -> Canonical<T> {
204-
let kinds = kinds.into_iter().map(|tk| {
205-
chalk_ir::CanonicalVarKind::new(
206-
chalk_ir::VariableKind::Ty(tk),
207-
chalk_ir::UniverseIndex::ROOT,
208-
)
209-
});
210-
Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
211-
}
212-
213199
// FIXME: get rid of this, just replace it by FnPointer
214200
/// A function signature as seen by type inference: Several parameter types and
215201
/// one return type.

crates/hir-ty/src/traits.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Trait solving using Chalk.
22
3-
use std::env::var;
3+
use std::{env::var, sync::Arc};
44

55
use chalk_ir::GoalData;
66
use chalk_recursive::Cache;
@@ -12,8 +12,9 @@ use stdx::panic_context;
1212
use syntax::SmolStr;
1313

1414
use crate::{
15-
db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment,
16-
Interner, Solution, TraitRefExt, Ty, TyKind, WhereClause,
15+
db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal,
16+
Guidance, InEnvironment, Interner, ProjectionTy, Solution, TraitRefExt, Ty, TyKind,
17+
WhereClause,
1718
};
1819

1920
/// This controls how much 'time' we give the Chalk solver before giving up.
@@ -64,6 +65,16 @@ impl TraitEnvironment {
6465
}
6566
}
6667

68+
pub(crate) fn normalize_projection_query(
69+
db: &dyn HirDatabase,
70+
projection: ProjectionTy,
71+
env: Arc<TraitEnvironment>,
72+
) -> Option<Ty> {
73+
let mut table = InferenceTable::new(db, env.clone());
74+
let ty = table.normalize_projection_ty(projection);
75+
Some(table.resolve_completely(ty))
76+
}
77+
6778
/// Solve a trait goal using Chalk.
6879
pub(crate) fn trait_solve_query(
6980
db: &dyn HirDatabase,

crates/hir/src/lib.rs

+4-25
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,9 @@ use hir_ty::{
6363
primitive::UintTy,
6464
subst_prefix,
6565
traits::FnTrait,
66-
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
67-
ClosureId, DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind,
68-
QuantifiedWhereClause, Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty,
69-
TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
66+
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
67+
GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
68+
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause,
7069
};
7170
use itertools::Itertools;
7271
use nameres::diagnostics::DefDiagnosticKind;
@@ -2880,28 +2879,8 @@ impl Type {
28802879
}
28812880
})
28822881
.build();
2883-
let goal = hir_ty::make_canonical(
2884-
InEnvironment::new(
2885-
&self.env.env,
2886-
AliasEq {
2887-
alias: AliasTy::Projection(projection),
2888-
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
2889-
.intern(Interner),
2890-
}
2891-
.cast(Interner),
2892-
),
2893-
[TyVariableKind::General].into_iter(),
2894-
);
28952882

2896-
match db.trait_solve(self.env.krate, goal)? {
2897-
Solution::Unique(s) => s
2898-
.value
2899-
.subst
2900-
.as_slice(Interner)
2901-
.first()
2902-
.map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())),
2903-
Solution::Ambig(_) => None,
2904-
}
2883+
db.normalize_projection(projection, self.env.clone()).map(|ty| self.derived(ty))
29052884
}
29062885

29072886
pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {

crates/ide/src/inlay_hints.rs

+68
Original file line numberDiff line numberDiff line change
@@ -1687,6 +1687,74 @@ fn main() {
16871687
);
16881688
}
16891689

1690+
#[test]
1691+
fn iterator_hint_regression_issue_12674() {
1692+
// Ensure we don't crash while solving the projection type of iterators.
1693+
check_expect(
1694+
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
1695+
r#"
1696+
//- minicore: iterators
1697+
struct S<T>(T);
1698+
impl<T> S<T> {
1699+
fn iter(&self) -> Iter<'_, T> { loop {} }
1700+
}
1701+
struct Iter<'a, T: 'a>(&'a T);
1702+
impl<'a, T> Iterator for Iter<'a, T> {
1703+
type Item = &'a T;
1704+
fn next(&mut self) -> Option<Self::Item> { loop {} }
1705+
}
1706+
struct Container<'a> {
1707+
elements: S<&'a str>,
1708+
}
1709+
struct SliceIter<'a, T>(&'a T);
1710+
impl<'a, T> Iterator for SliceIter<'a, T> {
1711+
type Item = &'a T;
1712+
fn next(&mut self) -> Option<Self::Item> { loop {} }
1713+
}
1714+
1715+
fn main(a: SliceIter<'_, Container>) {
1716+
a
1717+
.filter_map(|c| Some(c.elements.iter().filter_map(|v| Some(v))))
1718+
.map(|e| e);
1719+
}
1720+
"#,
1721+
expect![[r#"
1722+
[
1723+
InlayHint {
1724+
range: 484..554,
1725+
kind: ChainingHint,
1726+
label: [
1727+
"impl Iterator<Item = impl Iterator<Item = &&str>>",
1728+
],
1729+
tooltip: Some(
1730+
HoverRanged(
1731+
FileId(
1732+
0,
1733+
),
1734+
484..554,
1735+
),
1736+
),
1737+
},
1738+
InlayHint {
1739+
range: 484..485,
1740+
kind: ChainingHint,
1741+
label: [
1742+
"SliceIter<Container>",
1743+
],
1744+
tooltip: Some(
1745+
HoverRanged(
1746+
FileId(
1747+
0,
1748+
),
1749+
484..485,
1750+
),
1751+
),
1752+
},
1753+
]
1754+
"#]],
1755+
);
1756+
}
1757+
16901758
#[test]
16911759
fn infer_call_method_return_associated_types_with_generic() {
16921760
check_types(

0 commit comments

Comments
 (0)