<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
I've spent the better part of a working day troubleshooting this specific issue, and I don't think this issue is documented or already reported. I have a dictionary, which *sometimes* contains a list of dicts to be looped on, depending on what a key in the inside dict is set to.

So obviously I want to skip the task entirely when that list isn't present, and that is not a problem. But when combined with a check for a key value on item inside the loop, the when condition fails complaining about the list being undefined. Which is hugely annoying as I was checking explicitly for that in the first condition of my when statement.

This is part of a larger playbook which I cannot share, but I've managed to reproduce it with a small test case. I will paste two small playbooks, one that works and one that doesn't. (But in my opinion it should.)

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
ansible

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```
ansible-playbook 2.8.0a1.post0
  config file = /Users/jh/git/ansible_cisco/ansible.cfg
  configured module search path = [u'/Users/jh/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/jh/git/ansible_cisco/lib/python2.7/site-packages/ansible
  executable location = ./bin/ansible-playbook
  python version = 2.7.10 (default, Feb 22 2019, 21:55:15) [GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.37.14)]
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```
DEFAULT_STDOUT_CALLBACK(/Users/jh/git/ansible_cisco/ansible.cfg) = skippy
DEFAULT_TIMEOUT(/Users/jh/git/ansible_cisco/ansible.cfg) = 300
HOST_KEY_CHECKING(/Users/jh/git/ansible_cisco/ansible.cfg) = False
INTERPRETER_PYTHON(/Users/jh/git/ansible_cisco/ansible.cfg) = ./bin/python
PARAMIKO_LOOK_FOR_KEYS(/Users/jh/git/ansible_cisco/ansible.cfg) = False
PERSISTENT_COMMAND_TIMEOUT(/Users/jh/git/ansible_cisco/ansible.cfg) = 300
PERSISTENT_CONNECT_TIMEOUT(/Users/jh/git/ansible_cisco/ansible.cfg) = 300
RETRY_FILES_ENABLED(/Users/jh/git/ansible_cisco/ansible.cfg) = False
TRANSFORM_INVALID_GROUP_CHARS(/Users/jh/git/ansible_cisco/ansible.cfg) = ignore
```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
Running MacOS X Mojave and use a python virtualenv for the sole purpose of having stable versions of everything in this specific repository. None of this should matter though as this seems to be a purely ansible core thing.


##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

This playbook will fail with an error about mylist2 not being defined, despite the when statement explicitly checking for that. Remove the and item.test = test part from the when statement and it will work correctly.
```
---
- name: test ansible when defined
  hosts: localhost
  become: no
  gather_facts: no
  vars:
    mydict:
      var1: "val1"
      var2: "val2"
      mylist1:
        - test1
        - test2
  tasks:
    - debug:
        var: mydict

    - debug:
        msg: "This shouldn't be printed."
      with_items: "{{mydict.mylist2}}"
      when: mydict.mylist2 is defined and item.test = 'test'
```

This version, with the parts of the when statement on different lines works:
```
---
- name: test ansible when defined
  hosts: localhost
  become: no
  gather_facts: no
  vars:
    mydict:
      var1: "val1"
      var2: "val2"
      mylist1:
        - test1
        - test2
  tasks:
    - debug:
        var: mydict

    - debug:
        msg: "This shouldn't be printed."
      with_items: "{{mydict.mylist2}}"
      when:
        - mydict.mylist2 is defined
        - item.test = 'test'
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->

I would expect both cases to work, and just skip the second task.

```
./bin/ansible-playbook works.yml
 [WARNING]: No inventory was parsed, only implicit localhost is available

 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not
match 'all'


PLAY [test ansible when defined] *************************************************************************************

TASK [debug] *********************************************************************************************************
ok: [localhost] => {
    "mydict": {
        "mylist1": [
            "test1",
            "test2"
        ],
        "var1": "val1",
        "var2": "val2"
    }
}

TASK [debug] *********************************************************************************************************

PLAY RECAP ***********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
```

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```
./bin/ansible-playbook fails.yml
 [WARNING]: No inventory was parsed, only implicit localhost is available

 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not
match 'all'


PLAY [test ansible when defined] *************************************************************************************

TASK [debug] *********************************************************************************************************
ok: [localhost] => {
    "mydict": {
        "mylist1": [
            "test1",
            "test2"
        ],
        "var1": "val1",
        "var2": "val2"
    }
}

TASK [debug] *********************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "'dict object' has no attribute 'mylist2'"}

PLAY RECAP ***********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
```
elif self._task.loop is not None:
            items = templar.template(self._task.loop)
            if not isinstance(items, list):
                raise AnsibleError(
                    "Invalid data passed to 'loop', it requires a list, got this instead: %s."
                    " Hint: If you passed a list/dict of just one element,"
                    " try adding wantlist=True to your lookup invocation or use q/query instead of lookup." % items
                )
        
        
        
        for k in play_context_vars:
            if k in old_vars:
                self._job_vars[k] = old_vars[k]
            else:
                del self._job_vars[k]
        return items
    def _run_loop(self, items):
        '''
        Runs the task with the loop items specified and collates the result
        into an array named 'results' which is inserted into the final result
        along with the item for which the loop ran.
        '''
        results = []
        
        
        
        task_vars = self._job_vars
        loop_var = 'item'
        index_var = None