(*CallCommon).Signature() now returns non-nil even for
built-ins. Builtins are now created with specialized types for
each use. Added sanity-check.
CallCommon.HasEllipsis field eliminated. It was an incorrect
memoization of Signature().IsVariadic() used only for
printing.
Also: introduce and use newTypeVar utility.
R=gri
CC=golang-codereviews
https://golang.org/cl/46880044
Motivation:
Previously, we assumed that the set of types for which a
complete method set (containing all synthesized wrapper
functions) is required at runtime was the set of types
used as operands to some *ssa.MakeInterface instruction.
In fact, this is an underapproximation because types can
be derived from other ones via reflection, and some of
these may need methods. The reflect.Type API allows *T to
be derived from T, and these may have different method
sets. Reflection also allows almost any subcomponent of a
type to be accessed (with one exception: given T, defined
'type T struct{S}', you can reach S but not struct{S}).
As a result, the pointer analysis was unable to generate
all necessary constraints before running the solver,
causing a crash when reflection derives types whose
methods are unavailable. (A similar problem would afflict
an ahead-of-time compiler based on ssa. The ssa/interp
interpreter was immune only because it does not require
all wrapper methods to be created before execution
begins.)
Description:
This change causes the SSA builder to record, for each
package, the set of all types with non-empty method sets that
are referenced within that package. This set is accessed via
Packages.TypesWithMethodSets(). Program.TypesWithMethodSets()
returns its union across all packages.
The set of references that matter are:
- types of operands to some MakeInterface instruction (as before)
- types of all exported package members
- all subcomponents of the above, recursively.
This is a conservative approximation to the set of types
whose methods may be called dynamically.
We define the owning package of a type as follows:
- the owner of a named type is the package in which it is defined;
- the owner of a pointer-to-named type is the owner of that named type;
- the owner of all other types is nil.
A package must include the method sets for all types that it
owns, and all subcomponents of that type that are not owned by
another package, recursively. Types with an owner appear in
exactly one package; types with no owner (such as struct{T})
may appear within multiple packages.
(A typical Go compiler would emit multiple copies of these
methods as weak symbols; a typical linker would eliminate
duplicates.)
Also:
- go/types/typemap: implement hash function for *Tuple.
- pointer: generate nodes/constraints for all of
ssa.Program.TypesWithMethodSets().
Add rtti.go regression test.
- Add API test of Package.TypesWithMethodSets().
- Set Function.Pkg to nil (again) for wrapper functions,
since these may be shared by many packages.
- Remove a redundant logging statement.
- Document that ssa CREATE phase is in fact sequential.
Fixesgolang/go#6605
R=gri
CC=golang-dev
https://golang.org/cl/14920056
It is needed after all, as I discovered in the pointer analysis.
(ssa needs more API test coverage.)
Also:
- sanity: remove debugging cruft
- promote: don't redundantly include the function's
own name in its Synthetic string.
- print: IntuitiveMethodSet utility fixes a bug in the
printing logic (for interface types, mset(*T) is empty).
The function is also used by the Oracle.
R=crawshaw
CC=golang-dev
https://golang.org/cl/13116043
Fix bug: the Signature for an interface method wrapper
erroneously had a non-nil receiver.
Function:
- Set Pkg field non-nil even for wrappers.
It is equal to that of the wrapped function.
Only wrappers of error.Error
(and its embeddings in other interfaces) may have nil.
Sanity checker now asserts this.
- FullName() now uses .Synthetic field to discriminate
synthetic methods, not Pkg==nil.
- Fullname() uses new relType() utility to print receiver type
name unqualified if it belongs to the same package.
(Alloc.String also uses relType utility.)
CallCommon:
- Description(): fix switch logic broken when we
eliminated the Recv field.
- better docs.
R=david.crawshaw, crawshaw, gri
CC=golang-dev
https://golang.org/cl/13057043
stdlib_test runs the builder (in sanity-checking mode) over
the Go standard library. It also prints some stats about
the time and memory usage.
Also:
- importer.LoadPackage too (not just doImport) must consult
the cache to avoid creating duplicate Package instances for
the same import path when called serially from a test.
- importer: skip empty directories without an error.
- importer: print all errors, not just the first.
- visit.go: added AllFunctions utility for enumerating all
Functions in a Program.
- ssa.MethodSet is not safe to expose from the package since
it must be accessed under an (inaccessible) lock. (!!!)
This CL makes it unexported and restricts its use to the
single function Program.LookupMethod().
- Program.MethodSet() has gone.
Clients should instead iterate over the types.MethodSet
and call LookupMethod.
- Package.DumpTo(): improved efficiency of methodset printing
(by not creating wrappers) and accuracy (by showing * on
receiver type only when necessary).
- Program.CreatePackage: documented precondition and added
assertion.
R=gri
CC=golang-dev
https://golang.org/cl/12058048
buildDecl was visiting all decls in source order, but the spec
calls for visiting all vars and init() funcs in order, then
all remaining functions. These two passes are now called
buildInit(), buildFuncDecl().
+ Test.
Also:
- Added workaround to gcimporter for Func with pkg==nil.
- Prog.concreteMethods has been merged into Pkg.values.
- Prog.concreteMethod() renamed declaredFunc().
- s/mfunc/obj/ (name cleanup from recent gri CL)
R=gri
CC=golang-dev
https://golang.org/cl/12030044
A Method corresponds to a MethodVal Selection;
so the explicit Method object is not needed anymore.
- moved Selection code into separate file
- implemented Selection.String()
- improved and more consistent documentation
R=adonovan
CC=golang-dev
https://golang.org/cl/11950043
We now use LookupFieldOrMethod for all SelectorExprs, and
simplify the logic to discriminate the various cases.
We inline static calls to promoted/indirected functions,
dramatically reducing the number of functions created.
More tests are needed, but I'd like to submit this as-is.
In this CL, we:
- rely less on Id strings. Internally we now use
*types.Method (and its components) almost everywhere.
- stop thinking of types.Methods as objects. They don't
have stable identities. (Hopefully they will become
plain-old structs soon.)
- eliminate receiver indirection wrappers:
indirection and promotion are handled together by makeWrapper.
- Handle the interactions of promotion, indirection and
abstract methods much more cleanly.
- support receiver-bound interface method closures.
- break up builder.selectField so we can re-use parts
(emitFieldSelection).
- add importer.PackageInfo.classifySelector utility.
- delete interfaceMethodIndex()
- delete namedTypeMethodIndex()
- delete isSuperInterface() (replaced by types.IsAssignable)
- call memberFromObject on each declared concrete method's
*types.Func, not on every Method frem each method set, in the
CREATE phase for packages loaded by gcimporter.
go/types:
- document Func, Signature.Recv() better.
- use fmt in {Package,Label}.String
- reimplement Func.String to be prettier and to include method
receivers.
API changes:
- Function.method now holds the types.Method (soon to be
not-an-object) for synthetic wrappers.
- CallCommon.Method now contains an abstract (interface)
method object; was an abstract method index.
- CallCommon.MethodId() gone.
- Program.LookupMethod now takes a *Method not an Id string.
R=gri
CC=golang-dev
https://golang.org/cl/11674043
- implemented objset for tracking duplicates of fields and methods
which permitted a simpler and faster scope implementation in turn
- related cleanups and internal renames
- fixed a couple of identifier reporting bugs
Speed of type-checking itself increased by almost 10%
(from ~71Kloc/s to ~78Kloc/s on one machine, measured
via go test -run=Self).
R=adonovan
CC=golang-dev
https://golang.org/cl/11750043
Reduces by 94% the number of wrappers created during the tests.
(No appreciable difference in running time, sadly.)
R=gri
CC=golang-dev
https://golang.org/cl/11619043
Details:
- emitImplicitSelections now emits common code for implicit
field selections in both method and field lookups.
The last iteration over the LookupFieldOrMethod indices---the explicit,
final index---is handled by the caller.
- anonFieldPath, candidate and the BFS algo in buildMethodSet are all gone.
R=gri
CC=golang-dev
https://golang.org/cl/11576045
Temporarily remove Field objects in favor of Vars for struct fields.
In forthcoming CL, Fields will play the symmetric role to Methods, and
serve as lookup results including index information.
R=adonovan
CC=golang-dev
https://golang.org/cl/11594043
- removed a number of obsolete TODO(gri) comments.
- bring ssa.DefaultType back into sync with types.defaultType.
- re-enable types.Package.Path()!="" assertion.
- use Path() (not reflect pointer) in sort routine.
- make interp.checkInterface use types.MissingMethod.
- un-export ssa.MakeId function.
- inline pointer() into all callers, and delete.
- enable two more interp_tests: $GOROOT/test/{method3,cmp}.go
- add links to bugs to other interp_tests.
- add runtime.NumCPU to ssa/interp/externals.go
R=gri
CC=golang-dev
https://golang.org/cl/11353043
Objects:
- provide IsExported, SameName, uniqueName methods
- clean up a lot of dependent code
Scopes:
- don't add children to Universe scope (!)
- document Node, WriteTo
Types:
- remove Deref in favor of internal function deref
ssa, ssa/interp:
- introduced local deref, adjusted code
- fixed some "Underlying" bugs (pun intended)
R=adonovan
CC=golang-dev
https://golang.org/cl/11232043
This exposed a bug: we weren't creating Functions for methods
of imported named types.
Also:
- simplification: 'candidate' no longer contains 'concrete *Function'.
We look this up on demand.
NB: this CL contains a copy of CL 10935047 (use of typemap);
will submit/sync/resolve soon.
R=gri
CC=golang-dev
https://golang.org/cl/11051043
Yields a ~20% improvement in SSA construction time.
Also: better names for promotion wrapper functions.
R=gri
CC=golang-dev
https://golang.org/cl/11050043
We use the new field to determine whether or not a function is
synthetic, not Pos() == 0, so synthetic functions can have
positions too.
R=gri
CC=golang-dev
https://golang.org/cl/10916044
Before, all values received on some channel by Select would
flow to an empty interface, creating a spurious confluence for
flow analyses. Now, the tuple returned by Select has one
component for each 'receive' case.
Also, fixes:
- Removed workarounds for now-fixed typechecker bug in FuncLit+TypeAssert.
- sanity check that all Value Instructions have non-nil Type().
- Convert: document and sanity-check that at least one of the types is basic.
Also, other things to help clients:
- Define CallInstruction interface: common parts of Call, Go, Defer.
- Add CallCommon.Signature() method.
- Literal.Pos() is now populated.
R=gri
CC=golang-dev
https://golang.org/cl/10505043
methodIndex() utility was split and specialized to its two
cases, *Interface vs *Named, which are logically quite
different.
We can't memoize promotion wrappers yet; we need typemap.
Terminology:
- "thunks" are now "wrappers"
- "bridge methods" are now "promotion wrappers"
Where the diff is messy it's just because of indentation.
R=gri
CC=golang-dev
https://golang.org/cl/10282043
Method sets:
- Simplify CallCommon.
Avoid the implicit copy when calling a T method on a *T
receiver. This simplifies clients. Instead we generate
"indirection wrapper" functions that do this (like gc does).
New invariant:
m's receiver type is exactly T for all m in MethodSet(T)
- MakeInterface no longer holds the concrete type's MethodSet.
We can defer its computation this way.
- ssa.Type now just wraps a types.TypeName object.
MethodSets are computed as needed, not eagerly.
Position info:
- new CanonicalPos utility maps ast.Expr to canonical
token.Pos, as returned by {Instruction,Value}.Pos() methods.
- Don't set posn for implicit operations (e.g. varargs array alloc)
- Set position info for ChangeInterface and Slice instructions.
Cosmetic:
- add Member.Token() method
- simplify isPointer
- Omit words "interface", "slice" when printing MakeInterface,
MakeSlice; the type is enough.
- Comments on PathEnclosingInterval.
- Remove Function.FullName() where implicit String() suffices.
Also:
- Exposed NewLiteral to clients.
- Added ssa.Instruction.Parent() *Function
Added ssa.BasicBlock.Parent() *Function.
Added Sanity checks for above.
R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/10166045
Details:
- builder is now un-exported and is now a per-package entity.
- Package.nTo1Vars is now part of builder, where it belongs.
- CREATE phase code split out into its own file, create.go
- Context type is gone; it had become trivial after the
Importer refactoring.
- importer.PackageInfo.Imports() now encapsulates iteration
over imports.
Typical usage is now:
prog := ssa.NewProgram(imp.Fset, mode)
prog.CreatePackages(imp)
prog.BuildAll()
Builder.BuildPackage(Package) is now Package.Build()
Builder.BuildAllPackages() is now Program.BuildAll()
R=iant, gri
CC=golang-dev
https://golang.org/cl/9970044
The method index was hard-coded to zero, which works some of
the time. Apparently I just forgot to implement the
method-table lookup...
Added regression test.
R=gri
CC=golang-dev
https://golang.org/cl/9916043
PLEASE NOTE: the APIs for both "importer" and "ssa" packages
will continue to evolve and both need some polishing; the key
thing is that this CL splits them.
The go.types/importer package contains contains the Importer,
which takes care of the mechanics of loading a set of packages
and type-checking them. It exposes for each package a
PackageInfo containing:
- the package's ASTs (i.e. the input to the typechecker)
- the types.Package object
- the memoization of the typechecker callbacks for identifier
resolution, constant folding and expression type inference.
Method-set computation (and hence bridge-method creation) is
now moved to after creation of all packages: since they are no
longer created in topological order, we can't guarantee the
needed delegate methods exist yet.
ssa.Package no longer has public TypeOf, ObjectOf, ValueOf methods.
The private counterparts are valid only during the build phase.
Also:
- added to go/types an informative error (not crash) for an
importer() returning nil without error.
- removed Package.Name(), barely needed.
- changed Package.String() slightly.
- flag what looks like a bug in makeBridgeMethod. Will follow up.
R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/9898043
- First step towards unified use of scopes. Will enable
further simplifications.
- Removed various ForEach iterators in favor of the existing
accessor methods, for a thinner API.
- Renamed outer/Outer to parent/Parent for scopes.
- Removed check.lookup in favor of Scope.LookupParent.
R=adonovan
CC=golang-dev
https://golang.org/cl/9862044
Implement Pos() method for
Values: Parameter, Capture, Phi. (Not Literal, Builtin.)
Instructions: UnOp, BinOp, Store.
'address' (an lvalue) now needs position of '*' in "*addr".
Also:
- Un-export fields Pos_ Type_ Name_ Block_ from various values/instructions.
Define NewFunction() as a temporary measure.
Will try to eliminate calls from clients...
- Remove Implements{Value,Member,Interface} marker methods.
I've decided I don't like them.
- Func.addParamObj helper.
- Various comment fixes.
R=gri
CC=golang-dev
https://golang.org/cl/9740046
Extracted Builder.findMethod function to handle
methodset/receiver logic common to
function calls (Builder.setCall) and
bound method closure creation (Builder.selector).
Capture: added explicit Name, Type fields to Capture instead
of relying on Outer field, which is now un-exported since its
only purpose is to let Builder.expr(case *ast.FuncLit) know
which values to put in the closure; it is nilled immediately
after.
Simplified Function.lookup() logic: there's no need to walk
the Outer chain each time to set Alloc.Heap=true, as it's
already set during creation of the outermost
Capture{outer:*Alloc}.
Added interp/testdata/boundmeth.go test.
Cosmetic changes:
- add support for bound method thunks to Function.FullName().
- Simplified {Literal,Global,Builtin,Function}.String()
- doc: Captures are no longer necessarily addresses.
- added yet another missing pair of "()" (go/types accessors).
- print "Synthetic" not "Declared at -" for synthetic functions.
- use '$' not center-dot in synthetic identifiers (easier to type).
R=gri
CC=golang-dev
https://golang.org/cl/9654043