Spin-off from #914382: Contextual links incompatible with render cache.
Currently, drupal_render_cid_create() handles #cache['keys'] and #cache['granularity']. AFAIK, 'keys' are intended to be static strings, not things that can vary by user or other $request attributes. Meanwhile, 'granularity' can be a constant like DRUPAL_CACHE_PER_ROLE, DRUPAL_CACHE_PER_USER, or DRUPAL_CACHE_PER_PAGE, which drupal_render_cid_parts() expands based on the user and request.
In the case of #914382: Contextual links incompatible with render cache, I think per role granularity is too granular. Consider a site with multiple roles without 'access contextual links' permission. There's no reason for elements that render contextual links to require duplicate cache entries for each combination of roles, all of which lack that permission. But no granularity is also not ideal, because it results in extra HTML bloat sent to everyone who lacks permission to contextual links anyway (which on many sites, can be >99% of site visitors). I think the ideal is to vary the cache just by whether that permission is true or false.
A simple solution can be to simply add a 'permissions' keys to $element['#cache']. This could be set to an array of permissions (e.g., array('access contextual links')). drupal_render_cid_parts() could then convert that to $cid_parts, just like how it already does for 'granularity'.
A more expansive solution could be to introduce a 'contexts' key that can be an array of key/values. The keys could be callbacks/DIC service ids/plugin ids/whatever for code that can be passed the corresponding value and a $request object, and would return the corresponding $cid_parts. In this case, 'permissions' could be one such service, but modules could add more without needing to hack drupal_render_cid_parts().