Your script is triggering the ERR trap due to the return status of the control_operators call, which is non-zero. The test in the function does not directly trigger the trap.
The trap output indicates this by the line number it prints, which will be the line with the call to the function.
The trap output also indicates where this non-zero exit status comes from, which is the result of the test in the function. Since the test is the last thing executed in the function, this sets the function's exit status.
The function call is not part of an AND or OR list, so the trap is triggered.
 For you updated question, you forget that the ERR trap will still be called if the command that returns the non-zero exit status is the last command in the AND or OR list.
 From the bash manual, with my emphasis:
The
ERRtrap is not executed if the failed command is part of the command list immediately following awhileoruntilkeyword, part of the test in anifstatement, part of a command executed in a&&or||list except the command following the final&&or||, any command in a pipeline but the last, or if the command's return value is being inverted using!.
 Your example is true && false, and since false is last in the AND list, it triggers the ERR trap.
 Another way of saying this is that the ERR trap is called if the command that decides the exit status of a list or pipeline returns a non-zero exit status (or zero exit status if ! is used with that command).
 
                