]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] merge dev.regabi (618e3c1) into dev.typeparams
authorRob Findley <rfindley@google.com>
Tue, 9 Feb 2021 02:22:01 +0000 (21:22 -0500)
committerRob Findley <rfindley@google.com>
Tue, 9 Feb 2021 03:19:27 +0000 (22:19 -0500)
This involved a couple non-trivial fixes in go/types:
 - move the check for main function signature to resolver.go, to be
   consistent with init. Also, update uses of _InvalidInitSig to
   _InvalidInitDecl, consistent with what we decided for dev.regabi.
 - Update some tests in api_test.go which newly fail after CL 289715
   (fixing reporting of untyped nil) In all cases but one, these updates
   were consistent with types2. However, in one case types2 seems to be
   able to resolve more type information than go/types for a broken
   package. I left a TODO to investigate this further.

Change-Id: I8244b7c81654194edd5af8de689a13c262117dff

1  2 
src/go/types/api_test.go
src/go/types/assignments.go
src/go/types/conversions.go
src/go/types/decl.go
src/go/types/errorcodes.go
src/go/types/expr.go
src/go/types/resolver.go

index 014cd5282e6a1f8c21b91b2108a3d8881c9aa102,dde451ee3cf76e70a96f892c9e0049a46726bfc0..3ea14c9316b1c92a9a14ba72beb0779add688e7e
@@@ -281,28 -304,12 +317,30 @@@ func TestTypesInfo(t *testing.T) 
                },
  
                // tests for broken code that doesn't parse or type-check
-               {`package x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
-               {`package x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
-               {`package x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a, f: b,}}`, `b`, `string`},
-               {`package x3; var x = panic("");`, `panic`, `func(interface{})`},
+               {broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
+               {broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
+               {broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`},
+               {broken + `x3; var x = panic("");`, `panic`, `func(interface{})`},
                {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
-               {`package x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
+               {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
 +
 +              // parameterized functions
 +              {genericPkg + `p0; func f[T any](T); var _ = f(int)`, `f`, `func[T₁ any](T₁)`},
 +              {genericPkg + `p1; func f[T any](T); var _ = f(int)`, `f(int)`, `func(int)`},
-               {genericPkg + `p2; func f[T any](T); var _ = f(42)`, `f`, `func[T₁ any](T₁)`},
-               {genericPkg + `p2; func f[T any](T); var _ = f(42)`, `f(42)`, `()`},
++              {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ any](T₁)`},
++              {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`},
 +
 +              // type parameters
 +              {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t
 +              {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P₁ any]`},
 +              {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P₁ interface{}]`},
 +              {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P₁, Q₂ interface{}]`},
-               {genericPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `generic_t4.t[P₁, Q₂ interface{m()}]`},
++
++              // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here
++              {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`},
 +
 +              // instantiated types must be sanitized
 +              {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`},
        }
  
        for _, test := range tests {
Simple merge
Simple merge
index bd2c5466617a78f747f24ce6e84a76b0b45d4270,571e172351befb77219e544052cd7c00d6d5fb79..f2e68bbd5c3fe38e08f978b4e7f74b9bd50e6573
@@@ -511,9 -504,23 +511,23 @@@ func (check *Checker) constDecl(obj *Co
  func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
        assert(obj.typ == nil)
  
+       // If we have undefined variable types due to errors,
+       // mark variables as used to avoid follow-on errors.
+       // Matches compiler behavior.
+       defer func() {
+               if obj.typ == Typ[Invalid] {
+                       obj.used = true
+               }
+               for _, lhs := range lhs {
+                       if lhs.typ == Typ[Invalid] {
+                               lhs.used = true
+                       }
+               }
+       }()
        // determine type, if any
        if typ != nil {
 -              obj.typ = check.typ(typ)
 +              obj.typ = check.varType(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,
Simple merge
index 1deda99aaff30c57b73ecdc146d798ba65163ee9,f7fb0caeddb0e39bb5d0d2538425666cce6b0572..0d9540245502a26b80798eb28787aa631748d250
@@@ -584,23 -577,12 +584,24 @@@ func (check *Checker) implicitTypeAndVa
                case UntypedNil:
                        // Unsafe.Pointer is a basic type that includes nil.
                        if !hasNil(target) {
 -                              return nil
 +                              return nil, nil, _InvalidUntypedConversion
                        }
-                       // TODO(rFindley) return UntypedNil here (golang.org/issues/13061).
+                       // Preserve the type of nil as UntypedNil: see #13061.
 -                      return Typ[UntypedNil]
++                      return Typ[UntypedNil], nil, 0
                default:
 -                      return nil
 +                      return nil, nil, _InvalidUntypedConversion
 +              }
 +      case *Sum:
 +              ok := t.is(func(t Type) bool {
 +                      target, _, _ := check.implicitTypeAndValue(x, t)
 +                      return target != nil
 +              })
 +              if !ok {
 +                      return nil, nil, _InvalidUntypedConversion
 +              }
 +              // keep nil untyped (was bug #39755)
 +              if x.isNil() {
 +                      return Typ[UntypedNil], nil, 0
                }
        case *Interface:
                // Values must have concrete dynamic types. If the value is nil,
index 639ed121175cd51b5f8177c6a144e977fc1a4a18,b637f8b8cacf75793f564660081bc0c741daab1f..4f09237692837c3fb81275e7e9149feb0653bede
@@@ -373,20 -366,9 +373,26 @@@ func (check *Checker) collectObjects() 
                                info := &declInfo{file: fileScope, fdecl: d.decl}
                                name := d.decl.Name.Name
                                obj := NewFunc(d.decl.Name.Pos(), pkg, name, nil)
 -                              if d.decl.Recv == nil {
 +                              if !d.decl.IsMethod() {
                                        // regular function
-                                       if name == "init" {
 +                                      if d.decl.Recv != nil {
 +                                              check.error(d.decl.Recv, _BadRecv, "method is missing receiver")
 +                                              // treat as function
 +                                      }
-                                                       check.softErrorf(d.decl.Type.TParams, _InvalidInitSig, "func init must have no type parameters")
++                                      if name == "init" || (name == "main" && check.pkg.name == "main") {
++                                              code := _InvalidInitDecl
++                                              if name == "main" {
++                                                      code = _InvalidMainDecl
++                                              }
 +                                              if d.decl.Type.TParams != nil {
-                                                       check.softErrorf(d.decl, _InvalidInitSig, "func init must have no arguments and no return values")
++                                                      check.softErrorf(d.decl.Type.TParams, code, "func %s must have no type parameters", name)
 +                                              }
 +                                              if t := d.decl.Type; t.Params.NumFields() != 0 || t.Results != nil {
 +                                                      // TODO(rFindley) Should this be a hard error?
++                                                      check.softErrorf(d.decl, code, "func %s must have no arguments and no return values", name)
 +                                              }
++                                      }
+                                       if name == "init" {
                                                // don't declare init functions in the package scope - they are invisible
                                                obj.parent = pkg.scope
                                                check.recordDef(d.decl.Name, obj)