1
0
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:
griesemer 2017-08-15 14:44:26 +02:00 committed by Robert Griesemer
parent 9c9df65c53
commit b26ad605a9
3 changed files with 42 additions and 7 deletions

View File

@ -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

View File

@ -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")
}
}

View 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