May I suggest a few tweaks? First off is this variable initialization:
vars:
  hostlist: "{{ hostlist.split(',') }}"
If you’re passing in hostlist as an --extra-vars, this isn’t going to work.
It looks like you’re redefining the variable hostlist in terms of itself, but it doesn’t do that. Instead, it defines a new Play var (precedence 12) which has the same name as an Extra var (precedence 22). That doesn’t make the Extra var go away. Since Extra vars have the highest precedence, the identically named Play var’s value will never be seen. (It may “work” for you in older Ansibles, but it behaves as I’ve described above in my Ansible core 2.18.6.)
I recommend a different Extra var name, say hostlist_in, so your variable initialization becomes
hostlist: "{{ hostlist_in.split(',') }}"
This next one is personal preference, but I like to avoid creating index variables when filters can manipulate the data directly into the form I need. In this case, you want to create pairs of host names where the first or left host in each pair is always hostlist[0] and the second or right host is in turn each of the other hostlist hosts. The product filter will do exactly that.
loop: "{{ [hostlist[0]] | product(hostlist[1:]) }}"
Lastly, when posting code (or editing a prior post containing code - hint, hint) to the forum, precede and follow the code with lines containing only three back-ticks (“```”). You can include a syntax highlighting hint on the first line, like this:
```yaml
- name: Code never looked so good
  ansible.builtin.admire: |
    Hey, I can read this easily!
```
With the above changes, here’s my re-working of your test/example. Note that both hosts: and the Play var hostlist are derived from the same Extra var hostlist_in. It would be neat if you could use the ansible_play_hosts special variable which will contain the same hosts as your limit: and hostlist_in; then you wouldn’t have to pass in the hosts twice. Alas, ansible_play_hosts is a sorted list, and we must distinguish the first host from the others. (Which we could do, but that adds more code which kind of defeats the purpose.)
# test-playbook.yml
- name: Test the list of tasks
  hosts: "{{ hostlist_in | split(',') }}"
  gather_facts: false
  vars:
    hostlist: "{{ hostlist_in.split(',') }}"
  tasks:
    - name: Testing the use case
      ansible.builtin.include_role:
        name: test-usecase
      loop: "{{ [hostlist[0]] | product(hostlist[1:]) }}"
      loop_control:
        loop_var: hostpair
---
# role/test-usecase/tasks/main.yml
- name: Document this role inclusion
  ansible.builtin.debug:
    msg: "test-usecase -- primary: {{ hostpair[0] }}, secondary: {{ hostpair[1] }}"
  run_once: true
- name: Test block for primary host {{ hostpair[0] }}
  block:
    - name: Primary is {{ hostpair[0] }}
      ansible.builtin.shell: hostname
  when: inventory_hostname == hostpair[0]
- name: Test block for secondary host {{ hostpair[1] }}
  block:
    - name: Secondary is {{ hostpair[1] }}
      ansible.builtin.shell: hostname
  when: inventory_hostname == hostpair[1]