TypeCheckSameTypedExprs type checks a list of expressions, asserting that all resolved TypeExprs have the same type. An optional desired type can be provided, which will hint that type which the expressions should resolve to, if possible.
( ctx context.Context, semaCtx *SemaContext, desired *types.T, exprs ...Expr, )
| 2010 | // resolved TypeExprs have the same type. An optional desired type can be provided, |
| 2011 | // which will hint that type which the expressions should resolve to, if possible. |
| 2012 | func TypeCheckSameTypedExprs( |
| 2013 | ctx context.Context, semaCtx *SemaContext, desired *types.T, exprs ...Expr, |
| 2014 | ) ([]TypedExpr, *types.T, error) { |
| 2015 | switch len(exprs) { |
| 2016 | case 0: |
| 2017 | return nil, nil, nil |
| 2018 | case 1: |
| 2019 | typedExpr, err := exprs[0].TypeCheck(ctx, semaCtx, desired) |
| 2020 | if err != nil { |
| 2021 | return nil, nil, err |
| 2022 | } |
| 2023 | typ := typedExpr.ResolvedType() |
| 2024 | if typ == types.Unknown && desired != types.Any { |
| 2025 | // The expression had a NULL type, so we can return the desired type as |
| 2026 | // the expression type. |
| 2027 | typ = desired |
| 2028 | } |
| 2029 | return []TypedExpr{typedExpr}, typ, nil |
| 2030 | } |
| 2031 | |
| 2032 | // Handle tuples, which will in turn call into this function recursively for each element. |
| 2033 | if _, ok := exprs[0].(*Tuple); ok { |
| 2034 | return typeCheckSameTypedTupleExprs(ctx, semaCtx, desired, exprs...) |
| 2035 | } |
| 2036 | |
| 2037 | // Hold the resolved type expressions of the provided exprs, in order. |
| 2038 | // TODO(nvanbenschoten): Look into reducing allocations here. |
| 2039 | typedExprs := make([]TypedExpr, len(exprs)) |
| 2040 | |
| 2041 | constIdxs, placeholderIdxs, resolvableIdxs := typeCheckSplitExprs(ctx, semaCtx, exprs) |
| 2042 | |
| 2043 | s := typeCheckExprsState{ |
| 2044 | ctx: ctx, |
| 2045 | semaCtx: semaCtx, |
| 2046 | exprs: exprs, |
| 2047 | typedExprs: typedExprs, |
| 2048 | constIdxs: constIdxs, |
| 2049 | placeholderIdxs: placeholderIdxs, |
| 2050 | resolvableIdxs: resolvableIdxs, |
| 2051 | } |
| 2052 | |
| 2053 | switch { |
| 2054 | case len(resolvableIdxs) == 0 && len(constIdxs) == 0: |
| 2055 | if err := typeCheckSameTypedPlaceholders(s, desired); err != nil { |
| 2056 | return nil, nil, err |
| 2057 | } |
| 2058 | return typedExprs, desired, nil |
| 2059 | case len(resolvableIdxs) == 0: |
| 2060 | return typeCheckConstsAndPlaceholdersWithDesired(s, desired) |
| 2061 | default: |
| 2062 | firstValidIdx := -1 |
| 2063 | firstValidType := types.Unknown |
| 2064 | for i, j := range resolvableIdxs { |
| 2065 | typedExpr, err := exprs[j].TypeCheck(ctx, semaCtx, desired) |
| 2066 | if err != nil { |
| 2067 | return nil, nil, err |
| 2068 | } |
| 2069 | typedExprs[j] = typedExpr |
no test coverage detected