mirror of
https://github.com/golang/go
synced 2024-11-26 18:06:55 -07:00
77a2113925
Consider an interface value i of type I and concrete value c of type C. Prior to this CL, i==c was evaluated as I(c) == i Evaluating I(c) can allocate. This CL changes the evaluation of i==c to x, ok := i.(C); ok && x == c The new generated code is shorter and does not allocate directly. If C is small, as it is in every instance in the stdlib, the new code also uses less stack space and makes one runtime call instead of two. If C is very large, the original implementation is used. The cutoff for "very large" is 1<<16, following the stack vs heap cutoff used elsewhere. This kind of comparison occurs in 38 places in the stdlib, mostly in the net and os packages. benchmark old ns/op new ns/op delta BenchmarkEqEfaceConcrete 29.5 7.92 -73.15% BenchmarkEqIfaceConcrete 32.1 7.90 -75.39% BenchmarkNeEfaceConcrete 29.9 7.90 -73.58% BenchmarkNeIfaceConcrete 35.9 7.90 -77.99% Fixes #9370. Change-Id: I7c4555950bcd6406ee5c613be1f2128da2c9a2b7 Reviewed-on: https://go-review.googlesource.com/2096 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
128 lines
3.9 KiB
Go
128 lines
3.9 KiB
Go
// errorcheck
|
|
|
|
// 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.
|
|
|
|
// Verify that concrete/interface comparisons are
|
|
// typechecked correctly by the compiler.
|
|
|
|
package main
|
|
|
|
type I interface {
|
|
Method()
|
|
}
|
|
|
|
type C int
|
|
|
|
func (C) Method() {}
|
|
|
|
type G func()
|
|
|
|
func (G) Method() {}
|
|
|
|
var (
|
|
e interface{}
|
|
i I
|
|
c C
|
|
n int
|
|
f func()
|
|
g G
|
|
)
|
|
|
|
var (
|
|
_ = e == c
|
|
_ = e != c
|
|
_ = e >= c // ERROR "invalid operation.*not defined"
|
|
_ = c == e
|
|
_ = c != e
|
|
_ = c >= e // ERROR "invalid operation.*not defined"
|
|
|
|
_ = i == c
|
|
_ = i != c
|
|
_ = i >= c // ERROR "invalid operation.*not defined"
|
|
_ = c == i
|
|
_ = c != i
|
|
_ = c >= i // ERROR "invalid operation.*not defined"
|
|
|
|
_ = e == n
|
|
_ = e != n
|
|
_ = e >= n // ERROR "invalid operation.*not defined"
|
|
_ = n == e
|
|
_ = n != e
|
|
_ = n >= e // ERROR "invalid operation.*not defined"
|
|
|
|
// i and n are not assignable to each other
|
|
_ = i == n // ERROR "invalid operation.*mismatched types"
|
|
_ = i != n // ERROR "invalid operation.*mismatched types"
|
|
_ = i >= n // ERROR "invalid operation.*mismatched types"
|
|
_ = n == i // ERROR "invalid operation.*mismatched types"
|
|
_ = n != i // ERROR "invalid operation.*mismatched types"
|
|
_ = n >= i // ERROR "invalid operation.*mismatched types"
|
|
|
|
_ = e == 1
|
|
_ = e != 1
|
|
_ = e >= 1 // ERROR "invalid operation.*not defined"
|
|
_ = 1 == e
|
|
_ = 1 != e
|
|
_ = 1 >= e // ERROR "invalid operation.*not defined"
|
|
|
|
_ = i == 1 // ERROR "invalid operation.*mismatched types"
|
|
_ = i != 1 // ERROR "invalid operation.*mismatched types"
|
|
_ = i >= 1 // ERROR "invalid operation.*mismatched types"
|
|
_ = 1 == i // ERROR "invalid operation.*mismatched types"
|
|
_ = 1 != i // ERROR "invalid operation.*mismatched types"
|
|
_ = 1 >= i // ERROR "invalid operation.*mismatched types"
|
|
|
|
_ = e == f // ERROR "invalid operation.*not defined"
|
|
_ = e != f // ERROR "invalid operation.*not defined"
|
|
_ = e >= f // ERROR "invalid operation.*not defined"
|
|
_ = f == e // ERROR "invalid operation.*not defined"
|
|
_ = f != e // ERROR "invalid operation.*not defined"
|
|
_ = f >= e // ERROR "invalid operation.*not defined"
|
|
|
|
_ = i == f // ERROR "invalid operation.*mismatched types"
|
|
_ = i != f // ERROR "invalid operation.*mismatched types"
|
|
_ = i >= f // ERROR "invalid operation.*mismatched types"
|
|
_ = f == i // ERROR "invalid operation.*mismatched types"
|
|
_ = f != i // ERROR "invalid operation.*mismatched types"
|
|
_ = f >= i // ERROR "invalid operation.*mismatched types"
|
|
|
|
_ = e == g // ERROR "invalid operation.*not defined"
|
|
_ = e != g // ERROR "invalid operation.*not defined"
|
|
_ = e >= g // ERROR "invalid operation.*not defined"
|
|
_ = g == e // ERROR "invalid operation.*not defined"
|
|
_ = g != e // ERROR "invalid operation.*not defined"
|
|
_ = g >= e // ERROR "invalid operation.*not defined"
|
|
|
|
_ = i == g // ERROR "invalid operation.*not defined"
|
|
_ = i != g // ERROR "invalid operation.*not defined"
|
|
_ = i >= g // ERROR "invalid operation.*not defined"
|
|
_ = g == i // ERROR "invalid operation.*not defined"
|
|
_ = g != i // ERROR "invalid operation.*not defined"
|
|
_ = g >= i // ERROR "invalid operation.*not defined"
|
|
|
|
_ = _ == e // ERROR "cannot use _ as value"
|
|
_ = _ == i // ERROR "cannot use _ as value"
|
|
_ = _ == c // ERROR "cannot use _ as value"
|
|
_ = _ == n // ERROR "cannot use _ as value"
|
|
_ = _ == f // ERROR "cannot use _ as value"
|
|
_ = _ == g // ERROR "cannot use _ as value"
|
|
|
|
_ = e == _ // ERROR "cannot use _ as value"
|
|
_ = i == _ // ERROR "cannot use _ as value"
|
|
_ = c == _ // ERROR "cannot use _ as value"
|
|
_ = n == _ // ERROR "cannot use _ as value"
|
|
_ = f == _ // ERROR "cannot use _ as value"
|
|
_ = g == _ // ERROR "cannot use _ as value"
|
|
|
|
_ = _ == _ // ERROR "cannot use _ as value"
|
|
|
|
_ = e ^ c // ERROR "invalid operation.*mismatched types"
|
|
_ = c ^ e // ERROR "invalid operation.*mismatched types"
|
|
_ = 1 ^ e // ERROR "invalid operation.*mismatched types"
|
|
_ = e ^ 1 // ERROR "invalid operation.*mismatched types"
|
|
_ = 1 ^ c
|
|
_ = c ^ 1
|
|
)
|