function createMetaFields (results, nestedResults, childResults) {
  const allResults = computed(() => [nestedResults, childResults]
    .filter(res => res)
    .reduce((allRes, res) => {
      return allRes.concat(Object.values(unwrap(res)))
    }, [])
  )

  // returns `$dirty` as true, if all children are dirty
  const $dirty = computed({
    get () {
      return results.$dirty.value ||
        (allResults.value.length ? allResults.value.every(r => r.$dirty) : false)
    },
    set (v) {
      results.$dirty.value = v
    }
  })

  const $silentErrors = computed(() => {
    // current state level errors, fallback to empty array if root
    const modelErrors = unwrap(results.$silentErrors) || []

    // collect all nested and child $silentErrors
    const nestedErrors = allResults.value
      .filter(result => (unwrap(result).$silentErrors || []).length)
      .reduce((errors, result) => {
        return errors.concat(...result.$silentErrors)
      }, [])

    // merge the $silentErrors
    return modelErrors.concat(nestedErrors)
  })

  const $errors = computed(() => {
    // current state level errors, fallback to empty array if root
    const modelErrors = unwrap(results.$errors) || []

    // collect all nested and child $errors
    const nestedErrors = allResults.value
      .filter(result => (unwrap(result).$errors || []).length)
      .reduce((errors, result) => {
        return errors.concat(...result.$errors)
      }, [])

    // merge the $errors
    return modelErrors.concat(nestedErrors)
  })

  const $invalid = computed(() =>
    // if any of the nested values is invalid
    allResults.value.some(r => r.$invalid) ||
    // or if the current state is invalid
    unwrap(results.$invalid) ||
    // fallback to false if is root
    false
  )

  const $pending = computed(() =>
    // if any of the nested values is pending
    allResults.value.some(r => unwrap(r.$pending)) ||
    // if any of the current state validators is pending
    unwrap(results.$pending) ||
    // fallback to false if is root
    false
  )

  const $anyDirty = computed(() =>
    allResults.value.some(r => r.$dirty) ||
    allResults.value.some(r => r.$anyDirty) ||
    $dirty.value
  )

  const $error = computed(() => $dirty.value ? $pending.value || $invalid.value : false)

  const $touch = () => {
    // call the root $touch
    results.$touch()
    // call all nested level $touch
    allResults.value.forEach((result) => {
      result.$touch()
    })
  }

  const $commit = () => {
    // call the root $touch
    results.$commit()
    // call all nested level $touch
    allResults.value.forEach((result) => {
      result.$commit()
    })
  }

  const $reset = () => {
    // reset the root $dirty state
    results.$reset()
    // reset all the children $dirty states
    allResults.value.forEach((result) => {
      result.$reset()
    })
  }

  // Ensure that if all child and nested results are $dirty, this also becomes $dirty
  if (allResults.value.length && allResults.value.every(nr => nr.$dirty)) $touch()

  return {
    $dirty,
    $errors,
    $invalid,
    $anyDirty,
    $error,
    $pending,
    $touch,
    $reset,
    $silentErrors,
    $commit
  }
}
Generates the Meta fields from the results
@param {ValidationResult|{}} results
@param {Object.<string, VuelidateState>} nestedResults
@param {Object.<string, ValidationResult>} childResults
@return {{$anyDirty: Ref<Boolean>, $error: Ref<Boolean>, $invalid: Ref<Boolean>, $errors: Ref<ErrorObject[]>, $dirty: Ref<Boolean>, $touch: Function, $reset: Function }}