Right way to extend both `MulticallUpgradeable` and `UUPSUpgradeable`?

I am trying to extend MulticallUpgradeable and UUPSUpgradeable in the same contract; however, the two parts clash, as both define private _functionDelegateCall, making overriding to resolve the conflict not an option.

What's the right approach here?

:1234: Code to reproduce

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol";

contract ERC721Burnable is Initializable, ERC721Upgradeable, ERC721BurnableUpgradeable, MulticallUpgradeable, OwnableUpgradeable, UUPSUpgradeable {
    function initialize() initializer public {
        __ERC721_init("ERC721Burnable", "MTK");
        __ERC721Burnable_init();
        __Multicall_init();
        __Ownable_init();
        __UUPSUpgradeable_init();
    }

    function _authorizeUpgrade(address newImplementation)
        internal
        onlyOwner
        override
    {}
}

Expected: contract compiles.
Observed:

TypeError: Derived contract must override function "_functionDelegateCall". Two or more base classes define function with same name and parameter types.
  --> src/ERC721Burnable.sol:13:1:
   |
13 | contract ERC721Burnable is
   | ^ (Relevant source part starts here and spans across multiple lines).
Note: Definition in "ERC1967UpgradeUpgradeable":
   --> @openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:207:5:
    |
207 |     function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
    |     ^ (Relevant source part starts here and spans across multiple lines).
Note: Definition in "MulticallUpgradeable":
  --> @openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol:37:5:
   |
37 |     function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
   |     ^ (Relevant source part starts here and spans across multiple lines).


Error HH600: Compilation failed

or, if an attempt to override _functionDelegateCall is made,

TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?
  --> @openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol:37:5:
   |
37 |     function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
   |     ^ (Relevant source part starts here and spans across multiple lines).
Note: Overriding function is here:
  --> src/ERC721Burnable.sol:78:5:
   |
78 |     function _functionDelegateCall(address target, bytes memory data)
   |     ^ (Relevant source part starts here and spans across multiple lines).


TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?
   --> @openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:207:5:
    |
207 |     function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
    |     ^ (Relevant source part starts here and spans across multiple lines).
Note: Overriding function is here:
  --> src/ERC721Burnable.sol:78:5:
   |
78 |     function _functionDelegateCall(address target, bytes memory data)
   |     ^ (Relevant source part starts here and spans across multiple lines).


Error HH600: Compilation failed

:computer: Environment

  • hardhat 2.6.1
  • solc 0.8.7
  • @openzeppelin/contracts-upgradeable 4.3.1