From a5d85a6356dc761d047f46bf04eae09dc9ab80f9 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 23 May 2021 12:52:41 +0200 Subject: Add test for #8931 and better checking --- crates/hir_ty/src/lib.rs | 94 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 11 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 72093d75a..ef021978a 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -43,7 +43,6 @@ use hir_def::{ type_ref::{ConstScalar, Rawness}, TypeParamId, }; -use stdx::always; use crate::{db::HirDatabase, utils::generics}; @@ -329,14 +328,17 @@ pub(crate) fn fold_tys + Fold>( t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly") } -pub fn replace_errors_with_variables(t: T) -> Canonical +/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also +/// ensures there are no unbound variables or inference variables anywhere in +/// the `t`. +pub fn replace_errors_with_variables(t: &T) -> Canonical where - T: HasInterner + Fold, + T: HasInterner + Fold + Clone, T::Result: HasInterner, { use chalk_ir::{ fold::{Folder, SuperFold}, - Fallible, + Fallible, NoSolution, }; struct ErrorReplacer { vars: usize, @@ -363,18 +365,88 @@ where fn fold_inference_ty( &mut self, - var: InferenceVar, - kind: TyVariableKind, + _var: InferenceVar, + _kind: TyVariableKind, + _outer_binder: DebruijnIndex, + ) -> Fallible { + if cfg!(debug_assertions) { + // we don't want to just panic here, because then the error message + // won't contain the whole thing, which would not be very helpful + Err(NoSolution) + } else { + Ok(TyKind::Error.intern(&Interner)) + } + } + + fn fold_free_var_ty( + &mut self, + _bound_var: BoundVar, _outer_binder: DebruijnIndex, ) -> Fallible { - always!(false); - Ok(TyKind::InferenceVar(var, kind).intern(&Interner)) + if cfg!(debug_assertions) { + // we don't want to just panic here, because then the error message + // won't contain the whole thing, which would not be very helpful + Err(NoSolution) + } else { + Ok(TyKind::Error.intern(&Interner)) + } + } + + fn fold_inference_const( + &mut self, + _ty: Ty, + _var: InferenceVar, + _outer_binder: DebruijnIndex, + ) -> Fallible { + if cfg!(debug_assertions) { + Err(NoSolution) + } else { + Ok(dummy_usize_const()) + } + } + + fn fold_free_var_const( + &mut self, + _ty: Ty, + _bound_var: BoundVar, + _outer_binder: DebruijnIndex, + ) -> Fallible { + if cfg!(debug_assertions) { + Err(NoSolution) + } else { + Ok(dummy_usize_const()) + } + } + + fn fold_inference_lifetime( + &mut self, + _var: InferenceVar, + _outer_binder: DebruijnIndex, + ) -> Fallible { + if cfg!(debug_assertions) { + Err(NoSolution) + } else { + Ok(static_lifetime()) + } + } + + fn fold_free_var_lifetime( + &mut self, + _bound_var: BoundVar, + _outer_binder: DebruijnIndex, + ) -> Fallible { + if cfg!(debug_assertions) { + Err(NoSolution) + } else { + Ok(static_lifetime()) + } } } let mut error_replacer = ErrorReplacer { vars: 0 }; - let value = t - .fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) - .expect("fold failed unexpectedly"); + let value = match t.clone().fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) { + Ok(t) => t, + Err(_) => panic!("Encountered unbound or inference vars in {:?}", t), + }; let kinds = (0..error_replacer.vars).map(|_| { chalk_ir::CanonicalVarKind::new( chalk_ir::VariableKind::Ty(TyVariableKind::General), -- cgit v1.2.3