diff --git a/internal/checker/checker.go b/internal/checker/checker.go index a6b3a684c5..c28ec83087 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -262,6 +262,7 @@ type InferenceContext struct { mapper *TypeMapper // Mapper that fixes inferences nonFixingMapper *TypeMapper // Mapper that doesn't fix inferences returnMapper *TypeMapper // Type mapper for inferences from return types (if any) + outerReturnMapper *TypeMapper // Type mapper for inferences from return types of outer function (if any) inferredTypeParameters []*Type // Inferred type parameters for function result intraExpressionInferenceSites []IntraExpressionInferenceSite } @@ -7298,7 +7299,7 @@ func (c *Checker) instantiateTypeWithSingleGenericCallSignature(node *ast.Node, if !hasOverlappingInferences(context.inferences, inferences) { c.mergeInferences(context.inferences, inferences) context.inferredTypeParameters = core.Concatenate(context.inferredTypeParameters, uniqueTypeParameters) - return c.getOrCreateTypeFromSignature(instantiatedSignature, nil) + return c.getOrCreateTypeFromSignature(instantiatedSignature) } } } @@ -7306,7 +7307,7 @@ func (c *Checker) instantiateTypeWithSingleGenericCallSignature(node *ast.Node, // and thus get different inferred types. That this is cached on the *first* such attempt is not currently an issue, since expression // types *also* get cached on the first pass. If we ever properly speculate, though, the cached "isolatedSignatureType" signature // field absolutely needs to be included in the list of speculative caches. - return c.getOrCreateTypeFromSignature(c.instantiateSignatureInContextOf(signature, contextualSignature, context, nil), c.getOuterInferenceTypeParameters()) + return c.getOrCreateTypeFromSignature(c.instantiateSignatureInContextOf(signature, contextualSignature, context, nil)) } func (c *Checker) getOuterInferenceTypeParameters() []*Type { @@ -9164,7 +9165,7 @@ func (c *Checker) inferTypeArguments(node *ast.Node, signature *Signature, args contextualSignature := c.getSingleCallSignature(instantiatedType) var inferenceSourceType *Type if contextualSignature != nil && len(contextualSignature.typeParameters) != 0 { - inferenceSourceType = c.getOrCreateTypeFromSignature(c.getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters), nil) + inferenceSourceType = c.getOrCreateTypeFromSignature(c.getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) } else { inferenceSourceType = instantiatedType } @@ -9175,10 +9176,14 @@ func (c *Checker) inferTypeArguments(node *ast.Node, signature *Signature, args // from the return type. We need a separate inference pass here because (a) instantiation of // the source type uses the outer context's return mapper (which excludes inferences made from // outer arguments), and (b) we don't want any further inferences going into this context. + // We use `createOuterReturnMapper` to ensure that all occurrences of outer type parameters are + // replaced with inferences produced from the outer return type or preceding outer arguments. + // This protects against circular inferences, i.e. avoiding situations where inferences reference + // type parameters for which the inferences are being made. returnContext := c.newInferenceContext(signature.typeParameters, signature, context.flags, nil) var outerReturnMapper *TypeMapper if outerContext != nil { - outerReturnMapper = outerContext.returnMapper + outerReturnMapper = c.createOuterReturnMapper(outerContext) } returnSourceType := c.instantiateType(contextualType, outerReturnMapper) c.inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType, InferencePriorityNone, false) @@ -16328,6 +16333,10 @@ func (c *Checker) hasNonCircularBaseConstraint(t *Type) bool { // This is a worker function. Use getConstraintOfTypeParameter which guards against circular constraints func (c *Checker) getConstraintFromTypeParameter(t *Type) *Type { + if t.Flags()&TypeFlagsTypeParameter == 0 { + return nil + } + tp := t.AsTypeParameter() if tp.constraint == nil { var constraint *Type @@ -18447,8 +18456,10 @@ func (c *Checker) getSignatureInstantiation(sig *Signature, typeArguments []*Typ if returnSignature != nil { newReturnSignature := c.cloneSignature(returnSignature) newReturnSignature.typeParameters = inferredTypeParameters + newReturnType := c.getOrCreateTypeFromSignature(newReturnSignature) + newReturnType.AsObjectType().mapper = instantiatedSignature.mapper newInstantiatedSignature := c.cloneSignature(instantiatedSignature) - newInstantiatedSignature.resolvedReturnType = c.getOrCreateTypeFromSignature(newReturnSignature, nil) + newInstantiatedSignature.resolvedReturnType = newReturnType return newInstantiatedSignature } } @@ -18513,7 +18524,7 @@ func (c *Checker) getSingleSignature(t *Type, kind SignatureKind, allowMembers b return nil } -func (c *Checker) getOrCreateTypeFromSignature(sig *Signature, outerTypeParameters []*Type) *Type { +func (c *Checker) getOrCreateTypeFromSignature(sig *Signature) *Type { // There are two ways to declare a construct signature, one is by declaring a class constructor // using the constructor keyword, and the other is declaring a bare construct signature in an // object type literal or interface (using the new keyword). Each way of declaring a constructor @@ -18525,17 +18536,12 @@ func (c *Checker) getOrCreateTypeFromSignature(sig *Signature, outerTypeParamete } // If declaration is undefined, it is likely to be the signature of the default constructor. isConstructor := kind == ast.KindUnknown || kind == ast.KindConstructor || kind == ast.KindConstructSignature || kind == ast.KindConstructorType - // The type must have a symbol with a `Function` flag and a declaration in order to be correctly flagged as possibly containing - // type variables by `couldContainTypeVariables` - t := c.newObjectType(ObjectFlagsAnonymous|ObjectFlagsSingleSignatureType, c.newSymbol(ast.SymbolFlagsFunction, ast.InternalSymbolNameFunction)) - if sig.declaration != nil && !ast.NodeIsSynthesized(sig.declaration) { - t.symbol.Declarations = []*ast.Node{sig.declaration} - t.symbol.ValueDeclaration = sig.declaration - } - if outerTypeParameters == nil && sig.declaration != nil { - outerTypeParameters = c.getOuterTypeParameters(sig.declaration, true /*includeThisTypes*/) + + var symbol *ast.Symbol + if sig.declaration != nil { + symbol = sig.declaration.Symbol() } - t.AsSingleSignatureType().outerTypeParameters = outerTypeParameters + t := c.newObjectType(ObjectFlagsAnonymous|ObjectFlagsSingleSignatureType, symbol) if isConstructor { c.setStructuredTypeMembers(t, nil, nil, []*Signature{sig}, nil) } else { @@ -21182,6 +21188,9 @@ func (c *Checker) getDefaultTypeArgumentType(isInJavaScriptFile bool) *Type { // this gets the instantiated default type of its target. If the type parameter has no default type or // the default is circular, `undefined` is returned. func (c *Checker) getDefaultFromTypeParameter(t *Type) *Type { + if t.flags&TypeFlagsTypeParameter == 0 { + return nil + } defaultType := c.getResolvedTypeParameterDefault(t) if defaultType != c.noConstraintType && defaultType != c.circularConstraintType { return defaultType @@ -21349,7 +21358,6 @@ func (c *Checker) couldContainTypeVariablesWorker(t *Type) bool { } result := t.flags&TypeFlagsInstantiable != 0 || t.flags&TypeFlagsObject != 0 && !c.isNonGenericTopLevelType(t) && (objectFlags&ObjectFlagsReference != 0 && (t.AsTypeReference().node != nil || core.Some(c.getTypeArguments(t), c.couldContainTypeVariables)) || - objectFlags&ObjectFlagsSingleSignatureType != 0 && len(t.AsSingleSignatureType().outerTypeParameters) != 0 || objectFlags&ObjectFlagsAnonymous != 0 && t.symbol != nil && t.symbol.Flags&(ast.SymbolFlagsFunction|ast.SymbolFlagsMethod|ast.SymbolFlagsClass|ast.SymbolFlagsTypeLiteral|ast.SymbolFlagsObjectLiteral) != 0 && t.symbol.Declarations != nil || objectFlags&(ObjectFlagsMapped|ObjectFlagsReverseMapped|ObjectFlagsObjectRestType|ObjectFlagsInstantiationExpressionType) != 0) || t.flags&TypeFlagsUnionOrIntersection != 0 && t.flags&TypeFlagsEnumLiteral == 0 && !c.isNonGenericTopLevelType(t) && core.Some(t.Types(), c.couldContainTypeVariables) @@ -21456,9 +21464,8 @@ func (c *Checker) instantiateTypeWorker(t *Type, m *TypeMapper, alias *TypeAlias } // Handles instantiation of the following object types: -// AnonymousType (ObjectFlagsAnonymous) +// AnonymousType (ObjectFlagsAnonymous|ObjectFlagsSingleSignatureType) // TypeReference with node != nil (ObjectFlagsReference) -// SingleSignatureType (ObjectFlagsSingleSignatureType) // InstantiationExpressionType (ObjectFlagsInstantiationExpressionType) // MappedType (ObjectFlagsMapped) func (c *Checker) getObjectTypeInstantiation(t *Type, m *TypeMapper, alias *TypeAlias) *Type { @@ -21482,34 +21489,30 @@ func (c *Checker) getObjectTypeInstantiation(t *Type, m *TypeMapper, alias *Type default: target = t } - if t.objectFlags&ObjectFlagsSingleSignatureType != 0 { - typeParameters = t.AsSingleSignatureType().outerTypeParameters - } else { - typeParameters = links.outerTypeParameters - if typeParameters == nil { - // The first time an anonymous type is instantiated we compute and store a list of the type - // parameters that are in scope (and therefore potentially referenced). For type literals that - // aren't the right hand side of a generic type alias declaration we optimize by reducing the - // set of type parameters to those that are possibly referenced in the literal. - typeParameters = c.getOuterTypeParameters(declaration, true /*includeThisTypes*/) - if len(target.alias.TypeArguments()) == 0 { - if t.objectFlags&(ObjectFlagsReference|ObjectFlagsInstantiationExpressionType) != 0 { - typeParameters = core.Filter(typeParameters, func(tp *Type) bool { - return c.isTypeParameterPossiblyReferenced(tp, declaration) - }) - } else if target.symbol.Flags&(ast.SymbolFlagsMethod|ast.SymbolFlagsTypeLiteral) != 0 { - typeParameters = core.Filter(typeParameters, func(tp *Type) bool { - return core.Some(t.symbol.Declarations, func(d *ast.Node) bool { - return c.isTypeParameterPossiblyReferenced(tp, d) - }) + typeParameters = links.outerTypeParameters + if typeParameters == nil { + // The first time an anonymous type is instantiated we compute and store a list of the type + // parameters that are in scope (and therefore potentially referenced). For type literals that + // aren't the right hand side of a generic type alias declaration we optimize by reducing the + // set of type parameters to those that are possibly referenced in the literal. + typeParameters = c.getOuterTypeParameters(declaration, true /*includeThisTypes*/) + if len(target.alias.TypeArguments()) == 0 { + if t.objectFlags&(ObjectFlagsReference|ObjectFlagsInstantiationExpressionType) != 0 { + typeParameters = core.Filter(typeParameters, func(tp *Type) bool { + return c.isTypeParameterPossiblyReferenced(tp, declaration) + }) + } else if target.symbol.Flags&(ast.SymbolFlagsMethod|ast.SymbolFlagsTypeLiteral) != 0 { + typeParameters = core.Filter(typeParameters, func(tp *Type) bool { + return core.Some(t.symbol.Declarations, func(d *ast.Node) bool { + return c.isTypeParameterPossiblyReferenced(tp, d) }) - } - } - if typeParameters == nil { - typeParameters = []*Type{} + }) } - links.outerTypeParameters = typeParameters } + if typeParameters == nil { + typeParameters = []*Type{} + } + links.outerTypeParameters = typeParameters } if len(typeParameters) == 0 { return t @@ -21534,12 +21537,10 @@ func (c *Checker) getObjectTypeInstantiation(t *Type, m *TypeMapper, alias *Type } result := data.instantiations[key] if result == nil { - if t.objectFlags&ObjectFlagsSingleSignatureType != 0 { - result = c.instantiateAnonymousType(t, m, nil /*alias*/) - data.instantiations[key] = result - return result - } newMapper := newTypeMapper(typeParameters, typeArguments) + if target.objectFlags&ObjectFlagsSingleSignatureType != 0 && m != nil { + newMapper = c.combineTypeMappers(newMapper, m) + } switch { case target.objectFlags&ObjectFlagsReference != 0: result = c.createDeferredTypeReference(t.Target(), t.AsTypeReference().node, newMapper, newAlias) @@ -21635,8 +21636,6 @@ func (c *Checker) instantiateAnonymousType(t *Type, m *TypeMapper, alias *TypeAl freshTypeParameter.AsTypeParameter().mapper = m case t.objectFlags&ObjectFlagsInstantiationExpressionType != 0: result.AsInstantiationExpressionType().node = t.AsInstantiationExpressionType().node - case t.objectFlags&ObjectFlagsSingleSignatureType != 0: - result.AsSingleSignatureType().outerTypeParameters = t.AsSingleSignatureType().outerTypeParameters } if alias == nil { alias = c.instantiateTypeAlias(t.alias, m) @@ -24161,7 +24160,7 @@ func (c *Checker) newObjectType(objectFlags ObjectFlags, symbol *ast.Symbol) *Ty case objectFlags&ObjectFlagsInstantiationExpressionType != 0: data = &InstantiationExpressionType{} case objectFlags&ObjectFlagsSingleSignatureType != 0: - data = &SingleSignatureType{} + data = &ObjectType{} case objectFlags&ObjectFlagsAnonymous != 0: data = &ObjectType{} default: @@ -28447,7 +28446,7 @@ func (c *Checker) getContextualTypeForArgumentAtIndex(callTarget *ast.Node, argI func (c *Checker) getContextualTypeForDecorator(decorator *ast.Node) *Type { signature := c.getDecoratorCallSignature(decorator) if signature != nil { - return c.getOrCreateTypeFromSignature(signature, nil) + return c.getOrCreateTypeFromSignature(signature) } return nil } @@ -28977,7 +28976,7 @@ func (c *Checker) getESDecoratorCallSignature(decorator *ast.Node) *Signature { // instance, depending on whether the member was `static`. var valueType *Type if ast.IsMethodDeclaration(node) { - valueType = c.getOrCreateTypeFromSignature(c.getSignatureFromDeclaration(node), nil) + valueType = c.getOrCreateTypeFromSignature(c.getSignatureFromDeclaration(node)) } else { valueType = c.getTypeOfNode(node) } @@ -29144,7 +29143,7 @@ func (c *Checker) newESDecoratorCallSignature(targetType *Type, contextType *Typ // Creates a synthetic `FunctionType` func (c *Checker) newFunctionType(typeParameters []*Type, thisParameter *ast.Symbol, parameters []*ast.Symbol, returnType *Type) *Type { signature := c.newCallSignature(typeParameters, thisParameter, parameters, returnType) - return c.getOrCreateTypeFromSignature(signature, nil) + return c.getOrCreateTypeFromSignature(signature) } func (c *Checker) newGetterFunctionType(t *Type) *Type { diff --git a/internal/checker/inference.go b/internal/checker/inference.go index d395f03a98..5ef43cb52d 100644 --- a/internal/checker/inference.go +++ b/internal/checker/inference.go @@ -1349,6 +1349,19 @@ func (c *Checker) getMapperFromContext(n *InferenceContext) *TypeMapper { return n.mapper } +// Return a type mapper that combines the context's return mapper with a mapper that erases any additional type parameters +// to their inferences at the time of creation. +func (c *Checker) createOuterReturnMapper(context *InferenceContext) *TypeMapper { + if context.outerReturnMapper == nil { + mapper := c.cloneInferenceContext(context, InferenceFlagsNone).mapper + if context.returnMapper != nil { + mapper = newMergedTypeMapper(context.returnMapper, mapper) + } + context.outerReturnMapper = mapper + } + return context.outerReturnMapper +} + func (c *Checker) getCovariantInference(inference *InferenceInfo, signature *Signature) *Type { // Extract all object and array literal types and replace them with a single widened and normalized type. candidates := c.unionObjectAndArrayLiteralCandidates(inference.candidates) diff --git a/internal/checker/jsx.go b/internal/checker/jsx.go index 7f0342d76b..8512920510 100644 --- a/internal/checker/jsx.go +++ b/internal/checker/jsx.go @@ -1107,7 +1107,7 @@ func (c *Checker) getStaticTypeOfReferencedJsxConstructor(context *ast.Node) *Ty if isJsxIntrinsicTagName(context.TagName()) { result := c.getIntrinsicAttributesTypeFromJsxOpeningLikeElement(context) fakeSignature := c.createSignatureForJSXIntrinsic(context, result) - return c.getOrCreateTypeFromSignature(fakeSignature, nil) + return c.getOrCreateTypeFromSignature(fakeSignature) } tagType := c.checkExpressionCached(context.TagName()) if tagType.flags&TypeFlagsStringLiteral != 0 { @@ -1116,7 +1116,7 @@ func (c *Checker) getStaticTypeOfReferencedJsxConstructor(context *ast.Node) *Ty return c.errorType } fakeSignature := c.createSignatureForJSXIntrinsic(context, result) - return c.getOrCreateTypeFromSignature(fakeSignature, nil) + return c.getOrCreateTypeFromSignature(fakeSignature) } return tagType } diff --git a/internal/checker/nodebuilderimpl.go b/internal/checker/nodebuilderimpl.go index 7be790ad36..d6c913dd62 100644 --- a/internal/checker/nodebuilderimpl.go +++ b/internal/checker/nodebuilderimpl.go @@ -2376,7 +2376,7 @@ func (b *nodeBuilderImpl) createTypeNodeFromObjectType(t *Type) *ast.TypeNode { }) if len(abstractSignatures) > 0 { types := core.Map(abstractSignatures, func(s *Signature) *Type { - return b.ch.getOrCreateTypeFromSignature(s, nil) + return b.ch.getOrCreateTypeFromSignature(s) }) // count the number of type elements excluding abstract constructors typeElementCount := len(callSigs) + (len(ctorSigs) - len(abstractSignatures)) + len(resolved.indexInfos) + (core.IfElse(b.ctx.flags&nodebuilder.FlagsWriteClassExpressionAsTypeLiteral != 0, core.CountWhere(resolved.properties, func(p *ast.Symbol) bool { diff --git a/internal/checker/types.go b/internal/checker/types.go index 0a66c81c2f..f9b6f642e1 100644 --- a/internal/checker/types.go +++ b/internal/checker/types.go @@ -574,11 +574,10 @@ func (t *Type) ObjectFlags() ObjectFlags { // Casts for concrete struct types -func (t *Type) AsIntrinsicType() *IntrinsicType { return t.data.(*IntrinsicType) } -func (t *Type) AsLiteralType() *LiteralType { return t.data.(*LiteralType) } -func (t *Type) AsUniqueESSymbolType() *UniqueESSymbolType { return t.data.(*UniqueESSymbolType) } -func (t *Type) AsTupleType() *TupleType { return t.data.(*TupleType) } -func (t *Type) AsSingleSignatureType() *SingleSignatureType { return t.data.(*SingleSignatureType) } +func (t *Type) AsIntrinsicType() *IntrinsicType { return t.data.(*IntrinsicType) } +func (t *Type) AsLiteralType() *LiteralType { return t.data.(*LiteralType) } +func (t *Type) AsUniqueESSymbolType() *UniqueESSymbolType { return t.data.(*UniqueESSymbolType) } +func (t *Type) AsTupleType() *TupleType { return t.data.(*TupleType) } func (t *Type) AsInstantiationExpressionType() *InstantiationExpressionType { return t.data.(*InstantiationExpressionType) } @@ -838,10 +837,6 @@ func (t *StructuredType) Properties() []*ast.Symbol { // ObjectFlagsAnonymous|ObjectFlagsInstantiationExpression: Originating instantiation expression type // ObjectFlagsAnonymous|ObjectFlagsInstantiated|ObjectFlagsInstantiationExpression: Instantiated instantiation expression type -// SingleSignatureType: -// ObjectFlagsAnonymous|ObjectFlagsSingleSignatureType: Originating single signature type -// ObjectFlagsAnonymous|ObjectFlagsInstantiated|ObjectFlagsSingleSignatureType: Instantiated single signature type - // ReverseMappedType: // ObjectFlagsAnonymous|ObjectFlagsReverseMapped: Reverse mapped type @@ -948,13 +943,6 @@ func (t *TupleType) ElementFlags() []ElementFlags { return elementFlags } -// SingleSignatureType - -type SingleSignatureType struct { - ObjectType - outerTypeParameters []*Type -} - // InstantiationExpressionType type InstantiationExpressionType struct { diff --git a/internal/testrunner/compiler_runner.go b/internal/testrunner/compiler_runner.go index 1eb993988a..215cba9c8d 100644 --- a/internal/testrunner/compiler_runner.go +++ b/internal/testrunner/compiler_runner.go @@ -105,9 +105,6 @@ var skippedTests = []string{ "noImplicitUseStrict_amd.ts", "noImplicitAnyIndexingSuppressed.ts", "excessPropertyErrorsSuppressed.ts", - - // Broken - "inferenceFromGenericClassNoCrash1.ts", } func (r *CompilerBaselineRunner) RunTests(t *testing.T) { diff --git a/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types b/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types index bbceb8c94b..303a9ff827 100644 --- a/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types +++ b/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types @@ -80,7 +80,7 @@ type Result1 = ComponentProps; // that could be incorrectly reused by this one type Result2 = Test<{ component: typeof ComponentWithForwardRef }>; // no `T` leak ->Result2 : PropsWithoutRef> & { ref?: Ref | undefined; } +>Result2 : Omit & { ref?: Ref | undefined; } >component : >(props: PropsWithoutRef> & { ref?: Ref | undefined; }) => unknown >ComponentWithForwardRef : >(props: PropsWithoutRef> & { ref?: Ref | undefined; }) => unknown diff --git a/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types.diff b/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types.diff index ba4ea89164..d581065c3c 100644 --- a/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types.diff +++ b/testdata/baselines/reference/submodule/compiler/genericCallInferenceInConditionalTypes1.types.diff @@ -29,14 +29,7 @@ props: ComponentPropsWithoutRef, >props : PropsWithoutRef> -@@= skipped -38, +38 lines =@@ - - // that could be incorrectly reused by this one - type Result2 = Test<{ component: typeof ComponentWithForwardRef }>; // no `T` leak -->Result2 : Omit & { ref?: Ref | undefined; } -+>Result2 : PropsWithoutRef> & { ref?: Ref | undefined; } - >component : >(props: PropsWithoutRef> & { ref?: Ref | undefined; }) => unknown - >ComponentWithForwardRef : >(props: PropsWithoutRef> & { ref?: Ref | undefined; }) => unknown +@@= skipped -44, +44 lines =@@ // same as ComponentWithForwardRef above but using a resolved signature instead of a direct inferred result of `forwardRef` declare const ComponentWithForwardRef2: >( @@ -49,7 +42,7 @@ className?: string; >className : string | undefined -@@= skipped -25, +25 lines =@@ +@@= skipped -19, +19 lines =@@ ) => unknown; type Result3 = ComponentProps; diff --git a/testdata/baselines/reference/submodule/compiler/genericCallInferenceWithGenericLocalFunction.types b/testdata/baselines/reference/submodule/compiler/genericCallInferenceWithGenericLocalFunction.types index ba58eb6787..11ebc59664 100644 --- a/testdata/baselines/reference/submodule/compiler/genericCallInferenceWithGenericLocalFunction.types +++ b/testdata/baselines/reference/submodule/compiler/genericCallInferenceWithGenericLocalFunction.types @@ -96,25 +96,25 @@ const added3 = addedSome3({ c: true }); >true : true const addP3_other = withP3({ foo: 'bar' }); ->addP3_other : (from: I) => (from2: I2) => I & I2 & { a: number; } ->withP3({ foo: 'bar' }) : (from: I) => (from2: I2) => I & I2 & { a: number; } +>addP3_other : (from: I) => (from2: I2) => I & I2 & { foo: string; } +>withP3({ foo: 'bar' }) : (from: I) => (from2: I2) => I & I2 & { foo: string; } >withP3 :

(p: P) => (from: I) => (from2: I2) => I & I2 & P >{ foo: 'bar' } : { foo: string; } >foo : string >'bar' : "bar" const addedSome3_other = addP3_other({ qwerty: 123 }); ->addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { a: number; } ->addP3_other({ qwerty: 123 }) : (from2: I2) => { qwerty: number; } & I2 & { a: number; } ->addP3_other : (from: I) => (from2: I2) => I & I2 & { a: number; } +>addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { foo: string; } +>addP3_other({ qwerty: 123 }) : (from2: I2) => { qwerty: number; } & I2 & { foo: string; } +>addP3_other : (from: I) => (from2: I2) => I & I2 & { foo: string; } >{ qwerty: 123 } : { qwerty: number; } >qwerty : number >123 : 123 const added3_other = addedSome3_other({ bazinga: true }); ->added3_other : { qwerty: number; } & { bazinga: boolean; } & { a: number; } ->addedSome3_other({ bazinga: true }) : { qwerty: number; } & { bazinga: boolean; } & { a: number; } ->addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { a: number; } +>added3_other : { qwerty: number; } & { bazinga: boolean; } & { foo: string; } +>addedSome3_other({ bazinga: true }) : { qwerty: number; } & { bazinga: boolean; } & { foo: string; } +>addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { foo: string; } >{ bazinga: true } : { bazinga: true; } >bazinga : true >true : true diff --git a/testdata/baselines/reference/submodule/compiler/genericCallInferenceWithGenericLocalFunction.types.diff b/testdata/baselines/reference/submodule/compiler/genericCallInferenceWithGenericLocalFunction.types.diff deleted file mode 100644 index 1bd90ecba2..0000000000 --- a/testdata/baselines/reference/submodule/compiler/genericCallInferenceWithGenericLocalFunction.types.diff +++ /dev/null @@ -1,36 +0,0 @@ ---- old.genericCallInferenceWithGenericLocalFunction.types -+++ new.genericCallInferenceWithGenericLocalFunction.types -@@= skipped -95, +95 lines =@@ - >true : true - - const addP3_other = withP3({ foo: 'bar' }); -->addP3_other : (from: I) => (from2: I2) => I & I2 & { foo: string; } -->withP3({ foo: 'bar' }) : (from: I) => (from2: I2) => I & I2 & { foo: string; } -+>addP3_other : (from: I) => (from2: I2) => I & I2 & { a: number; } -+>withP3({ foo: 'bar' }) : (from: I) => (from2: I2) => I & I2 & { a: number; } - >withP3 :

(p: P) => (from: I) => (from2: I2) => I & I2 & P - >{ foo: 'bar' } : { foo: string; } - >foo : string - >'bar' : "bar" - - const addedSome3_other = addP3_other({ qwerty: 123 }); -->addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { foo: string; } -->addP3_other({ qwerty: 123 }) : (from2: I2) => { qwerty: number; } & I2 & { foo: string; } -->addP3_other : (from: I) => (from2: I2) => I & I2 & { foo: string; } -+>addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { a: number; } -+>addP3_other({ qwerty: 123 }) : (from2: I2) => { qwerty: number; } & I2 & { a: number; } -+>addP3_other : (from: I) => (from2: I2) => I & I2 & { a: number; } - >{ qwerty: 123 } : { qwerty: number; } - >qwerty : number - >123 : 123 - - const added3_other = addedSome3_other({ bazinga: true }); -->added3_other : { qwerty: number; } & { bazinga: boolean; } & { foo: string; } -->addedSome3_other({ bazinga: true }) : { qwerty: number; } & { bazinga: boolean; } & { foo: string; } -->addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { foo: string; } -+>added3_other : { qwerty: number; } & { bazinga: boolean; } & { a: number; } -+>addedSome3_other({ bazinga: true }) : { qwerty: number; } & { bazinga: boolean; } & { a: number; } -+>addedSome3_other : (from2: I2) => { qwerty: number; } & I2 & { a: number; } - >{ bazinga: true } : { bazinga: true; } - >bazinga : true - >true : true \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.errors.txt b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.errors.txt new file mode 100644 index 0000000000..6103c38d6d --- /dev/null +++ b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.errors.txt @@ -0,0 +1,14 @@ +inferenceFromGenericClassNoCrash1.ts(5,3): error TS2564: Property 't' has no initializer and is not definitely assigned in the constructor. + + +==== inferenceFromGenericClassNoCrash1.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576 + + function RenderFlagsMixin object>(Base?: T) {} + class Container { + t: T; + ~ +!!! error TS2564: Property 't' has no initializer and is not definitely assigned in the constructor. + } + RenderFlagsMixin(Container); + \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.symbols b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.symbols new file mode 100644 index 0000000000..aa8dca0a91 --- /dev/null +++ b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.symbols @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/inferenceFromGenericClassNoCrash1.ts] //// + +=== inferenceFromGenericClassNoCrash1.ts === +// https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576 + +function RenderFlagsMixin object>(Base?: T) {} +>RenderFlagsMixin : Symbol(RenderFlagsMixin, Decl(inferenceFromGenericClassNoCrash1.ts, 0, 0)) +>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 26)) +>args : Symbol(args, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 41)) +>Base : Symbol(Base, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 68)) +>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 26)) + +class Container { +>Container : Symbol(Container, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 80)) +>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 3, 16)) + + t: T; +>t : Symbol(Container.t, Decl(inferenceFromGenericClassNoCrash1.ts, 3, 20)) +>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 3, 16)) +} +RenderFlagsMixin(Container); +>RenderFlagsMixin : Symbol(RenderFlagsMixin, Decl(inferenceFromGenericClassNoCrash1.ts, 0, 0)) +>Container : Symbol(Container, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 80)) + diff --git a/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.types b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.types new file mode 100644 index 0000000000..1db355347a --- /dev/null +++ b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.types @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/inferenceFromGenericClassNoCrash1.ts] //// + +=== inferenceFromGenericClassNoCrash1.ts === +// https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576 + +function RenderFlagsMixin object>(Base?: T) {} +>RenderFlagsMixin : object>(Base?: T | undefined) => void +>args : any[] +>Base : T | undefined + +class Container { +>Container : Container + + t: T; +>t : T +} +RenderFlagsMixin(Container); +>RenderFlagsMixin(Container) : void +>RenderFlagsMixin : object>(Base?: T | undefined) => void +>Container : typeof Container + diff --git a/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.types.diff b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.types.diff new file mode 100644 index 0000000000..5ac0241f8c --- /dev/null +++ b/testdata/baselines/reference/submodule/compiler/inferenceFromGenericClassNoCrash1.types.diff @@ -0,0 +1,18 @@ +--- old.inferenceFromGenericClassNoCrash1.types ++++ new.inferenceFromGenericClassNoCrash1.types +@@= skipped -3, +3 lines =@@ + // https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576 + + function RenderFlagsMixin object>(Base?: T) {} +->RenderFlagsMixin : object>(Base?: T) => void ++>RenderFlagsMixin : object>(Base?: T | undefined) => void + >args : any[] + >Base : T | undefined + +@@= skipped -12, +12 lines =@@ + } + RenderFlagsMixin(Container); + >RenderFlagsMixin(Container) : void +->RenderFlagsMixin : object>(Base?: T) => void ++>RenderFlagsMixin : object>(Base?: T | undefined) => void + >Container : typeof Container diff --git a/testdata/baselines/reference/submodule/compiler/nestedGenericSpreadInference.types b/testdata/baselines/reference/submodule/compiler/nestedGenericSpreadInference.types index 5f36c4da7f..043c9d9a34 100644 --- a/testdata/baselines/reference/submodule/compiler/nestedGenericSpreadInference.types +++ b/testdata/baselines/reference/submodule/compiler/nestedGenericSpreadInference.types @@ -14,10 +14,10 @@ declare function call(x: { x: (...args: A) => T }, ...ar >args : A const leak = call(wrap((x: T) => x), 1); ->leak : number ->call(wrap((x: T) => x), 1) : number +>leak : unknown +>call(wrap((x: T) => x), 1) : unknown >call : (x: { x: (...args: A) => T; }, ...args: A) => T ->wrap((x: T) => x) : { x: (x: A[0]) => A[0]; } +>wrap((x: T) => x) : { x: (x: unknown) => unknown; } >wrap : (x: X) => { x: X; } >(x: T) => x : (x: T) => T >x : T diff --git a/testdata/baselines/reference/submodule/compiler/nestedGenericSpreadInference.types.diff b/testdata/baselines/reference/submodule/compiler/nestedGenericSpreadInference.types.diff deleted file mode 100644 index 30ea05eea3..0000000000 --- a/testdata/baselines/reference/submodule/compiler/nestedGenericSpreadInference.types.diff +++ /dev/null @@ -1,16 +0,0 @@ ---- old.nestedGenericSpreadInference.types -+++ new.nestedGenericSpreadInference.types -@@= skipped -13, +13 lines =@@ - >args : A - - const leak = call(wrap((x: T) => x), 1); -->leak : unknown -->call(wrap((x: T) => x), 1) : unknown -+>leak : number -+>call(wrap((x: T) => x), 1) : number - >call : (x: { x: (...args: A) => T; }, ...args: A) => T -->wrap((x: T) => x) : { x: (x: unknown) => unknown; } -+>wrap((x: T) => x) : { x: (x: A[0]) => A[0]; } - >wrap : (x: X) => { x: X; } - >(x: T) => x : (x: T) => T - >x : T \ No newline at end of file