Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.206
diff -u -p -r1.206 module.inc
--- includes/module.inc	21 Nov 2010 10:19:48 -0000	1.206
+++ includes/module.inc	23 Nov 2010 07:23:58 -0000
@@ -591,7 +591,20 @@ function module_disable($module_list, $d
  *   implemented in that module.
  */
 function module_hook($module, $hook) {
-  return function_exists($module . '_' . $hook);
+  $function = $module . '_' . $hook;
+  if (function_exists($function)) {
+    return TRUE;
+  }
+  // If the hook implementation does not exist, check whether it may live in an
+  // optional include file registered via hook_hook_info().
+  $hook_info = module_hook_info();
+  if (isset($hook_info[$hook]['group'])) {
+    module_load_include('inc', $module, $module . '.' . $hook_info[$hook]['group']);
+    if (function_exists($function)) {
+      return TRUE;
+    }
+  }
+  return FALSE;
 }
 
 /**
@@ -695,10 +708,15 @@ function module_implements($hook, $sort 
  * Retrieve a list of what hooks are explicitly declared.
  */
 function module_hook_info() {
-  $hook_info = &drupal_static(__FUNCTION__, array());
-
-  if (empty($hook_info)) {
-    $cache = cache_get('hook_info', 'cache_bootstrap');
+  // This function is indirectly invoked from bootstrap_invoke_all(). Therefore,
+  // caches have to be specific to the current bootstrap phase, or otherwise the
+  // cache would be primed with hooks of bootstrap modules only.
+  $cid = __FUNCTION__ . ':' . drupal_bootstrap(NULL, FALSE);
+  $hook_info = &drupal_static($cid);
+
+  if (!isset($hook_info)) {
+    $hook_info = array();
+    $cache = cache_get($cid, 'cache_bootstrap');
     if ($cache === FALSE) {
       // Rebuild the cache and save it.
       // We can't use module_invoke_all() here or it would cause an infinite
@@ -719,7 +737,7 @@ function module_hook_info() {
           $function($hook_info);
         }
       }
-      cache_set('hook_info', $hook_info, 'cache_bootstrap');
+      cache_set($cid, $hook_info, 'cache_bootstrap');
     }
     else {
       $hook_info = $cache->data;
@@ -767,6 +785,7 @@ function module_invoke() {
     return call_user_func_array($module . '_' . $hook, $args);
   }
 }
+
 /**
  * Invoke a hook in all enabled modules that implement it.
  *
