diff --git a/crates/els/diagnostics.rs b/crates/els/diagnostics.rs
index 7442ba9c1..a927a0add 100644
--- a/crates/els/diagnostics.rs
+++ b/crates/els/diagnostics.rs
@@ -289,10 +289,16 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
         }
         if let Some((mut lowerer, mut irs)) = self.steal_lowerer(&uri) {
             if let Some((hir_diff, hir)) =
-                HIRDiff::new(ast_diff, &mut lowerer).zip(irs.hir.as_mut())
+                HIRDiff::new(ast_diff.clone(), &mut lowerer).zip(irs.hir.as_mut())
             {
                 crate::_log!(self, "hir_diff: {hir_diff}");
                 hir_diff.update(hir);
+                if let Some(ast) = irs.ast.as_mut() {
+                    ast_diff.update(ast);
+                }
+            }
+            if let Some(hir) = irs.hir.as_mut() {
+                HIRDiff::fix(&new, &mut hir.module, &mut lowerer);
             }
             self.restore_lowerer(uri, lowerer, irs);
         }
diff --git a/crates/els/diff.rs b/crates/els/diff.rs
index 6096e315e..c2689d4e3 100644
--- a/crates/els/diff.rs
+++ b/crates/els/diff.rs
@@ -8,6 +8,7 @@ use erg_compiler::erg_parser::ast::Module;
 use erg_compiler::hir;
 use erg_compiler::hir::HIR;
 use erg_compiler::lower::ASTLowerer;
+use erg_compiler::ty::HasType;
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum ASTDiff {
@@ -67,6 +68,29 @@ impl ASTDiff {
     pub const fn is_nop(&self) -> bool {
         matches!(self, Self::Nop)
     }
+
+    pub fn update(self, mut old: impl DerefMut<Target = ast::Module>) {
+        match self {
+            Self::Addition(idx, expr) => {
+                if idx > old.len() {
+                    old.push(expr);
+                } else {
+                    old.insert(idx, expr);
+                }
+            }
+            Self::Deletion(usize) => {
+                if old.get(usize).is_some() {
+                    old.remove(usize);
+                }
+            }
+            Self::Modification(idx, expr) => {
+                if let Some(old_expr) = old.get_mut(idx) {
+                    *old_expr = expr;
+                }
+            }
+            Self::Nop => {}
+        }
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -93,12 +117,10 @@ impl HIRDiff {
         match diff {
             ASTDiff::Deletion(idx) => Some(Self::Deletion(idx)),
             ASTDiff::Addition(idx, expr) => {
-                let expr = lowerer
-                    .lower_chunk(expr, None)
-                    .map_err(|_err| {
-                        // crate::_log!(self, "err: {err}");
-                    })
-                    .ok()?;
+                let expr = match lowerer.lower_and_resolve_chunk(expr, None) {
+                    Ok(expr) => expr,
+                    Err((opt_expr, _err)) => opt_expr?,
+                };
                 Some(Self::Addition(idx, expr))
             }
             ASTDiff::Modification(idx, expr) => {
@@ -110,12 +132,10 @@ impl HIRDiff {
                         lowerer.unregister(name);
                     }
                 }
-                let expr = lowerer
-                    .lower_chunk(expr, None)
-                    .map_err(|_err| {
-                        // crate::_log!(self, "err: {err}");
-                    })
-                    .ok()?;
+                let expr = match lowerer.lower_and_resolve_chunk(expr, None) {
+                    Ok(expr) => expr,
+                    Err((opt_expr, _err)) => opt_expr?,
+                };
                 Some(Self::Modification(idx, expr))
             }
             ASTDiff::Nop => Some(Self::Nop),
@@ -144,4 +164,23 @@ impl HIRDiff {
             Self::Nop => {}
         }
     }
+
+    pub fn fix(ast: &ast::Module, hir: &mut hir::Module, lowerer: &mut ASTLowerer) -> usize {
+        let mut fixed = 0;
+        for (ast_chunk, chunk) in ast.iter().zip(hir.iter_mut()) {
+            if ast_chunk.name() != chunk.name() {
+                continue;
+            }
+            if chunk.ref_t().contains_failure() {
+                match lowerer.lower_and_resolve_chunk(ast_chunk.clone(), None) {
+                    Ok(expr) | Err((Some(expr), _)) => {
+                        *chunk = expr;
+                        fixed += 1;
+                    }
+                    _ => {}
+                }
+            }
+        }
+        fixed
+    }
 }
diff --git a/crates/erg_compiler/context/generalize.rs b/crates/erg_compiler/context/generalize.rs
index 3ca454aed..c8a7acf66 100644
--- a/crates/erg_compiler/context/generalize.rs
+++ b/crates/erg_compiler/context/generalize.rs
@@ -1529,7 +1529,11 @@ impl Context {
     /// Resolution should start at a deeper level.
     /// For example, if it is a lambda function, the body should be checked before the signature.
     /// However, a binop call error, etc., is more important then binop operands.
-    fn resolve_expr_t(&self, expr: &mut hir::Expr, qnames: &Set<Str>) -> TyCheckResult<()> {
+    pub(crate) fn resolve_expr_t(
+        &self,
+        expr: &mut hir::Expr,
+        qnames: &Set<Str>,
+    ) -> TyCheckResult<()> {
         match expr {
             hir::Expr::Literal(_) => Ok(()),
             hir::Expr::Accessor(acc) => {
diff --git a/crates/erg_compiler/hir.rs b/crates/erg_compiler/hir.rs
index c646954b5..36a445bae 100644
--- a/crates/erg_compiler/hir.rs
+++ b/crates/erg_compiler/hir.rs
@@ -3008,7 +3008,7 @@ impl Expr {
         match self {
             Self::Literal(_) => "literal",
             Self::Accessor(_) => "accessor",
-            Self::List(_) => "array",
+            Self::List(_) => "list",
             Self::Tuple(_) => "tuple",
             Self::Dict(_) => "dict",
             Self::Set(_) => "set",
diff --git a/crates/erg_compiler/lower.rs b/crates/erg_compiler/lower.rs
index 65de5141e..021cdbc1e 100644
--- a/crates/erg_compiler/lower.rs
+++ b/crates/erg_compiler/lower.rs
@@ -3606,7 +3606,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
     /// The meaning of TypeAscription changes between chunk and expr.
     /// For example, `x: Int`, as expr, is `x` itself,
     /// but as chunk, it declares that `x` is of type `Int`, and is valid even before `x` is defined.
-    pub fn lower_chunk(
+    pub(crate) fn lower_chunk(
         &mut self,
         chunk: ast::Expr,
         expect: Option<&Type>,
@@ -3633,6 +3633,24 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
         }
     }
 
+    pub fn lower_and_resolve_chunk(
+        &mut self,
+        chunk: ast::Expr,
+        expect: Option<&Type>,
+    ) -> FailableOption<hir::Expr> {
+        match self.lower_chunk(chunk, expect) {
+            Ok(mut chunk) => {
+                let _ = self.module.context.resolve_expr_t(&mut chunk, &set! {});
+                Ok(chunk)
+            }
+            Err((Some(mut chunk), errs)) => {
+                let _ = self.module.context.resolve_expr_t(&mut chunk, &set! {});
+                Err((Some(chunk), errs))
+            }
+            Err((None, errs)) => Err((None, errs)),
+        }
+    }
+
     fn lower_block(
         &mut self,
         ast_block: ast::Block,
diff --git a/crates/erg_parser/ast.rs b/crates/erg_parser/ast.rs
index 88aa861f0..b8c5192b7 100644
--- a/crates/erg_parser/ast.rs
+++ b/crates/erg_parser/ast.rs
@@ -2,6 +2,7 @@
 use std::borrow::Borrow;
 use std::fmt;
 use std::fmt::Write as _;
+use std::hash::{Hash, Hasher};
 
 use erg_common::consts::ERG_MODE;
 use erg_common::error::Location;
@@ -2559,13 +2560,28 @@ impl ConstBlock {
 }
 
 #[pyclass(get_all, set_all)]
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug)]
 pub struct ConstDefBody {
     pub op: Token,
     pub block: ConstBlock,
     pub id: DefId,
 }
 
+impl PartialEq for ConstDefBody {
+    fn eq(&self, other: &Self) -> bool {
+        self.op == other.op && self.block == other.block
+    }
+}
+
+impl Eq for ConstDefBody {}
+
+impl Hash for ConstDefBody {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.op.hash(state);
+        self.block.hash(state);
+    }
+}
+
 impl_locational!(ConstDefBody, lossy op, block);
 
 #[pymethods]
@@ -2613,7 +2629,7 @@ impl ConstDef {
 }
 
 #[pyclass]
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug)]
 pub struct ConstLambda {
     pub sig: Box<LambdaSignature>,
     pub op: Token,
@@ -2621,6 +2637,22 @@ pub struct ConstLambda {
     pub id: DefId,
 }
 
+impl PartialEq for ConstLambda {
+    fn eq(&self, other: &Self) -> bool {
+        self.sig == other.sig && self.op == other.op && self.body == other.body
+    }
+}
+
+impl Eq for ConstLambda {}
+
+impl Hash for ConstLambda {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.sig.hash(state);
+        self.op.hash(state);
+        self.body.hash(state);
+    }
+}
+
 impl NestedDisplay for ConstLambda {
     fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
         write!(f, "({}) {} {}", self.sig, self.op.content, self.body)
@@ -5495,6 +5527,8 @@ impl LambdaSignature {
     }
 }
 
+/// Definition ID.
+/// IDs are comparable, but `Def`s with different IDs are equal if the node contents are the same.
 #[pyclass(subclass)]
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct DefId(pub usize);
@@ -5506,7 +5540,7 @@ impl DefId {
 }
 
 #[pyclass(get_all, set_all)]
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug)]
 pub struct Lambda {
     pub sig: LambdaSignature,
     /// for detecting func/proc
@@ -5515,6 +5549,22 @@ pub struct Lambda {
     pub id: DefId,
 }
 
+impl PartialEq for Lambda {
+    fn eq(&self, other: &Self) -> bool {
+        self.sig == other.sig && self.op == other.op && self.body == other.body
+    }
+}
+
+impl Eq for Lambda {}
+
+impl Hash for Lambda {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.sig.hash(state);
+        self.op.hash(state);
+        self.body.hash(state);
+    }
+}
+
 impl NestedDisplay for Lambda {
     fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
         writeln!(f, "{} {}", self.sig, self.op.content)?;
@@ -5762,7 +5812,7 @@ impl DefKind {
 }
 
 #[pyclass(get_all, set_all)]
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug)]
 pub struct DefBody {
     pub op: Token,
     pub block: Block,
@@ -5771,6 +5821,21 @@ pub struct DefBody {
 
 impl_locational!(DefBody, lossy op, block);
 
+impl PartialEq for DefBody {
+    fn eq(&self, other: &Self) -> bool {
+        self.op == other.op && self.block == other.block
+    }
+}
+
+impl Eq for DefBody {}
+
+impl Hash for DefBody {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.op.hash(state);
+        self.block.hash(state);
+    }
+}
+
 #[pymethods]
 impl DefBody {
     #[staticmethod]
@@ -5896,7 +5961,7 @@ impl ReDef {
 ///     f(a) = ...
 /// ```
 #[pyclass]
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone)]
 pub struct Methods {
     pub id: DefId,
     pub class: TypeSpec,
@@ -5905,6 +5970,26 @@ pub struct Methods {
     pub attrs: ClassAttrs,
 }
 
+impl PartialEq for Methods {
+    fn eq(&self, other: &Self) -> bool {
+        self.class == other.class
+            && self.class_as_expr == other.class_as_expr
+            && self.vis == other.vis
+            && self.attrs == other.attrs
+    }
+}
+
+impl Eq for Methods {}
+
+impl Hash for Methods {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.class.hash(state);
+        self.class_as_expr.hash(state);
+        self.vis.hash(state);
+        self.attrs.hash(state);
+    }
+}
+
 impl NestedDisplay for Methods {
     fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
         writeln!(f, "{}{}", self.class, self.vis)?;