From e6d8970e07586ba483c9a1d7e2eca3601dde504f Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 14 Aug 2024 09:37:20 +0900 Subject: [PATCH] fix: Panic while canonicalizing erroneous projection type --- crates/hir-ty/src/infer.rs | 3 ++- crates/hir-ty/src/tests/regression.rs | 21 +++++++++++++++++++++ crates/hir-ty/src/traits.rs | 14 ++++++++++++-- 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 = ::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, ) -> 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)