Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/cast.rs')
-rw-r--r--crates/hir-ty/src/infer/cast.rs39
1 files changed, 39 insertions, 0 deletions
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index ae91404436..caa3960a22 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -120,6 +120,13 @@ impl CastCheck {
});
}
+ // Chalk doesn't support trait upcasting and fails to solve some obvious goals
+ // when the trait environment contains some recursive traits (See issue #18047)
+ // We skip cast checks for such cases for now, until the next-gen solver.
+ if contains_dyn_trait(&self.cast_ty) {
+ return Ok(());
+ }
+
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &self.cast_ty) {
apply_adjustments(self.source_expr, adj);
set_coercion_cast(self.source_expr);
@@ -410,3 +417,35 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result<Option<Pointe
}
}
}
+
+fn contains_dyn_trait(ty: &Ty) -> bool {
+ use std::ops::ControlFlow;
+
+ use chalk_ir::{
+ visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
+ DebruijnIndex,
+ };
+
+ struct DynTraitVisitor;
+
+ impl TypeVisitor<Interner> for DynTraitVisitor {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn interner(&self) -> Interner {
+ Interner
+ }
+
+ fn visit_ty(&mut self, ty: &Ty, outer_binder: DebruijnIndex) -> ControlFlow<Self::BreakTy> {
+ match ty.kind(Interner) {
+ TyKind::Dyn(_) => ControlFlow::Break(()),
+ _ => ty.super_visit_with(self.as_dyn(), outer_binder),
+ }
+ }
+ }
+
+ ty.visit_with(DynTraitVisitor.as_dyn(), DebruijnIndex::INNERMOST).is_break()
+}