aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r--crates/hir_ty/src/lib.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 06d5cd0b6..56f60c46b 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -43,6 +43,7 @@ use hir_def::{
43 type_ref::{ConstScalar, Rawness}, 43 type_ref::{ConstScalar, Rawness},
44 TypeParamId, 44 TypeParamId,
45}; 45};
46use stdx::always;
46 47
47use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 48use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
48 49
@@ -326,3 +327,58 @@ pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>(
326 } 327 }
327 t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly") 328 t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
328} 329}
330
331pub fn replace_errors_with_variables<T>(t: T) -> Canonical<T::Result>
332where
333 T: HasInterner<Interner = Interner> + Fold<Interner>,
334 T::Result: HasInterner<Interner = Interner>,
335{
336 use chalk_ir::{
337 fold::{Folder, SuperFold},
338 Fallible,
339 };
340 struct ErrorReplacer {
341 vars: usize,
342 }
343 impl<'i> Folder<'i, Interner> for ErrorReplacer {
344 fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
345 self
346 }
347
348 fn interner(&self) -> &'i Interner {
349 &Interner
350 }
351
352 fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
353 if let TyKind::Error = ty.kind(&Interner) {
354 let index = self.vars;
355 self.vars += 1;
356 Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(&Interner))
357 } else {
358 let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
359 Ok(ty)
360 }
361 }
362
363 fn fold_inference_ty(
364 &mut self,
365 var: InferenceVar,
366 kind: TyVariableKind,
367 _outer_binder: DebruijnIndex,
368 ) -> Fallible<Ty> {
369 always!(false);
370 Ok(TyKind::InferenceVar(var, kind).intern(&Interner))
371 }
372 }
373 let mut error_replacer = ErrorReplacer { vars: 0 };
374 let value = t
375 .fold_with(&mut error_replacer, DebruijnIndex::INNERMOST)
376 .expect("fold failed unexpectedly");
377 let kinds = (0..error_replacer.vars).map(|_| {
378 chalk_ir::CanonicalVarKind::new(
379 chalk_ir::VariableKind::Ty(TyVariableKind::General),
380 chalk_ir::UniverseIndex::ROOT,
381 )
382 });
383 Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
384}