blob: 5237c062c750de128ceec9892e9aec153e6a6e6b [file] [log] [blame]
// Copyright 2022 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 main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"go/types"
"log"
"golang.org/x/exp/typeparams"
)
const src = `
//!+input
package p
type Pair[L, R comparable] struct {
left L
right R
}
func (p Pair[L, _]) Left() L {
return p.left
}
func (p Pair[_, R]) Right() R {
return p.right
}
// M does not use type parameters, and therefore implements the Mer interface.
func (p Pair[_, _]) M() int { return 0 }
type LeftRighter[L, R comparable] interface {
Left() L
Right() R
}
type Mer interface {
M() int
}
// F and G have identical signatures "modulo renaming", H does not.
func F[P any](P) int { return 0 }
func G[Q any](Q) int { return 1 }
func H[R ~int](R) int { return 2 }
//!-input
`
// !+ordinary
func OrdinaryPredicates(pkg *types.Package) {
var (
Pair = pkg.Scope().Lookup("Pair").Type()
LeftRighter = pkg.Scope().Lookup("LeftRighter").Type()
Mer = pkg.Scope().Lookup("Mer").Type()
F = pkg.Scope().Lookup("F").Type()
G = pkg.Scope().Lookup("G").Type()
H = pkg.Scope().Lookup("H").Type()
)
fmt.Println("AssignableTo(Pair, LeftRighter)", types.AssignableTo(Pair, LeftRighter))
fmt.Println("AssignableTo(Pair, Mer): ", types.AssignableTo(Pair, Mer))
fmt.Println("Identical(F, G)", types.Identical(F, G))
fmt.Println("Identical(F, H)", types.Identical(F, H))
}
//!-ordinary
/*
//!+ordinaryoutput
AssignableTo(Pair, LeftRighter) false
AssignableTo(Pair, Mer): true
Identical(F, G) true
Identical(F, H) false
//!-ordinaryoutput
*/
// !+generic
func GenericPredicates(pkg *types.Package) {
var (
Pair = pkg.Scope().Lookup("Pair").Type()
LeftRighter = pkg.Scope().Lookup("LeftRighter").Type()
)
fmt.Println("GenericAssignableTo(Pair, LeftRighter)", typeparams.GenericAssignableTo(nil, Pair, LeftRighter))
}
//!-generic
/*
//!+genericoutput
GenericAssignableTo(Pair, LeftRighter) true
//!-genericoutput
*/
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", src, 0)
if err != nil {
log.Fatal(err)
}
conf := types.Config{}
pkg, err := conf.Check("p", fset, []*ast.File{f}, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("=== ordinary ===")
OrdinaryPredicates(pkg)
fmt.Println("=== generic ===")
GenericPredicates(pkg)
}