Repository: numba/numba

Issue:
Refactor: extract common logic of target registry selection
`_OverloadAttributeTemplate` and `_IntrinsicTemplate` both contain this logic. Perhaps factor out, not necessary for this PR though.

_Originally posted by @stuartarchibald in https://github.com/numba/numba/pull/7061#discussion_r658699089_


Discussion:

Resolving patch:
diff --git a/numba/core/typing/templates.py b/numba/core/typing/templates.py
--- a/numba/core/typing/templates.py
+++ b/numba/core/typing/templates.py
@@ -882,22 +882,25 @@ def make_overload_template(func, overload_func, jit_options, strict,
     return type(base)(name, (base,), dct)
 
 
-class _IntrinsicTemplate(AbstractTemplate):
-    """
-    A base class of templates for intrinsic definition
-    """
+class _TemplateTargetHelperMixin(object):
+    """Mixin for helper methods that assist with target/registry resolution"""
 
-    def generic(self, args, kws):
-        """
-        Type the intrinsic by the arguments.
+    def _get_target_registry(self, reason):
+        """Returns the registry for the current target.
+
+        Parameters
+        ----------
+        reason: str
+            Reason for the resolution. Expects a noun.
+        Returns
+        -------
+        reg : a registry suitable for the current target.
         """
         from numba.core.target_extension import (_get_local_target_checked,
                                                  dispatcher_registry)
-        from numba.core.imputils import builtin_registry
-
-        cache_key = self.context, args, tuple(kws.items())
         hwstr = self.metadata.get('target', 'generic')
-        target_hw = _get_local_target_checked(self.context, hwstr, "intrinsic")
+        target_hw = _get_local_target_checked(self.context, hwstr, reason)
+        # Get registry for the current hardware
         disp = dispatcher_registry[target_hw]
         tgtctx = disp.targetdescr.target_context
         # This is all workarounds...
@@ -929,7 +932,20 @@ def generic(self, args, kws):
             # Pick a registry in which to install intrinsics
             registries = iter(tgtctx._registries)
             reg = next(registries)
-        lower_builtin = reg.lower
+        return reg
+
+
+class _IntrinsicTemplate(_TemplateTargetHelperMixin, AbstractTemplate):
+    """
+    A base class of templates for intrinsic definition
+    """
+
+    def generic(self, args, kws):
+        """
+        Type the intrinsic by the arguments.
+        """
+        lower_builtin = self._get_target_registry('intrinsic').lower
+        cache_key = self.context, args, tuple(kws.items())
         try:
             return self._impl_cache[cache_key]
         except KeyError:
@@ -1007,7 +1023,7 @@ def _resolve(self, value, attr):
     generic_resolve = NotImplemented
 
 
-class _OverloadAttributeTemplate(AttributeTemplate):
+class _OverloadAttributeTemplate(_TemplateTargetHelperMixin, AttributeTemplate):
     """
     A base class of templates for @overload_attribute functions.
     """
@@ -1018,30 +1034,11 @@ def __init__(self, context):
         self.context = context
         self._init_once()
 
-    def _get_target_registry(self):
-        """Returns the registry for the current target
-        """
-        from numba.core.target_extension import (_get_local_target_checked,
-                                                 dispatcher_registry)
-        hwstr = self.metadata.get('target', 'generic')
-        target_hw = _get_local_target_checked(self.context, hwstr, "attribute")
-        # Get resgistry for the current hardware
-        disp = dispatcher_registry[target_hw]
-        tgtctx = disp.targetdescr.target_context
-        tgtctx.refresh()
-        if builtin_registry in tgtctx._registries:
-            reg = builtin_registry
-        else:
-            # Pick a registry in which to install intrinsics
-            registries = iter(tgtctx._registries)
-            reg = next(registries)
-        return reg
-
     def _init_once(self):
         cls = type(self)
         attr = cls._attr
 
-        lower_getattr = self._get_target_registry().lower_getattr
+        lower_getattr = self._get_target_registry('attribute').lower_getattr
 
         @lower_getattr(cls.key, attr)
         def getattr_impl(context, builder, typ, value):
@@ -1085,7 +1082,7 @@ def _init_once(self):
         attr = self._attr
 
         try:
-            registry = self._get_target_registry()
+            registry = self._get_target_registry('method')
         except InternalTargetMismatchError:
             # Target mismatch. Do not register attribute lookup here.
             pass


Test patch: