code: def complete_abstract_value(
      exe_context,  # type: ExecutionContext
      return_type,  # type: Union[GraphQLInterfaceType, GraphQLUnionType]
      field_asts,  # type: List[Field]
      info,  # type: ResolveInfo
      path,  # type: List[Union[int, str]]
      result,  # type: Any
  ):
      # type: (...) -> Dict[str, Any]
      
      runtime_type = None  # type: Union[str, GraphQLObjectType, None]
  
      # Field type must be Object, Interface or Union and expect sub-selections.
      if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)):
          if return_type.resolve_type:
              runtime_type = return_type.resolve_type(result, info)
          else:
              runtime_type = get_default_resolve_type_fn(result, info, return_type)
  
      if isinstance(runtime_type, string_types):
          runtime_type = info.schema.get_type(runtime_type)  # type: ignore
  
      if not isinstance(runtime_type, GraphQLObjectType):
          raise GraphQLError(
              (
                  "Abstract type {} must resolve to an Object type at runtime "
                  + 'for field {}.{} with value "{}", received "{}".'
              ).format(
                  return_type, info.parent_type, info.field_name, result, runtime_type
              ),
              field_asts,
          )
  
      if not exe_context.schema.is_possible_type(return_type, runtime_type):
          raise GraphQLError(
              u'Runtime Object type "{}" is not a possible type for "{}".'.format(
                  runtime_type, return_type
              ),
              field_asts,
          )
  
      return complete_object_value(
          exe_context, runtime_type, field_asts, info, path, result
      )
docs: Complete an value of an abstract type by determining the runtime type of that value, then completing based
      on that type.