]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.17] cmd/go: write go.mod requirements more consistently for go...
authorJay Conrod <jayconrod@google.com>
Thu, 9 Sep 2021 16:38:55 +0000 (09:38 -0700)
committerHeschi Kreinick <heschi@google.com>
Tue, 28 Sep 2021 20:30:45 +0000 (20:30 +0000)
If go.mod declares 1.17 or higher, when the go command rewrites go.mod
(for example, after 'go mod tidy'), it will be more consistent about
moving requirements in two blocks, one containing only direct
requirements, and one containing only indirect requirements.

The go command will not move requirements into or out of a block with
comments. It may still update versions and "// indirect" comments, and
it may delete unneeded requirements though.

Fixes #47756

Change-Id: Ia6fb3e302be53097893abf01aa7cea60ac7b069a
Reviewed-on: https://go-review.googlesource.com/c/go/+/343432
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit 3c764babe7b5e01a4e04b1a2c7975cdb5c5651a0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/351465
TryBot-Result: Go Bot <gobot@golang.org>

src/cmd/go.mod
src/cmd/go.sum
src/cmd/go/testdata/script/mod_all.txt
src/cmd/go/testdata/script/mod_retention.txt
src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt
src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
src/cmd/vendor/modules.txt
src/go.mod

index cd03968eedcf618d0ecef8da89ce790646dba399..ecb7b9bf4214ca87b4802041c707e76e678dd019 100644 (file)
@@ -4,12 +4,15 @@ go 1.17
 
 require (
        github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a
-       github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect
        golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e
-       golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
-       golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
-       golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
+       golang.org/x/mod v0.5.1
        golang.org/x/term v0.0.0-20210503060354-a79de5458b56
        golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9
+)
+
+require (
+       github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect
+       golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
+       golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
        golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 )
index d728acaec9925e702dac5a61edeaebac48d878c6..42a7a20c0b418989f68a383cd742f0f8025b93a8 100644 (file)
@@ -13,8 +13,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI=
 golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a h1:e8qnjKz4EE6OjRki9wTadWSIogINvq10sMcuBRORxMY=
-golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
+golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
index 090eeee22df263579b99075bb227f5f32372e0dd..8be6716d84cf25784990bfc5626b658ee3d14d79 100644 (file)
@@ -202,9 +202,9 @@ go mod edit -go=1.17 u/go.mod
 go mod edit -go=1.17 w/go.mod
 go mod edit -go=1.17 x/go.mod
 go mod edit -go=1.17
-cp go.mod go.mod.orig
+cmp go.mod go.mod.beforetidy
 go mod tidy
-cmp go.mod go.mod.orig
+cmp go.mod go.mod.aftertidy
 
 # With lazy loading, 'go list all' with neither -mod=vendor nor -test should
 # match -mod=vendor without -test in 1.15.
@@ -466,3 +466,66 @@ module example.com/x
 go 1.15
 -- x/x.go --
 package x
+-- go.mod.beforetidy --
+module example.com/main
+
+// Note: this go.mod file initially specifies go 1.15,
+// but includes some redundant roots so that it
+// also already obeys the 1.17 lazy loading invariants.
+go 1.17
+
+require (
+       example.com/a v0.1.0
+       example.com/b v0.1.0 // indirect
+       example.com/q v0.1.0
+       example.com/r v0.1.0 // indirect
+       example.com/t v0.1.0
+       example.com/u v0.1.0 // indirect
+)
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b
+       example.com/c v0.1.0 => ./c
+       example.com/d v0.1.0 => ./d
+       example.com/q v0.1.0 => ./q
+       example.com/r v0.1.0 => ./r
+       example.com/s v0.1.0 => ./s
+       example.com/t v0.1.0 => ./t
+       example.com/u v0.1.0 => ./u
+       example.com/w v0.1.0 => ./w
+       example.com/x v0.1.0 => ./x
+)
+-- go.mod.aftertidy --
+module example.com/main
+
+// Note: this go.mod file initially specifies go 1.15,
+// but includes some redundant roots so that it
+// also already obeys the 1.17 lazy loading invariants.
+go 1.17
+
+require (
+       example.com/a v0.1.0
+       example.com/q v0.1.0
+       example.com/t v0.1.0
+)
+
+require (
+       example.com/b v0.1.0 // indirect
+       example.com/r v0.1.0 // indirect
+       example.com/u v0.1.0 // indirect
+)
+
+replace (
+       example.com/a v0.1.0 => ./a
+       example.com/b v0.1.0 => ./b
+       example.com/c v0.1.0 => ./c
+       example.com/d v0.1.0 => ./d
+       example.com/q v0.1.0 => ./q
+       example.com/r v0.1.0 => ./r
+       example.com/s v0.1.0 => ./s
+       example.com/t v0.1.0 => ./t
+       example.com/u v0.1.0 => ./u
+       example.com/w v0.1.0 => ./w
+       example.com/x v0.1.0 => ./x
+)
index 7a371b18068cd2e6619fc7ffdf14ddf03fa63898..14c6c16e93122fe9cce65cdb1d0b0376edbc8f78 100644 (file)
@@ -81,14 +81,14 @@ require (
 package x
 import _ "rsc.io/quote"
 -- go.mod.crlf --
-module m\r
-\r
-go 1.14\r
-\r
-require (\r
-       rsc.io/quote v1.5.2\r
-       rsc.io/testonly v1.0.0 // indirect\r
-)\r
+module m
+
+go 1.14
+
+require (
+       rsc.io/quote v1.5.2
+       rsc.io/testonly v1.0.0 // indirect
+)
 -- go.mod.unsorted --
 module m
 
@@ -139,10 +139,10 @@ module m
 
 go $goversion
 
+require rsc.io/quote v1.5.2
+
 require (
-       rsc.io/quote v1.5.2
+       golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
        rsc.io/sampler v1.3.0 // indirect
        rsc.io/testonly v1.0.0 // indirect
 )
-
-require golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
index c544cb7413fcdc6b4f791d98429fd7c8e3bc7feb..e17409e776e662eed698e05f8a2d89c31a821686 100644 (file)
@@ -72,10 +72,9 @@ go 1.17
 
 replace example.net/indirect v0.1.0 => ./indirect
 
-require (
-       example.net/ambiguous/nested v0.1.0 // indirect
-       example.net/indirect v0.1.0
-)
+require example.net/indirect v0.1.0
+
+require example.net/ambiguous/nested v0.1.0 // indirect
 -- all-m.txt --
 example.com/m
 example.net/ambiguous v0.1.0
index ea9e42e87e20fc57b7e14164f9f606954ccad269..11313f144c3a340f35da2cb037d3512ee39680dd 100644 (file)
@@ -97,10 +97,9 @@ replace (
        example.net/requireincompatible v0.1.0 => ./requireincompatible
 )
 
-require (
-       example.com/retract/incompatible v1.0.0 // indirect
-       example.net/lazy v0.1.0
-)
+require example.net/lazy v0.1.0
+
+require example.com/retract/incompatible v1.0.0 // indirect
 -- incompatible.go --
 package incompatible
 
index 78f83fa7144f0318379ebb0c4797540959c7b511..ca03e70ea1121e5dc55780b284e1acfb67b84e3a 100644 (file)
@@ -956,170 +956,217 @@ func (f *File) SetRequire(req []*Require) {
 
 // SetRequireSeparateIndirect updates the requirements of f to contain the given
 // requirements. Comment contents (except for 'indirect' markings) are retained
-// from the first existing requirement for each module path, and block structure
-// is maintained as long as the indirect markings match.
+// from the first existing requirement for each module path. Like SetRequire,
+// SetRequireSeparateIndirect adds requirements for new paths in req,
+// updates the version and "// indirect" comment on existing requirements,
+// and deletes requirements on paths not in req. Existing duplicate requirements
+// are deleted.
 //
-// Any requirements on paths not already present in the file are added. Direct
-// requirements are added to the last block containing *any* other direct
-// requirement. Indirect requirements are added to the last block containing
-// *only* other indirect requirements. If no suitable block exists, a new one is
-// added, with the last block containing a direct dependency (if any)
-// immediately before the first block containing only indirect dependencies.
+// As its name suggests, SetRequireSeparateIndirect puts direct and indirect
+// requirements into two separate blocks, one containing only direct
+// requirements, and the other containing only indirect requirements.
+// SetRequireSeparateIndirect may move requirements between these two blocks
+// when their indirect markings change. However, SetRequireSeparateIndirect
+// won't move requirements from other blocks, especially blocks with comments.
 //
-// The Syntax field is ignored for requirements in the given blocks.
+// If the file initially has one uncommented block of requirements,
+// SetRequireSeparateIndirect will split it into a direct-only and indirect-only
+// block. This aids in the transition to separate blocks.
 func (f *File) SetRequireSeparateIndirect(req []*Require) {
-       type modKey struct {
-               path     string
-               indirect bool
-       }
-       need := make(map[modKey]string)
-       for _, r := range req {
-               need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version
+       // hasComments returns whether a line or block has comments
+       // other than "indirect".
+       hasComments := func(c Comments) bool {
+               return len(c.Before) > 0 || len(c.After) > 0 || len(c.Suffix) > 1 ||
+                       (len(c.Suffix) == 1 &&
+                               strings.TrimSpace(strings.TrimPrefix(c.Suffix[0].Token, string(slashSlash))) != "indirect")
        }
 
-       comments := make(map[string]Comments)
-       for _, r := range f.Require {
-               v, ok := need[modKey{r.Mod.Path, r.Indirect}]
-               if !ok {
-                       if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok {
-                               if _, dup := comments[r.Mod.Path]; !dup {
-                                       comments[r.Mod.Path] = r.Syntax.Comments
-                               }
+       // moveReq adds r to block. If r was in another block, moveReq deletes
+       // it from that block and transfers its comments.
+       moveReq := func(r *Require, block *LineBlock) {
+               var line *Line
+               if r.Syntax == nil {
+                       line = &Line{Token: []string{AutoQuote(r.Mod.Path), r.Mod.Version}}
+                       r.Syntax = line
+                       if r.Indirect {
+                               r.setIndirect(true)
                        }
-                       r.markRemoved()
-                       continue
+               } else {
+                       line = new(Line)
+                       *line = *r.Syntax
+                       if !line.InBlock && len(line.Token) > 0 && line.Token[0] == "require" {
+                               line.Token = line.Token[1:]
+                       }
+                       r.Syntax.Token = nil // Cleanup will delete the old line.
+                       r.Syntax = line
                }
-               r.setVersion(v)
-               delete(need, modKey{r.Mod.Path, r.Indirect})
+               line.InBlock = true
+               block.Line = append(block.Line, line)
        }
 
+       // Examine existing require lines and blocks.
        var (
-               lastDirectOrMixedBlock Expr
-               firstIndirectOnlyBlock Expr
-               lastIndirectOnlyBlock  Expr
+               // We may insert new requirements into the last uncommented
+               // direct-only and indirect-only blocks. We may also move requirements
+               // to the opposite block if their indirect markings change.
+               lastDirectIndex   = -1
+               lastIndirectIndex = -1
+
+               // If there are no direct-only or indirect-only blocks, a new block may
+               // be inserted after the last require line or block.
+               lastRequireIndex = -1
+
+               // If there's only one require line or block, and it's uncommented,
+               // we'll move its requirements to the direct-only or indirect-only blocks.
+               requireLineOrBlockCount = 0
+
+               // Track the block each requirement belongs to (if any) so we can
+               // move them later.
+               lineToBlock = make(map[*Line]*LineBlock)
        )
-       for _, stmt := range f.Syntax.Stmt {
+       for i, stmt := range f.Syntax.Stmt {
                switch stmt := stmt.(type) {
                case *Line:
                        if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
                                continue
                        }
-                       if isIndirect(stmt) {
-                               lastIndirectOnlyBlock = stmt
-                       } else {
-                               lastDirectOrMixedBlock = stmt
+                       lastRequireIndex = i
+                       requireLineOrBlockCount++
+                       if !hasComments(stmt.Comments) {
+                               if isIndirect(stmt) {
+                                       lastIndirectIndex = i
+                               } else {
+                                       lastDirectIndex = i
+                               }
                        }
+
                case *LineBlock:
                        if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
                                continue
                        }
-                       indirectOnly := true
+                       lastRequireIndex = i
+                       requireLineOrBlockCount++
+                       allDirect := len(stmt.Line) > 0 && !hasComments(stmt.Comments)
+                       allIndirect := len(stmt.Line) > 0 && !hasComments(stmt.Comments)
                        for _, line := range stmt.Line {
-                               if len(line.Token) == 0 {
-                                       continue
-                               }
-                               if !isIndirect(line) {
-                                       indirectOnly = false
-                                       break
+                               lineToBlock[line] = stmt
+                               if hasComments(line.Comments) {
+                                       allDirect = false
+                                       allIndirect = false
+                               } else if isIndirect(line) {
+                                       allDirect = false
+                               } else {
+                                       allIndirect = false
                                }
                        }
-                       if indirectOnly {
-                               lastIndirectOnlyBlock = stmt
-                               if firstIndirectOnlyBlock == nil {
-                                       firstIndirectOnlyBlock = stmt
-                               }
-                       } else {
-                               lastDirectOrMixedBlock = stmt
+                       if allDirect {
+                               lastDirectIndex = i
+                       }
+                       if allIndirect {
+                               lastIndirectIndex = i
                        }
                }
        }
 
-       isOrContainsStmt := func(stmt Expr, target Expr) bool {
-               if stmt == target {
-                       return true
-               }
-               if stmt, ok := stmt.(*LineBlock); ok {
-                       if target, ok := target.(*Line); ok {
-                               for _, line := range stmt.Line {
-                                       if line == target {
-                                               return true
-                                       }
-                               }
+       oneFlatUncommentedBlock := requireLineOrBlockCount == 1 &&
+               !hasComments(*f.Syntax.Stmt[lastRequireIndex].Comment())
+
+       // Create direct and indirect blocks if needed. Convert lines into blocks
+       // if needed. If we end up with an empty block or a one-line block,
+       // Cleanup will delete it or convert it to a line later.
+       insertBlock := func(i int) *LineBlock {
+               block := &LineBlock{Token: []string{"require"}}
+               f.Syntax.Stmt = append(f.Syntax.Stmt, nil)
+               copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:])
+               f.Syntax.Stmt[i] = block
+               return block
+       }
+
+       ensureBlock := func(i int) *LineBlock {
+               switch stmt := f.Syntax.Stmt[i].(type) {
+               case *LineBlock:
+                       return stmt
+               case *Line:
+                       block := &LineBlock{
+                               Token: []string{"require"},
+                               Line:  []*Line{stmt},
                        }
+                       stmt.Token = stmt.Token[1:] // remove "require"
+                       stmt.InBlock = true
+                       f.Syntax.Stmt[i] = block
+                       return block
+               default:
+                       panic(fmt.Sprintf("unexpected statement: %v", stmt))
                }
-               return false
        }
 
-       addRequire := func(path, vers string, indirect bool, comments Comments) {
-               var line *Line
-               if indirect {
-                       if lastIndirectOnlyBlock != nil {
-                               line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers)
-                       } else {
-                               // Add a new require block after the last direct-only or mixed "require"
-                               // block (if any).
-                               //
-                               // (f.Syntax.addLine would add the line to an existing "require" block if
-                               // present, but here the existing "require" blocks are all direct-only, so
-                               // we know we need to add a new block instead.)
-                               line = &Line{Token: []string{"require", path, vers}}
-                               lastIndirectOnlyBlock = line
-                               firstIndirectOnlyBlock = line // only block implies first block
-                               if lastDirectOrMixedBlock == nil {
-                                       f.Syntax.Stmt = append(f.Syntax.Stmt, line)
-                               } else {
-                                       for i, stmt := range f.Syntax.Stmt {
-                                               if isOrContainsStmt(stmt, lastDirectOrMixedBlock) {
-                                                       f.Syntax.Stmt = append(f.Syntax.Stmt, nil)     // increase size
-                                                       copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up
-                                                       f.Syntax.Stmt[i+1] = line
-                                                       break
-                                               }
-                                       }
-                               }
-                       }
+       var lastDirectBlock *LineBlock
+       if lastDirectIndex < 0 {
+               if lastIndirectIndex >= 0 {
+                       lastDirectIndex = lastIndirectIndex
+                       lastIndirectIndex++
+               } else if lastRequireIndex >= 0 {
+                       lastDirectIndex = lastRequireIndex + 1
                } else {
-                       if lastDirectOrMixedBlock != nil {
-                               line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers)
-                       } else {
-                               // Add a new require block before the first indirect block (if any).
-                               //
-                               // That way if the file initially contains only indirect lines,
-                               // the direct lines still appear before it: we preserve existing
-                               // structure, but only to the extent that that structure already
-                               // reflects the direct/indirect split.
-                               line = &Line{Token: []string{"require", path, vers}}
-                               lastDirectOrMixedBlock = line
-                               if firstIndirectOnlyBlock == nil {
-                                       f.Syntax.Stmt = append(f.Syntax.Stmt, line)
-                               } else {
-                                       for i, stmt := range f.Syntax.Stmt {
-                                               if isOrContainsStmt(stmt, firstIndirectOnlyBlock) {
-                                                       f.Syntax.Stmt = append(f.Syntax.Stmt, nil)   // increase size
-                                                       copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up
-                                                       f.Syntax.Stmt[i] = line
-                                                       break
-                                               }
-                                       }
-                               }
-                       }
+                       lastDirectIndex = len(f.Syntax.Stmt)
                }
+               lastDirectBlock = insertBlock(lastDirectIndex)
+       } else {
+               lastDirectBlock = ensureBlock(lastDirectIndex)
+       }
 
-               line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before)
-               line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix)
+       var lastIndirectBlock *LineBlock
+       if lastIndirectIndex < 0 {
+               lastIndirectIndex = lastDirectIndex + 1
+               lastIndirectBlock = insertBlock(lastIndirectIndex)
+       } else {
+               lastIndirectBlock = ensureBlock(lastIndirectIndex)
+       }
 
-               r := &Require{
-                       Mod:      module.Version{Path: path, Version: vers},
-                       Indirect: indirect,
-                       Syntax:   line,
+       // Delete requirements we don't want anymore.
+       // Update versions and indirect comments on requirements we want to keep.
+       // If a requirement is in last{Direct,Indirect}Block with the wrong
+       // indirect marking after this, or if the requirement is in an single
+       // uncommented mixed block (oneFlatUncommentedBlock), move it to the
+       // correct block.
+       //
+       // Some blocks may be empty after this. Cleanup will remove them.
+       need := make(map[string]*Require)
+       for _, r := range req {
+               need[r.Mod.Path] = r
+       }
+       have := make(map[string]*Require)
+       for _, r := range f.Require {
+               path := r.Mod.Path
+               if need[path] == nil || have[path] != nil {
+                       // Requirement not needed, or duplicate requirement. Delete.
+                       r.markRemoved()
+                       continue
+               }
+               have[r.Mod.Path] = r
+               r.setVersion(need[path].Mod.Version)
+               r.setIndirect(need[path].Indirect)
+               if need[path].Indirect &&
+                       (oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastDirectBlock) {
+                       moveReq(r, lastIndirectBlock)
+               } else if !need[path].Indirect &&
+                       (oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastIndirectBlock) {
+                       moveReq(r, lastDirectBlock)
                }
-               r.setIndirect(indirect)
-               f.Require = append(f.Require, r)
        }
 
-       for k, vers := range need {
-               addRequire(k.path, vers, k.indirect, comments[k.path])
+       // Add new requirements.
+       for path, r := range need {
+               if have[path] == nil {
+                       if r.Indirect {
+                               moveReq(r, lastIndirectBlock)
+                       } else {
+                               moveReq(r, lastDirectBlock)
+                       }
+                       f.Require = append(f.Require, r)
+               }
        }
+
        f.SortBlocks()
 }
 
index 34dbdaf5dd3a74d28f40b28fb8d209ce1d6576bd..aa00b9b95b0888f10ba4737cce921984842c1aa9 100644 (file)
@@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
 ## explicit; go 1.17
 golang.org/x/crypto/ed25519
 golang.org/x/crypto/ed25519/internal/edwards25519
-# golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
+# golang.org/x/mod v0.5.1
 ## explicit; go 1.17
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/modfile
index a89afcc101bc81d040d37f635cbf144ae751bbb1..72d13f1b5625773ea02598460297aa2e183b8505 100644 (file)
@@ -5,6 +5,9 @@ go 1.17
 require (
        golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
        golang.org/x/net v0.0.0-20210901185426-6d2eada6345e
+)
+
+require (
        golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
        golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect
 )