package cases func do(args ...int) error { return nil } var errState error // Safe: both names are fresh in the block that would receive the hoisted statement. func freshNames() { v, err := multi( // want `init clause spans 3 lines` 1, ) if err != nil { _ = v } } // Safe: "_" declares nothing and err is fresh. func blankAndFresh() { _, err := multi( // want `init clause spans 3 lines` 1, ) if err != nil { _ = err } } // Safe: "=" assigns to an existing variable; it declares nothing at all. func plainAssign() error { var err error err = do( // want `init clause spans 3 lines` 1, ) if err != nil { return err } return nil } // Unsafe: err already exists in the enclosing block. Hoisting the ":=" would // assign to that err rather than declaring a new one, so the returned error // would silently change. func shadowsExistingLocal() error { v, err := multi(1) if err != nil { return err } _ = v if v2, err := multi( // want `init clause spans 3 lines` 2, ); err != nil { _ = v2 } return err } // Unsafe: the same names are redeclared later in this block, so hoisting turns // the later ":=" into "no new variables on left side of :=". func declaredLaterInBlock() { if v, err := multi( // want `init clause spans 3 lines` 1, ); err != nil { _ = v } v, err := multi(2) _, _ = v, err } // Unsafe: err is a parameter, so hoisting would rebind it for the rest of the body. func shadowsParam(err error) { if v, err := multi( // want `init clause spans 3 lines` 1, ); err != nil { _ = v } } // Conservatively refused: shadowing a package-level name. Nothing reads errState // after the if here, so this one would in fact be safe -- the check does not try // to prove that. func shadowsPackageLevel() { if v, errState := multi( // want `init clause spans 3 lines` 1, ); errState != nil { _ = v } }