Merge pull request #61 from max-schaefer/better-method-sets

Reformulate `Method.hasQualifiedName` in terms of method sets
This commit is contained in:
Sauyon Lee
2020-03-17 07:46:19 -04:00
committed by GitHub
20 changed files with 289 additions and 23 deletions

View File

@@ -427,21 +427,40 @@ class Method extends Function {
)
}
/**
* Holds if this method has name `m` and its receiver base type has qualified name `tp`.
*/
override predicate hasQualifiedName(string tp, string m) {
tp = getReceiverBaseType().getQualifiedName() and
m = getName()
/** Holds if this method has name `m` and belongs to the method set of type `tp` or `*tp`. */
private predicate isIn(NamedType tp, string m) {
this = tp.getMethod(m) or
this = tp.getPointerType().getMethod(m)
}
/**
* Holds if this method has name `m` and its receiver base type is declared in package `pkg` and
* has name `tp`.
* Holds if this method has name `m` and belongs to the method set of a type `T` or `*T` where
* `T` has qualified name `tp`.
*
* Note that `meth.hasQualifiedName(tp, m)` is almost, but not quite, equivalent to
* `exists(Type t | tp = t.getQualifiedName() and meth = t.getMethod(m))`: the latter
* distinguishes between the method sets of `T` and `*T`, while the former does not.
*/
override predicate hasQualifiedName(string tp, string m) {
exists(NamedType t |
this.isIn(t, m) and
tp = t.getQualifiedName()
)
}
/**
* Holds if this method has name `m` and belongs to the method set of a type `T` or `*T` where
* `T` is declared in package `pkg` and has name `tp`.
*
* Note that `meth.hasQualifiedName(pkg, tp, m)` is almost, but not quite, equivalent to
* `exists(Type t | t.hasQualifiedName(pkg, tp) and meth = t.getMethod(m))`: the latter
* distinguishes between the method sets of `T` and `*T`, while the former does not.
*/
predicate hasQualifiedName(string pkg, string tp, string m) {
getReceiverBaseType().hasQualifiedName(pkg, tp) and
m = getName()
exists(NamedType t |
this.isIn(t, m) and
t.hasQualifiedName(pkg, tp)
)
}
/**

View File

@@ -40,6 +40,9 @@ class Type extends @type {
/**
* Gets the method `m` belonging to the method set of this type, if any.
*
* Note that this predicate never has a result for struct types. Methods are associated
* with the corresponding named type instead.
*/
Method getMethod(string m) {
result.getReceiverType() = this and
@@ -441,11 +444,29 @@ class PointerType extends @pointertype, CompositeType {
override Package getPackage() { result = this.getBaseType().getPackage() }
override Method getMethod(string m) {
// https://golang.org/ref/spec#Method_sets: "the method set of a pointer type *T is
// the set of all methods declared with receiver *T or T"
result = CompositeType.super.getMethod(m)
or
// https://golang.org/ref/spec#Method_sets: "the method set of a pointer type *T is
// the set of all methods declared with receiver *T or T"
result = getBaseType().getMethod(m)
or
// promoted methods from embedded types
exists(StructType s, Type embedded |
s = getBaseType().(NamedType).getUnderlyingType() and
s.hasOwnField(_, _, embedded, true) and
// ensure that `m` can be promoted
not s.hasOwnField(_, m, _, _) and
not exists(Method m2 | m2.getReceiverBaseType() = getBaseType() and m2.getName() = m)
|
result = embedded.getMethod(m)
or
// If S contains an embedded field T, the method set of *S includes promoted methods with receiver T or T*
not embedded instanceof PointerType and
result = embedded.getPointerType().getMethod(m)
or
// If S contains an embedded field *T, the method set of *S includes promoted methods with receiver T or *T
result = embedded.(PointerType).getBaseType().getMethod(m)
)
}
override string pp() { result = "* " + getBaseType().pp() }
@@ -566,12 +587,6 @@ class SendRecvChanType extends @sendrcvchantype, ChanType {
/** A named type. */
class NamedType extends @namedtype, CompositeType {
/** Gets a method with name `m` defined on this type. */
MethodDecl getMethodDecl(string m) {
result.getName() = m and
this = result.getReceiverBaseType()
}
/** Gets the type which this type is defined to be. */
Type getBaseType() { underlying_type(this, result) }
@@ -580,6 +595,21 @@ class NamedType extends @namedtype, CompositeType {
or
methodhosts(result, this) and
result.getName() = m
or
// handle promoted methods
exists(StructType s, Type embedded |
s = getBaseType() and
s.hasOwnField(_, _, embedded, true) and
// ensure `m` can be promoted
not s.hasOwnField(_, m, _, _) and
not exists(Method m2 | m2.getReceiverType() = this and m2.getName() = m)
|
// If S contains an embedded field T, the method set of S includes promoted methods with receiver T
result = embedded.getMethod(m)
or
// If S contains an embedded field *T, the method set of S includes promoted methods with receiver T or *T
result = embedded.(PointerType).getBaseType().getMethod(m)
)
}
override Type getUnderlyingType() { result = getBaseType().getUnderlyingType() }

View File

@@ -1,3 +1,9 @@
| pkg1/embedding.go:19:23:19:26 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/embedding.go:22:27:22:30 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/embedding.go:25:24:25:31 | embedder | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/embedding.go:28:24:28:31 | embedder | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/embedding.go:36:2:36:5 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/embedding.go:37:2:37:2 | f | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/tst.go:4:2:4:2 | f | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/tst.go:5:2:5:4 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/tst.go:6:2:6:4 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |

View File

@@ -1,3 +1,13 @@
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | base |
| pkg1/embedding.go:22:27:22:30 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder | base |
| pkg1/embedding.go:25:24:25:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | embedder |
| pkg1/embedding.go:25:24:25:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | embedder |
| pkg1/embedding.go:28:24:28:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | embedder |
| pkg1/embedding.go:28:24:28:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | embedder |
| pkg1/embedding.go:36:2:36:5 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder4 | base |
| pkg1/embedding.go:37:2:37:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder4 | f |
| pkg1/tst.go:4:2:4:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | f |
| pkg1/tst.go:5:2:5:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | Foo |
| pkg1/tst.go:6:2:6:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | Bar |

View File

@@ -1,3 +1,13 @@
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | base |
| pkg1/embedding.go:22:27:22:30 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | ptrembedder | base |
| pkg1/embedding.go:25:24:25:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | embedder |
| pkg1/embedding.go:25:24:25:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | embedder |
| pkg1/embedding.go:28:24:28:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | embedder |
| pkg1/embedding.go:28:24:28:31 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | embedder |
| pkg1/embedding.go:36:2:36:5 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder4 | base |
| pkg1/embedding.go:37:2:37:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder4 | f |
| pkg1/tst.go:4:2:4:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | f |
| pkg1/tst.go:5:2:5:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | Foo |
| pkg1/tst.go:6:2:6:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | Bar |

View File

@@ -1,4 +1,10 @@
| * Foo | 1 |
| * base | 2 |
| * embedder | 2 |
| * embedder2 | 2 |
| * embedder3 | 2 |
| * embedder4 | 1 |
| * ptrembedder | 2 |
| A | 1 |
| A2 | 1 |
| AC | 3 |
@@ -7,3 +13,11 @@
| B | 2 |
| C | 2 |
| Foo | 1 |
| T | 1 |
| T3 | 1 |
| T4 | 1 |
| base | 1 |
| embedder | 1 |
| embedder2 | 1 |
| embedder3 | 1 |
| ptrembedder | 2 |

View File

@@ -1 +0,0 @@
| Foo | half | pkg1/tst.go:33:1:35:1 | function declaration |

View File

@@ -1,4 +0,0 @@
import go
from NamedType t, string m
select t, m, t.getMethodDecl(m)

View File

@@ -13,3 +13,8 @@
| T | half | func() Foo |
| T3 | half | func() Foo |
| T4 | half | func() Foo |
| embedder | f | func() int |
| embedder2 | f | func() int |
| embedder3 | f | func() int |
| ptrembedder | f | func() int |
| ptrembedder | g | func() int |

View File

@@ -0,0 +1,27 @@
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | ptrembedder | f |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder4 | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | ptrembedder | g |
| pkg1/embedding.go:30:18:30:18 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | f |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | A | m |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | m |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AEmbedded | m |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AExtended | m |
| pkg1/interfaces.go:8:2:8:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | B | m |
| pkg1/interfaces.go:9:2:9:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | B | n |
| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | n |
| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | C | n |
| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | o |
| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | C | o |
| pkg1/interfaces.go:28:2:28:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AExtended | n |
| pkg1/interfaces.go:32:2:32:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | A2 | m |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | half |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | half |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | half |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | half |

View File

@@ -0,0 +1,5 @@
import go
from Method meth, string pkg, string tp, string m
where meth.hasQualifiedName(pkg, tp, m)
select meth.getDeclaration(), pkg, tp, m

View File

@@ -0,0 +1,27 @@
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | ptrembedder | f |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder4 | g |
| pkg1/embedding.go:14:14:14:14 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | ptrembedder | g |
| pkg1/embedding.go:30:18:30:18 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | f |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | A | m |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | m |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AEmbedded | m |
| pkg1/interfaces.go:4:2:4:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AExtended | m |
| pkg1/interfaces.go:8:2:8:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | B | m |
| pkg1/interfaces.go:9:2:9:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | B | n |
| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | n |
| pkg1/interfaces.go:13:2:13:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | C | n |
| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AC | o |
| pkg1/interfaces.go:14:2:14:2 | o | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | C | o |
| pkg1/interfaces.go:28:2:28:2 | n | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | AExtended | n |
| pkg1/interfaces.go:32:2:32:2 | m | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | A2 | m |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | half |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | half |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | half |
| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | half |

View File

@@ -0,0 +1,5 @@
import go
from Method meth, string pkg, string tp, string m
where meth.hasQualifiedName(pkg, tp, m)
select meth.getDeclaration(), pkg, tp, m

View File

@@ -1,4 +1,15 @@
| * Foo | half | pkg1/tst.go:33:16:33:19 | half |
| * base | f | pkg1/embedding.go:10:13:10:13 | f |
| * base | g | pkg1/embedding.go:14:14:14:14 | g |
| * embedder | f | pkg1/embedding.go:10:13:10:13 | f |
| * embedder | g | pkg1/embedding.go:14:14:14:14 | g |
| * embedder2 | f | pkg1/embedding.go:10:13:10:13 | f |
| * embedder2 | g | pkg1/embedding.go:14:14:14:14 | g |
| * embedder3 | f | pkg1/embedding.go:30:18:30:18 | f |
| * embedder3 | g | pkg1/embedding.go:14:14:14:14 | g |
| * embedder4 | g | pkg1/embedding.go:14:14:14:14 | g |
| * ptrembedder | f | pkg1/embedding.go:10:13:10:13 | f |
| * ptrembedder | g | pkg1/embedding.go:14:14:14:14 | g |
| A | m | pkg1/interfaces.go:4:2:4:2 | m |
| A2 | m | pkg1/interfaces.go:32:2:32:2 | m |
| AC | m | pkg1/interfaces.go:4:2:4:2 | m |
@@ -12,3 +23,12 @@
| C | n | pkg1/interfaces.go:13:2:13:2 | n |
| C | o | pkg1/interfaces.go:14:2:14:2 | o |
| Foo | half | pkg1/tst.go:33:16:33:19 | half |
| T | half | pkg1/tst.go:33:16:33:19 | half |
| T3 | half | pkg1/tst.go:33:16:33:19 | half |
| T4 | half | pkg1/tst.go:33:16:33:19 | half |
| base | f | pkg1/embedding.go:10:13:10:13 | f |
| embedder | f | pkg1/embedding.go:10:13:10:13 | f |
| embedder2 | f | pkg1/embedding.go:10:13:10:13 | f |
| embedder3 | f | pkg1/embedding.go:30:18:30:18 | f |
| ptrembedder | f | pkg1/embedding.go:10:13:10:13 | f |
| ptrembedder | g | pkg1/embedding.go:14:14:14:14 | g |

View File

@@ -13,3 +13,9 @@
| T2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 |
| T3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 |
| T4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 |
| base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.base |
| embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder |
| embedder2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 |
| embedder3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 |
| embedder4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder4 |
| ptrembedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder |

View File

@@ -1,6 +1,10 @@
| main.go:5:1:5:30 | function declaration | 1 |
| main.go:7:1:9:1 | function declaration | 2 |
| main.go:11:1:11:14 | function declaration | 0 |
| pkg1/embedding.go:10:1:12:1 | function declaration | 0 |
| pkg1/embedding.go:14:1:16:1 | function declaration | 0 |
| pkg1/embedding.go:30:1:32:1 | function declaration | 0 |
| pkg1/embedding.go:40:1:61:1 | function declaration | 0 |
| pkg1/tst.go:33:1:35:1 | function declaration | 0 |
| pkg1/tst.go:37:1:37:26 | function declaration | 1 |
| pkg1/tst.go:39:1:57:1 | function declaration | 2 |

View File

@@ -1,6 +1,10 @@
| main.go:5:1:5:30 | function declaration | 0 |
| main.go:7:1:9:1 | function declaration | 2 |
| main.go:11:1:11:14 | function declaration | 0 |
| pkg1/embedding.go:10:1:12:1 | function declaration | 1 |
| pkg1/embedding.go:14:1:16:1 | function declaration | 1 |
| pkg1/embedding.go:30:1:32:1 | function declaration | 1 |
| pkg1/embedding.go:40:1:61:1 | function declaration | 0 |
| pkg1/tst.go:33:1:35:1 | function declaration | 1 |
| pkg1/tst.go:37:1:37:26 | function declaration | 0 |
| pkg1/tst.go:39:1:57:1 | function declaration | 0 |

View File

@@ -19,3 +19,15 @@
| T4 | pkg1/tst.go:19:9:22:1 | struct type | Foo | * Foo |
| T4 | pkg1/tst.go:19:9:22:1 | struct type | flag | bool |
| T4 | pkg1/tst.go:19:9:22:1 | struct type | val | int |
| embedder | pkg1/embedding.go:19:15:19:28 | struct type | base | base |
| embedder2 | pkg1/embedding.go:25:16:25:33 | struct type | base | base |
| embedder2 | pkg1/embedding.go:25:16:25:33 | struct type | embedder | embedder |
| embedder2 | pkg1/embedding.go:28:16:28:33 | struct type | base | base |
| embedder2 | pkg1/embedding.go:28:16:28:33 | struct type | embedder | embedder |
| embedder3 | pkg1/embedding.go:25:16:25:33 | struct type | base | base |
| embedder3 | pkg1/embedding.go:25:16:25:33 | struct type | embedder | embedder |
| embedder3 | pkg1/embedding.go:28:16:28:33 | struct type | base | base |
| embedder3 | pkg1/embedding.go:28:16:28:33 | struct type | embedder | embedder |
| embedder4 | pkg1/embedding.go:35:16:38:1 | struct type | base | base |
| embedder4 | pkg1/embedding.go:35:16:38:1 | struct type | f | int |
| ptrembedder | pkg1/embedding.go:22:18:22:32 | struct type | base | * base |

View File

@@ -13,3 +13,9 @@
| T2 | T2 |
| T3 | T3 |
| T4 | T4 |
| base | base |
| embedder | embedder |
| embedder2 | embedder2 |
| embedder3 | embedder3 |
| embedder4 | embedder4 |
| ptrembedder | ptrembedder |

View File

@@ -0,0 +1,61 @@
package pkg1
import (
"fmt"
)
// `base` and `*base` have method `f`; `*base` also has method `g`
type base struct{}
func (base) f() int {
return 1
}
func (*base) g() int {
return 2
}
// `embedder` and `*embedder` have promoted method `f` from `base`; `*embedder` also has method `g` from `*base`
type embedder struct{ base }
// `ptrembedder` and `*ptrembedder` have promoted methods `f` from `base` and `g` from `*base`
type ptrembedder struct{ *base }
// `embedder2` and `*embedder2` have promoted method `f` from `base`; `*embedder2` also has method `g` from `*base`
type embedder2 struct{ embedder }
// `embedder3` and `*embedder3` have their own version of `f`; `*embedder3` also has promoted method `g` from `*base`
type embedder3 struct{ embedder }
func (embedder3) f() int {
return 3
}
// `embedder4` and `*embedder4` do not have a method `f`; `*embedder4` has promoted method `g` from `*base`
type embedder4 struct {
base
f int
}
func main() {
var (
b base
bp *base = &b
e embedder
ep *embedder = &e
pe ptrembedder = ptrembedder{bp}
pep *ptrembedder = &pe
e2 embedder2
e2p *embedder2 = &e2
e3 embedder3
e3p *embedder3 = &e3
e4 embedder4
e4p *embedder4 = &e4
)
fmt.Println(base.f(b), (*base).f(bp) /*base.g(b),*/, (*base).g(bp))
fmt.Println(embedder.f(e), (*embedder).f(ep) /*embedder.g(e),*/, (*embedder).g(ep))
fmt.Println(ptrembedder.f(pe), (*ptrembedder).f(pep), ptrembedder.g(pe), (*ptrembedder).g(pep))
fmt.Println(embedder2.f(e2), (*embedder2).f(e2p) /*embedder2.g(e2),*/, (*embedder2).g(e2p))
fmt.Println(embedder3.f(e3), (*embedder3).f(e3p) /*embedder3.g(e3),*/, (*embedder3).g(e3p))
fmt.Println( /*embedder4.f(e4), (*embedder4).f(e4p), embedder4.g(e3),*/ (*embedder4).g(e4p))
}