public static function set(&$data, $path, $value)
    {
        Assert::isArrayAccessible($data);
        Assert::stringNotEmpty($path);

        $queue = explode('/', $path);
        // Optimization for simple sets.
        if (count($queue) === 1) {
            if ($path === '[]') {
                $data[] = $value;
            } elseif (static::$unsetMarker && $value === static::$unsetMarker) {
                unset($data[$path]);
            } else {
                $data[$path] = $value;
            }

            return;
        }

        $invalidKey = null;
        $current = &$data;
        while (($key = array_shift($queue)) !== null) {
            if (!is_array($current) && !($current instanceof ArrayAccess)) {
                throw new RuntimeException(
                    sprintf(
                        "Cannot set '%s', because '%s' is already set and not an array or an object implementing ArrayAccess.",
                        $path,
                        $invalidKey
                    )
                );
            }
            if (!$queue) {
                if ($key === '[]') {
                    $current[] = $value;
                } elseif (static::$unsetMarker && $value === static::$unsetMarker) {
                    unset($current[$key]);
                } else {
                    $current[$key] = $value;
                }

                return;
            }

            if ($current instanceof Bag && !($current instanceof MutableBag)) {
                Deprecated::warn('Mutating items in a ' . Bag::class, 1.1, 'Use a ' . MutableBag::class . ' instead.');
            }

            if (!isset($current[$key])) {
                $current[$key] = [];
            }

            $next = null;
            if ($current instanceof ArrayAccess && !static::canReturnArraysByReference($current, $key, $next, $e)) {
                throw new RuntimeException(
                    sprintf(
                        "Cannot set '%s', because '%s' is an %s which does not return arrays by reference from its offsetGet() method. See %s for an example of how to do this.",
                        $path,
                        $invalidKey,
                        get_class($current),
                        MutableBag::class
                    ),
                    0,
                    $e
                );
            }

            // If checking if object can return arrays by ref needed to fetch the value in the object then
            // use that so we don't have to fetch the value again.
            if ($next !== null) {
                $current = &$next;
                unset($next); // so assigning null above doesn't wipe out actual data
            } else {
                $current = &$current[$key];
            }

            $invalidKey = $key;
        }
    }