mirror of
https://github.com/golang/go
synced 2024-11-19 12:44:51 -07:00
go/importer: make source importer more tolerant in presence of errors
If the source importer only encounters "soft" type checking errors it can safely return the type-checked package because it will be completely set up. This makes the source importer slightly more robust in the presence of errors. Fixes #20855. Change-Id: I5af9ccdb30eee6bca7a0fab872f6057bde521bf3 Reviewed-on: https://go-review.googlesource.com/55730 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
9c9df65c53
commit
b26ad605a9
@ -128,19 +128,33 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type
|
|||||||
}
|
}
|
||||||
|
|
||||||
// type-check package files
|
// type-check package files
|
||||||
|
var firstHardErr error
|
||||||
conf := types.Config{
|
conf := types.Config{
|
||||||
IgnoreFuncBodies: true,
|
IgnoreFuncBodies: true,
|
||||||
FakeImportC: true,
|
FakeImportC: true,
|
||||||
Importer: p,
|
// continue type-checking after the first error
|
||||||
Sizes: p.sizes,
|
Error: func(err error) {
|
||||||
|
if firstHardErr == nil && !err.(types.Error).Soft {
|
||||||
|
firstHardErr = err
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Importer: p,
|
||||||
|
Sizes: p.sizes,
|
||||||
}
|
}
|
||||||
pkg, err = conf.Check(bp.ImportPath, p.fset, files, nil)
|
pkg, err = conf.Check(bp.ImportPath, p.fset, files, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Type-checking stops after the first error (types.Config.Error is not set),
|
// If there was a hard error it is possibly unsafe
|
||||||
// so the returned package is very likely incomplete. Don't return it since
|
// to use the package as it may not be fully populated.
|
||||||
// we don't know its condition: It's very likely unsafe to use and it's also
|
// Do not return it (see also #20837, #20855).
|
||||||
// not added to p.packages which may cause further problems (issue #20837).
|
if firstHardErr != nil {
|
||||||
return nil, fmt.Errorf("type-checking package %q failed (%v)", bp.ImportPath, err)
|
pkg = nil
|
||||||
|
err = firstHardErr // give preference to first hard error over any soft error
|
||||||
|
}
|
||||||
|
return pkg, fmt.Errorf("type-checking package %q failed (%v)", bp.ImportPath, err)
|
||||||
|
}
|
||||||
|
if firstHardErr != nil {
|
||||||
|
// this can only happen if we have a bug in go/types
|
||||||
|
panic("package is not safe yet no error was returned")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.packages[bp.ImportPath] = pkg
|
p.packages[bp.ImportPath] = pkg
|
||||||
|
@ -148,3 +148,17 @@ func TestReimport(t *testing.T) {
|
|||||||
t.Errorf("got %v; want reimport error", err)
|
t.Errorf("got %v; want reimport error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIssue20855(t *testing.T) {
|
||||||
|
if !testenv.HasSrc() {
|
||||||
|
t.Skip("no source code available")
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg, err := importer.ImportFrom("go/internal/srcimporter/testdata/issue20855", ".", 0)
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "missing function body") {
|
||||||
|
t.Fatalf("got unexpected or no error: %v", err)
|
||||||
|
}
|
||||||
|
if pkg == nil {
|
||||||
|
t.Error("got no package despite no hard errors")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
7
src/go/internal/srcimporter/testdata/issue20855/issue20855.go
vendored
Normal file
7
src/go/internal/srcimporter/testdata/issue20855/issue20855.go
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Copyright 2017 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 issue20855
|
||||||
|
|
||||||
|
func init() // "missing function body" is a soft error
|
Loading…
Reference in New Issue
Block a user