Unnamed repository; edit this file 'description' to name the repository.
fix: Panic while canonicalizing erroneous projection type
Shoyu Vanilla 2024-08-14
parent 78c2bdc · commit e6d8970
-rw-r--r--crates/hir-ty/src/infer.rs3
-rw-r--r--crates/hir-ty/src/tests/regression.rs21
-rw-r--r--crates/hir-ty/src/traits.rs14
3 files changed, 35 insertions, 3 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 45d423d03c..5a7deab3a4 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -1436,7 +1436,8 @@ impl<'a> InferenceContext<'a> {
let remaining = unresolved.map(|it| path.segments()[it..].len()).filter(|it| it > &0);
let ty = match ty.kind(Interner) {
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
- self.db.normalize_projection(proj_ty.clone(), self.table.trait_env.clone())
+ let ty = self.table.normalize_projection_ty(proj_ty.clone());
+ self.table.resolve_ty_shallow(&ty)
}
_ => ty,
};
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 2819838612..26e9243e73 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2141,3 +2141,24 @@ fn test() {
}"#,
);
}
+
+#[test]
+fn issue_17866() {
+ check_infer(
+ r#"
+trait T {
+ type A;
+}
+
+type Foo = <S as T>::A;
+
+fn main() {
+ Foo {};
+}
+"#,
+ expect![[r#"
+ 60..75 '{ Foo {}; }': ()
+ 66..72 'Foo {}': {unknown}
+ "#]],
+ );
+}
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index c46382a0ea..00791c5149 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -14,13 +14,13 @@ use hir_def::{
};
use hir_expand::name::Name;
use intern::sym;
-use stdx::panic_context;
+use stdx::{never, panic_context};
use triomphe::Arc;
use crate::{
db::HirDatabase, infer::unify::InferenceTable, utils::UnevaluatedConstEvaluatorFolder, AliasEq,
AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment, Interner, ProjectionTy,
- ProjectionTyExt, Solution, TraitRefExt, Ty, TyKind, WhereClause,
+ ProjectionTyExt, Solution, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause,
};
/// This controls how much 'time' we give the Chalk solver before giving up.
@@ -90,6 +90,16 @@ pub(crate) fn normalize_projection_query(
projection: ProjectionTy,
env: Arc<TraitEnvironment>,
) -> Ty {
+ if projection.substitution.iter(Interner).any(|arg| {
+ arg.ty(Interner)
+ .is_some_and(|ty| ty.data(Interner).flags.intersects(TypeFlags::HAS_TY_INFER))
+ }) {
+ never!(
+ "Invoking `normalize_projection_query` with a projection type containing inference var"
+ );
+ return TyKind::Error.intern(Interner);
+ }
+
let mut table = InferenceTable::new(db, env);
let ty = table.normalize_projection_ty(projection);
table.resolve_completely(ty)