docs: private SoyType getElementType(SoyType collectionType, ForNonemptyNode node) {
      Preconditions.checkNotNull(collectionType);
      switch (collectionType.getKind()) {
        case UNKNOWN:
          // If we don't know anything about the base type, then make no assumptions
          // about the field type.
          return UnknownType.getInstance();
  
        case LIST:
          if (collectionType == ListType.EMPTY_LIST) {
            errorReporter.report(node.getParent().getSourceLocation(), EMPTY_LIST_FOREACH);
            return ErrorType.getInstance();
          }
          return ((ListType) collectionType).getElementType();
  
        case UNION:
          {
            // If it's a union, then do the field type calculation for each member of
            // the union and combine the result.
            UnionType unionType = (UnionType) collectionType;
            List<SoyType> fieldTypes = new ArrayList<>(unionType.getMembers().size());
            for (SoyType unionMember : unionType.getMembers()) {
              SoyType elementType = getElementType(unionMember, node);
              if (elementType.getKind() == SoyType.Kind.ERROR) {
                return ErrorType.getInstance();
              }
              fieldTypes.add(elementType);
            }
            return SoyTypes.computeLowestCommonType(typeRegistry, fieldTypes);
          }
  
        default:
          errorReporter.report(
              node.getParent().getSourceLocation(),
              BAD_FOREACH_TYPE,
              node.getExpr().toSourceString(),
              node.getExpr().getType()); // Report the outermost union type in the error.
          return ErrorType.getInstance();
      }
    }