code: def get_defaulted_type(
      schema: Schema, tag: str, type: str
  ) -> Tuple[str, str, bool]:
      """
      Given the type string for a field of a given tag, determine the type of the after-defaulting
      value.  This is used by the auto-generated getters, so that parts of the code which consume
      experiment configs can use compile-time checks to know which pointer-typed fields values might
      be nil and which ones have defaults and will never be nil.
      """
      prop = schema.schema["properties"].get(tag, {})
      if prop is True:
          prop = {}
      default = prop.get("default")
  
      required = tag in schema.schema.get("required", [])
      eventuallyRequired = required or tag in schema.schema.get(
          "eventuallyRequired", []
      )
  
      KNOWN_MAP_OR_SLICE_ALIAS_TYPES = [
          "BindMountsConfigV0",
          "DevicesConfigV0",
          "HyperparametersV0",
          "LabelsV0",
          "LogPoliciesConfigV0",
          # Technically Name is a struct containing a string pointer, which exists only to
          # handle the semantics of runtime defaultables.  But it has the same mechanics as a map or
          # slice alias, so we include it here.
          "Name",
      ]
  
      # Disallow pointers for required fields in all cases.
      if required and type.startswith("*"):
          raise AssertionError(
              f"ERROR: {schema.golang_title}.{tag} type ({type}) must not be a pointer, since it is "
              "a required field"
          )
  
      # There are two ways that you can know the final value of a pointer field will never be nil;
      # either the default value is not null, or the field is required/eventuallyRequired.
      if default is not None or eventuallyRequired:
          if type.startswith("*map[") or type.startswith("*[]"):
              raise AssertionError(
                  f"ERROR: {tag} type ({type}) is a pointer to a map or slice type.\n"
                  "This is not allowed, since maps and slices can be nil by default, so it is\n"
                  "an unnecesary layer of indirection which complicates the code."
              )
          elif type.startswith("**"):
              raise AssertionError(
                  f"{tag} type ({type}) must not be a double pointer"
              )
          elif type.startswith("*"):
              # Pointers are nil-able, and the non-nil type is without the '*'.
              type = type[1:]
          elif (
              type.startswith("map[")
              or type.startswith("[]")
              or type in KNOWN_MAP_OR_SLICE_ALIAS_TYPES
          ):
              # Maps and Slices are nil-able, and the non-nil type is just the same type.
              pass
          elif not required:
              raise AssertionError(
                  f"ERROR: {schema.golang_title}.{tag} type ({type}) must be nil-able, since it is "
                  "not required.  This is because `nil` is how we represent values which were not "
                  "provided by the user.  Nilable types are pointers, slices, or maps.\n"
                  "\n"
                  f"Note: if {type} is a type alias for a map or slice type, like:\n"
                  "\n"
                  "    type BindMountsConfigV0 []BindMounts\n"
                  "\n"
                  f'then you can safely just add "{type}" to KNOWN_MAP_OR_SLICE_ALIAS_TYPES\n'
                  "in schemas/gen.py to avoid this error."
              )
  
      return type, default, required
  
imports: import argparse
  import json
  import os
  import re
  import sys
  from typing import List, Optional, Tuple
label_desc: Use image node_id 8 for calling a global function with example usage: get_defaulted_type(schema, tag, type) and returns: type,  default,  required