From 35f9d8e5b903a026433c36dd91eabe58eff9503a Mon Sep 17 00:00:00 2001
From: Denis Isaev <denis@golangci.com>
Date: Sat, 30 Jun 2018 19:02:25 +0300
Subject: [PATCH] Fix unparam crash on nil constant

---
 Gopkg.lock                             |  6 +++---
 Gopkg.toml                             |  2 +-
 pkg/golinters/unparam.go               |  4 ++--
 vendor/mvdan.cc/unparam/check/check.go | 28 +++++++++++++++++---------
 4 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/Gopkg.lock b/Gopkg.lock
index e2065fe6..420617c7 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -410,10 +410,10 @@
   revision = "adc824a0674b99099789b6188a058d485eaf61c0"
 
 [[projects]]
-  branch = "master"
+  branch = "fix-crash-on-nil-constant"
   name = "mvdan.cc/unparam"
   packages = ["check"]
-  revision = "31deaf77ea9671c648eee0054071487bce1b4b41"
+  revision = "f30d69ad8b55690d0e814cdd96e955834e0d0ee1"
   source = "github.com/golangci/unparam"
 
 [[projects]]
@@ -431,6 +431,6 @@
 [solve-meta]
   analyzer-name = "dep"
   analyzer-version = 1
-  inputs-digest = "c81f352144bce99702ee1976f4fc0679c133b22861d72f152df4ca7c614adf81"
+  inputs-digest = "9844330f4bbfb7620dd00fce3bf03f3aae60f82de82764e817881e76a20888f6"
   solver-name = "gps-cdcl"
   solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
index 95c639fe..6062d4e8 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -26,7 +26,7 @@
 
 [[constraint]]
   name = "mvdan.cc/unparam"
-  branch = "master"
+  branch = "fix-crash-on-nil-constant"
   source = "github.com/golangci/unparam"
 
 [[constraint]]
diff --git a/pkg/golinters/unparam.go b/pkg/golinters/unparam.go
index 956eb004..9b4f9d89 100644
--- a/pkg/golinters/unparam.go
+++ b/pkg/golinters/unparam.go
@@ -22,8 +22,8 @@ func (lint Unparam) Run(ctx context.Context, lintCtx *linter.Context) ([]result.
 	us := &lintCtx.Settings().Unparam
 
 	c := &check.Checker{}
-	c.Algo(us.Algo)
-	c.Exported(us.CheckExported)
+	c.CallgraphAlgorithm(us.Algo)
+	c.CheckExportedFuncs(us.CheckExported)
 	c.Program(lintCtx.Program)
 	c.ProgramSSA(lintCtx.SSAProgram)
 
diff --git a/vendor/mvdan.cc/unparam/check/check.go b/vendor/mvdan.cc/unparam/check/check.go
index c49efa93..ce9297dc 100644
--- a/vendor/mvdan.cc/unparam/check/check.go
+++ b/vendor/mvdan.cc/unparam/check/check.go
@@ -133,13 +133,13 @@ func (c *Checker) ProgramSSA(prog *ssa.Program) {
 	c.prog = prog
 }
 
-// Algo supplies Checker with the call graph construction algorithm.
-func (c *Checker) Algo(algo string) {
+// CallgraphAlgorithm supplies Checker with the call graph construction algorithm.
+func (c *Checker) CallgraphAlgorithm(algo string) {
 	c.algo = algo
 }
 
-// Algo supplies Checker with the exported setting.
-func (c *Checker) Exported(exported bool) {
+// CheckExportedFuncs sets whether to inspect exported functions
+func (c *Checker) CheckExportedFuncs(exported bool) {
 	c.exported = exported
 }
 
@@ -255,6 +255,16 @@ func (c *Checker) addIssue(fn *ssa.Function, pos token.Pos, format string, args
 	})
 }
 
+// constantValueToString returns string representation for constant value
+func constantValueToString(val constant.Value) string {
+	valStr := "nil" // an untyped nil is a nil constant.Value
+	if val != nil {
+		valStr = val.String()
+	}
+
+	return valStr
+}
+
 // checkFunc checks a single function for unused parameters.
 func (c *Checker) checkFunc(fn *ssa.Function, pkgInfo *loader.PackageInfo) {
 	c.debug("func %s\n", fn.RelString(fn.Package().Pkg))
@@ -310,10 +320,7 @@ func (c *Checker) checkFunc(fn *ssa.Function, pkgInfo *loader.PackageInfo) {
 			// just one non-nil return (too many false positives)
 			continue
 		}
-		valStr := "nil" // an untyped nil is a nil constant.Value
-		if val != nil {
-			valStr = val.String()
-		}
+		valStr := constantValueToString(val)
 		if calledInReturn(inboundCalls) {
 			continue
 		}
@@ -497,10 +504,11 @@ func (c *Checker) alwaysReceivedConst(in []*callgraph.Edge, par *ssa.Parameter,
 			seenOrig = ""
 		}
 	}
-	if seenOrig != "" && seenOrig != seen.String() {
+	seenStr := constantValueToString(seen)
+	if seenOrig != "" && seenOrig != seenStr {
 		return fmt.Sprintf("%s (%v)", seenOrig, seen)
 	}
-	return seen.String()
+	return seenStr
 }
 
 // anyRealUse reports whether a parameter has any relevant use within its