if !ok {
base.FatalfAt(g.pos(name), "unknown name %v", name)
}
- obj := ir.CaptureName(g.pos(obj2), ir.CurFunc, g.obj(obj2))
+ obj := ir.CaptureName(g.pos(name), ir.CurFunc, g.obj(obj2))
if obj.Defn != nil && obj.Defn.Op() == ir.ONAME {
// If CaptureName created a closure variable, then transfer the
// type of the captured name to the new closure variable.
if stmt.Rhs == nil {
n = IncDec(g.pos(stmt), op, g.expr(stmt.Lhs))
} else {
- n = ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs))
+ // Eval rhs before lhs, for compatibility with noder1
+ rhs := g.expr(stmt.Rhs)
+ lhs := g.expr(stmt.Lhs)
+ n = ir.NewAssignOpStmt(g.pos(stmt), op, lhs, rhs)
}
if n.X.Typecheck() == 3 {
n.SetTypecheck(3)
return n
}
- names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def)
+ // Eval rhs before lhs, for compatibility with noder1
rhs := g.exprList(stmt.Rhs)
+ names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def)
// We must delay transforming the assign statement if any of the
// lhs or rhs nodes are also delayed, since transformAssign needs
key, value := unpackTwo(lhs)
n := ir.NewRangeStmt(g.pos(r), key, value, g.expr(r.X), g.blockStmt(stmt.Body))
n.Def = initDefn(n, names)
+ if key != nil {
+ transformCheckAssign(n, key)
+ }
+ if value != nil {
+ transformCheckAssign(n, value)
+ }
return n
}
// recursive types have been fully constructed before we call CheckSize.
if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() {
types.CheckSize(res)
+ if res.IsPtr() {
+ // Pointers always have their size set, even though their element
+ // may not have its size set.
+ types.CheckSize(res.Elem())
+ }
}
return res
}
case *syntax.CallExpr:
tv := g.info.Types[n.Fun]
if tv.IsBuiltin() {
- switch builtin := n.Fun.(type) {
+ fun := n.Fun
+ for {
+ builtin, ok := fun.(*syntax.ParenExpr)
+ if !ok {
+ break
+ }
+ fun = builtin.X
+ }
+ switch builtin := fun.(type) {
case *syntax.Name:
g.validateBuiltin(builtin.Value, n)
case *syntax.SelectorExpr:
// (somewhat closely following the structure of exprfmt in fmt.go)
case ir.ONIL:
n := n.(*ir.NilExpr)
- if !n.Type().HasNil() {
+ // If n is a typeparam, it will have already been checked
+ // for proper use by the types2 typechecker.
+ if !n.Type().IsTypeParam() && !n.Type().HasNil() {
base.Fatalf("unexpected type for nil: %v", n.Type())
}
w.op(ir.ONIL)
)
var g3Failures = setOf(
- "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault)
- "fixedbugs/issue17270.go", // ICE in irgen
- "fixedbugs/issue20174.go", // ICE due to width not calculated (probably irgen's fault)
- "fixedbugs/issue20250.go", // correct diagnostics, but different lines (probably irgen's fault)
- "fixedbugs/issue37837.go", // ICE due to width not calculated
- "fixedbugs/issue9691.go", // "cannot assign to int(.autotmp_4)" (probably irgen's fault)
+ "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault)
"typeparam/nested.go", // -G=3 doesn't support function-local types with generics
--- /dev/null
+// compile -G=3
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// copied from cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go
+
+package p
+
+func _[T interface{~map[string]int}](x T) {
+ _ = x == nil
+}
+
+// simplified test case from issue
+
+type PathParamsConstraint interface {
+ ~map[string]string | ~[]struct{key, value string}
+}
+
+type PathParams[T PathParamsConstraint] struct {
+ t T
+}
+
+func (pp *PathParams[T]) IsNil() bool {
+ return pp.t == nil // this must succeed
+}