// Code generated by "precompile.go". DO NOT EDIT.

package rulesdata

import "github.com/quasilyte/go-ruleguard/ruleguard/ir"

var PrecompiledRules = &ir.File{
	PkgPath:       "gorules",
	CustomDecls:   []string{},
	BundleImports: []ir.BundleImport{},
	RuleGroups: []ir.RuleGroup{
		{
			Line:        11,
			Name:        "redundantSprint",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects redundant fmt.Sprint calls",
			DocBefore:   "fmt.Sprint(x)",
			DocAfter:    "x.String()",
			Rules: []ir.Rule{
				{
					Line: 12,
					SyntaxPatterns: []ir.PatternString{
						{Line: 12, Value: "fmt.Sprint($x)"},
						{Line: 12, Value: "fmt.Sprintf(\"%s\", $x)"},
						{Line: 12, Value: "fmt.Sprintf(\"%v\", $x)"},
					},
					ReportTemplate:  "use $x.String() instead",
					SuggestTemplate: "$x.String()",
					WhereExpr: ir.FilterExpr{
						Line: 13,
						Op:   ir.FilterAndOp,
						Src:  "!m[\"x\"].Type.Is(`reflect.Value`) && m[\"x\"].Type.Implements(`fmt.Stringer`)",
						Args: []ir.FilterExpr{
							{
								Line: 13,
								Op:   ir.FilterNotOp,
								Src:  "!m[\"x\"].Type.Is(`reflect.Value`)",
								Args: []ir.FilterExpr{{
									Line:  13,
									Op:    ir.FilterVarTypeIsOp,
									Src:   "m[\"x\"].Type.Is(`reflect.Value`)",
									Value: "x",
									Args:  []ir.FilterExpr{{Line: 13, Op: ir.FilterStringOp, Src: "`reflect.Value`", Value: "reflect.Value"}},
								}},
							},
							{
								Line:  13,
								Op:    ir.FilterVarTypeImplementsOp,
								Src:   "m[\"x\"].Type.Implements(`fmt.Stringer`)",
								Value: "x",
								Args:  []ir.FilterExpr{{Line: 13, Op: ir.FilterStringOp, Src: "`fmt.Stringer`", Value: "fmt.Stringer"}},
							},
						},
					},
				},
				{
					Line: 17,
					SyntaxPatterns: []ir.PatternString{
						{Line: 17, Value: "fmt.Sprint($x)"},
						{Line: 17, Value: "fmt.Sprintf(\"%s\", $x)"},
						{Line: 17, Value: "fmt.Sprintf(\"%v\", $x)"},
					},
					ReportTemplate:  "$x is already string",
					SuggestTemplate: "$x",
					WhereExpr: ir.FilterExpr{
						Line:  18,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"x\"].Type.Is(`string`)",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 18, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
					},
				},
			},
		},
		{
			Line:        27,
			Name:        "deferUnlambda",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects deferred function literals that can be simplified",
			DocBefore:   "defer func() { f() }()",
			DocAfter:    "defer f()",
			Rules: []ir.Rule{
				{
					Line:           28,
					SyntaxPatterns: []ir.PatternString{{Line: 28, Value: "defer func() { $f($*args) }()"}},
					ReportTemplate: "can rewrite as `defer $f($args)`",
					WhereExpr: ir.FilterExpr{
						Line: 29,
						Op:   ir.FilterAndOp,
						Src:  "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\" && m[\"f\"].Text != \"recover\" && m[\"args\"].Const",
						Args: []ir.FilterExpr{
							{
								Line: 29,
								Op:   ir.FilterAndOp,
								Src:  "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\" && m[\"f\"].Text != \"recover\"",
								Args: []ir.FilterExpr{
									{
										Line: 29,
										Op:   ir.FilterAndOp,
										Src:  "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\"",
										Args: []ir.FilterExpr{
											{
												Line:  29,
												Op:    ir.FilterVarNodeIsOp,
												Src:   "m[\"f\"].Node.Is(`Ident`)",
												Value: "f",
												Args:  []ir.FilterExpr{{Line: 29, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}},
											},
											{
												Line: 29,
												Op:   ir.FilterNeqOp,
												Src:  "m[\"f\"].Text != \"panic\"",
												Args: []ir.FilterExpr{
													{Line: 29, Op: ir.FilterVarTextOp, Src: "m[\"f\"].Text", Value: "f"},
													{Line: 29, Op: ir.FilterStringOp, Src: "\"panic\"", Value: "panic"},
												},
											},
										},
									},
									{
										Line: 29,
										Op:   ir.FilterNeqOp,
										Src:  "m[\"f\"].Text != \"recover\"",
										Args: []ir.FilterExpr{
											{Line: 29, Op: ir.FilterVarTextOp, Src: "m[\"f\"].Text", Value: "f"},
											{Line: 29, Op: ir.FilterStringOp, Src: "\"recover\"", Value: "recover"},
										},
									},
								},
							},
							{
								Line:  29,
								Op:    ir.FilterVarConstOp,
								Src:   "m[\"args\"].Const",
								Value: "args",
							},
						},
					},
				},
				{
					Line:           32,
					SyntaxPatterns: []ir.PatternString{{Line: 32, Value: "defer func() { $pkg.$f($*args) }()"}},
					ReportTemplate: "can rewrite as `defer $pkg.$f($args)`",
					WhereExpr: ir.FilterExpr{
						Line: 33,
						Op:   ir.FilterAndOp,
						Src:  "m[\"f\"].Node.Is(`Ident`) && m[\"args\"].Const && m[\"pkg\"].Object.Is(`PkgName`)",
						Args: []ir.FilterExpr{
							{
								Line: 33,
								Op:   ir.FilterAndOp,
								Src:  "m[\"f\"].Node.Is(`Ident`) && m[\"args\"].Const",
								Args: []ir.FilterExpr{
									{
										Line:  33,
										Op:    ir.FilterVarNodeIsOp,
										Src:   "m[\"f\"].Node.Is(`Ident`)",
										Value: "f",
										Args:  []ir.FilterExpr{{Line: 33, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}},
									},
									{
										Line:  33,
										Op:    ir.FilterVarConstOp,
										Src:   "m[\"args\"].Const",
										Value: "args",
									},
								},
							},
							{
								Line:  33,
								Op:    ir.FilterVarObjectIsOp,
								Src:   "m[\"pkg\"].Object.Is(`PkgName`)",
								Value: "pkg",
								Args:  []ir.FilterExpr{{Line: 33, Op: ir.FilterStringOp, Src: "`PkgName`", Value: "PkgName"}},
							},
						},
					},
				},
			},
		},
		{
			Line:        41,
			Name:        "badLock",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects suspicious mutex lock/unlock operations",
			DocBefore:   "mu.Lock(); mu.Unlock()",
			DocAfter:    "mu.Lock(); defer mu.Unlock()",
			Rules: []ir.Rule{
				{
					Line:           45,
					SyntaxPatterns: []ir.PatternString{{Line: 45, Value: "$mu1.Lock(); $mu2.Unlock()"}},
					ReportTemplate: "defer is missing, mutex is unlocked immediately",
					WhereExpr: ir.FilterExpr{
						Line: 46,
						Op:   ir.FilterEqOp,
						Src:  "m[\"mu1\"].Text == m[\"mu2\"].Text",
						Args: []ir.FilterExpr{
							{Line: 46, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
							{Line: 46, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
						},
					},
					LocationVar: "mu2",
				},
				{
					Line:           50,
					SyntaxPatterns: []ir.PatternString{{Line: 50, Value: "$mu1.RLock(); $mu2.RUnlock()"}},
					ReportTemplate: "defer is missing, mutex is unlocked immediately",
					WhereExpr: ir.FilterExpr{
						Line: 51,
						Op:   ir.FilterEqOp,
						Src:  "m[\"mu1\"].Text == m[\"mu2\"].Text",
						Args: []ir.FilterExpr{
							{Line: 51, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
							{Line: 51, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
						},
					},
					LocationVar: "mu2",
				},
				{
					Line:           56,
					SyntaxPatterns: []ir.PatternString{{Line: 56, Value: "$mu1.Lock(); defer $mu2.RUnlock()"}},
					ReportTemplate: "suspicious unlock, maybe Unlock was intended?",
					WhereExpr: ir.FilterExpr{
						Line: 57,
						Op:   ir.FilterEqOp,
						Src:  "m[\"mu1\"].Text == m[\"mu2\"].Text",
						Args: []ir.FilterExpr{
							{Line: 57, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
							{Line: 57, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
						},
					},
					LocationVar: "mu2",
				},
				{
					Line:           61,
					SyntaxPatterns: []ir.PatternString{{Line: 61, Value: "$mu1.RLock(); defer $mu2.Unlock()"}},
					ReportTemplate: "suspicious unlock, maybe RUnlock was intended?",
					WhereExpr: ir.FilterExpr{
						Line: 62,
						Op:   ir.FilterEqOp,
						Src:  "m[\"mu1\"].Text == m[\"mu2\"].Text",
						Args: []ir.FilterExpr{
							{Line: 62, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
							{Line: 62, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
						},
					},
					LocationVar: "mu2",
				},
				{
					Line:           67,
					SyntaxPatterns: []ir.PatternString{{Line: 67, Value: "$mu1.Lock(); defer $mu2.Lock()"}},
					ReportTemplate: "maybe defer $mu1.Unlock() was intended?",
					WhereExpr: ir.FilterExpr{
						Line: 68,
						Op:   ir.FilterEqOp,
						Src:  "m[\"mu1\"].Text == m[\"mu2\"].Text",
						Args: []ir.FilterExpr{
							{Line: 68, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
							{Line: 68, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
						},
					},
					LocationVar: "mu2",
				},
				{
					Line:           72,
					SyntaxPatterns: []ir.PatternString{{Line: 72, Value: "$mu1.RLock(); defer $mu2.RLock()"}},
					ReportTemplate: "maybe defer $mu1.RUnlock() was intended?",
					WhereExpr: ir.FilterExpr{
						Line: 73,
						Op:   ir.FilterEqOp,
						Src:  "m[\"mu1\"].Text == m[\"mu2\"].Text",
						Args: []ir.FilterExpr{
							{Line: 73, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"},
							{Line: 73, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"},
						},
					},
					LocationVar: "mu2",
				},
			},
		},
		{
			Line:        82,
			Name:        "httpNoBody",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects nil usages in http.NewRequest calls, suggesting http.NoBody as an alternative",
			DocBefore:   "http.NewRequest(\"GET\", url, nil)",
			DocAfter:    "http.NewRequest(\"GET\", url, http.NoBody)",
			Rules: []ir.Rule{
				{
					Line:            83,
					SyntaxPatterns:  []ir.PatternString{{Line: 83, Value: "http.NewRequest($method, $url, $nil)"}},
					ReportTemplate:  "http.NoBody should be preferred to the nil request body",
					SuggestTemplate: "http.NewRequest($method, $url, http.NoBody)",
					WhereExpr: ir.FilterExpr{
						Line: 84,
						Op:   ir.FilterEqOp,
						Src:  "m[\"nil\"].Text == \"nil\"",
						Args: []ir.FilterExpr{
							{Line: 84, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"},
							{Line: 84, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"},
						},
					},
				},
				{
					Line:            88,
					SyntaxPatterns:  []ir.PatternString{{Line: 88, Value: "http.NewRequestWithContext($ctx, $method, $url, $nil)"}},
					ReportTemplate:  "http.NoBody should be preferred to the nil request body",
					SuggestTemplate: "http.NewRequestWithContext($ctx, $method, $url, http.NoBody)",
					WhereExpr: ir.FilterExpr{
						Line: 89,
						Op:   ir.FilterEqOp,
						Src:  "m[\"nil\"].Text == \"nil\"",
						Args: []ir.FilterExpr{
							{Line: 89, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"},
							{Line: 89, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"},
						},
					},
				},
				{
					Line:            93,
					SyntaxPatterns:  []ir.PatternString{{Line: 93, Value: "httptest.NewRequest($method, $url, $nil)"}},
					ReportTemplate:  "http.NoBody should be preferred to the nil request body",
					SuggestTemplate: "httptest.NewRequest($method, $url, http.NoBody)",
					WhereExpr: ir.FilterExpr{
						Line: 94,
						Op:   ir.FilterEqOp,
						Src:  "m[\"nil\"].Text == \"nil\"",
						Args: []ir.FilterExpr{
							{Line: 94, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"},
							{Line: 94, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"},
						},
					},
				},
			},
		},
		{
			Line:        104,
			Name:        "preferDecodeRune",
			MatcherName: "m",
			DocTags:     []string{"performance", "experimental"},
			DocSummary:  "Detects expressions like []rune(s)[0] that may cause unwanted rune slice allocation",
			DocBefore:   "r := []rune(s)[0]",
			DocAfter:    "r, _ := utf8.DecodeRuneInString(s)",
			DocNote:     "See Go issue for details: https://github.com/golang/go/issues/45260",
			Rules: []ir.Rule{{
				Line:           105,
				SyntaxPatterns: []ir.PatternString{{Line: 105, Value: "[]rune($s)[0]"}},
				ReportTemplate: "consider replacing $$ with utf8.DecodeRuneInString($s)",
				WhereExpr: ir.FilterExpr{
					Line:  106,
					Op:    ir.FilterVarTypeIsOp,
					Src:   "m[\"s\"].Type.Is(`string`)",
					Value: "s",
					Args:  []ir.FilterExpr{{Line: 106, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
				},
			}},
		},
		{
			Line:        114,
			Name:        "sloppyLen",
			MatcherName: "m",
			DocTags:     []string{"style"},
			DocSummary:  "Detects usage of `len` when result is obvious or doesn't make sense",
			DocBefore:   "len(arr) <= 0",
			DocAfter:    "len(arr) == 0",
			Rules: []ir.Rule{
				{
					Line:           115,
					SyntaxPatterns: []ir.PatternString{{Line: 115, Value: "len($_) >= 0"}},
					ReportTemplate: "$$ is always true",
				},
				{
					Line:           116,
					SyntaxPatterns: []ir.PatternString{{Line: 116, Value: "len($_) < 0"}},
					ReportTemplate: "$$ is always false",
				},
				{
					Line:           117,
					SyntaxPatterns: []ir.PatternString{{Line: 117, Value: "len($x) <= 0"}},
					ReportTemplate: "$$ can be len($x) == 0",
				},
			},
		},
		{
			Line:        124,
			Name:        "valSwap",
			MatcherName: "m",
			DocTags:     []string{"style"},
			DocSummary:  "Detects value swapping code that are not using parallel assignment",
			DocBefore:   "*tmp = *x; *x = *y; *y = *tmp",
			DocAfter:    "*x, *y = *y, *x",
			Rules: []ir.Rule{{
				Line:           125,
				SyntaxPatterns: []ir.PatternString{{Line: 125, Value: "$tmp := $y; $y = $x; $x = $tmp"}},
				ReportTemplate: "can re-write as `$y, $x = $x, $y`",
			}},
		},
		{
			Line:        133,
			Name:        "switchTrue",
			MatcherName: "m",
			DocTags:     []string{"style"},
			DocSummary:  "Detects switch-over-bool statements that use explicit `true` tag value",
			DocBefore:   "switch true {...}",
			DocAfter:    "switch {...}",
			Rules: []ir.Rule{
				{
					Line:           134,
					SyntaxPatterns: []ir.PatternString{{Line: 134, Value: "switch true { $*_ }"}},
					ReportTemplate: "replace 'switch true {}' with 'switch {}'",
				},
				{
					Line:           136,
					SyntaxPatterns: []ir.PatternString{{Line: 136, Value: "switch $x; true { $*_ }"}},
					ReportTemplate: "replace 'switch $x; true {}' with 'switch $x; {}'",
				},
			},
		},
		{
			Line:        144,
			Name:        "flagDeref",
			MatcherName: "m",
			DocTags:     []string{"diagnostic"},
			DocSummary:  "Detects immediate dereferencing of `flag` package pointers",
			DocBefore:   "b := *flag.Bool(\"b\", false, \"b docs\")",
			DocAfter:    "var b bool; flag.BoolVar(&b, \"b\", false, \"b docs\")",
			Rules: []ir.Rule{
				{
					Line:           145,
					SyntaxPatterns: []ir.PatternString{{Line: 145, Value: "*flag.Bool($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.BoolVar",
				},
				{
					Line:           146,
					SyntaxPatterns: []ir.PatternString{{Line: 146, Value: "*flag.Duration($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.DurationVar",
				},
				{
					Line:           147,
					SyntaxPatterns: []ir.PatternString{{Line: 147, Value: "*flag.Float64($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Float64Var",
				},
				{
					Line:           148,
					SyntaxPatterns: []ir.PatternString{{Line: 148, Value: "*flag.Int($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.IntVar",
				},
				{
					Line:           149,
					SyntaxPatterns: []ir.PatternString{{Line: 149, Value: "*flag.Int64($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Int64Var",
				},
				{
					Line:           150,
					SyntaxPatterns: []ir.PatternString{{Line: 150, Value: "*flag.String($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.StringVar",
				},
				{
					Line:           151,
					SyntaxPatterns: []ir.PatternString{{Line: 151, Value: "*flag.Uint($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.UintVar",
				},
				{
					Line:           152,
					SyntaxPatterns: []ir.PatternString{{Line: 152, Value: "*flag.Uint64($*_)"}},
					ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Uint64Var",
				},
			},
		},
		{
			Line:        159,
			Name:        "emptyStringTest",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects empty string checks that can be written more idiomatically",
			DocBefore:   "len(s) == 0",
			DocAfter:    "s == \"\"",
			Rules: []ir.Rule{
				{
					Line:           160,
					SyntaxPatterns: []ir.PatternString{{Line: 160, Value: "len($s) != 0"}},
					ReportTemplate: "replace `$$` with `$s != \"\"`",
					WhereExpr: ir.FilterExpr{
						Line:  161,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"s\"].Type.Is(`string`)",
						Value: "s",
						Args:  []ir.FilterExpr{{Line: 161, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
					},
				},
				{
					Line:           164,
					SyntaxPatterns: []ir.PatternString{{Line: 164, Value: "len($s) == 0"}},
					ReportTemplate: "replace `$$` with `$s == \"\"`",
					WhereExpr: ir.FilterExpr{
						Line:  165,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"s\"].Type.Is(`string`)",
						Value: "s",
						Args:  []ir.FilterExpr{{Line: 165, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
					},
				},
			},
		},
		{
			Line:        173,
			Name:        "stringXbytes",
			MatcherName: "m",
			DocTags:     []string{"performance"},
			DocSummary:  "Detects redundant conversions between string and []byte",
			DocBefore:   "copy(b, []byte(s))",
			DocAfter:    "copy(b, s)",
			Rules: []ir.Rule{
				{
					Line:           174,
					SyntaxPatterns: []ir.PatternString{{Line: 174, Value: "copy($_, []byte($s))"}},
					ReportTemplate: "can simplify `[]byte($s)` to `$s`",
				},
				{
					Line:            176,
					SyntaxPatterns:  []ir.PatternString{{Line: 176, Value: "string($b) == \"\""}},
					ReportTemplate:  "suggestion: len($b) == 0",
					SuggestTemplate: "len($b) == 0",
					WhereExpr: ir.FilterExpr{
						Line:  176,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"b\"].Type.Is(`[]byte`)",
						Value: "b",
						Args:  []ir.FilterExpr{{Line: 176, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
					},
				},
				{
					Line:            177,
					SyntaxPatterns:  []ir.PatternString{{Line: 177, Value: "string($b) != \"\""}},
					ReportTemplate:  "suggestion: len($b) != 0",
					SuggestTemplate: "len($b) != 0",
					WhereExpr: ir.FilterExpr{
						Line:  177,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"b\"].Type.Is(`[]byte`)",
						Value: "b",
						Args:  []ir.FilterExpr{{Line: 177, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
					},
				},
				{
					Line:            179,
					SyntaxPatterns:  []ir.PatternString{{Line: 179, Value: "len(string($b))"}},
					ReportTemplate:  "suggestion: len($b)",
					SuggestTemplate: "len($b)",
					WhereExpr: ir.FilterExpr{
						Line:  179,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"b\"].Type.Is(`[]byte`)",
						Value: "b",
						Args:  []ir.FilterExpr{{Line: 179, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
					},
				},
				{
					Line:            181,
					SyntaxPatterns:  []ir.PatternString{{Line: 181, Value: "string($x) == string($y)"}},
					ReportTemplate:  "suggestion: bytes.Equal($x, $y)",
					SuggestTemplate: "bytes.Equal($x, $y)",
					WhereExpr: ir.FilterExpr{
						Line: 182,
						Op:   ir.FilterAndOp,
						Src:  "m[\"x\"].Type.Is(`[]byte`) && m[\"y\"].Type.Is(`[]byte`)",
						Args: []ir.FilterExpr{
							{
								Line:  182,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"x\"].Type.Is(`[]byte`)",
								Value: "x",
								Args:  []ir.FilterExpr{{Line: 182, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
							},
							{
								Line:  182,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"y\"].Type.Is(`[]byte`)",
								Value: "y",
								Args:  []ir.FilterExpr{{Line: 182, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
							},
						},
					},
				},
				{
					Line:            185,
					SyntaxPatterns:  []ir.PatternString{{Line: 185, Value: "string($x) != string($y)"}},
					ReportTemplate:  "suggestion: !bytes.Equal($x, $y)",
					SuggestTemplate: "!bytes.Equal($x, $y)",
					WhereExpr: ir.FilterExpr{
						Line: 186,
						Op:   ir.FilterAndOp,
						Src:  "m[\"x\"].Type.Is(`[]byte`) && m[\"y\"].Type.Is(`[]byte`)",
						Args: []ir.FilterExpr{
							{
								Line:  186,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"x\"].Type.Is(`[]byte`)",
								Value: "x",
								Args:  []ir.FilterExpr{{Line: 186, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
							},
							{
								Line:  186,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"y\"].Type.Is(`[]byte`)",
								Value: "y",
								Args:  []ir.FilterExpr{{Line: 186, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}},
							},
						},
					},
				},
				{
					Line:            189,
					SyntaxPatterns:  []ir.PatternString{{Line: 189, Value: "$re.Match([]byte($s))"}},
					ReportTemplate:  "suggestion: $re.MatchString($s)",
					SuggestTemplate: "$re.MatchString($s)",
					WhereExpr: ir.FilterExpr{
						Line: 190,
						Op:   ir.FilterAndOp,
						Src:  "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)",
						Args: []ir.FilterExpr{
							{
								Line:  190,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"re\"].Type.Is(`*regexp.Regexp`)",
								Value: "re",
								Args:  []ir.FilterExpr{{Line: 190, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}},
							},
							{
								Line:  190,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"s\"].Type.Is(`string`)",
								Value: "s",
								Args:  []ir.FilterExpr{{Line: 190, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
							},
						},
					},
				},
				{
					Line:            193,
					SyntaxPatterns:  []ir.PatternString{{Line: 193, Value: "$re.FindIndex([]byte($s))"}},
					ReportTemplate:  "suggestion: $re.FindStringIndex($s)",
					SuggestTemplate: "$re.FindStringIndex($s)",
					WhereExpr: ir.FilterExpr{
						Line: 194,
						Op:   ir.FilterAndOp,
						Src:  "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)",
						Args: []ir.FilterExpr{
							{
								Line:  194,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"re\"].Type.Is(`*regexp.Regexp`)",
								Value: "re",
								Args:  []ir.FilterExpr{{Line: 194, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}},
							},
							{
								Line:  194,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"s\"].Type.Is(`string`)",
								Value: "s",
								Args:  []ir.FilterExpr{{Line: 194, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
							},
						},
					},
				},
				{
					Line:            197,
					SyntaxPatterns:  []ir.PatternString{{Line: 197, Value: "$re.FindAllIndex([]byte($s), $n)"}},
					ReportTemplate:  "suggestion: $re.FindAllStringIndex($s, $n)",
					SuggestTemplate: "$re.FindAllStringIndex($s, $n)",
					WhereExpr: ir.FilterExpr{
						Line: 198,
						Op:   ir.FilterAndOp,
						Src:  "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)",
						Args: []ir.FilterExpr{
							{
								Line:  198,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"re\"].Type.Is(`*regexp.Regexp`)",
								Value: "re",
								Args:  []ir.FilterExpr{{Line: 198, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}},
							},
							{
								Line:  198,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"s\"].Type.Is(`string`)",
								Value: "s",
								Args:  []ir.FilterExpr{{Line: 198, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
							},
						},
					},
				},
			},
		},
		{
			Line:        207,
			Name:        "indexAlloc",
			MatcherName: "m",
			DocTags:     []string{"performance"},
			DocSummary:  "Detects strings.Index calls that may cause unwanted allocs",
			DocBefore:   "strings.Index(string(x), y)",
			DocAfter:    "bytes.Index(x, []byte(y))",
			DocNote:     "See Go issue for details: https://github.com/golang/go/issues/25864",
			Rules: []ir.Rule{{
				Line:           208,
				SyntaxPatterns: []ir.PatternString{{Line: 208, Value: "strings.Index(string($x), $y)"}},
				ReportTemplate: "consider replacing $$ with bytes.Index($x, []byte($y))",
				WhereExpr: ir.FilterExpr{
					Line: 209,
					Op:   ir.FilterAndOp,
					Src:  "m[\"x\"].Pure && m[\"y\"].Pure",
					Args: []ir.FilterExpr{
						{Line: 209, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
						{Line: 209, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
					},
				},
			}},
		},
		{
			Line:        217,
			Name:        "wrapperFunc",
			MatcherName: "m",
			DocTags:     []string{"style"},
			DocSummary:  "Detects function calls that can be replaced with convenience wrappers",
			DocBefore:   "wg.Add(-1)",
			DocAfter:    "wg.Done()",
			Rules: []ir.Rule{
				{
					Line:           218,
					SyntaxPatterns: []ir.PatternString{{Line: 218, Value: "$wg.Add(-1)"}},
					ReportTemplate: "use WaitGroup.Done method in `$$`",
					WhereExpr: ir.FilterExpr{
						Line:  219,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"wg\"].Type.Is(`sync.WaitGroup`)",
						Value: "wg",
						Args:  []ir.FilterExpr{{Line: 219, Op: ir.FilterStringOp, Src: "`sync.WaitGroup`", Value: "sync.WaitGroup"}},
					},
				},
				{
					Line:           222,
					SyntaxPatterns: []ir.PatternString{{Line: 222, Value: "$buf.Truncate(0)"}},
					ReportTemplate: "use Buffer.Reset method in `$$`",
					WhereExpr: ir.FilterExpr{
						Line:  223,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"buf\"].Type.Is(`bytes.Buffer`)",
						Value: "buf",
						Args:  []ir.FilterExpr{{Line: 223, Op: ir.FilterStringOp, Src: "`bytes.Buffer`", Value: "bytes.Buffer"}},
					},
				},
				{
					Line:           226,
					SyntaxPatterns: []ir.PatternString{{Line: 226, Value: "http.HandlerFunc(http.NotFound)"}},
					ReportTemplate: "use http.NotFoundHandler method in `$$`",
				},
				{
					Line:           228,
					SyntaxPatterns: []ir.PatternString{{Line: 228, Value: "strings.SplitN($_, $_, -1)"}},
					ReportTemplate: "use strings.Split method in `$$`",
				},
				{
					Line:           229,
					SyntaxPatterns: []ir.PatternString{{Line: 229, Value: "strings.Replace($_, $_, $_, -1)"}},
					ReportTemplate: "use strings.ReplaceAll method in `$$`",
				},
				{
					Line:           230,
					SyntaxPatterns: []ir.PatternString{{Line: 230, Value: "strings.Map(unicode.ToTitle, $_)"}},
					ReportTemplate: "use strings.ToTitle method in `$$`",
				},
				{
					Line: 231,
					SyntaxPatterns: []ir.PatternString{
						{Line: 231, Value: "strings.Index($s1, $s2) >= 0"},
						{Line: 231, Value: "strings.Index($s1, $s2) != -1"},
					},
					ReportTemplate:  "suggestion: strings.Contains($s1, $s2)",
					SuggestTemplate: "strings.Contains($s1, $s2)",
				},
				{
					Line: 232,
					SyntaxPatterns: []ir.PatternString{
						{Line: 232, Value: "strings.IndexAny($s1, $s2) >= 0"},
						{Line: 232, Value: "strings.IndexAny($s1, $s2) != -1"},
					},
					ReportTemplate:  "suggestion: strings.ContainsAny($s1, $s2)",
					SuggestTemplate: "strings.ContainsAny($s1, $s2)",
				},
				{
					Line: 233,
					SyntaxPatterns: []ir.PatternString{
						{Line: 233, Value: "strings.IndexRune($s1, $s2) >= 0"},
						{Line: 233, Value: "strings.IndexRune($s1, $s2) != -1"},
					},
					ReportTemplate:  "suggestion: strings.ContainsRune($s1, $s2)",
					SuggestTemplate: "strings.ContainsRune($s1, $s2)",
				},
				{
					Line: 235,
					SyntaxPatterns: []ir.PatternString{
						{Line: 235, Value: "$i := strings.Index($s, $sep); $*_; $x, $y = $s[:$i], $s[$i+1:]"},
						{Line: 236, Value: "$i := strings.Index($s, $sep); $*_; $x = $s[:$i]; $*_; $y = $s[$i+1:]"},
					},
					ReportTemplate:  "suggestion: $x, $y, _ = strings.Cut($s, $sep)",
					SuggestTemplate: "$x, $y, _ = strings.Cut($s, $sep)",
					WhereExpr: ir.FilterExpr{
						Line:  237,
						Op:    ir.FilterGoVersionGreaterEqThanOp,
						Src:   "m.GoVersion().GreaterEqThan(\"1.18\")",
						Value: "1.18",
					},
				},
				{
					Line: 240,
					SyntaxPatterns: []ir.PatternString{
						{Line: 241, Value: "if $i := strings.Index($s, $sep); $i != -1 { $*_; $x, $y = $s[:$i], $s[$i+1:]; $*_ }"},
						{Line: 242, Value: "if $i := strings.Index($s, $sep); $i != -1 { $*_; $x = $s[:$i]; $*_; $y = $s[$i+1:]; $*_ }"},
						{Line: 243, Value: "if $i := strings.Index($s, $sep); $i >= 0 { $*_; $x, $y = $s[:$i], $s[$i+1:]; $*_ }"},
						{Line: 244, Value: "if $i := strings.Index($s, $sep); $i >= 0 { $*_; $x = $s[:$i]; $*_; $y = $s[$i+1:]; $*_ }"},
					},
					ReportTemplate:  "suggestion: if $x, $y, ok = strings.Cut($s, $sep); ok { ... }",
					SuggestTemplate: "if $x, $y, ok = strings.Cut($s, $sep); ok { ... }",
					WhereExpr: ir.FilterExpr{
						Line:  245,
						Op:    ir.FilterGoVersionGreaterEqThanOp,
						Src:   "m.GoVersion().GreaterEqThan(\"1.18\")",
						Value: "1.18",
					},
				},
				{
					Line:           248,
					SyntaxPatterns: []ir.PatternString{{Line: 248, Value: "bytes.SplitN(b, []byte(\".\"), -1)"}},
					ReportTemplate: "use bytes.Split method in `$$`",
				},
				{
					Line:           249,
					SyntaxPatterns: []ir.PatternString{{Line: 249, Value: "bytes.Replace($_, $_, $_, -1)"}},
					ReportTemplate: "use bytes.ReplaceAll method in `$$`",
				},
				{
					Line:           250,
					SyntaxPatterns: []ir.PatternString{{Line: 250, Value: "bytes.Map(unicode.ToUpper, $_)"}},
					ReportTemplate: "use bytes.ToUpper method in `$$`",
				},
				{
					Line:           251,
					SyntaxPatterns: []ir.PatternString{{Line: 251, Value: "bytes.Map(unicode.ToLower, $_)"}},
					ReportTemplate: "use bytes.ToLower method in `$$`",
				},
				{
					Line:           252,
					SyntaxPatterns: []ir.PatternString{{Line: 252, Value: "bytes.Map(unicode.ToTitle, $_)"}},
					ReportTemplate: "use bytes.ToTitle method in `$$`",
				},
				{
					Line: 253,
					SyntaxPatterns: []ir.PatternString{
						{Line: 253, Value: "bytes.Index($b1, $b2) >= 0"},
						{Line: 253, Value: "bytes.Index($b1, $b2) != -1"},
					},
					ReportTemplate:  "suggestion: bytes.Contains($b1, $b2)",
					SuggestTemplate: "bytes.Contains($b1, $b2)",
				},
				{
					Line: 254,
					SyntaxPatterns: []ir.PatternString{
						{Line: 254, Value: "bytes.IndexAny($b1, $b2) >= 0"},
						{Line: 254, Value: "bytes.IndexAny($b1, $b2) != -1"},
					},
					ReportTemplate:  "suggestion: bytes.ContainsAny($b1, $b2)",
					SuggestTemplate: "bytes.ContainsAny($b1, $b2)",
				},
				{
					Line: 255,
					SyntaxPatterns: []ir.PatternString{
						{Line: 255, Value: "bytes.IndexRune($b1, $b2) >= 0"},
						{Line: 255, Value: "bytes.IndexRune($b1, $b2) != -1"},
					},
					ReportTemplate:  "suggestion: bytes.ContainsRune($b1, $b2)",
					SuggestTemplate: "bytes.ContainsRune($b1, $b2)",
				},
				{
					Line:           257,
					SyntaxPatterns: []ir.PatternString{{Line: 257, Value: "draw.DrawMask($_, $_, $_, $_, nil, image.Point{}, $_)"}},
					ReportTemplate: "use draw.Draw method in `$$`",
				},
			},
		},
		{
			Line:        265,
			Name:        "regexpMust",
			MatcherName: "m",
			DocTags:     []string{"style"},
			DocSummary:  "Detects `regexp.Compile*` that can be replaced with `regexp.MustCompile*`",
			DocBefore:   "re, _ := regexp.Compile(\"const pattern\")",
			DocAfter:    "re := regexp.MustCompile(\"const pattern\")",
			Rules: []ir.Rule{
				{
					Line:           266,
					SyntaxPatterns: []ir.PatternString{{Line: 266, Value: "regexp.Compile($pat)"}},
					ReportTemplate: "for const patterns like $pat, use regexp.MustCompile",
					WhereExpr: ir.FilterExpr{
						Line:  267,
						Op:    ir.FilterVarConstOp,
						Src:   "m[\"pat\"].Const",
						Value: "pat",
					},
				},
				{
					Line:           270,
					SyntaxPatterns: []ir.PatternString{{Line: 270, Value: "regexp.CompilePOSIX($pat)"}},
					ReportTemplate: "for const patterns like $pat, use regexp.MustCompilePOSIX",
					WhereExpr: ir.FilterExpr{
						Line:  271,
						Op:    ir.FilterVarConstOp,
						Src:   "m[\"pat\"].Const",
						Value: "pat",
					},
				},
			},
		},
		{
			Line:        279,
			Name:        "badCall",
			MatcherName: "m",
			DocTags:     []string{"diagnostic"},
			DocSummary:  "Detects suspicious function calls",
			DocBefore:   "strings.Replace(s, from, to, 0)",
			DocAfter:    "strings.Replace(s, from, to, -1)",
			Rules: []ir.Rule{
				{
					Line:           280,
					SyntaxPatterns: []ir.PatternString{{Line: 280, Value: "strings.Replace($_, $_, $_, $zero)"}},
					ReportTemplate: "suspicious arg 0, probably meant -1",
					WhereExpr: ir.FilterExpr{
						Line: 281,
						Op:   ir.FilterEqOp,
						Src:  "m[\"zero\"].Value.Int() == 0",
						Args: []ir.FilterExpr{
							{
								Line:  281,
								Op:    ir.FilterVarValueIntOp,
								Src:   "m[\"zero\"].Value.Int()",
								Value: "zero",
							},
							{
								Line:  281,
								Op:    ir.FilterIntOp,
								Src:   "0",
								Value: int64(0),
							},
						},
					},
					LocationVar: "zero",
				},
				{
					Line:           283,
					SyntaxPatterns: []ir.PatternString{{Line: 283, Value: "bytes.Replace($_, $_, $_, $zero)"}},
					ReportTemplate: "suspicious arg 0, probably meant -1",
					WhereExpr: ir.FilterExpr{
						Line: 284,
						Op:   ir.FilterEqOp,
						Src:  "m[\"zero\"].Value.Int() == 0",
						Args: []ir.FilterExpr{
							{
								Line:  284,
								Op:    ir.FilterVarValueIntOp,
								Src:   "m[\"zero\"].Value.Int()",
								Value: "zero",
							},
							{
								Line:  284,
								Op:    ir.FilterIntOp,
								Src:   "0",
								Value: int64(0),
							},
						},
					},
					LocationVar: "zero",
				},
				{
					Line:           287,
					SyntaxPatterns: []ir.PatternString{{Line: 287, Value: "strings.SplitN($_, $_, $zero)"}},
					ReportTemplate: "suspicious arg 0, probably meant -1",
					WhereExpr: ir.FilterExpr{
						Line: 288,
						Op:   ir.FilterEqOp,
						Src:  "m[\"zero\"].Value.Int() == 0",
						Args: []ir.FilterExpr{
							{
								Line:  288,
								Op:    ir.FilterVarValueIntOp,
								Src:   "m[\"zero\"].Value.Int()",
								Value: "zero",
							},
							{
								Line:  288,
								Op:    ir.FilterIntOp,
								Src:   "0",
								Value: int64(0),
							},
						},
					},
					LocationVar: "zero",
				},
				{
					Line:           290,
					SyntaxPatterns: []ir.PatternString{{Line: 290, Value: "bytes.SplitN($_, $_, $zero)"}},
					ReportTemplate: "suspicious arg 0, probably meant -1",
					WhereExpr: ir.FilterExpr{
						Line: 291,
						Op:   ir.FilterEqOp,
						Src:  "m[\"zero\"].Value.Int() == 0",
						Args: []ir.FilterExpr{
							{
								Line:  291,
								Op:    ir.FilterVarValueIntOp,
								Src:   "m[\"zero\"].Value.Int()",
								Value: "zero",
							},
							{
								Line:  291,
								Op:    ir.FilterIntOp,
								Src:   "0",
								Value: int64(0),
							},
						},
					},
					LocationVar: "zero",
				},
				{
					Line:           294,
					SyntaxPatterns: []ir.PatternString{{Line: 294, Value: "append($_)"}},
					ReportTemplate: "no-op append call, probably missing arguments",
				},
				{
					Line:           296,
					SyntaxPatterns: []ir.PatternString{{Line: 296, Value: "filepath.Join($_)"}},
					ReportTemplate: "suspicious Join on 1 argument",
				},
			},
		},
		{
			Line:        303,
			Name:        "assignOp",
			MatcherName: "m",
			DocTags:     []string{"style"},
			DocSummary:  "Detects assignments that can be simplified by using assignment operators",
			DocBefore:   "x = x * 2",
			DocAfter:    "x *= 2",
			Rules: []ir.Rule{
				{
					Line:           304,
					SyntaxPatterns: []ir.PatternString{{Line: 304, Value: "$x = $x + 1"}},
					ReportTemplate: "replace `$$` with `$x++`",
					WhereExpr:      ir.FilterExpr{Line: 304, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           305,
					SyntaxPatterns: []ir.PatternString{{Line: 305, Value: "$x = $x - 1"}},
					ReportTemplate: "replace `$$` with `$x--`",
					WhereExpr:      ir.FilterExpr{Line: 305, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           307,
					SyntaxPatterns: []ir.PatternString{{Line: 307, Value: "$x = $x + $y"}},
					ReportTemplate: "replace `$$` with `$x += $y`",
					WhereExpr:      ir.FilterExpr{Line: 307, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           308,
					SyntaxPatterns: []ir.PatternString{{Line: 308, Value: "$x = $x - $y"}},
					ReportTemplate: "replace `$$` with `$x -= $y`",
					WhereExpr:      ir.FilterExpr{Line: 308, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           310,
					SyntaxPatterns: []ir.PatternString{{Line: 310, Value: "$x = $x * $y"}},
					ReportTemplate: "replace `$$` with `$x *= $y`",
					WhereExpr:      ir.FilterExpr{Line: 310, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           311,
					SyntaxPatterns: []ir.PatternString{{Line: 311, Value: "$x = $x / $y"}},
					ReportTemplate: "replace `$$` with `$x /= $y`",
					WhereExpr:      ir.FilterExpr{Line: 311, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           312,
					SyntaxPatterns: []ir.PatternString{{Line: 312, Value: "$x = $x % $y"}},
					ReportTemplate: "replace `$$` with `$x %= $y`",
					WhereExpr:      ir.FilterExpr{Line: 312, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           313,
					SyntaxPatterns: []ir.PatternString{{Line: 313, Value: "$x = $x & $y"}},
					ReportTemplate: "replace `$$` with `$x &= $y`",
					WhereExpr:      ir.FilterExpr{Line: 313, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           314,
					SyntaxPatterns: []ir.PatternString{{Line: 314, Value: "$x = $x | $y"}},
					ReportTemplate: "replace `$$` with `$x |= $y`",
					WhereExpr:      ir.FilterExpr{Line: 314, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           315,
					SyntaxPatterns: []ir.PatternString{{Line: 315, Value: "$x = $x ^ $y"}},
					ReportTemplate: "replace `$$` with `$x ^= $y`",
					WhereExpr:      ir.FilterExpr{Line: 315, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           316,
					SyntaxPatterns: []ir.PatternString{{Line: 316, Value: "$x = $x << $y"}},
					ReportTemplate: "replace `$$` with `$x <<= $y`",
					WhereExpr:      ir.FilterExpr{Line: 316, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           317,
					SyntaxPatterns: []ir.PatternString{{Line: 317, Value: "$x = $x >> $y"}},
					ReportTemplate: "replace `$$` with `$x >>= $y`",
					WhereExpr:      ir.FilterExpr{Line: 317, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line:           318,
					SyntaxPatterns: []ir.PatternString{{Line: 318, Value: "$x = $x &^ $y"}},
					ReportTemplate: "replace `$$` with `$x &^= $y`",
					WhereExpr:      ir.FilterExpr{Line: 318, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
			},
		},
		{
			Line:        325,
			Name:        "preferWriteByte",
			MatcherName: "m",
			DocTags:     []string{"performance", "experimental", "opinionated"},
			DocSummary:  "Detects WriteRune calls with rune literal argument that is single byte and reports to use WriteByte instead",
			DocBefore:   "w.WriteRune('\\n')",
			DocAfter:    "w.WriteByte('\\n')",
			Rules: []ir.Rule{{
				Line:           329,
				SyntaxPatterns: []ir.PatternString{{Line: 329, Value: "$w.WriteRune($c)"}},
				ReportTemplate: "consider writing single byte rune $c with $w.WriteByte($c)",
				WhereExpr: ir.FilterExpr{
					Line: 330,
					Op:   ir.FilterAndOp,
					Src:  "m[\"w\"].Type.Implements(\"io.ByteWriter\") && (m[\"c\"].Const && m[\"c\"].Value.Int() < runeSelf)",
					Args: []ir.FilterExpr{
						{
							Line:  330,
							Op:    ir.FilterVarTypeImplementsOp,
							Src:   "m[\"w\"].Type.Implements(\"io.ByteWriter\")",
							Value: "w",
							Args:  []ir.FilterExpr{{Line: 330, Op: ir.FilterStringOp, Src: "\"io.ByteWriter\"", Value: "io.ByteWriter"}},
						},
						{
							Line: 330,
							Op:   ir.FilterAndOp,
							Src:  "(m[\"c\"].Const && m[\"c\"].Value.Int() < runeSelf)",
							Args: []ir.FilterExpr{
								{
									Line:  330,
									Op:    ir.FilterVarConstOp,
									Src:   "m[\"c\"].Const",
									Value: "c",
								},
								{
									Line: 330,
									Op:   ir.FilterLtOp,
									Src:  "m[\"c\"].Value.Int() < runeSelf",
									Args: []ir.FilterExpr{
										{
											Line:  330,
											Op:    ir.FilterVarValueIntOp,
											Src:   "m[\"c\"].Value.Int()",
											Value: "c",
										},
										{
											Line:  330,
											Op:    ir.FilterIntOp,
											Src:   "runeSelf",
											Value: int64(128),
										},
									},
								},
							},
						},
					},
				},
			}},
		},
		{
			Line:        338,
			Name:        "preferFprint",
			MatcherName: "m",
			DocTags:     []string{"performance", "experimental"},
			DocSummary:  "Detects fmt.Sprint(f/ln) calls which can be replaced with fmt.Fprint(f/ln)",
			DocBefore:   "w.Write([]byte(fmt.Sprintf(\"%x\", 10)))",
			DocAfter:    "fmt.Fprintf(w, \"%x\", 10)",
			Rules: []ir.Rule{
				{
					Line:            339,
					SyntaxPatterns:  []ir.PatternString{{Line: 339, Value: "$w.Write([]byte(fmt.Sprint($*args)))"}},
					ReportTemplate:  "fmt.Fprint($w, $args) should be preferred to the $$",
					SuggestTemplate: "fmt.Fprint($w, $args)",
					WhereExpr: ir.FilterExpr{
						Line:  340,
						Op:    ir.FilterVarTypeImplementsOp,
						Src:   "m[\"w\"].Type.Implements(\"io.Writer\")",
						Value: "w",
						Args:  []ir.FilterExpr{{Line: 340, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
					},
				},
				{
					Line:            344,
					SyntaxPatterns:  []ir.PatternString{{Line: 344, Value: "$w.Write([]byte(fmt.Sprintf($*args)))"}},
					ReportTemplate:  "fmt.Fprintf($w, $args) should be preferred to the $$",
					SuggestTemplate: "fmt.Fprintf($w, $args)",
					WhereExpr: ir.FilterExpr{
						Line:  345,
						Op:    ir.FilterVarTypeImplementsOp,
						Src:   "m[\"w\"].Type.Implements(\"io.Writer\")",
						Value: "w",
						Args:  []ir.FilterExpr{{Line: 345, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
					},
				},
				{
					Line:            349,
					SyntaxPatterns:  []ir.PatternString{{Line: 349, Value: "$w.Write([]byte(fmt.Sprintln($*args)))"}},
					ReportTemplate:  "fmt.Fprintln($w, $args) should be preferred to the $$",
					SuggestTemplate: "fmt.Fprintln($w, $args)",
					WhereExpr: ir.FilterExpr{
						Line:  350,
						Op:    ir.FilterVarTypeImplementsOp,
						Src:   "m[\"w\"].Type.Implements(\"io.Writer\")",
						Value: "w",
						Args:  []ir.FilterExpr{{Line: 350, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
					},
				},
				{
					Line:            354,
					SyntaxPatterns:  []ir.PatternString{{Line: 354, Value: "io.WriteString($w, fmt.Sprint($*args))"}},
					ReportTemplate:  "suggestion: fmt.Fprint($w, $args)",
					SuggestTemplate: "fmt.Fprint($w, $args)",
				},
				{
					Line:            355,
					SyntaxPatterns:  []ir.PatternString{{Line: 355, Value: "io.WriteString($w, fmt.Sprintf($*args))"}},
					ReportTemplate:  "suggestion: fmt.Fprintf($w, $args)",
					SuggestTemplate: "fmt.Fprintf($w, $args)",
				},
				{
					Line:            356,
					SyntaxPatterns:  []ir.PatternString{{Line: 356, Value: "io.WriteString($w, fmt.Sprintln($*args))"}},
					ReportTemplate:  "suggestion: fmt.Fprintln($w, $args)",
					SuggestTemplate: "fmt.Fprintln($w, $args)",
				},
				{
					Line:            358,
					SyntaxPatterns:  []ir.PatternString{{Line: 358, Value: "$w.WriteString(fmt.Sprint($*args))"}},
					ReportTemplate:  "suggestion: fmt.Fprint($w, $args)",
					SuggestTemplate: "fmt.Fprint($w, $args)",
					WhereExpr: ir.FilterExpr{
						Line: 359,
						Op:   ir.FilterAndOp,
						Src:  "m[\"w\"].Type.Implements(\"io.Writer\") && m[\"w\"].Type.Implements(\"io.StringWriter\")",
						Args: []ir.FilterExpr{
							{
								Line:  359,
								Op:    ir.FilterVarTypeImplementsOp,
								Src:   "m[\"w\"].Type.Implements(\"io.Writer\")",
								Value: "w",
								Args:  []ir.FilterExpr{{Line: 359, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
							},
							{
								Line:  359,
								Op:    ir.FilterVarTypeImplementsOp,
								Src:   "m[\"w\"].Type.Implements(\"io.StringWriter\")",
								Value: "w",
								Args:  []ir.FilterExpr{{Line: 359, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
							},
						},
					},
				},
				{
					Line:            361,
					SyntaxPatterns:  []ir.PatternString{{Line: 361, Value: "$w.WriteString(fmt.Sprintf($*args))"}},
					ReportTemplate:  "suggestion: fmt.Fprintf($w, $args)",
					SuggestTemplate: "fmt.Fprintf($w, $args)",
					WhereExpr: ir.FilterExpr{
						Line: 362,
						Op:   ir.FilterAndOp,
						Src:  "m[\"w\"].Type.Implements(\"io.Writer\") && m[\"w\"].Type.Implements(\"io.StringWriter\")",
						Args: []ir.FilterExpr{
							{
								Line:  362,
								Op:    ir.FilterVarTypeImplementsOp,
								Src:   "m[\"w\"].Type.Implements(\"io.Writer\")",
								Value: "w",
								Args:  []ir.FilterExpr{{Line: 362, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
							},
							{
								Line:  362,
								Op:    ir.FilterVarTypeImplementsOp,
								Src:   "m[\"w\"].Type.Implements(\"io.StringWriter\")",
								Value: "w",
								Args:  []ir.FilterExpr{{Line: 362, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
							},
						},
					},
				},
				{
					Line:            364,
					SyntaxPatterns:  []ir.PatternString{{Line: 364, Value: "$w.WriteString(fmt.Sprintln($*args))"}},
					ReportTemplate:  "suggestion: fmt.Fprintln($w, $args)",
					SuggestTemplate: "fmt.Fprintln($w, $args)",
					WhereExpr: ir.FilterExpr{
						Line: 365,
						Op:   ir.FilterAndOp,
						Src:  "m[\"w\"].Type.Implements(\"io.Writer\") && m[\"w\"].Type.Implements(\"io.StringWriter\")",
						Args: []ir.FilterExpr{
							{
								Line:  365,
								Op:    ir.FilterVarTypeImplementsOp,
								Src:   "m[\"w\"].Type.Implements(\"io.Writer\")",
								Value: "w",
								Args:  []ir.FilterExpr{{Line: 365, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}},
							},
							{
								Line:  365,
								Op:    ir.FilterVarTypeImplementsOp,
								Src:   "m[\"w\"].Type.Implements(\"io.StringWriter\")",
								Value: "w",
								Args:  []ir.FilterExpr{{Line: 365, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
							},
						},
					},
				},
			},
		},
		{
			Line:        373,
			Name:        "dupArg",
			MatcherName: "m",
			DocTags:     []string{"diagnostic"},
			DocSummary:  "Detects suspicious duplicated arguments",
			DocBefore:   "copy(dst, dst)",
			DocAfter:    "copy(dst, src)",
			Rules: []ir.Rule{
				{
					Line: 374,
					SyntaxPatterns: []ir.PatternString{
						{Line: 374, Value: "$x.Equal($x)"},
						{Line: 374, Value: "$x.Equals($x)"},
						{Line: 374, Value: "$x.Compare($x)"},
						{Line: 374, Value: "$x.Cmp($x)"},
					},
					ReportTemplate: "suspicious method call with the same argument and receiver",
					WhereExpr:      ir.FilterExpr{Line: 375, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
				{
					Line: 378,
					SyntaxPatterns: []ir.PatternString{
						{Line: 378, Value: "copy($x, $x)"},
						{Line: 379, Value: "math.Max($x, $x)"},
						{Line: 380, Value: "math.Min($x, $x)"},
						{Line: 381, Value: "reflect.Copy($x, $x)"},
						{Line: 382, Value: "reflect.DeepEqual($x, $x)"},
						{Line: 383, Value: "strings.Contains($x, $x)"},
						{Line: 384, Value: "strings.Compare($x, $x)"},
						{Line: 385, Value: "strings.EqualFold($x, $x)"},
						{Line: 386, Value: "strings.HasPrefix($x, $x)"},
						{Line: 387, Value: "strings.HasSuffix($x, $x)"},
						{Line: 388, Value: "strings.Index($x, $x)"},
						{Line: 389, Value: "strings.LastIndex($x, $x)"},
						{Line: 390, Value: "strings.Split($x, $x)"},
						{Line: 391, Value: "strings.SplitAfter($x, $x)"},
						{Line: 392, Value: "strings.SplitAfterN($x, $x, $_)"},
						{Line: 393, Value: "strings.SplitN($x, $x, $_)"},
						{Line: 394, Value: "strings.Replace($_, $x, $x, $_)"},
						{Line: 395, Value: "strings.ReplaceAll($_, $x, $x)"},
						{Line: 396, Value: "bytes.Contains($x, $x)"},
						{Line: 397, Value: "bytes.Compare($x, $x)"},
						{Line: 398, Value: "bytes.Equal($x, $x)"},
						{Line: 399, Value: "bytes.EqualFold($x, $x)"},
						{Line: 400, Value: "bytes.HasPrefix($x, $x)"},
						{Line: 401, Value: "bytes.HasSuffix($x, $x)"},
						{Line: 402, Value: "bytes.Index($x, $x)"},
						{Line: 403, Value: "bytes.LastIndex($x, $x)"},
						{Line: 404, Value: "bytes.Split($x, $x)"},
						{Line: 405, Value: "bytes.SplitAfter($x, $x)"},
						{Line: 406, Value: "bytes.SplitAfterN($x, $x, $_)"},
						{Line: 407, Value: "bytes.SplitN($x, $x, $_)"},
						{Line: 408, Value: "bytes.Replace($_, $x, $x, $_)"},
						{Line: 409, Value: "bytes.ReplaceAll($_, $x, $x)"},
						{Line: 410, Value: "types.Identical($x, $x)"},
						{Line: 411, Value: "types.IdenticalIgnoreTags($x, $x)"},
						{Line: 412, Value: "draw.Draw($x, $_, $x, $_, $_)"},
					},
					ReportTemplate: "suspicious duplicated args in $$",
					WhereExpr:      ir.FilterExpr{Line: 413, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
				},
			},
		},
		{
			Line:        421,
			Name:        "returnAfterHttpError",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects suspicious http.Error call without following return",
			DocBefore:   "if err != nil { http.Error(...); }",
			DocAfter:    "if err != nil { http.Error(...); return; }",
			Rules: []ir.Rule{{
				Line:           422,
				SyntaxPatterns: []ir.PatternString{{Line: 422, Value: "if $_ { $*_; http.Error($w, $err, $code) }"}},
				ReportTemplate: "Possibly return is missed after the http.Error call",
				LocationVar:    "w",
			}},
		},
		{
			Line:        431,
			Name:        "preferFilepathJoin",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects concatenation with os.PathSeparator which can be replaced with filepath.Join",
			DocBefore:   "x + string(os.PathSeparator) + y",
			DocAfter:    "filepath.Join(x, y)",
			Rules: []ir.Rule{{
				Line:            432,
				SyntaxPatterns:  []ir.PatternString{{Line: 432, Value: "$x + string(os.PathSeparator) + $y"}},
				ReportTemplate:  "filepath.Join($x, $y) should be preferred to the $$",
				SuggestTemplate: "filepath.Join($x, $y)",
				WhereExpr: ir.FilterExpr{
					Line: 433,
					Op:   ir.FilterAndOp,
					Src:  "m[\"x\"].Type.Is(`string`) && m[\"y\"].Type.Is(`string`)",
					Args: []ir.FilterExpr{
						{
							Line:  433,
							Op:    ir.FilterVarTypeIsOp,
							Src:   "m[\"x\"].Type.Is(`string`)",
							Value: "x",
							Args:  []ir.FilterExpr{{Line: 433, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
						},
						{
							Line:  433,
							Op:    ir.FilterVarTypeIsOp,
							Src:   "m[\"y\"].Type.Is(`string`)",
							Value: "y",
							Args:  []ir.FilterExpr{{Line: 433, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
						},
					},
				},
			}},
		},
		{
			Line:        442,
			Name:        "preferStringWriter",
			MatcherName: "m",
			DocTags:     []string{"performance", "experimental"},
			DocSummary:  "Detects w.Write or io.WriteString calls which can be replaced with w.WriteString",
			DocBefore:   "w.Write([]byte(\"foo\"))",
			DocAfter:    "w.WriteString(\"foo\")",
			Rules: []ir.Rule{
				{
					Line:            443,
					SyntaxPatterns:  []ir.PatternString{{Line: 443, Value: "$w.Write([]byte($s))"}},
					ReportTemplate:  "$w.WriteString($s) should be preferred to the $$",
					SuggestTemplate: "$w.WriteString($s)",
					WhereExpr: ir.FilterExpr{
						Line:  444,
						Op:    ir.FilterVarTypeImplementsOp,
						Src:   "m[\"w\"].Type.Implements(\"io.StringWriter\")",
						Value: "w",
						Args:  []ir.FilterExpr{{Line: 444, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
					},
				},
				{
					Line:            448,
					SyntaxPatterns:  []ir.PatternString{{Line: 448, Value: "io.WriteString($w, $s)"}},
					ReportTemplate:  "$w.WriteString($s) should be preferred to the $$",
					SuggestTemplate: "$w.WriteString($s)",
					WhereExpr: ir.FilterExpr{
						Line:  449,
						Op:    ir.FilterVarTypeImplementsOp,
						Src:   "m[\"w\"].Type.Implements(\"io.StringWriter\")",
						Value: "w",
						Args:  []ir.FilterExpr{{Line: 449, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}},
					},
				},
			},
		},
		{
			Line:        458,
			Name:        "sliceClear",
			MatcherName: "m",
			DocTags:     []string{"performance", "experimental"},
			DocSummary:  "Detects slice clear loops, suggests an idiom that is recognized by the Go compiler",
			DocBefore:   "for i := 0; i < len(buf); i++ { buf[i] = 0 }",
			DocAfter:    "for i := range buf { buf[i] = 0 }",
			Rules: []ir.Rule{{
				Line:           459,
				SyntaxPatterns: []ir.PatternString{{Line: 459, Value: "for $i := 0; $i < len($xs); $i++ { $xs[$i] = $zero }"}},
				ReportTemplate: "rewrite as for-range so compiler can recognize this pattern",
				WhereExpr: ir.FilterExpr{
					Line: 460,
					Op:   ir.FilterEqOp,
					Src:  "m[\"zero\"].Value.Int() == 0",
					Args: []ir.FilterExpr{
						{
							Line:  460,
							Op:    ir.FilterVarValueIntOp,
							Src:   "m[\"zero\"].Value.Int()",
							Value: "zero",
						},
						{
							Line:  460,
							Op:    ir.FilterIntOp,
							Src:   "0",
							Value: int64(0),
						},
					},
				},
			}},
		},
		{
			Line:        468,
			Name:        "syncMapLoadAndDelete",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects sync.Map load+delete operations that can be replaced with LoadAndDelete",
			DocBefore:   "v, ok := m.Load(k); if ok { m.Delete($k); f(v); }",
			DocAfter:    "v, deleted := m.LoadAndDelete(k); if deleted { f(v) }",
			Rules: []ir.Rule{{
				Line:           469,
				SyntaxPatterns: []ir.PatternString{{Line: 469, Value: "$_, $ok := $m.Load($k); if $ok { $m.Delete($k); $*_ }"}},
				ReportTemplate: "use $m.LoadAndDelete to perform load+delete operations atomically",
				WhereExpr: ir.FilterExpr{
					Line: 470,
					Op:   ir.FilterAndOp,
					Src:  "m.GoVersion().GreaterEqThan(\"1.15\") &&\n\tm[\"m\"].Type.Is(`*sync.Map`)",
					Args: []ir.FilterExpr{
						{
							Line:  470,
							Op:    ir.FilterGoVersionGreaterEqThanOp,
							Src:   "m.GoVersion().GreaterEqThan(\"1.15\")",
							Value: "1.15",
						},
						{
							Line:  471,
							Op:    ir.FilterVarTypeIsOp,
							Src:   "m[\"m\"].Type.Is(`*sync.Map`)",
							Value: "m",
							Args:  []ir.FilterExpr{{Line: 471, Op: ir.FilterStringOp, Src: "`*sync.Map`", Value: "*sync.Map"}},
						},
					},
				},
			}},
		},
		{
			Line:        479,
			Name:        "sprintfQuotedString",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects \"%s\" formatting directives that can be replaced with %q",
			DocBefore:   "fmt.Sprintf(`\"%s\"`, s)",
			DocAfter:    "fmt.Sprintf(`%q`, s)",
			Rules: []ir.Rule{{
				Line:           480,
				SyntaxPatterns: []ir.PatternString{{Line: 480, Value: "fmt.Sprintf($s, $*_)"}},
				ReportTemplate: "use %q instead of \"%s\" for quoted strings",
				WhereExpr: ir.FilterExpr{
					Line: 481,
					Op:   ir.FilterOrOp,
					Src:  "m[\"s\"].Text.Matches(\"^`.*\\\"%s\\\".*`$\") ||\n\tm[\"s\"].Text.Matches(`^\".*\\\\\"%s\\\\\".*\"$`)",
					Args: []ir.FilterExpr{
						{
							Line:  481,
							Op:    ir.FilterVarTextMatchesOp,
							Src:   "m[\"s\"].Text.Matches(\"^`.*\\\"%s\\\".*`$\")",
							Value: "s",
							Args:  []ir.FilterExpr{{Line: 481, Op: ir.FilterStringOp, Src: "\"^`.*\\\"%s\\\".*`$\"", Value: "^`.*\"%s\".*`$"}},
						},
						{
							Line:  482,
							Op:    ir.FilterVarTextMatchesOp,
							Src:   "m[\"s\"].Text.Matches(`^\".*\\\\\"%s\\\\\".*\"$`)",
							Value: "s",
							Args:  []ir.FilterExpr{{Line: 482, Op: ir.FilterStringOp, Src: "`^\".*\\\\\"%s\\\\\".*\"$`", Value: "^\".*\\\\\"%s\\\\\".*\"$"}},
						},
					},
				},
			}},
		},
		{
			Line:        490,
			Name:        "offBy1",
			MatcherName: "m",
			DocTags:     []string{"diagnostic"},
			DocSummary:  "Detects various off-by-one kind of errors",
			DocBefore:   "xs[len(xs)]",
			DocAfter:    "xs[len(xs)-1]",
			Rules: []ir.Rule{
				{
					Line:            491,
					SyntaxPatterns:  []ir.PatternString{{Line: 491, Value: "$x[len($x)]"}},
					ReportTemplate:  "index expr always panics; maybe you wanted $x[len($x)-1]?",
					SuggestTemplate: "$x[len($x)-1]",
					WhereExpr: ir.FilterExpr{
						Line: 492,
						Op:   ir.FilterAndOp,
						Src:  "m[\"x\"].Pure && m[\"x\"].Type.Is(`[]$_`)",
						Args: []ir.FilterExpr{
							{Line: 492, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
							{
								Line:  492,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"x\"].Type.Is(`[]$_`)",
								Value: "x",
								Args:  []ir.FilterExpr{{Line: 492, Op: ir.FilterStringOp, Src: "`[]$_`", Value: "[]$_"}},
							},
						},
					},
				},
				{
					Line: 499,
					SyntaxPatterns: []ir.PatternString{
						{Line: 500, Value: "$i := strings.Index($s, $_); $_ := $slicing[$i:]"},
						{Line: 501, Value: "$i := strings.Index($s, $_); $_ = $slicing[$i:]"},
						{Line: 502, Value: "$i := bytes.Index($s, $_); $_ := $slicing[$i:]"},
						{Line: 503, Value: "$i := bytes.Index($s, $_); $_ = $slicing[$i:]"},
					},
					ReportTemplate: "Index() can return -1; maybe you wanted to do $s[$i+1:]",
					WhereExpr: ir.FilterExpr{
						Line: 504,
						Op:   ir.FilterEqOp,
						Src:  "m[\"s\"].Text == m[\"slicing\"].Text",
						Args: []ir.FilterExpr{
							{Line: 504, Op: ir.FilterVarTextOp, Src: "m[\"s\"].Text", Value: "s"},
							{Line: 504, Op: ir.FilterVarTextOp, Src: "m[\"slicing\"].Text", Value: "slicing"},
						},
					},
					LocationVar: "slicing",
				},
				{
					Line: 508,
					SyntaxPatterns: []ir.PatternString{
						{Line: 509, Value: "$i := strings.Index($s, $_); $_ := $slicing[:$i]"},
						{Line: 510, Value: "$i := strings.Index($s, $_); $_ = $slicing[:$i]"},
						{Line: 511, Value: "$i := bytes.Index($s, $_); $_ := $slicing[:$i]"},
						{Line: 512, Value: "$i := bytes.Index($s, $_); $_ = $slicing[:$i]"},
					},
					ReportTemplate: "Index() can return -1; maybe you wanted to do $s[:$i+1]",
					WhereExpr: ir.FilterExpr{
						Line: 513,
						Op:   ir.FilterEqOp,
						Src:  "m[\"s\"].Text == m[\"slicing\"].Text",
						Args: []ir.FilterExpr{
							{Line: 513, Op: ir.FilterVarTextOp, Src: "m[\"s\"].Text", Value: "s"},
							{Line: 513, Op: ir.FilterVarTextOp, Src: "m[\"slicing\"].Text", Value: "slicing"},
						},
					},
					LocationVar: "slicing",
				},
				{
					Line: 517,
					SyntaxPatterns: []ir.PatternString{
						{Line: 518, Value: "$s[strings.Index($s, $_):]"},
						{Line: 519, Value: "$s[:strings.Index($s, $_)]"},
						{Line: 520, Value: "$s[bytes.Index($s, $_):]"},
						{Line: 521, Value: "$s[:bytes.Index($s, $_)]"},
					},
					ReportTemplate: "Index() can return -1; maybe you wanted to do Index()+1",
				},
			},
		},
		{
			Line:        529,
			Name:        "unslice",
			MatcherName: "m",
			DocTags:     []string{"style"},
			DocSummary:  "Detects slice expressions that can be simplified to sliced expression itself",
			DocBefore:   "copy(b[:], values...)",
			DocAfter:    "copy(b, values...)",
			Rules: []ir.Rule{{
				Line:            530,
				SyntaxPatterns:  []ir.PatternString{{Line: 530, Value: "$s[:]"}},
				ReportTemplate:  "could simplify $$ to $s",
				SuggestTemplate: "$s",
				WhereExpr: ir.FilterExpr{
					Line: 531,
					Op:   ir.FilterOrOp,
					Src:  "m[\"s\"].Type.Is(`string`) || m[\"s\"].Type.Is(`[]$_`)",
					Args: []ir.FilterExpr{
						{
							Line:  531,
							Op:    ir.FilterVarTypeIsOp,
							Src:   "m[\"s\"].Type.Is(`string`)",
							Value: "s",
							Args:  []ir.FilterExpr{{Line: 531, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}},
						},
						{
							Line:  531,
							Op:    ir.FilterVarTypeIsOp,
							Src:   "m[\"s\"].Type.Is(`[]$_`)",
							Value: "s",
							Args:  []ir.FilterExpr{{Line: 531, Op: ir.FilterStringOp, Src: "`[]$_`", Value: "[]$_"}},
						},
					},
				},
			}},
		},
		{
			Line:        540,
			Name:        "yodaStyleExpr",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects Yoda style expressions and suggests to replace them",
			DocBefore:   "return nil != ptr",
			DocAfter:    "return ptr != nil",
			Rules: []ir.Rule{
				{
					Line:           541,
					SyntaxPatterns: []ir.PatternString{{Line: 541, Value: "$constval != $x"}},
					ReportTemplate: "consider to change order in expression to $x != $constval",
					WhereExpr: ir.FilterExpr{
						Line: 541,
						Op:   ir.FilterAndOp,
						Src:  "m[\"constval\"].Node.Is(`BasicLit`) && !m[\"x\"].Node.Is(`BasicLit`)",
						Args: []ir.FilterExpr{
							{
								Line:  541,
								Op:    ir.FilterVarNodeIsOp,
								Src:   "m[\"constval\"].Node.Is(`BasicLit`)",
								Value: "constval",
								Args:  []ir.FilterExpr{{Line: 541, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
							},
							{
								Line: 541,
								Op:   ir.FilterNotOp,
								Src:  "!m[\"x\"].Node.Is(`BasicLit`)",
								Args: []ir.FilterExpr{{
									Line:  541,
									Op:    ir.FilterVarNodeIsOp,
									Src:   "m[\"x\"].Node.Is(`BasicLit`)",
									Value: "x",
									Args:  []ir.FilterExpr{{Line: 541, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
								}},
							},
						},
					},
				},
				{
					Line:           543,
					SyntaxPatterns: []ir.PatternString{{Line: 543, Value: "$constval == $x"}},
					ReportTemplate: "consider to change order in expression to $x == $constval",
					WhereExpr: ir.FilterExpr{
						Line: 543,
						Op:   ir.FilterAndOp,
						Src:  "m[\"constval\"].Node.Is(`BasicLit`) && !m[\"x\"].Node.Is(`BasicLit`)",
						Args: []ir.FilterExpr{
							{
								Line:  543,
								Op:    ir.FilterVarNodeIsOp,
								Src:   "m[\"constval\"].Node.Is(`BasicLit`)",
								Value: "constval",
								Args:  []ir.FilterExpr{{Line: 543, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
							},
							{
								Line: 543,
								Op:   ir.FilterNotOp,
								Src:  "!m[\"x\"].Node.Is(`BasicLit`)",
								Args: []ir.FilterExpr{{
									Line:  543,
									Op:    ir.FilterVarNodeIsOp,
									Src:   "m[\"x\"].Node.Is(`BasicLit`)",
									Value: "x",
									Args:  []ir.FilterExpr{{Line: 543, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
								}},
							},
						},
					},
				},
				{
					Line:           546,
					SyntaxPatterns: []ir.PatternString{{Line: 546, Value: "nil != $x"}},
					ReportTemplate: "consider to change order in expression to $x != nil",
					WhereExpr: ir.FilterExpr{
						Line: 546,
						Op:   ir.FilterNotOp,
						Src:  "!m[\"x\"].Node.Is(`BasicLit`)",
						Args: []ir.FilterExpr{{
							Line:  546,
							Op:    ir.FilterVarNodeIsOp,
							Src:   "m[\"x\"].Node.Is(`BasicLit`)",
							Value: "x",
							Args:  []ir.FilterExpr{{Line: 546, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
						}},
					},
				},
				{
					Line:           548,
					SyntaxPatterns: []ir.PatternString{{Line: 548, Value: "nil == $x"}},
					ReportTemplate: "consider to change order in expression to $x == nil",
					WhereExpr: ir.FilterExpr{
						Line: 548,
						Op:   ir.FilterNotOp,
						Src:  "!m[\"x\"].Node.Is(`BasicLit`)",
						Args: []ir.FilterExpr{{
							Line:  548,
							Op:    ir.FilterVarNodeIsOp,
							Src:   "m[\"x\"].Node.Is(`BasicLit`)",
							Value: "x",
							Args:  []ir.FilterExpr{{Line: 548, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}},
						}},
					},
				},
			},
		},
		{
			Line:        556,
			Name:        "equalFold",
			MatcherName: "m",
			DocTags:     []string{"performance", "experimental"},
			DocSummary:  "Detects unoptimal strings/bytes case-insensitive comparison",
			DocBefore:   "strings.ToLower(x) == strings.ToLower(y)",
			DocAfter:    "strings.EqualFold(x, y)",
			Rules: []ir.Rule{
				{
					Line: 565,
					SyntaxPatterns: []ir.PatternString{
						{Line: 566, Value: "strings.ToLower($x) == $y"},
						{Line: 567, Value: "strings.ToLower($x) == strings.ToLower($y)"},
						{Line: 568, Value: "$x == strings.ToLower($y)"},
						{Line: 569, Value: "strings.ToUpper($x) == $y"},
						{Line: 570, Value: "strings.ToUpper($x) == strings.ToUpper($y)"},
						{Line: 571, Value: "$x == strings.ToUpper($y)"},
					},
					ReportTemplate:  "consider replacing with strings.EqualFold($x, $y)",
					SuggestTemplate: "strings.EqualFold($x, $y)",
					WhereExpr: ir.FilterExpr{
						Line: 572,
						Op:   ir.FilterAndOp,
						Src:  "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text",
						Args: []ir.FilterExpr{
							{
								Line: 572,
								Op:   ir.FilterAndOp,
								Src:  "m[\"x\"].Pure && m[\"y\"].Pure",
								Args: []ir.FilterExpr{
									{Line: 572, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
									{Line: 572, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
								},
							},
							{
								Line: 572,
								Op:   ir.FilterNeqOp,
								Src:  "m[\"x\"].Text != m[\"y\"].Text",
								Args: []ir.FilterExpr{
									{Line: 572, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"},
									{Line: 572, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"},
								},
							},
						},
					},
				},
				{
					Line: 577,
					SyntaxPatterns: []ir.PatternString{
						{Line: 578, Value: "strings.ToLower($x) != $y"},
						{Line: 579, Value: "strings.ToLower($x) != strings.ToLower($y)"},
						{Line: 580, Value: "$x != strings.ToLower($y)"},
						{Line: 581, Value: "strings.ToUpper($x) != $y"},
						{Line: 582, Value: "strings.ToUpper($x) != strings.ToUpper($y)"},
						{Line: 583, Value: "$x != strings.ToUpper($y)"},
					},
					ReportTemplate:  "consider replacing with !strings.EqualFold($x, $y)",
					SuggestTemplate: "!strings.EqualFold($x, $y)",
					WhereExpr: ir.FilterExpr{
						Line: 584,
						Op:   ir.FilterAndOp,
						Src:  "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text",
						Args: []ir.FilterExpr{
							{
								Line: 584,
								Op:   ir.FilterAndOp,
								Src:  "m[\"x\"].Pure && m[\"y\"].Pure",
								Args: []ir.FilterExpr{
									{Line: 584, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
									{Line: 584, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
								},
							},
							{
								Line: 584,
								Op:   ir.FilterNeqOp,
								Src:  "m[\"x\"].Text != m[\"y\"].Text",
								Args: []ir.FilterExpr{
									{Line: 584, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"},
									{Line: 584, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"},
								},
							},
						},
					},
				},
				{
					Line: 589,
					SyntaxPatterns: []ir.PatternString{
						{Line: 590, Value: "bytes.Equal(bytes.ToLower($x), $y)"},
						{Line: 591, Value: "bytes.Equal(bytes.ToLower($x), bytes.ToLower($y))"},
						{Line: 592, Value: "bytes.Equal($x, bytes.ToLower($y))"},
						{Line: 593, Value: "bytes.Equal(bytes.ToUpper($x), $y)"},
						{Line: 594, Value: "bytes.Equal(bytes.ToUpper($x), bytes.ToUpper($y))"},
						{Line: 595, Value: "bytes.Equal($x, bytes.ToUpper($y))"},
					},
					ReportTemplate:  "consider replacing with bytes.EqualFold($x, $y)",
					SuggestTemplate: "bytes.EqualFold($x, $y)",
					WhereExpr: ir.FilterExpr{
						Line: 596,
						Op:   ir.FilterAndOp,
						Src:  "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text",
						Args: []ir.FilterExpr{
							{
								Line: 596,
								Op:   ir.FilterAndOp,
								Src:  "m[\"x\"].Pure && m[\"y\"].Pure",
								Args: []ir.FilterExpr{
									{Line: 596, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"},
									{Line: 596, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"},
								},
							},
							{
								Line: 596,
								Op:   ir.FilterNeqOp,
								Src:  "m[\"x\"].Text != m[\"y\"].Text",
								Args: []ir.FilterExpr{
									{Line: 596, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"},
									{Line: 596, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"},
								},
							},
						},
					},
				},
			},
		},
		{
			Line:        605,
			Name:        "argOrder",
			MatcherName: "m",
			DocTags:     []string{"diagnostic"},
			DocSummary:  "Detects suspicious arguments order",
			DocBefore:   "strings.HasPrefix(\"#\", userpass)",
			DocAfter:    "strings.HasPrefix(userpass, \"#\")",
			Rules: []ir.Rule{{
				Line: 606,
				SyntaxPatterns: []ir.PatternString{
					{Line: 607, Value: "strings.HasPrefix($lit, $s)"},
					{Line: 608, Value: "bytes.HasPrefix($lit, $s)"},
					{Line: 609, Value: "strings.HasSuffix($lit, $s)"},
					{Line: 610, Value: "bytes.HasSuffix($lit, $s)"},
					{Line: 611, Value: "strings.Contains($lit, $s)"},
					{Line: 612, Value: "bytes.Contains($lit, $s)"},
					{Line: 613, Value: "strings.TrimPrefix($lit, $s)"},
					{Line: 614, Value: "bytes.TrimPrefix($lit, $s)"},
					{Line: 615, Value: "strings.TrimSuffix($lit, $s)"},
					{Line: 616, Value: "bytes.TrimSuffix($lit, $s)"},
					{Line: 617, Value: "strings.Split($lit, $s)"},
					{Line: 618, Value: "bytes.Split($lit, $s)"},
				},
				ReportTemplate: "$lit and $s arguments order looks reversed",
				WhereExpr: ir.FilterExpr{
					Line: 619,
					Op:   ir.FilterAndOp,
					Src:  "(m[\"lit\"].Const || m[\"lit\"].ConstSlice) &&\n\t!(m[\"s\"].Const || m[\"s\"].ConstSlice) &&\n\t!m[\"lit\"].Node.Is(`Ident`)",
					Args: []ir.FilterExpr{
						{
							Line: 619,
							Op:   ir.FilterAndOp,
							Src:  "(m[\"lit\"].Const || m[\"lit\"].ConstSlice) &&\n\t!(m[\"s\"].Const || m[\"s\"].ConstSlice)",
							Args: []ir.FilterExpr{
								{
									Line: 619,
									Op:   ir.FilterOrOp,
									Src:  "(m[\"lit\"].Const || m[\"lit\"].ConstSlice)",
									Args: []ir.FilterExpr{
										{
											Line:  619,
											Op:    ir.FilterVarConstOp,
											Src:   "m[\"lit\"].Const",
											Value: "lit",
										},
										{
											Line:  619,
											Op:    ir.FilterVarConstSliceOp,
											Src:   "m[\"lit\"].ConstSlice",
											Value: "lit",
										},
									},
								},
								{
									Line: 620,
									Op:   ir.FilterNotOp,
									Src:  "!(m[\"s\"].Const || m[\"s\"].ConstSlice)",
									Args: []ir.FilterExpr{{
										Line: 620,
										Op:   ir.FilterOrOp,
										Src:  "(m[\"s\"].Const || m[\"s\"].ConstSlice)",
										Args: []ir.FilterExpr{
											{
												Line:  620,
												Op:    ir.FilterVarConstOp,
												Src:   "m[\"s\"].Const",
												Value: "s",
											},
											{
												Line:  620,
												Op:    ir.FilterVarConstSliceOp,
												Src:   "m[\"s\"].ConstSlice",
												Value: "s",
											},
										},
									}},
								},
							},
						},
						{
							Line: 621,
							Op:   ir.FilterNotOp,
							Src:  "!m[\"lit\"].Node.Is(`Ident`)",
							Args: []ir.FilterExpr{{
								Line:  621,
								Op:    ir.FilterVarNodeIsOp,
								Src:   "m[\"lit\"].Node.Is(`Ident`)",
								Value: "lit",
								Args:  []ir.FilterExpr{{Line: 621, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}},
							}},
						},
					},
				},
			}},
		},
		{
			Line:        629,
			Name:        "stringConcatSimplify",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects string concat operations that can be simplified",
			DocBefore:   "strings.Join([]string{x, y}, \"_\")",
			DocAfter:    "x + \"_\" + y",
			Rules: []ir.Rule{
				{
					Line:            630,
					SyntaxPatterns:  []ir.PatternString{{Line: 630, Value: "strings.Join([]string{$x, $y}, \"\")"}},
					ReportTemplate:  "suggestion: $x + $y",
					SuggestTemplate: "$x + $y",
				},
				{
					Line:            631,
					SyntaxPatterns:  []ir.PatternString{{Line: 631, Value: "strings.Join([]string{$x, $y, $z}, \"\")"}},
					ReportTemplate:  "suggestion: $x + $y + $z",
					SuggestTemplate: "$x + $y + $z",
				},
				{
					Line:            632,
					SyntaxPatterns:  []ir.PatternString{{Line: 632, Value: "strings.Join([]string{$x, $y}, $glue)"}},
					ReportTemplate:  "suggestion: $x + $glue + $y",
					SuggestTemplate: "$x + $glue + $y",
				},
			},
		},
		{
			Line:        639,
			Name:        "timeExprSimplify",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects manual conversion to milli- or microseconds",
			DocBefore:   "t.Unix() / 1000",
			DocAfter:    "t.UnixMilli()",
			Rules: []ir.Rule{
				{
					Line:            644,
					SyntaxPatterns:  []ir.PatternString{{Line: 644, Value: "$t.Unix() / 1000"}},
					ReportTemplate:  "use $t.UnixMilli() instead of $$",
					SuggestTemplate: "$t.UnixMilli()",
					WhereExpr: ir.FilterExpr{
						Line: 645,
						Op:   ir.FilterAndOp,
						Src:  "m.GoVersion().GreaterEqThan(\"1.17\") && isTime(m[\"t\"])",
						Args: []ir.FilterExpr{
							{
								Line:  645,
								Op:    ir.FilterGoVersionGreaterEqThanOp,
								Src:   "m.GoVersion().GreaterEqThan(\"1.17\")",
								Value: "1.17",
							},
							{
								Line: 645,
								Op:   ir.FilterOrOp,
								Src:  "isTime(m[\"t\"])",
								Args: []ir.FilterExpr{
									{
										Line:  645,
										Op:    ir.FilterVarTypeIsOp,
										Src:   "m[\"t\"].Type.Is(`time.Time`)",
										Value: "t",
										Args:  []ir.FilterExpr{{Line: 641, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}},
									},
									{
										Line:  645,
										Op:    ir.FilterVarTypeIsOp,
										Src:   "m[\"t\"].Type.Is(`*time.Time`)",
										Value: "t",
										Args:  []ir.FilterExpr{{Line: 641, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}},
									},
								},
							},
						},
					},
				},
				{
					Line:            649,
					SyntaxPatterns:  []ir.PatternString{{Line: 649, Value: "$t.UnixNano() * 1000"}},
					ReportTemplate:  "use $t.UnixMicro() instead of $$",
					SuggestTemplate: "$t.UnixMicro()",
					WhereExpr: ir.FilterExpr{
						Line: 650,
						Op:   ir.FilterAndOp,
						Src:  "m.GoVersion().GreaterEqThan(\"1.17\") && isTime(m[\"t\"])",
						Args: []ir.FilterExpr{
							{
								Line:  650,
								Op:    ir.FilterGoVersionGreaterEqThanOp,
								Src:   "m.GoVersion().GreaterEqThan(\"1.17\")",
								Value: "1.17",
							},
							{
								Line: 650,
								Op:   ir.FilterOrOp,
								Src:  "isTime(m[\"t\"])",
								Args: []ir.FilterExpr{
									{
										Line:  650,
										Op:    ir.FilterVarTypeIsOp,
										Src:   "m[\"t\"].Type.Is(`time.Time`)",
										Value: "t",
										Args:  []ir.FilterExpr{{Line: 641, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}},
									},
									{
										Line:  650,
										Op:    ir.FilterVarTypeIsOp,
										Src:   "m[\"t\"].Type.Is(`*time.Time`)",
										Value: "t",
										Args:  []ir.FilterExpr{{Line: 641, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}},
									},
								},
							},
						},
					},
				},
			},
		},
		{
			Line:        659,
			Name:        "timeCmpSimplify",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects Before/After call of time.Time that can be simplified",
			DocBefore:   "!t.Before(tt)",
			DocAfter:    "t.After(tt)",
			Rules: []ir.Rule{
				{
					Line:            664,
					SyntaxPatterns:  []ir.PatternString{{Line: 664, Value: "!$t.Before($tt)"}},
					ReportTemplate:  "suggestion: $t.After($tt)",
					SuggestTemplate: "$t.After($tt)",
					WhereExpr: ir.FilterExpr{
						Line: 665,
						Op:   ir.FilterOrOp,
						Src:  "isTime(m[\"t\"])",
						Args: []ir.FilterExpr{
							{
								Line:  665,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"t\"].Type.Is(`time.Time`)",
								Value: "t",
								Args:  []ir.FilterExpr{{Line: 661, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}},
							},
							{
								Line:  665,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"t\"].Type.Is(`*time.Time`)",
								Value: "t",
								Args:  []ir.FilterExpr{{Line: 661, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}},
							},
						},
					},
				},
				{
					Line:            668,
					SyntaxPatterns:  []ir.PatternString{{Line: 668, Value: "!$t.After($tt)"}},
					ReportTemplate:  "suggestion: $t.Before($tt)",
					SuggestTemplate: "$t.Before($tt)",
					WhereExpr: ir.FilterExpr{
						Line: 669,
						Op:   ir.FilterOrOp,
						Src:  "isTime(m[\"t\"])",
						Args: []ir.FilterExpr{
							{
								Line:  669,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"t\"].Type.Is(`time.Time`)",
								Value: "t",
								Args:  []ir.FilterExpr{{Line: 661, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}},
							},
							{
								Line:  669,
								Op:    ir.FilterVarTypeIsOp,
								Src:   "m[\"t\"].Type.Is(`*time.Time`)",
								Value: "t",
								Args:  []ir.FilterExpr{{Line: 661, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}},
							},
						},
					},
				},
			},
		},
		{
			Line:        677,
			Name:        "exposedSyncMutex",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects exposed methods from sync.Mutex and sync.RWMutex",
			DocBefore:   "type Foo struct{ ...; sync.Mutex; ... }",
			DocAfter:    "type Foo struct{ ...; mu sync.Mutex; ... }",
			Rules: []ir.Rule{
				{
					Line:           682,
					SyntaxPatterns: []ir.PatternString{{Line: 682, Value: "type $x struct { $*_; sync.Mutex; $*_ }"}},
					ReportTemplate: "don't embed sync.Mutex",
					WhereExpr: ir.FilterExpr{
						Line:  683,
						Op:    ir.FilterVarTextMatchesOp,
						Src:   "isExported(m[\"x\"])",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 679, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
					},
				},
				{
					Line:           686,
					SyntaxPatterns: []ir.PatternString{{Line: 686, Value: "type $x struct { $*_; *sync.Mutex; $*_ }"}},
					ReportTemplate: "don't embed *sync.Mutex",
					WhereExpr: ir.FilterExpr{
						Line:  687,
						Op:    ir.FilterVarTextMatchesOp,
						Src:   "isExported(m[\"x\"])",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 679, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
					},
				},
				{
					Line:           690,
					SyntaxPatterns: []ir.PatternString{{Line: 690, Value: "type $x struct { $*_; sync.RWMutex; $*_ }"}},
					ReportTemplate: "don't embed sync.RWMutex",
					WhereExpr: ir.FilterExpr{
						Line:  691,
						Op:    ir.FilterVarTextMatchesOp,
						Src:   "isExported(m[\"x\"])",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 679, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
					},
				},
				{
					Line:           694,
					SyntaxPatterns: []ir.PatternString{{Line: 694, Value: "type $x struct { $*_; *sync.RWMutex; $*_ }"}},
					ReportTemplate: "don't embed *sync.RWMutex",
					WhereExpr: ir.FilterExpr{
						Line:  695,
						Op:    ir.FilterVarTextMatchesOp,
						Src:   "isExported(m[\"x\"])",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 679, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}},
					},
				},
			},
		},
		{
			Line:        703,
			Name:        "badSorting",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects bad usage of sort package",
			DocBefore:   "xs = sort.StringSlice(xs)",
			DocAfter:    "sort.Strings(xs)",
			Rules: []ir.Rule{
				{
					Line:            704,
					SyntaxPatterns:  []ir.PatternString{{Line: 704, Value: "$x = sort.IntSlice($x)"}},
					ReportTemplate:  "suspicious sort.IntSlice usage, maybe sort.Ints was intended?",
					SuggestTemplate: "sort.Ints($x)",
					WhereExpr: ir.FilterExpr{
						Line:  705,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"x\"].Type.Is(`[]int`)",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 705, Op: ir.FilterStringOp, Src: "`[]int`", Value: "[]int"}},
					},
				},
				{
					Line:            709,
					SyntaxPatterns:  []ir.PatternString{{Line: 709, Value: "$x = sort.Float64Slice($x)"}},
					ReportTemplate:  "suspicious sort.Float64s usage, maybe sort.Float64s was intended?",
					SuggestTemplate: "sort.Float64s($x)",
					WhereExpr: ir.FilterExpr{
						Line:  710,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"x\"].Type.Is(`[]float64`)",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 710, Op: ir.FilterStringOp, Src: "`[]float64`", Value: "[]float64"}},
					},
				},
				{
					Line:            714,
					SyntaxPatterns:  []ir.PatternString{{Line: 714, Value: "$x = sort.StringSlice($x)"}},
					ReportTemplate:  "suspicious sort.StringSlice usage, maybe sort.Strings was intended?",
					SuggestTemplate: "sort.Strings($x)",
					WhereExpr: ir.FilterExpr{
						Line:  715,
						Op:    ir.FilterVarTypeIsOp,
						Src:   "m[\"x\"].Type.Is(`[]string`)",
						Value: "x",
						Args:  []ir.FilterExpr{{Line: 715, Op: ir.FilterStringOp, Src: "`[]string`", Value: "[]string"}},
					},
				},
			},
		},
		{
			Line:        724,
			Name:        "externalErrorReassign",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects suspicious reassigment of error from another package",
			DocBefore:   "io.EOF = nil",
			DocAfter:    "/* don't do it */",
			Rules: []ir.Rule{{
				Line:           725,
				SyntaxPatterns: []ir.PatternString{{Line: 725, Value: "$pkg.$err = $x"}},
				ReportTemplate: "suspicious reassigment of error from another package",
				WhereExpr: ir.FilterExpr{
					Line: 726,
					Op:   ir.FilterAndOp,
					Src:  "m[\"err\"].Type.Is(`error`) && m[\"pkg\"].Object.Is(`PkgName`)",
					Args: []ir.FilterExpr{
						{
							Line:  726,
							Op:    ir.FilterVarTypeIsOp,
							Src:   "m[\"err\"].Type.Is(`error`)",
							Value: "err",
							Args:  []ir.FilterExpr{{Line: 726, Op: ir.FilterStringOp, Src: "`error`", Value: "error"}},
						},
						{
							Line:  726,
							Op:    ir.FilterVarObjectIsOp,
							Src:   "m[\"pkg\"].Object.Is(`PkgName`)",
							Value: "pkg",
							Args:  []ir.FilterExpr{{Line: 726, Op: ir.FilterStringOp, Src: "`PkgName`", Value: "PkgName"}},
						},
					},
				},
			}},
		},
		{
			Line:        734,
			Name:        "emptyDecl",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects suspicious empty declarations blocks",
			DocBefore:   "var()",
			DocAfter:    "/* nothing */",
			Rules: []ir.Rule{
				{
					Line:           735,
					SyntaxPatterns: []ir.PatternString{{Line: 735, Value: "var()"}},
					ReportTemplate: "empty var() block",
				},
				{
					Line:           736,
					SyntaxPatterns: []ir.PatternString{{Line: 736, Value: "const()"}},
					ReportTemplate: "empty const() block",
				},
				{
					Line:           737,
					SyntaxPatterns: []ir.PatternString{{Line: 737, Value: "type()"}},
					ReportTemplate: "empty type() block",
				},
			},
		},
		{
			Line:        744,
			Name:        "dynamicFmtString",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects suspicious formatting strings usage",
			DocBefore:   "fmt.Errorf(msg)",
			DocAfter:    "fmt.Errorf(\"%s\", msg)",
			Rules: []ir.Rule{
				{
					Line:            745,
					SyntaxPatterns:  []ir.PatternString{{Line: 745, Value: "fmt.Errorf($f)"}},
					ReportTemplate:  "use errors.New($f) or fmt.Errorf(\"%s\", $f) instead",
					SuggestTemplate: "errors.New($f)",
					WhereExpr: ir.FilterExpr{
						Line: 746,
						Op:   ir.FilterNotOp,
						Src:  "!m[\"f\"].Const",
						Args: []ir.FilterExpr{{
							Line:  746,
							Op:    ir.FilterVarConstOp,
							Src:   "m[\"f\"].Const",
							Value: "f",
						}},
					},
				},
				{
					Line:            750,
					SyntaxPatterns:  []ir.PatternString{{Line: 750, Value: "fmt.Errorf($f($*args))"}},
					ReportTemplate:  "use errors.New($f($*args)) or fmt.Errorf(\"%s\", $f($*args)) instead",
					SuggestTemplate: "errors.New($f($*args))",
				},
			},
		},
		{
			Line:        759,
			Name:        "stringsCompare",
			MatcherName: "m",
			DocTags:     []string{"style", "experimental"},
			DocSummary:  "Detects strings.Compare usage",
			DocBefore:   "strings.Compare(x, y)",
			DocAfter:    "x < y",
			Rules: []ir.Rule{
				{
					Line:            760,
					SyntaxPatterns:  []ir.PatternString{{Line: 760, Value: "strings.Compare($s1, $s2) == 0"}},
					ReportTemplate:  "suggestion: $s1 == $s2",
					SuggestTemplate: "$s1 == $s2",
				},
				{
					Line: 763,
					SyntaxPatterns: []ir.PatternString{
						{Line: 763, Value: "strings.Compare($s1, $s2) == -1"},
						{Line: 764, Value: "strings.Compare($s1, $s2) < 0"},
					},
					ReportTemplate:  "suggestion: $s1 < $s2",
					SuggestTemplate: "$s1 < $s2",
				},
				{
					Line: 767,
					SyntaxPatterns: []ir.PatternString{
						{Line: 767, Value: "strings.Compare($s1, $s2) == 1"},
						{Line: 768, Value: "strings.Compare($s1, $s2) > 0"},
					},
					ReportTemplate:  "suggestion: $s1 > $s2",
					SuggestTemplate: "$s1 > $s2",
				},
			},
		},
		{
			Line:        776,
			Name:        "uncheckedInlineErr",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects unchecked errors in if statements",
			DocBefore:   "if err := expr(); err2 != nil { /*...*/ }",
			DocAfter:    "if err := expr(); err != nil { /*...*/ }",
			Rules: []ir.Rule{{
				Line: 777,
				SyntaxPatterns: []ir.PatternString{
					{Line: 778, Value: "if $err := $_($*_); $err2 != nil { $*_ }"},
					{Line: 779, Value: "if $err = $_($*_); $err2 != nil { $*_ }"},
					{Line: 780, Value: "if $*_, $err := $_($*_); $err2 != nil { $*_ }"},
					{Line: 781, Value: "if $*_, $err = $_($*_); $err2 != nil { $*_ }"},
				},
				ReportTemplate: "$err error is unchecked, maybe intended to check it instead of $err2",
				WhereExpr: ir.FilterExpr{
					Line: 782,
					Op:   ir.FilterAndOp,
					Src:  "m[\"err\"].Type.Implements(\"error\") && m[\"err2\"].Type.Implements(\"error\") &&\n\tm[\"err\"].Text != m[\"err2\"].Text",
					Args: []ir.FilterExpr{
						{
							Line: 782,
							Op:   ir.FilterAndOp,
							Src:  "m[\"err\"].Type.Implements(\"error\") && m[\"err2\"].Type.Implements(\"error\")",
							Args: []ir.FilterExpr{
								{
									Line:  782,
									Op:    ir.FilterVarTypeImplementsOp,
									Src:   "m[\"err\"].Type.Implements(\"error\")",
									Value: "err",
									Args:  []ir.FilterExpr{{Line: 782, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}},
								},
								{
									Line:  782,
									Op:    ir.FilterVarTypeImplementsOp,
									Src:   "m[\"err2\"].Type.Implements(\"error\")",
									Value: "err2",
									Args:  []ir.FilterExpr{{Line: 782, Op: ir.FilterStringOp, Src: "\"error\"", Value: "error"}},
								},
							},
						},
						{
							Line: 783,
							Op:   ir.FilterNeqOp,
							Src:  "m[\"err\"].Text != m[\"err2\"].Text",
							Args: []ir.FilterExpr{
								{Line: 783, Op: ir.FilterVarTextOp, Src: "m[\"err\"].Text", Value: "err"},
								{Line: 783, Op: ir.FilterVarTextOp, Src: "m[\"err2\"].Text", Value: "err2"},
							},
						},
					},
				},
				LocationVar: "err",
			}},
		},
		{
			Line:        792,
			Name:        "sloppyTestFuncName",
			MatcherName: "m",
			DocTags:     []string{"diagnostic", "experimental"},
			DocSummary:  "Detects unsupported test and benchmark funcs",
			DocBefore:   "func TessstUnit(t *testing.T)",
			DocAfter:    "func TestUnit(t *testing.T)",
			Rules: []ir.Rule{
				{
					Line:           793,
					SyntaxPatterns: []ir.PatternString{{Line: 793, Value: "func $test($_ *testing.T) { $*_ }"}},
					ReportTemplate: "function $test should be of form TestXXX(t *testing.T)",
					WhereExpr: ir.FilterExpr{
						Line: 794,
						Op:   ir.FilterAndOp,
						Src:  "!m[\"test\"].Text.Matches(\"Test.*\") &&\n\t!m[\"test\"].Text.Matches(\"test.*\")",
						Args: []ir.FilterExpr{
							{
								Line: 794,
								Op:   ir.FilterNotOp,
								Src:  "!m[\"test\"].Text.Matches(\"Test.*\")",
								Args: []ir.FilterExpr{{
									Line:  794,
									Op:    ir.FilterVarTextMatchesOp,
									Src:   "m[\"test\"].Text.Matches(\"Test.*\")",
									Value: "test",
									Args:  []ir.FilterExpr{{Line: 794, Op: ir.FilterStringOp, Src: "\"Test.*\"", Value: "Test.*"}},
								}},
							},
							{
								Line: 795,
								Op:   ir.FilterNotOp,
								Src:  "!m[\"test\"].Text.Matches(\"test.*\")",
								Args: []ir.FilterExpr{{
									Line:  795,
									Op:    ir.FilterVarTextMatchesOp,
									Src:   "m[\"test\"].Text.Matches(\"test.*\")",
									Value: "test",
									Args:  []ir.FilterExpr{{Line: 795, Op: ir.FilterStringOp, Src: "\"test.*\"", Value: "test.*"}},
								}},
							},
						},
					},
				},
				{
					Line:           798,
					SyntaxPatterns: []ir.PatternString{{Line: 798, Value: "func $bench($_ *testing.B) { $*_ }"}},
					ReportTemplate: "function $bench should be of form BenchmarkXXX(b *testing.B)",
					WhereExpr: ir.FilterExpr{
						Line: 799,
						Op:   ir.FilterAndOp,
						Src:  "!m[\"bench\"].Text.Matches(\"Benchmark.*\") &&\n\t!m[\"bench\"].Text.Matches(\"bench.*\")",
						Args: []ir.FilterExpr{
							{
								Line: 799,
								Op:   ir.FilterNotOp,
								Src:  "!m[\"bench\"].Text.Matches(\"Benchmark.*\")",
								Args: []ir.FilterExpr{{
									Line:  799,
									Op:    ir.FilterVarTextMatchesOp,
									Src:   "m[\"bench\"].Text.Matches(\"Benchmark.*\")",
									Value: "bench",
									Args:  []ir.FilterExpr{{Line: 799, Op: ir.FilterStringOp, Src: "\"Benchmark.*\"", Value: "Benchmark.*"}},
								}},
							},
							{
								Line: 800,
								Op:   ir.FilterNotOp,
								Src:  "!m[\"bench\"].Text.Matches(\"bench.*\")",
								Args: []ir.FilterExpr{{
									Line:  800,
									Op:    ir.FilterVarTextMatchesOp,
									Src:   "m[\"bench\"].Text.Matches(\"bench.*\")",
									Value: "bench",
									Args:  []ir.FilterExpr{{Line: 800, Op: ir.FilterStringOp, Src: "\"bench.*\"", Value: "bench.*"}},
								}},
							},
						},
					},
				},
				{
					Line:           803,
					SyntaxPatterns: []ir.PatternString{{Line: 803, Value: "func $test($_ *testing.T) { $*_ }"}},
					ReportTemplate: "function $test looks like a test helper, consider to change 1st param to 'tb testing.TB'",
					WhereExpr: ir.FilterExpr{
						Line:  804,
						Op:    ir.FilterVarTextMatchesOp,
						Src:   "m[\"test\"].Text.Matches(\"^test.*\")",
						Value: "test",
						Args:  []ir.FilterExpr{{Line: 804, Op: ir.FilterStringOp, Src: "\"^test.*\"", Value: "^test.*"}},
					},
				},
				{
					Line:           807,
					SyntaxPatterns: []ir.PatternString{{Line: 807, Value: "func $bench($_ *testing.B) { $*_ }"}},
					ReportTemplate: "function $bench looks like a benchmark helper, consider to change 1st param to 'tb testing.TB'",
					WhereExpr: ir.FilterExpr{
						Line:  808,
						Op:    ir.FilterVarTextMatchesOp,
						Src:   "m[\"bench\"].Text.Matches(\"^bench(mark)?.*\")",
						Value: "bench",
						Args:  []ir.FilterExpr{{Line: 808, Op: ir.FilterStringOp, Src: "\"^bench(mark)?.*\"", Value: "^bench(mark)?.*"}},
					},
				},
			},
		},
	},
}

