Skip to content

Commit 220b44e

Browse files
bozaromvdan
authored andcommitted
cue/load: add package import cycle error
When two or more packages import each other resulting in a cycle, cue/load used to cause an infinite loop. Error instead, since we explicitly don't support import cycles, per https://cuelang.org/docs/references/spec/#import-declarations: It is illegal for a package to import itself, directly or indirectly Fixes #849 Closes #2469 as merged as of commit ce73397. Signed-off-by: Artem V. Navrotskiy <[email protected]> Change-Id: I1928717b3df3c5e6c48eb4fa30966f26079e19c6 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1167597 TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]> Reviewed-by: Roger Peppe <[email protected]>
1 parent 66ebe0f commit 220b44e

File tree

5 files changed

+48
-8
lines changed

5 files changed

+48
-8
lines changed

cue/load/import.go

+13-8
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ import (
5151
// _ anonymous files (which may be marked with _)
5252
// * all packages
5353
func (l *loader) importPkg(pos token.Pos, p *build.Instance) []*build.Instance {
54+
retErr := func(errs errors.Error) []*build.Instance {
55+
// XXX: move this loop to ReportError
56+
for _, err := range errors.Errors(errs) {
57+
p.ReportError(err)
58+
}
59+
return []*build.Instance{p}
60+
}
61+
62+
for _, item := range l.stk {
63+
if item == p.ImportPath {
64+
return retErr(&PackageError{Message: errors.NewMessagef("package import cycle not allowed")})
65+
}
66+
}
5467
l.stk.Push(p.ImportPath)
5568
defer l.stk.Pop()
5669

@@ -61,14 +74,6 @@ func (l *loader) importPkg(pos token.Pos, p *build.Instance) []*build.Instance {
6174
return []*build.Instance{p}
6275
}
6376

64-
retErr := func(errs errors.Error) []*build.Instance {
65-
// XXX: move this loop to ReportError
66-
for _, err := range errors.Errors(errs) {
67-
p.ReportError(err)
68-
}
69-
return []*build.Instance{p}
70-
}
71-
7277
fp := newFileProcessor(cfg, p, l.tagger)
7378

7479
if p.PkgName == "" {

cue/load/loader_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,23 @@ module: mod.test/test
330330
root: $CWD/testdata/testmod
331331
dir: $CWD/testdata/testmod/tagsbad
332332
display:./tagsbad`,
333+
}, {
334+
cfg: &Config{
335+
Dir: testdataDir,
336+
},
337+
args: args("./cycle"),
338+
want: `
339+
err: import failed: import failed: import failed: package import cycle not allowed:
340+
$CWD/testdata/testmod/cycle/cycle.cue:3:8
341+
$CWD/testdata/testmod/cue.mod/pkg/mod.test/cycle/bar/bar.cue:3:8
342+
$CWD/testdata/testmod/cue.mod/pkg/mod.test/cycle/foo/foo.cue:3:8
343+
path: mod.test/test/cycle
344+
module: mod.test/test
345+
root: $CWD/testdata/testmod
346+
dir: $CWD/testdata/testmod/cycle
347+
display:./cycle
348+
files:
349+
$CWD/testdata/testmod/cycle/cycle.cue`,
333350
}}
334351
for i, tc := range testCases {
335352
t.Run(strconv.Itoa(i)+"/"+strings.Join(tc.args, ":"), func(t *testing.T) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package bar
2+
3+
import "mod.test/cycle/foo"
4+
5+
#Bar1: foo.#Foo1 + 8
6+
#Bar2: foo.#Foo2 + 16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package foo
2+
3+
import "mod.test/cycle/bar"
4+
5+
#Foo1: 1
6+
#Foo2: bar.#Bar1 + 2
7+
#Foo: bar.#Bar2 + 4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package cycle
2+
3+
import "mod.test/cycle/foo"
4+
5+
Foo: foo.#Foo

0 commit comments

Comments
 (0)