diff --git a/pkg/lint/linter/context.go b/pkg/lint/linter/context.go
index 1c4902e1..a9f9d7d7 100644
--- a/pkg/lint/linter/context.go
+++ b/pkg/lint/linter/context.go
@@ -1,6 +1,8 @@
 package linter
 
 import (
+	"go/ast"
+
 	"golang.org/x/tools/go/packages"
 
 	"github.com/golangci/golangci-lint/internal/pkgcache"
@@ -30,3 +32,18 @@ type Context struct {
 func (c *Context) Settings() *config.LintersSettings {
 	return &c.Cfg.LintersSettings
 }
+
+func (c *Context) ClearTypesInPackages() {
+	for _, p := range c.Packages {
+		clearTypes(p)
+	}
+	for _, p := range c.OriginalPackages {
+		clearTypes(p)
+	}
+}
+
+func clearTypes(p *packages.Package) {
+	p.Types = nil
+	p.TypesInfo = nil
+	p.Syntax = []*ast.File{}
+}
diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go
index 8ce01c79..4dc40f3f 100644
--- a/pkg/lint/runner.go
+++ b/pkg/lint/runner.go
@@ -111,29 +111,14 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
 		}
 	}()
 
-	// pkgs will get dirty while analyzing, which affects to other linters' result.
-	// To avoid this issue, we clone the loaded packages rather than directly using them.
-	oldPackages := lintCtx.Packages
-	oldOriginalPackages := lintCtx.OriginalPackages
-	clone := func(pkgs []*gopackages.Package) []*gopackages.Package {
-		clonedPkgs := make([]*gopackages.Package, len(pkgs))
-		for i, pkg := range pkgs {
-			p := *pkg
-			clonedPkgs[i] = &p
-		}
-		return clonedPkgs
-	}
-	lintCtx.Packages = clone(lintCtx.Packages)
-	lintCtx.OriginalPackages = clone(lintCtx.OriginalPackages)
-
 	specificLintCtx := *lintCtx
 	specificLintCtx.Log = r.Log.Child(lc.Name())
 
+	// Packages in lintCtx might be dirty due to the last analysis,
+	// which affects to the next analysis.
+	// To avoid this issue, we clear type information from the packages.
+	specificLintCtx.ClearTypesInPackages()
 	issues, err := lc.Linter.Run(ctx, &specificLintCtx)
-
-	lintCtx.Packages = oldPackages
-	lintCtx.OriginalPackages = oldOriginalPackages
-
 	if err != nil {
 		return nil, err
 	}