From 206e194a0f629c94672d72e3ac242871b8e9073a Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 30 May 2025 15:14:34 -0700 Subject: [PATCH] Ensure we don't copy OrderedMaps --- internal/checker/checker.go | 4 ++-- internal/collections/ordered_map.go | 14 +++++++++++++- internal/tsoptions/tsconfigparsing.go | 4 ++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 8bb47b0286..9a1d547ac9 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -20072,7 +20072,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s if singleProp == nil || isUnion && (propSet.Size() != 0 || checkFlags&ast.CheckFlagsPartial != 0) && checkFlags&(ast.CheckFlagsContainsPrivate|ast.CheckFlagsContainsProtected) != 0 && - !(propSet.Size() != 0 && c.hasCommonDeclaration(propSet)) { + !(propSet.Size() != 0 && c.hasCommonDeclaration(&propSet)) { // No property was found, or, in a union, a property has a private or protected declaration in one // constituent, but is missing or has a different declaration in another constituent. return nil @@ -20194,7 +20194,7 @@ func isPrototypeProperty(symbol *ast.Symbol) bool { return symbol.Flags&ast.SymbolFlagsMethod != 0 || symbol.CheckFlags&ast.CheckFlagsSyntheticMethod != 0 } -func (c *Checker) hasCommonDeclaration(symbols collections.OrderedSet[*ast.Symbol]) bool { +func (c *Checker) hasCommonDeclaration(symbols *collections.OrderedSet[*ast.Symbol]) bool { var commonDeclarations core.Set[*ast.Node] for symbol := range symbols.Values() { if len(symbol.Declarations) == 0 { diff --git a/internal/collections/ordered_map.go b/internal/collections/ordered_map.go index f95273a5bf..4e1dcf2d47 100644 --- a/internal/collections/ordered_map.go +++ b/internal/collections/ordered_map.go @@ -18,10 +18,22 @@ import ( // OrderedMap is an insertion ordered map. type OrderedMap[K comparable, V any] struct { + _ noCopy keys []K mp map[K]V } +// noCopy may be embedded into structs which must not be copied +// after the first use. +// +// See https://golang.org/issues/8005#issuecomment-190753527 +// for details. +type noCopy struct{} + +// Lock is a no-op used by -copylocks checker from `go vet`. +func (*noCopy) Lock() {} +func (*noCopy) Unlock() {} + // NewOrderedMapWithSizeHint creates a new OrderedMap with a hint for the number of elements it will contain. func NewOrderedMapWithSizeHint[K comparable, V any](hint int) *OrderedMap[K, V] { m := newMapWithSizeHint[K, V](hint) @@ -191,7 +203,7 @@ func (m *OrderedMap[K, V]) clone() OrderedMap[K, V] { } } -func (m OrderedMap[K, V]) MarshalJSON() ([]byte, error) { +func (m *OrderedMap[K, V]) MarshalJSON() ([]byte, error) { if len(m.mp) == 0 { return []byte("{}"), nil } diff --git a/internal/tsoptions/tsconfigparsing.go b/internal/tsoptions/tsconfigparsing.go index 44782554e6..b1ec70866a 100644 --- a/internal/tsoptions/tsconfigparsing.go +++ b/internal/tsoptions/tsconfigparsing.go @@ -1471,7 +1471,7 @@ func hasFileWithHigherPriorityExtension(file string, extensions [][]string, hasF // Removes files included via wildcard expansion with a lower extension priority that have already been included. // file is the path to the file. -func removeWildcardFilesWithLowerPriorityExtension(file string, wildcardFiles collections.OrderedMap[string, string], extensions [][]string, keyMapper func(value string) string) { +func removeWildcardFilesWithLowerPriorityExtension(file string, wildcardFiles *collections.OrderedMap[string, string], extensions [][]string, keyMapper func(value string) string) { var extensionGroup []string for _, group := range extensions { if tspath.FileExtensionIsOneOf(file, group) { @@ -1575,7 +1575,7 @@ func getFileNamesFromConfigSpecs( // extension due to the user-defined order of entries in the // "include" array. If there is a lower priority extension in the // same directory, we should remove it. - removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMappper) + removeWildcardFilesWithLowerPriorityExtension(file, &wildcardFileMap, supportedExtensions, keyMappper) key := keyMappper(file) if !literalFileMap.Has(key) && !wildcardFileMap.Has(key) { wildcardFileMap.Set(key, file)