// Copyright 2014 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.

package issues

import "fmt"

func issue7035() {
	type T struct{ X int }
	_ = func() {
		fmt.Println() // must refer to imported fmt rather than the fmt below
	}
	fmt := new(T)
	_ = fmt.X
}

func issue8066() {
	const (
		_ = float32(340282356779733661637539395458142568447)
		_ = float32(340282356779733661637539395458142568448 /* ERROR cannot convert */ )
	)
}

// Check that a missing identifier doesn't lead to a spurious error cascade.
func issue8799a() {
	x, ok := missing /* ERROR undeclared */ ()
	_ = !ok
	_ = x
}

func issue8799b(x int, ok bool) {
	x, ok = missing /* ERROR undeclared */ ()
	_ = !ok
	_ = x
}

func issue9182() {
	type Point C /* ERROR undeclared */ .Point
	// no error for composite literal based on unknown type
	_ = Point{x: 1, y: 2}
}

func f0() (a []int)         { return }
func f1() (a []int, b int)  { return }
func f2() (a, b []int)      { return }

func append_([]int, ...int) {}

func issue9473(a []int, b ...int) {
	// variadic builtin function
	_ = append(f0())
	_ = append(f0(), f0()...)
	_ = append(f1())
	_ = append(f2 /* ERROR cannot use .* in argument */ ())
	_ = append(f2()... /* ERROR cannot use ... */ )
	_ = append(f0(), f1 /* ERROR 2-valued f1 */ ())
	_ = append(f0(), f2 /* ERROR 2-valued f2 */ ())
	_ = append(f0(), f1 /* ERROR 2-valued f1 */ ()...)
	_ = append(f0(), f2 /* ERROR 2-valued f2 */ ()...)

	// variadic user-defined function
	append_(f0())
	append_(f0(), f0()...)
	append_(f1())
	append_(f2 /* ERROR cannot use .* in argument */ ())
	append_(f2()... /* ERROR cannot use ... */ )
	append_(f0(), f1 /* ERROR 2-valued f1 */ ())
	append_(f0(), f2 /* ERROR 2-valued f2 */ ())
	append_(f0(), f1 /* ERROR 2-valued f1 */ ()...)
	append_(f0(), f2 /* ERROR 2-valued f2 */ ()...)
}

// Check that embedding a non-interface type in an interface results in a good error message.
func issue10979() {
	type _ interface {
		int /* ERROR int is not an interface */
	}
	type T struct{}
	type _ interface {
		T /* ERROR T is not an interface */
	}
	type _ interface {
		nosuchtype /* ERROR undeclared name: nosuchtype */
	}
	type _ interface {
		fmt /* ERROR Nosuchtype not declared by package fmt */ .Nosuchtype
	}
	type _ interface {
		nosuchpkg /* ERROR undeclared name: nosuchpkg */ .Nosuchtype
	}
	type I interface {
		I /* ERROR I\.m \(value of type func\(I\)\) is not a type */ .m
		m()
	}
}

// issue11347
// These should not crash.
var a1, b1 /* ERROR cycle */ , c1 /* ERROR cycle */ b1 = 0 > 0<<""[""[c1]]>c1
var a2, b2 /* ERROR cycle */ = 0 /* ERROR mismatch */ /* ERROR mismatch */ > 0<<""[b2]
var a3, b3 /* ERROR cycle */ = int /* ERROR mismatch */ /* ERROR mismatch */ (1<<""[b3])

// issue10260
// Check that error messages explain reason for interface assignment failures.
type (
	I0 interface{}
	I1 interface{ foo() }
	I2 interface{ foo(x int) }
	T0 struct{}
	T1 struct{}
	T2 struct{}
)

func (*T1) foo() {}
func (*T2) foo(x int) {}

func issue10260() {
	var (
		i0 I0
		i1 I1
		i2 I2
		t0 *T0
		t1 *T1
		t2 *T2
	)
	i1 = i0 /* ERROR cannot use .* missing method foo */
	i1 = t0 /* ERROR cannot use .* missing method foo */
	i1 = i2 /* ERROR cannot use .* wrong type for method foo */
	i1 = t2 /* ERROR cannot use .* wrong type for method foo */
	i2 = i1 /* ERROR cannot use .* wrong type for method foo */
	i2 = t1 /* ERROR cannot use .* wrong type for method foo */

	_ = func() I1 { return i0 /* ERROR cannot use .* missing method foo */ }
	_ = func() I1 { return t0 /* ERROR cannot use .* missing method foo */ }
	_ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
	_ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
	_ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
	_ = func() I2 { return t1 /* ERROR cannot use .* wrong type for method foo */ }

	// a few more - less exhaustive now

	f := func(I1, I2){}
	f(i0 /* ERROR cannot use .* missing method foo */ , i1 /* ERROR cannot use .* wrong type for method foo */)

	_ = [...]I1{i0 /* ERROR cannot use .* missing method foo */ }
	_ = [...]I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
	_ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
	_ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
	_ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
	_ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }

	make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */
	make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */
}

// Check that constants representable as integers are in integer form
// before being used in operations that are only defined on integers.
func issue14229() {
	// from the issue
	const _ = int64(-1<<63) % 1e6

	// related
	const (
		a int = 3
		b = 4.0
		_ = a / b
		_ = a % b
		_ = b / a
		_ = 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
}
