fix: handle lifetime variables in projection normalization
This commit is contained in:
parent
2e9f1204ca
commit
efb56160c9
@ -150,6 +150,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
id: chalk_db::AssociatedTyValueId,
|
||||
) -> Arc<chalk_db::AssociatedTyValue>;
|
||||
|
||||
#[salsa::invoke(crate::traits::normalize_projection_query)]
|
||||
#[salsa::transparent]
|
||||
fn normalize_projection(
|
||||
&self,
|
||||
projection: crate::ProjectionTy,
|
||||
env: Arc<crate::TraitEnvironment>,
|
||||
) -> Option<crate::Ty>;
|
||||
|
||||
#[salsa::invoke(trait_solve_wait)]
|
||||
#[salsa::transparent]
|
||||
fn trait_solve(
|
||||
|
@ -196,20 +196,6 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
|
||||
make_binders_with_count(db, usize::MAX, generics, value)
|
||||
}
|
||||
|
||||
// FIXME: get rid of this
|
||||
pub fn make_canonical<T: HasInterner<Interner = Interner>>(
|
||||
value: T,
|
||||
kinds: impl IntoIterator<Item = TyVariableKind>,
|
||||
) -> Canonical<T> {
|
||||
let kinds = kinds.into_iter().map(|tk| {
|
||||
chalk_ir::CanonicalVarKind::new(
|
||||
chalk_ir::VariableKind::Ty(tk),
|
||||
chalk_ir::UniverseIndex::ROOT,
|
||||
)
|
||||
});
|
||||
Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
|
||||
}
|
||||
|
||||
// FIXME: get rid of this, just replace it by FnPointer
|
||||
/// A function signature as seen by type inference: Several parameter types and
|
||||
/// one return type.
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Trait solving using Chalk.
|
||||
|
||||
use std::env::var;
|
||||
use std::{env::var, sync::Arc};
|
||||
|
||||
use chalk_ir::GoalData;
|
||||
use chalk_recursive::Cache;
|
||||
@ -12,8 +12,9 @@ use stdx::panic_context;
|
||||
use syntax::SmolStr;
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment,
|
||||
Interner, Solution, TraitRefExt, Ty, TyKind, WhereClause,
|
||||
db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal,
|
||||
Guidance, InEnvironment, Interner, ProjectionTy, Solution, TraitRefExt, Ty, TyKind,
|
||||
WhereClause,
|
||||
};
|
||||
|
||||
/// This controls how much 'time' we give the Chalk solver before giving up.
|
||||
@ -64,6 +65,16 @@ impl TraitEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalize_projection_query(
|
||||
db: &dyn HirDatabase,
|
||||
projection: ProjectionTy,
|
||||
env: Arc<TraitEnvironment>,
|
||||
) -> Option<Ty> {
|
||||
let mut table = InferenceTable::new(db, env.clone());
|
||||
let ty = table.normalize_projection_ty(projection);
|
||||
Some(table.resolve_completely(ty))
|
||||
}
|
||||
|
||||
/// Solve a trait goal using Chalk.
|
||||
pub(crate) fn trait_solve_query(
|
||||
db: &dyn HirDatabase,
|
||||
|
@ -63,10 +63,9 @@ use hir_ty::{
|
||||
primitive::UintTy,
|
||||
subst_prefix,
|
||||
traits::FnTrait,
|
||||
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
|
||||
ClosureId, DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind,
|
||||
QuantifiedWhereClause, Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty,
|
||||
TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
|
||||
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
|
||||
GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
|
||||
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use nameres::diagnostics::DefDiagnosticKind;
|
||||
@ -2880,28 +2879,8 @@ impl Type {
|
||||
}
|
||||
})
|
||||
.build();
|
||||
let goal = hir_ty::make_canonical(
|
||||
InEnvironment::new(
|
||||
&self.env.env,
|
||||
AliasEq {
|
||||
alias: AliasTy::Projection(projection),
|
||||
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
|
||||
.intern(Interner),
|
||||
}
|
||||
.cast(Interner),
|
||||
),
|
||||
[TyVariableKind::General].into_iter(),
|
||||
);
|
||||
|
||||
match db.trait_solve(self.env.krate, goal)? {
|
||||
Solution::Unique(s) => s
|
||||
.value
|
||||
.subst
|
||||
.as_slice(Interner)
|
||||
.first()
|
||||
.map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())),
|
||||
Solution::Ambig(_) => None,
|
||||
}
|
||||
db.normalize_projection(projection, self.env.clone()).map(|ty| self.derived(ty))
|
||||
}
|
||||
|
||||
pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
|
||||
|
@ -1687,6 +1687,74 @@ fn main() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_hint_regression_issue_12674() {
|
||||
// Ensure we don't crash while solving the projection type of iterators.
|
||||
check_expect(
|
||||
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
|
||||
r#"
|
||||
//- minicore: iterators
|
||||
struct S<T>(T);
|
||||
impl<T> S<T> {
|
||||
fn iter(&self) -> Iter<'_, T> { loop {} }
|
||||
}
|
||||
struct Iter<'a, T: 'a>(&'a T);
|
||||
impl<'a, T> Iterator for Iter<'a, T> {
|
||||
type Item = &'a T;
|
||||
fn next(&mut self) -> Option<Self::Item> { loop {} }
|
||||
}
|
||||
struct Container<'a> {
|
||||
elements: S<&'a str>,
|
||||
}
|
||||
struct SliceIter<'a, T>(&'a T);
|
||||
impl<'a, T> Iterator for SliceIter<'a, T> {
|
||||
type Item = &'a T;
|
||||
fn next(&mut self) -> Option<Self::Item> { loop {} }
|
||||
}
|
||||
|
||||
fn main(a: SliceIter<'_, Container>) {
|
||||
a
|
||||
.filter_map(|c| Some(c.elements.iter().filter_map(|v| Some(v))))
|
||||
.map(|e| e);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
InlayHint {
|
||||
range: 484..554,
|
||||
kind: ChainingHint,
|
||||
label: [
|
||||
"impl Iterator<Item = impl Iterator<Item = &&str>>",
|
||||
],
|
||||
tooltip: Some(
|
||||
HoverRanged(
|
||||
FileId(
|
||||
0,
|
||||
),
|
||||
484..554,
|
||||
),
|
||||
),
|
||||
},
|
||||
InlayHint {
|
||||
range: 484..485,
|
||||
kind: ChainingHint,
|
||||
label: [
|
||||
"SliceIter<Container>",
|
||||
],
|
||||
tooltip: Some(
|
||||
HoverRanged(
|
||||
FileId(
|
||||
0,
|
||||
),
|
||||
484..485,
|
||||
),
|
||||
),
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_call_method_return_associated_types_with_generic() {
|
||||
check_types(
|
||||
|
Loading…
x
Reference in New Issue
Block a user