(n *InferenceState, source *Type, target *Type)
| 64 | } |
| 65 | |
| 66 | func (c *Checker) inferFromTypes(n *InferenceState, source *Type, target *Type) { |
| 67 | if !c.couldContainTypeVariables(target) || c.isNoInferType(target) { |
| 68 | return |
| 69 | } |
| 70 | if source == c.wildcardType || source == c.blockedStringType { |
| 71 | // We are inferring from an 'any' type. We want to infer this type for every type parameter |
| 72 | // referenced in the target type, so we record it as the propagation type and infer from the |
| 73 | // target to itself. Then, as we find candidates we substitute the propagation type. |
| 74 | savePropagationType := n.propagationType |
| 75 | n.propagationType = source |
| 76 | c.inferFromTypes(n, target, target) |
| 77 | n.propagationType = savePropagationType |
| 78 | return |
| 79 | } |
| 80 | if source.alias != nil && target.alias != nil && source.alias.symbol == target.alias.symbol { |
| 81 | if len(source.alias.typeArguments) != 0 || len(target.alias.typeArguments) != 0 { |
| 82 | // Source and target are types originating in the same generic type alias declaration. |
| 83 | // Simply infer from source type arguments to target type arguments, with defaults applied. |
| 84 | params := c.typeAliasLinks.Get(source.alias.symbol).typeParameters |
| 85 | minParams := c.getMinTypeArgumentCount(params) |
| 86 | nodeIsInJsFile := ast.IsInJSFile(source.alias.symbol.ValueDeclaration) |
| 87 | sourceTypes := c.fillMissingTypeArguments(source.alias.typeArguments, params, minParams, nodeIsInJsFile) |
| 88 | targetTypes := c.fillMissingTypeArguments(target.alias.typeArguments, params, minParams, nodeIsInJsFile) |
| 89 | c.inferFromTypeArguments(n, sourceTypes, targetTypes, c.getAliasVariances(source.alias.symbol)) |
| 90 | } |
| 91 | // And if there weren't any type arguments, there's no reason to run inference as the types must be the same. |
| 92 | return |
| 93 | } |
| 94 | if source == target && source.flags&TypeFlagsUnionOrIntersection != 0 { |
| 95 | // When source and target are the same union or intersection type, just relate each constituent |
| 96 | // type to itself. |
| 97 | for _, t := range source.Types() { |
| 98 | c.inferFromTypes(n, t, t) |
| 99 | } |
| 100 | return |
| 101 | } |
| 102 | if target.flags&TypeFlagsUnion != 0 { |
| 103 | var sourceTypes []*Type |
| 104 | if source.flags&TypeFlagsUnion != 0 { |
| 105 | sourceTypes = source.Types() |
| 106 | } else { |
| 107 | sourceTypes = []*Type{source} |
| 108 | } |
| 109 | // First, infer between identically matching source and target constituents and remove the |
| 110 | // matching types. |
| 111 | tempSources, tempTargets := c.inferFromMatchingTypes(n, sourceTypes, target.Distributed(), (*Checker).isTypeOrBaseIdenticalTo) |
| 112 | // Next, infer between closely matching source and target constituents and remove |
| 113 | // the matching types. Types closely match when they are instantiations of the same |
| 114 | // object type or instantiations of the same type alias. |
| 115 | sources, targets := c.inferFromMatchingTypes(n, tempSources, tempTargets, (*Checker).isTypeCloselyMatchedBy) |
| 116 | if len(targets) == 0 { |
| 117 | return |
| 118 | } |
| 119 | target = c.getUnionType(targets) |
| 120 | if len(sources) == 0 { |
| 121 | // All source constituents have been matched and there is nothing further to infer from. |
| 122 | // However, simply making no inferences is undesirable because it could ultimately mean |
| 123 | // inferring a type parameter constraint. Instead, make a lower priority inference from |
no test coverage detected