From 30fc940c70ee5ee27f0a455248735b8b57f34fb7 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 20 May 2016 17:26:24 -0700 Subject: [PATCH] go/types: don't drop type in n:1 var decl if one is given In n:1 variable declarations (multiple lhs variables with single multi-valued initialization expression) where also a variable type is provided, make sure that that type is assigned to all variables on the lhs before the init expression assignment is checked. Otherwise, (some) variables are assumed to take the type of the corresponding value of the multi-valued init expression. Fixes #15755. Change-Id: I969cb5a95c85e28dbb38abd7fa7df16ff5554c03 Reviewed-on: https://go-review.googlesource.com/23313 Reviewed-by: Alan Donovan --- src/go/types/decl.go | 19 +++++++++++++++++++ src/go/types/testdata/issues.src | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index f064f6856f..1ecfb35f60 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -141,6 +141,14 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { // determine type, if any if typ != nil { obj.typ = check.typ(typ) + // We cannot spread the type to all lhs variables if there + // are more than one since that would mark them as checked + // (see Checker.objDecl) and the assignment of init exprs, + // if any, would not be checked. + // + // TODO(gri) If we have no init expr, we should distribute + // a given type otherwise we need to re-evalate the type + // expr for each lhs variable, leading to duplicate work. } // check initialization @@ -173,6 +181,17 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { panic("inconsistent lhs") } } + + // We have multiple variables on the lhs and one init expr. + // Make sure all variables have been given the same type if + // one was specified, otherwise they assume the type of the + // init expression values (was issue #15755). + if typ != nil { + for _, lhs := range lhs { + lhs.typ = obj.typ + } + } + check.initVars(lhs, []ast.Expr{init}, token.NoPos) } diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src index 4fe0c62938..6579aa3b11 100644 --- a/src/go/types/testdata/issues.src +++ b/src/go/types/testdata/issues.src @@ -170,3 +170,19 @@ func issue14229() { _ = b % a ) } + +// Check that in a n:1 variable declaration with type and initialization +// expression the type is distributed to all variables of the lhs before +// the initialization expression assignment is checked. +func issue15755() { + // from issue + var i interface{} + type b bool + var x, y b = i.(b) + _ = x == y + + // related: we should see an error since the result of f1 is ([]int, int) + var u, v []int = f1 /* ERROR cannot use f1 */ () + _ = u + _ = v +} -- 2.48.1