schema compile FEATURE two step unres resolution

There is module unres resolved after the module
is compiled and global unres that is resolved
after all the newly implemented modules are
compiled.
diff --git a/src/common.h b/src/common.h
index d5209c5..1bdec36 100644
--- a/src/common.h
+++ b/src/common.h
@@ -220,8 +220,6 @@
     struct dict_table dict;           /**< dictionary to effectively store strings used in the context related structures */
     struct ly_set search_paths;       /**< set of directories where to search for schema's imports/includes */
     struct ly_set list;               /**< set of loaded YANG schemas */
-    struct ly_set implementing;       /**< set of YANG schemas being atomically implemented (compiled); the first added
-                                           module is always the explcitly implemented module, the other ones are dependencies */
     ly_module_imp_clb imp_clb;        /**< Optional callback for retrieving missing included or imported models in a custom way. */
     void *imp_clb_data;               /**< Optional private data for ::ly_ctx.imp_clb */
     uint16_t module_set_id;           /**< ID of the current set of schemas */
diff --git a/src/context.c b/src/context.c
index 59c7093..981ed42 100644
--- a/src/context.c
+++ b/src/context.c
@@ -33,6 +33,7 @@
 #include "parser_data.h"
 #include "path.h"
 #include "plugins_types.h"
+#include "schema_compile.h"
 #include "set.h"
 #include "tree.h"
 #include "tree_data.h"
@@ -182,10 +183,22 @@
 ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision, const char **features)
 {
     struct lys_module *result = NULL;
+    struct lys_glob_unres unres = {0};
+    LY_ERR ret = LY_SUCCESS;
 
     LY_CHECK_ARG_RET(ctx, ctx, name, NULL);
 
-    LY_CHECK_RET(lysp_load_module(ctx, name, revision, 1, features, &result), NULL);
+    LY_CHECK_GOTO(ret = lysp_load_module(ctx, name, revision, 1, features, &unres, &result), cleanup);
+
+    /* resolve unres and revert, if needed */
+    LY_CHECK_GOTO(ret = lys_compile_unres_glob(ctx, &unres), cleanup);
+
+cleanup:
+    if (ret) {
+        lys_compile_unres_glob_revert(ctx, &unres);
+        result = NULL;
+    }
+    lys_compile_unres_glob_erase(ctx, &unres);
     return result;
 }
 
@@ -199,6 +212,7 @@
     uint32_t i;
     struct ly_in *in = NULL;
     LY_ERR rc = LY_SUCCESS;
+    struct lys_glob_unres unres = {0};
 
     LY_CHECK_ARG_RET(NULL, new_ctx, LY_EINVAL);
 
@@ -254,15 +268,20 @@
     for (i = 0; i < ((options & LY_CTX_NO_YANGLIBRARY) ? (LY_INTERNAL_MODS_COUNT - 2) : LY_INTERNAL_MODS_COUNT); i++) {
         ly_in_memory(in, internal_modules[i].data);
         LY_CHECK_GOTO(rc = lys_create_module(ctx, in, internal_modules[i].format, internal_modules[i].implemented,
-                NULL, NULL, NULL, &module), error);
+                NULL, NULL, NULL, &unres, &module), error);
     }
 
+    /* resolve global unres */
+    LY_CHECK_GOTO(rc = lys_compile_unres_glob(ctx, &unres), error);
+
     ly_in_free(in, 0);
+    lys_compile_unres_glob_erase(ctx, &unres);
     *new_ctx = ctx;
     return rc;
 
 error:
     ly_in_free(in, 0);
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_ctx_destroy(ctx, NULL);
     return rc;
 }
diff --git a/src/parser_internal.h b/src/parser_internal.h
index 4b1b26a..b8208f6 100644
--- a/src/parser_internal.h
+++ b/src/parser_internal.h
@@ -76,9 +76,11 @@
  * @param[in] in Input structure.
  * @param[in,out] mod Prepared module structure where the parsed information, including the parsed
  * module structure, will be filled in.
- * @return LY_ERR value - LY_SUCCESS, LY_EINVAL or LY_EVALID.
+ * @param[in,out] unres Global unres structure.
+ * @return LY_ERR values.
  */
-LY_ERR yang_parse_module(struct lys_yang_parser_ctx **context, struct ly_in *in, struct lys_module *mod);
+LY_ERR yang_parse_module(struct lys_yang_parser_ctx **context, struct ly_in *in, struct lys_module *mod,
+        struct lys_glob_unres *unres);
 
 /**
  * @brief Parse module from YIN data.
@@ -87,10 +89,11 @@
  * @param[in] in Input structure.
  * @param[in,out] mod Prepared module structure where the parsed information, including the parsed
  * module structure, will be filled in.
- *
+ * @param[in,out] unres Global unres structure.
  * @return LY_ERR values.
  */
-LY_ERR yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod);
+LY_ERR yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod,
+        struct lys_glob_unres *unres);
 
 /**
  * @brief Parse submodule from YIN data.
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 39e719e..702a3d2 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -4529,6 +4529,7 @@
     *context = calloc(1, sizeof **context);
     LY_CHECK_ERR_RET(!(*context), LOGMEM(ly_ctx), LY_EMEM);
     (*context)->format = LYS_IN_YANG;
+    (*context)->unres = main_ctx->unres;
     (*context)->pos_type = LY_VLOG_LINE;
     (*context)->line = 1;
 
@@ -4587,7 +4588,7 @@
 }
 
 LY_ERR
-yang_parse_module(struct lys_yang_parser_ctx **context, struct ly_in *in, struct lys_module *mod)
+yang_parse_module(struct lys_yang_parser_ctx **context, struct ly_in *in, struct lys_module *mod, struct lys_glob_unres *unres)
 {
     LY_ERR ret = LY_SUCCESS;
     char *word;
@@ -4599,6 +4600,7 @@
     *context = calloc(1, sizeof **context);
     LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
     (*context)->format = LYS_IN_YANG;
+    (*context)->unres = unres;
     (*context)->pos_type = LY_VLOG_LINE;
     (*context)->line = 1;
 
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 3c8ab36..8949665 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -3775,6 +3775,7 @@
     *yin_ctx = calloc(1, sizeof **yin_ctx);
     LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
     (*yin_ctx)->format = LYS_IN_YIN;
+    (*yin_ctx)->unres = main_ctx->unres;
     LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
 
     mod_p = calloc(1, sizeof *mod_p);
@@ -3827,7 +3828,7 @@
 }
 
 LY_ERR
-yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
+yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod, struct lys_glob_unres *unres)
 {
     LY_ERR ret = LY_SUCCESS;
     enum ly_stmt kw = LY_STMT_NONE;
@@ -3837,6 +3838,7 @@
     *yin_ctx = calloc(1, sizeof **yin_ctx);
     LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
     (*yin_ctx)->format = LYS_IN_YIN;
+    (*yin_ctx)->unres = unres;
     LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
 
     mod_p = calloc(1, sizeof *mod_p);
diff --git a/src/path.c b/src/path.c
index 1b2496c..e565dfe 100644
--- a/src/path.c
+++ b/src/path.c
@@ -381,12 +381,14 @@
 static LY_ERR
 ly_path_compile_prefix(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const struct lys_module *cur_mod,
         const struct lysc_node *prev_ctx_node, const struct lyxp_expr *expr, uint16_t tok_idx, uint8_t lref,
-        LY_PREFIX_FORMAT format, void *prefix_data, const struct lys_module **mod, const char **name, size_t *name_len)
+        LY_PREFIX_FORMAT format, void *prefix_data, struct lys_glob_unres *unres, const struct lys_module **mod,
+        const char **name, size_t *name_len)
 {
     const char *pref;
     size_t len;
 
     assert(expr->tokens[tok_idx] == LYXP_TOKEN_NAMETEST);
+    assert((lref != LY_PATH_LREF_TRUE) || unres);
 
     /* get prefix */
     if ((pref = strnstr(expr->expr + expr->tok_pos[tok_idx], ":", expr->tok_len[tok_idx]))) {
@@ -408,7 +410,7 @@
                 LOGVAL_P(ctx, cur_node, LYVE_XPATH, "Not implemented module \"%s\" in path.", (*mod)->name);
                 return LY_EVALID;
             }
-            LY_CHECK_RET(lys_set_implemented((struct lys_module *)*mod, NULL));
+            LY_CHECK_RET(lys_set_implemented_r((struct lys_module *)*mod, NULL, unres));
         }
     } else {
         switch (format) {
@@ -479,7 +481,7 @@
         do {
             /* NameTest, find the key */
             LY_CHECK_RET(ly_path_compile_prefix(ctx, cur_node, cur_mod, ctx_node, expr, *tok_idx, LY_PATH_LREF_FALSE,
-                    format, prefix_data, &mod, &name, &name_len));
+                    format, prefix_data, NULL, &mod, &name, &name_len));
             key = lys_find_child(ctx_node, mod, name, name_len, 0, 0);
             if (!key) {
                 LOGVAL_P(ctx, cur_node, LYVE_XPATH, "Not found node \"%.*s\" in path.", name_len, name);
@@ -600,11 +602,13 @@
  * @param[in,out] tok_idx Index in @p expr, is adjusted for parsed tokens.
  * @param[in] format Format of the path.
  * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
+ * @param[in,out] unres Global unres structure for newly implemented modules.
  * @return LY_ERR value.
  */
 static LY_ERR
 ly_path_compile_predicate_leafref(const struct lysc_node *ctx_node, const struct lysc_node *cur_node,
-        const struct lyxp_expr *expr, uint16_t *tok_idx, LY_PREFIX_FORMAT format, void *prefix_data)
+        const struct lyxp_expr *expr, uint16_t *tok_idx, LY_PREFIX_FORMAT format, void *prefix_data,
+        struct lys_glob_unres *unres)
 {
     const struct lysc_node *key, *node, *node2;
     const struct lys_module *mod;
@@ -629,7 +633,7 @@
     do {
         /* NameTest, find the key */
         LY_CHECK_RET(ly_path_compile_prefix(cur_node->module->ctx, cur_node, cur_node->module, ctx_node, expr, *tok_idx,
-                LY_PATH_LREF_TRUE, format, prefix_data, &mod, &name, &name_len));
+                LY_PATH_LREF_TRUE, format, prefix_data, unres, &mod, &name, &name_len));
         key = lys_find_child(ctx_node, mod, name, name_len, 0, 0);
         if (!key) {
             LOGVAL_P(cur_node->module->ctx, cur_node, LYVE_XPATH, "Not found node \"%.*s\" in path.", name_len, name);
@@ -688,7 +692,7 @@
             /* NameTest */
             assert(expr->tokens[*tok_idx] == LYXP_TOKEN_NAMETEST);
             LY_CHECK_RET(ly_path_compile_prefix(cur_node->module->ctx, cur_node, cur_node->module, node, expr, *tok_idx,
-                    LY_PATH_LREF_TRUE, format, prefix_data, &mod, &name, &name_len));
+                    LY_PATH_LREF_TRUE, format, prefix_data, unres, &mod, &name, &name_len));
             node2 = lys_find_child(node, mod, name, name_len, 0, 0);
             if (!node2) {
                 LOGVAL_P(cur_node->module->ctx, cur_node, LYVE_XPATH, "Not found node \"%.*s\" in path.", name_len, name);
@@ -722,7 +726,7 @@
 LY_ERR
 ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, const struct lysc_node *ctx_node,
         const struct lyxp_expr *expr, uint8_t lref, uint8_t oper, uint8_t target, LY_PREFIX_FORMAT format,
-        void *prefix_data, struct ly_path **path)
+        void *prefix_data, struct lys_glob_unres *unres, struct ly_path **path)
 {
     LY_ERR ret = LY_SUCCESS;
     uint16_t tok_idx = 0;
@@ -790,7 +794,7 @@
 
         /* get module and node name */
         LY_CHECK_GOTO(ret = ly_path_compile_prefix(ctx, cur_node, cur_mod, ctx_node, expr, tok_idx, lref, format,
-                prefix_data, &mod, &name, &name_len), cleanup);
+                prefix_data, unres, &mod, &name, &name_len), cleanup);
         ++tok_idx;
 
         /* find the next node */
@@ -808,7 +812,7 @@
 
         /* compile any predicates */
         if (lref == LY_PATH_LREF_TRUE) {
-            ret = ly_path_compile_predicate_leafref(ctx_node, cur_node, expr, &tok_idx, format, prefix_data);
+            ret = ly_path_compile_predicate_leafref(ctx_node, cur_node, expr, &tok_idx, format, prefix_data, unres);
         } else {
             ret = ly_path_compile_predicate(ctx, cur_node, cur_mod, ctx_node, expr, &tok_idx, format, prefix_data,
                     &p->predicates, &p->pred_type);
diff --git a/src/path.h b/src/path.h
index f1e4fa3..a6e8149 100644
--- a/src/path.h
+++ b/src/path.h
@@ -25,6 +25,7 @@
 struct ly_ctx;
 struct lys_module;
 struct lysc_node;
+struct lys_glob_unres;
 struct lyxp_expr;
 
 enum ly_path_pred_type {
@@ -154,12 +155,13 @@
  * @param[in] target Target option (@ref path_target_options).
  * @param[in] format Format of the path.
  * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
+ * @param[in,out] unres Global unres structure for newly implemented modules, needed only if @p lref is ::LY_PATH_LREF_TRUE.
  * @param[out] path Compiled path.
  * @return LY_ERR value.
  */
 LY_ERR ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, const struct lysc_node *ctx_node,
         const struct lyxp_expr *expr, uint8_t lref, uint8_t oper, uint8_t target, LY_PREFIX_FORMAT format,
-        void *prefix_data, struct ly_path **path);
+        void *prefix_data, struct lys_glob_unres *unres, struct ly_path **path);
 
 /**
  * @brief Compile predicate into ly_path_predicate structure. Only simple predicates (not leafref) are supported.
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 446b2f7..0564eeb 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -726,7 +726,8 @@
 static LY_ERR
 ly_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     LY_ERR ret;
     int64_t num;
@@ -782,7 +783,8 @@
 static LY_ERR
 ly_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     LY_ERR ret;
     uint64_t num;
@@ -836,7 +838,8 @@
 static LY_ERR
 ly_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     int64_t d;
     struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
@@ -901,7 +904,8 @@
 static LY_ERR
 ly_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     size_t start = 0, stop = 0, count = 0, u, termination = 0;
     struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
@@ -1003,7 +1007,8 @@
 static LY_ERR
 ly_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     struct lysc_type_str *type_str = (struct lysc_type_str *)type;
 
@@ -1042,7 +1047,8 @@
 static LY_ERR
 ly_type_store_bits(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
     size_t item_len;
@@ -1221,7 +1227,8 @@
 static LY_ERR
 ly_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     LY_ARRAY_COUNT_TYPE u;
     char *errmsg = NULL;
@@ -1273,7 +1280,8 @@
 static LY_ERR
 ly_type_store_boolean(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     int8_t i;
 
@@ -1314,7 +1322,8 @@
 static LY_ERR
 ly_type_store_empty(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
-        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     /* check hints */
     LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
@@ -1380,7 +1389,7 @@
 static LY_ERR
 ly_type_store_identityref(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
-        struct lyd_value *storage, struct ly_err_item **err)
+        struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
 {
     struct lysc_type_identityref *type_ident = (struct lysc_type_identityref *)type;
     const char *id_name, *prefix = value;
@@ -1452,7 +1461,7 @@
     } else if (!mod->implemented) {
         /* non-implemented module */
         if (options & LY_TYPE_STORE_IMPLEMENT) {
-            LY_CHECK_RET(lys_set_implemented((struct lys_module *)mod, NULL));
+            LY_CHECK_RET(lys_set_implemented_r((struct lys_module *)mod, NULL, unres));
         } else {
             rc = asprintf(&errmsg, "Invalid identityref \"%.*s\" value - identity found in non-implemented module \"%s\".",
                     (int)value_len, value, mod->name);
@@ -1555,7 +1564,7 @@
 static LY_ERR
 ly_type_store_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
-        struct lyd_value *storage, struct ly_err_item **err)
+        struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)type;
@@ -1593,12 +1602,12 @@
 
     if (options & LY_TYPE_STORE_IMPLEMENT) {
         /* implement all prefixes */
-        LY_CHECK_GOTO(ret = lys_compile_expr_implement(ctx, exp, format, prefix_data, 1, NULL), error);
+        LY_CHECK_GOTO(ret = lys_compile_expr_implement(ctx, exp, format, prefix_data, 1, unres, NULL), error);
     }
 
     /* resolve it on schema tree */
     ret = ly_path_compile(ctx, NULL, ctx_node, exp, LY_PATH_LREF_FALSE, lysc_is_output(ctx_node) ?
-            LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, format, prefix_data, &path);
+            LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, format, prefix_data, unres, &path);
     if (ret) {
         rc = asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - semantic error.", (int)value_len, value);
         goto error;
@@ -1953,7 +1962,7 @@
 static LY_ERR
 ly_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
-        struct lyd_value *storage, struct ly_err_item **err)
+        struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
@@ -1962,7 +1971,7 @@
 
     /* store the value as the real type of the leafref target */
     ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data,
-            hints, ctx_node, storage, err);
+            hints, ctx_node, storage, unres, err);
     if (ret == LY_EINCOMPLETE) {
         /* it is irrelevant whether the target type needs some resolving */
         ret = LY_SUCCESS;
@@ -2053,7 +2062,8 @@
 
 static LY_ERR
 ly_type_union_store_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_value_subvalue *subvalue,
-        ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct ly_err_item **err)
+        ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lys_glob_unres *unres,
+        struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
     LY_ARRAY_COUNT_TYPE u;
@@ -2069,9 +2079,8 @@
 
     /* use the first usable subtype to store the value */
     for (u = 0; u < LY_ARRAY_COUNT(types); ++u) {
-        ret = types[u]->plugin->store(ctx, types[u], subvalue->original, strlen(subvalue->original),
-                0, subvalue->format, subvalue->prefix_data,
-                subvalue->hints, subvalue->ctx_node, &subvalue->value, err);
+        ret = types[u]->plugin->store(ctx, types[u], subvalue->original, strlen(subvalue->original), 0, subvalue->format,
+                subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err);
         if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
             if (resolve && (ret == LY_EINCOMPLETE)) {
                 /* we need the value resolved */
@@ -2117,7 +2126,7 @@
 static LY_ERR
 ly_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
         uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
-        struct lyd_value *storage, struct ly_err_item **err)
+        struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lysc_type_union *type_u = (struct lysc_type_union *)type;
@@ -2149,7 +2158,7 @@
     subvalue->ctx_node = ctx_node;
 
     /* use the first usable subtype to store the value */
-    ret = ly_type_union_store_type(ctx, type_u->types, subvalue, 0, NULL, NULL, err);
+    ret = ly_type_union_store_type(ctx, type_u->types, subvalue, 0, NULL, NULL, unres, err);
     LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
 
 cleanup:
@@ -2201,7 +2210,7 @@
     *err = NULL;
 
     /* store and resolve the value */
-    ret = ly_type_union_store_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, err);
+    ret = ly_type_union_store_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, NULL, err);
     LY_CHECK_RET(ret);
 
     /* success, update the canonical value */
diff --git a/src/plugins_types.h b/src/plugins_types.h
index ea8e531..7c43767 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -28,6 +28,7 @@
 
 struct ly_ctx;
 struct lys_module;
+struct lys_glob_unres;
 struct lysc_ident;
 struct lysc_node;
 struct lysc_pattern;
@@ -192,6 +193,7 @@
  * @param[in] hints Bitmap of [value hints](@ref lydvalhints) of all the allowed value types.
  * @param[in] ctx_node The @p value schema context node.
  * @param[out] storage Storage for the value in the type's specific encoding. All the members should be filled by the plugin.
+ * @param[in,out] unres Global unres structure for newly implemented modules. Set only if ::LY_TYPE_STORE_IMPLEMENT is used.
  * @param[out] err Optionally provided error information in case of failure. If not provided to the caller, a generic
  *             error message is prepared instead. The error structure can be created by ::ly_err_new().
  * @return LY_SUCCESS on success,
@@ -200,7 +202,7 @@
  */
 typedef LY_ERR (*ly_type_store_clb)(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value,
         size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
-        const struct lysc_node *ctx_node, struct lyd_value *storage, struct ly_err_item **err);
+        const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
 
 /**
  * @brief Callback to validate the stored value in data.
diff --git a/src/schema_compile.c b/src/schema_compile.c
index da1eaa9..70e423e 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -338,7 +338,8 @@
             ly_in_free(in, 1);
         }
         if (!mod) {
-            if (lysp_load_module(ctx->ctx, imp_p->module->name, imp_p->module->revision, 0, NULL, (struct lys_module **)&mod)) {
+            if (lysp_load_module(ctx->ctx, imp_p->module->name, imp_p->module->revision, 0, NULL, ctx->unres,
+                    (struct lys_module **)&mod)) {
                 LOGERR(ctx->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
                         imp_p->module->name, ctx->cur_mod->name);
                 return LY_ENOTFOUND;
@@ -858,7 +859,7 @@
 
 LY_ERR
 lys_compile_expr_implement(const struct ly_ctx *ctx, const struct lyxp_expr *expr, LY_PREFIX_FORMAT format,
-        void *prefix_data, ly_bool implement, const struct lys_module **mod_p)
+        void *prefix_data, ly_bool implement, struct lys_glob_unres *unres, const struct lys_module **mod_p)
 {
     uint32_t i;
     const char *ptr, *start;
@@ -886,7 +887,7 @@
         if (!mod->implemented) {
             /* unimplemented module found */
             if (implement) {
-                LY_CHECK_RET(lys_set_implemented((struct lys_module *)mod, NULL));
+                LY_CHECK_RET(lys_set_implemented_r((struct lys_module *)mod, NULL, unres));
             } else {
                 *mod_p = mod;
                 break;
@@ -902,10 +903,11 @@
  *
  * @param[in] ctx Compile context.
  * @param[in] node Node to check.
+ * @param[in,out] unres Global unres structure.
  * @return LY_ERR value
  */
 static LY_ERR
-lys_compile_unres_xpath(struct lysc_ctx *ctx, const struct lysc_node *node)
+lys_compile_unres_xpath(struct lysc_ctx *ctx, const struct lysc_node *node, struct lys_glob_unres *unres)
 {
     struct lyxp_set tmp_set;
     uint32_t i, opts;
@@ -974,7 +976,7 @@
         /* first check whether all the referenced modules are implemented */
         mod = NULL;
         ret = lys_compile_expr_implement(ctx->ctx, when[u]->cond, LY_PREF_SCHEMA_RESOLVED, when[u]->prefixes,
-                ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED, &mod);
+                ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED, unres, &mod);
         if (ret) {
             goto cleanup;
         } else if (mod) {
@@ -1024,7 +1026,7 @@
         /* first check whether all the referenced modules are implemented */
         mod = NULL;
         ret = lys_compile_expr_implement(ctx->ctx, musts[u].cond, LY_PREF_SCHEMA_RESOLVED, musts[u].prefixes,
-                ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED, &mod);
+                ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED, unres, &mod);
         if (ret) {
             goto cleanup;
         } else if (mod) {
@@ -1075,10 +1077,12 @@
  * @param[in] ctx Compile context.
  * @param[in] node Context node for the leafref.
  * @param[in] lref Leafref to check/resolve.
+ * @param[in,out] unres Global unres structure.
  * @return LY_ERR value.
  */
 static LY_ERR
-lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, struct lysc_type_leafref *lref)
+lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, struct lysc_type_leafref *lref,
+        struct lys_glob_unres *unres)
 {
     const struct lysc_node *target = NULL, *siter;
     struct ly_path *p;
@@ -1088,7 +1092,8 @@
 
     /* try to find the target */
     LY_CHECK_RET(ly_path_compile(ctx->ctx, node->module, node, lref->path, LY_PATH_LREF_TRUE, lysc_is_output(node) ?
-            LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, LY_PREF_SCHEMA_RESOLVED, lref->prefixes, &p));
+            LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, LY_PREF_SCHEMA_RESOLVED, lref->prefixes,
+            unres, &p));
 
     /* get the target node */
     target = p[LY_ARRAY_COUNT(p) - 1].node;
@@ -1146,11 +1151,12 @@
  * @param[in] dflt Default value.
  * @param[in] dflt_pmod Parsed module of the @p dflt to resolve possible prefixes.
  * @param[in,out] storage Storage for the compiled default value.
+ * @param[in,out] unres Global unres structure for newly implemented modules.
  * @return LY_ERR value.
  */
 static LY_ERR
 lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_type *type, const char *dflt,
-        const struct lysp_module *dflt_pmod, struct lyd_value *storage)
+        const struct lysp_module *dflt_pmod, struct lyd_value *storage, struct lys_glob_unres *unres)
 {
     LY_ERR ret;
     uint32_t options;
@@ -1158,7 +1164,7 @@
 
     options = (ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED) ? LY_TYPE_STORE_IMPLEMENT : 0;
     ret = type->plugin->store(ctx->ctx, type, dflt, strlen(dflt), options, LY_PREF_SCHEMA, (void *)dflt_pmod,
-            LYD_HINT_SCHEMA, node, storage, &err);
+            LYD_HINT_SCHEMA, node, storage, unres, &err);
     if (ret == LY_EINCOMPLETE) {
         /* we have no data so we will not be resolving it */
         ret = LY_SUCCESS;
@@ -1187,10 +1193,12 @@
  * @param[in] ctx Compile context.
  * @param[in] leaf Leaf that the default value is for.
  * @param[in] dflt Default value to compile.
+ * @param[in,out] unres Global unres structure for newly implemented modules.
  * @return LY_ERR value.
  */
 static LY_ERR
-lys_compile_unres_leaf_dlft(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, struct lysp_qname *dflt)
+lys_compile_unres_leaf_dlft(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, struct lysp_qname *dflt,
+        struct lys_glob_unres *unres)
 {
     LY_ERR ret;
 
@@ -1206,7 +1214,7 @@
     LY_CHECK_ERR_RET(!leaf->dflt, LOGMEM(ctx->ctx), LY_EMEM);
 
     /* store the default value */
-    ret = lys_compile_unres_dflt(ctx, (struct lysc_node *)leaf, leaf->type, dflt->str, dflt->mod, leaf->dflt);
+    ret = lys_compile_unres_dflt(ctx, (struct lysc_node *)leaf, leaf->type, dflt->str, dflt->mod, leaf->dflt, unres);
     if (ret) {
         free(leaf->dflt);
         leaf->dflt = NULL;
@@ -1222,11 +1230,12 @@
  * @param[in] llist Leaf-list that the default value(s) are for.
  * @param[in] dflt Default value to compile, in case of a single value.
  * @param[in] dflts Sized array of default values, in case of more values.
+ * @param[in,out] unres Global unres structure for newly implemented modules.
  * @return LY_ERR value.
  */
 static LY_ERR
 lys_compile_unres_llist_dflts(struct lysc_ctx *ctx, struct lysc_node_leaflist *llist, struct lysp_qname *dflt,
-        struct lysp_qname *dflts)
+        struct lysp_qname *dflts, struct lys_glob_unres *unres)
 {
     LY_ERR ret;
     LY_ARRAY_COUNT_TYPE orig_count, u, v;
@@ -1253,14 +1262,14 @@
         LY_ARRAY_FOR(dflts, u) {
             llist->dflts[orig_count + u] = calloc(1, sizeof **llist->dflts);
             ret = lys_compile_unres_dflt(ctx, (struct lysc_node *)llist, llist->type, dflts[u].str, dflts[u].mod,
-                    llist->dflts[orig_count + u]);
+                    llist->dflts[orig_count + u], unres);
             LY_CHECK_ERR_RET(ret, free(llist->dflts[orig_count + u]), ret);
             LY_ARRAY_INCREMENT(llist->dflts);
         }
     } else {
         llist->dflts[orig_count] = calloc(1, sizeof **llist->dflts);
         ret = lys_compile_unres_dflt(ctx, (struct lysc_node *)llist, llist->type, dflt->str, dflt->mod,
-                llist->dflts[orig_count]);
+                llist->dflts[orig_count], unres);
         LY_CHECK_ERR_RET(ret, free(llist->dflts[orig_count]), ret);
         LY_ARRAY_INCREMENT(llist->dflts);
     }
@@ -1285,24 +1294,168 @@
     return LY_SUCCESS;
 }
 
+LY_ERR
+lys_compile_unres_glob(struct ly_ctx *ctx, struct lys_glob_unres *unres)
+{
+    struct lysc_node *node;
+    struct lysc_type *type, *typeiter;
+    struct lysc_type_leafref *lref;
+    struct lysc_ctx cctx = {0};
+    LY_ARRAY_COUNT_TYPE v;
+    uint32_t i;
+
+    if (unres->recompile) {
+        /* recompile all the modules and resolve the new unres instead (during recompilation) */
+        unres->recompile = 0;
+        return lys_recompile(ctx, 1);
+    }
+
+    /* fake compile context */
+    cctx.ctx = ctx;
+    cctx.path_len = 1;
+    cctx.path[0] = '/';
+
+    /* for leafref, we need 2 rounds - first detects circular chain by storing the first referred type (which
+     * can be also leafref, in case it is already resolved, go through the chain and check that it does not
+     * point to the starting leafref type). The second round stores the first non-leafref type for later data validation. */
+    for (i = 0; i < unres->leafrefs.count; ++i) {
+        node = unres->leafrefs.objs[i];
+        cctx.cur_mod = node->module;
+        cctx.pmod = node->module->parsed;
+
+        assert(node->nodetype & (LYS_LEAF | LYS_LEAFLIST));
+        type = ((struct lysc_node_leaf *)node)->type;
+        if (type->basetype == LY_TYPE_LEAFREF) {
+            LY_CHECK_RET(lys_compile_unres_leafref(&cctx, node, (struct lysc_type_leafref *)type, unres));
+        } else if (type->basetype == LY_TYPE_UNION) {
+            LY_ARRAY_FOR(((struct lysc_type_union *)type)->types, v) {
+                if (((struct lysc_type_union *)type)->types[v]->basetype == LY_TYPE_LEAFREF) {
+                    lref = (struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v];
+                    LY_CHECK_RET(lys_compile_unres_leafref(&cctx, node, lref, unres));
+                }
+            }
+        }
+    }
+    while (unres->leafrefs.count) {
+        node = unres->leafrefs.objs[unres->leafrefs.count - 1];
+        cctx.cur_mod = node->module;
+        cctx.pmod = node->module->parsed;
+
+        /* store pointer to the real type */
+        type = ((struct lysc_node_leaf *)node)->type;
+        if (type->basetype == LY_TYPE_LEAFREF) {
+            for (typeiter = ((struct lysc_type_leafref *)type)->realtype;
+                    typeiter->basetype == LY_TYPE_LEAFREF;
+                    typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
+            ((struct lysc_type_leafref *)type)->realtype = typeiter;
+        } else if (type->basetype == LY_TYPE_UNION) {
+            LY_ARRAY_FOR(((struct lysc_type_union *)type)->types, v) {
+                if (((struct lysc_type_union *)type)->types[v]->basetype == LY_TYPE_LEAFREF) {
+                    for (typeiter = ((struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v])->realtype;
+                            typeiter->basetype == LY_TYPE_LEAFREF;
+                            typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
+                    ((struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v])->realtype = typeiter;
+                }
+            }
+        }
+
+        ly_set_rm_index(&unres->leafrefs, unres->leafrefs.count - 1, NULL);
+    }
+
+    /* check xpath */
+    while (unres->xpath.count) {
+        node = unres->xpath.objs[unres->xpath.count - 1];
+        cctx.cur_mod = node->module;
+        cctx.pmod = node->module->parsed;
+
+        LY_CHECK_RET(lys_compile_unres_xpath(&cctx, node, unres));
+
+        ly_set_rm_index(&unres->xpath, unres->xpath.count - 1, NULL);
+    }
+
+    /* finish incomplete default values compilation */
+    while (unres->dflts.count) {
+        struct lysc_unres_dflt *r = unres->dflts.objs[unres->dflts.count - 1];
+        cctx.cur_mod = r->leaf->module;
+        cctx.pmod = r->leaf->module->parsed;
+
+        if (r->leaf->nodetype == LYS_LEAF) {
+            LY_CHECK_RET(lys_compile_unres_leaf_dlft(&cctx, r->leaf, r->dflt, unres));
+        } else {
+            LY_CHECK_RET(lys_compile_unres_llist_dflts(&cctx, r->llist, r->dflt, r->dflts, unres));
+        }
+        lysc_unres_dflt_free(ctx, r);
+
+        ly_set_rm_index(&unres->dflts, unres->dflts.count - 1, NULL);
+    }
+
+    /* some unres items may have been added */
+    if (unres->leafrefs.count || unres->xpath.count || unres->dflts.count) {
+        return lys_compile_unres_glob(ctx, unres);
+    }
+
+    return LY_SUCCESS;
+}
+
+void
+lys_compile_unres_glob_revert(struct ly_ctx *ctx, struct lys_glob_unres *unres)
+{
+    uint32_t i;
+    struct lys_module *m;
+
+    for (i = 0; i < unres->implementing.count; ++i) {
+        m = unres->implementing.objs[i];
+        assert(m->implemented);
+
+        /* make the module correctly non-implemented again */
+        m->implemented = 0;
+        lys_precompile_augments_deviations_revert(ctx, m);
+    }
+
+    for (i = 0; i < unres->creating.count; ++i) {
+        m = unres->creating.objs[i];
+
+        /* remove the module from the context and free it */
+        ly_set_rm(&ctx->list, m, NULL);
+        lys_module_free(m, NULL);
+    }
+
+    if (unres->implementing.count) {
+        /* recompile because some implemented modules are no longer implemented */
+        lys_recompile(ctx, 0);
+    }
+}
+
+void
+lys_compile_unres_glob_erase(const struct ly_ctx *ctx, struct lys_glob_unres *unres)
+{
+    uint32_t i;
+
+    ly_set_erase(&unres->implementing, NULL);
+    ly_set_erase(&unres->creating, NULL);
+    for (i = 0; i < unres->dflts.count; ++i) {
+        lysc_unres_dflt_free(ctx, unres->dflts.objs[i]);
+    }
+    ly_set_erase(&unres->dflts, NULL);
+    ly_set_erase(&unres->xpath, NULL);
+    ly_set_erase(&unres->leafrefs, NULL);
+}
+
 /**
- * @brief Finish compilation of all the unres sets of a compile context.
+ * @brief Finish compilation of all the module unres sets in a compile context.
  *
  * @param[in] ctx Compile context with unres sets.
  * @return LY_ERR value.
  */
 static LY_ERR
-lys_compile_unres(struct lysc_ctx *ctx)
+lys_compile_unres_mod(struct lysc_ctx *ctx)
 {
     struct lysc_node *node;
     struct lysc_action **actions;
     struct lysc_notif **notifs;
-    struct lysc_type *type, *typeiter;
-    struct lysc_type_leafref *lref;
     struct lysc_augment *aug;
     struct lysc_deviation *dev;
     struct ly_set disabled_op = {0};
-    LY_ARRAY_COUNT_TYPE v;
     uint32_t i;
 
 #define ARRAY_DEL_ITEM(array, item) \
@@ -1373,59 +1526,6 @@
     }
     ly_set_erase(&disabled_op, NULL);
 
-    /* for leafref, we need 2 rounds - first detects circular chain by storing the first referred type (which
-     * can be also leafref, in case it is already resolved, go through the chain and check that it does not
-     * point to the starting leafref type). The second round stores the first non-leafref type for later data validation. */
-    for (i = 0; i < ctx->leafrefs.count; ++i) {
-        node = ctx->leafrefs.objs[i];
-        assert(node->nodetype & (LYS_LEAF | LYS_LEAFLIST));
-        type = ((struct lysc_node_leaf *)node)->type;
-        if (type->basetype == LY_TYPE_LEAFREF) {
-            LY_CHECK_RET(lys_compile_unres_leafref(ctx, node, (struct lysc_type_leafref *)type));
-        } else if (type->basetype == LY_TYPE_UNION) {
-            LY_ARRAY_FOR(((struct lysc_type_union *)type)->types, v) {
-                if (((struct lysc_type_union *)type)->types[v]->basetype == LY_TYPE_LEAFREF) {
-                    lref = (struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v];
-                    LY_CHECK_RET(lys_compile_unres_leafref(ctx, node, lref));
-                }
-            }
-        }
-    }
-    for (i = 0; i < ctx->leafrefs.count; ++i) {
-        /* store pointer to the real type */
-        type = ((struct lysc_node_leaf *)ctx->leafrefs.objs[i])->type;
-        if (type->basetype == LY_TYPE_LEAFREF) {
-            for (typeiter = ((struct lysc_type_leafref *)type)->realtype;
-                    typeiter->basetype == LY_TYPE_LEAFREF;
-                    typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
-            ((struct lysc_type_leafref *)type)->realtype = typeiter;
-        } else if (type->basetype == LY_TYPE_UNION) {
-            LY_ARRAY_FOR(((struct lysc_type_union *)type)->types, v) {
-                if (((struct lysc_type_union *)type)->types[v]->basetype == LY_TYPE_LEAFREF) {
-                    for (typeiter = ((struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v])->realtype;
-                            typeiter->basetype == LY_TYPE_LEAFREF;
-                            typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
-                    ((struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v])->realtype = typeiter;
-                }
-            }
-        }
-    }
-
-    /* check xpath */
-    for (i = 0; i < ctx->xpath.count; ++i) {
-        LY_CHECK_RET(lys_compile_unres_xpath(ctx, ctx->xpath.objs[i]));
-    }
-
-    /* finish incomplete default values compilation */
-    for (i = 0; i < ctx->dflts.count; ++i) {
-        struct lysc_unres_dflt *r = ctx->dflts.objs[i];
-        if (r->leaf->nodetype == LYS_LEAF) {
-            LY_CHECK_RET(lys_compile_unres_leaf_dlft(ctx, r->leaf, r->dflt));
-        } else {
-            LY_CHECK_RET(lys_compile_unres_llist_dflts(ctx, r->llist, r->dflt, r->dflts));
-        }
-    }
-
     /* check that all augments were applied */
     for (i = 0; i < ctx->augs.count; ++i) {
         aug = ctx->augs.objs[i];
@@ -1453,6 +1553,50 @@
 }
 
 /**
+ * @brief Erase all the module unres sets in a compile context.
+ *
+ * @param[in] ctx Compile context with unres sets.
+ * @param[in] error Whether the compilation finished with an error or not.
+ */
+static void
+lys_compile_unres_mod_erase(struct lysc_ctx *ctx, ly_bool error)
+{
+    uint32_t i;
+
+    ly_set_erase(&ctx->groupings, NULL);
+    ly_set_erase(&ctx->tpdf_chain, NULL);
+    ly_set_erase(&ctx->disabled, NULL);
+
+    if (!error) {
+        /* there can be no leftover deviations or augments */
+        LY_CHECK_ERR_RET(ctx->augs.count, LOGINT(ctx->ctx), );
+        LY_CHECK_ERR_RET(ctx->devs.count, LOGINT(ctx->ctx), );
+
+        ly_set_erase(&ctx->augs, NULL);
+        ly_set_erase(&ctx->devs, NULL);
+        ly_set_erase(&ctx->uses_augs, NULL);
+        ly_set_erase(&ctx->uses_rfns, NULL);
+    } else {
+        for (i = 0; i < ctx->augs.count; ++i) {
+            lysc_augment_free(ctx->ctx, ctx->augs.objs[i]);
+        }
+        ly_set_erase(&ctx->augs, NULL);
+        for (i = 0; i < ctx->devs.count; ++i) {
+            lysc_deviation_free(ctx->ctx, ctx->devs.objs[i]);
+        }
+        ly_set_erase(&ctx->devs, NULL);
+        for (i = 0; i < ctx->uses_augs.count; ++i) {
+            lysc_augment_free(ctx->ctx, ctx->uses_augs.objs[i]);
+        }
+        ly_set_erase(&ctx->uses_augs, NULL);
+        for (i = 0; i < ctx->uses_rfns.count; ++i) {
+            lysc_refine_free(ctx->ctx, ctx->uses_rfns.objs[i]);
+        }
+        ly_set_erase(&ctx->uses_rfns, NULL);
+    }
+}
+
+/**
  * @brief Compile identites in the current module and all its submodules.
  *
  * @param[in] ctx Compile context.
@@ -1490,54 +1634,24 @@
     return LY_SUCCESS;
 }
 
-static LY_ERR
-lys_recompile_mod(struct lys_module *mod, ly_bool log)
-{
-    LY_ERR ret;
-    uint32_t prev_lo;
-    struct lysp_import *imp;
-
-    if (!mod->implemented || mod->compiled) {
-        /* nothing to do */
-        return LY_SUCCESS;
-    }
-
-    /* we need all implemented imports to be recompiled */
-    LY_ARRAY_FOR(mod->parsed->imports, struct lysp_import, imp) {
-        LY_CHECK_RET(lys_recompile_mod(imp->module, log));
-    }
-
-    if (!log) {
-        /* recompile, must succeed because it was already compiled; hide messages because any
-         * warnings were already printed, are not really relevant, and would hide the real error */
-        prev_lo = ly_log_options(0);
-    }
-    ret = lys_compile(mod, 0);
-    if (!log) {
-        ly_log_options(prev_lo);
-    }
-
-    if (ret && !log) {
-        LOGERR(mod->ctx, ret, "Recompilation of module \"%s\" failed.", mod->name);
-    }
-    return ret;
-}
-
 LY_ERR
-lys_recompile(struct ly_ctx *ctx, const struct lys_module *skip)
+lys_recompile(struct ly_ctx *ctx, ly_bool log)
 {
     uint32_t idx;
     struct lys_module *mod;
-    LY_ERR ret = LY_SUCCESS, r;
+    struct lys_glob_unres unres = {0};
+    LY_ERR ret = LY_SUCCESS;
+    uint32_t prev_lo;
+
+    if (!log) {
+        /* recompile, must succeed because the modules were already compiled; hide messages because any
+         * warnings were already printed, are not really relevant, and would hide the real error */
+        prev_lo = ly_log_options(0);
+    }
 
     /* free all the modules */
     for (idx = 0; idx < ctx->list.count; ++idx) {
         mod = ctx->list.objs[idx];
-        /* skip this module */
-        if (skip && (mod == skip)) {
-            continue;
-        }
-
         if (mod->compiled) {
             /* free the module */
             lysc_module_free(mod->compiled, NULL);
@@ -1551,27 +1665,34 @@
     /* recompile all the modules */
     for (idx = 0; idx < ctx->list.count; ++idx) {
         mod = ctx->list.objs[idx];
-
-        /* skip this module */
-        if (skip && (mod == skip)) {
+        if (!mod->implemented || mod->compiled) {
+            /* nothing to do */
             continue;
         }
 
-        /* compile again */
-        r = lys_recompile_mod(mod, skip ? 1 : 0);
-        if (r) {
-            if (skip) {
-                return r;
+        /* recompile */
+        ret = lys_compile(mod, 0, &unres);
+        if (ret) {
+            if (!log) {
+                LOGERR(mod->ctx, ret, "Recompilation of module \"%s\" failed.", mod->name);
             }
-            ret = r;
+            goto cleanup;
         }
     }
 
+    /* resolve global unres */
+    LY_CHECK_GOTO(ret = lys_compile_unres_glob(ctx, &unres), cleanup);
+
+cleanup:
+    if (!log) {
+        ly_log_options(prev_lo);
+    }
+    lys_compile_unres_glob_erase(ctx, &unres);
     return ret;
 }
 
 LY_ERR
-lys_compile(struct lys_module *mod, uint32_t options)
+lys_compile(struct lys_module *mod, uint32_t options, struct lys_glob_unres *unres)
 {
     struct lysc_ctx ctx = {0};
     struct lysc_module *mod_c;
@@ -1580,7 +1701,6 @@
     struct lysp_node *pnode;
     struct lysp_grp *grps;
     LY_ARRAY_COUNT_TYPE u;
-    uint32_t i;
     LY_ERR ret = LY_SUCCESS;
 
     LY_CHECK_ARG_RET(NULL, mod, mod->parsed, !mod->compiled, mod->ctx, LY_EINVAL);
@@ -1601,6 +1721,7 @@
     ctx.options = options;
     ctx.path_len = 1;
     ctx.path[0] = '/';
+    ctx.unres = unres;
 
     mod->compiled = mod_c = calloc(1, sizeof *mod_c);
     LY_CHECK_ERR_RET(!mod_c, LOGMEM(mod->ctx), LY_EMEM);
@@ -1686,56 +1807,15 @@
     }
     ctx.pmod = sp;
 
-    /* finish compilation for all unresolved items in the context */
-    LY_CHECK_GOTO(ret = lys_compile_unres(&ctx), error);
+    /* finish compilation for all unresolved module items in the context */
+    LY_CHECK_GOTO(ret = lys_compile_unres_mod(&ctx), error);
 
-    /* there can be no leftover deviations or augments */
-    LY_CHECK_ERR_GOTO(ctx.augs.count, LOGINT(ctx.ctx); ret = LY_EINT, error);
-    LY_CHECK_ERR_GOTO(ctx.devs.count, LOGINT(ctx.ctx); ret = LY_EINT, error);
-
-    for (i = 0; i < ctx.dflts.count; ++i) {
-        lysc_unres_dflt_free(ctx.ctx, ctx.dflts.objs[i]);
-    }
-    ly_set_erase(&ctx.dflts, NULL);
-    ly_set_erase(&ctx.xpath, NULL);
-    ly_set_erase(&ctx.leafrefs, NULL);
-    ly_set_erase(&ctx.groupings, NULL);
-    ly_set_erase(&ctx.tpdf_chain, NULL);
-    ly_set_erase(&ctx.disabled, NULL);
-    ly_set_erase(&ctx.augs, NULL);
-    ly_set_erase(&ctx.devs, NULL);
-    ly_set_erase(&ctx.uses_augs, NULL);
-    ly_set_erase(&ctx.uses_rfns, NULL);
-
+    lys_compile_unres_mod_erase(&ctx, 0);
     return LY_SUCCESS;
 
 error:
     lys_precompile_augments_deviations_revert(ctx.ctx, mod);
-    for (i = 0; i < ctx.dflts.count; ++i) {
-        lysc_unres_dflt_free(ctx.ctx, ctx.dflts.objs[i]);
-    }
-    ly_set_erase(&ctx.dflts, NULL);
-    ly_set_erase(&ctx.xpath, NULL);
-    ly_set_erase(&ctx.leafrefs, NULL);
-    ly_set_erase(&ctx.groupings, NULL);
-    ly_set_erase(&ctx.tpdf_chain, NULL);
-    ly_set_erase(&ctx.disabled, NULL);
-    for (i = 0; i < ctx.augs.count; ++i) {
-        lysc_augment_free(ctx.ctx, ctx.augs.objs[i]);
-    }
-    ly_set_erase(&ctx.augs, NULL);
-    for (i = 0; i < ctx.devs.count; ++i) {
-        lysc_deviation_free(ctx.ctx, ctx.devs.objs[i]);
-    }
-    ly_set_erase(&ctx.devs, NULL);
-    for (i = 0; i < ctx.uses_augs.count; ++i) {
-        lysc_augment_free(ctx.ctx, ctx.uses_augs.objs[i]);
-    }
-    ly_set_erase(&ctx.uses_augs, NULL);
-    for (i = 0; i < ctx.uses_rfns.count; ++i) {
-        lysc_refine_free(ctx.ctx, ctx.uses_rfns.objs[i]);
-    }
-    ly_set_erase(&ctx.uses_rfns, NULL);
+    lys_compile_unres_mod_erase(&ctx, 1);
     lysc_module_free(mod_c, NULL);
     mod->compiled = NULL;
 
diff --git a/src/schema_compile.h b/src/schema_compile.h
index f4eb2b2..63665fb 100644
--- a/src/schema_compile.h
+++ b/src/schema_compile.h
@@ -59,15 +59,13 @@
     struct lys_module *cur_mod; /**< module currently being compiled, used as the current module for unprefixed nodes */
     struct lysp_module *pmod;   /**< parsed module being processed, used for searching imports to resolve prefixed nodes */
     struct ly_set groupings;    /**< stack for groupings circular check */
-    struct ly_set xpath;        /**< when/must to check */
-    struct ly_set leafrefs;     /**< to validate leafref's targets */
-    struct ly_set dflts;        /**< set of incomplete default values */
     struct ly_set tpdf_chain;
     struct ly_set disabled;     /**< set of compiled nodes whose if-feature(s) was not satisifed */
     struct ly_set augs;         /**< set of compiled non-applied top-level augments */
     struct ly_set devs;         /**< set of compiled non-applied deviations */
     struct ly_set uses_augs;    /**< set of compiled non-applied uses augments */
     struct ly_set uses_rfns;    /**< set of compiled non-applied uses refines */
+    struct lys_glob_unres *unres;  /**< global unres sets */
     uint32_t path_len;
     uint32_t options;           /**< various @ref scflags. */
 #define LYSC_CTX_BUFSIZE 4078
@@ -75,6 +73,21 @@
 };
 
 /**
+ * @brief Structure for unresolved items that may depend on any implemented module data so their resolution
+ * can only be performed after all module basic compilation is done.
+ */
+struct lys_glob_unres {
+    struct ly_set implementing; /**< set of YANG schemas being atomically implemented (compiled); the first added
+                                    module is always the explcitly implemented module, the other ones are dependencies */
+    struct ly_set creating;     /**< set of YANG schemas being atomically created (parsed); it is a subset of implemented
+                                    and all these modules are freed if any error occurs */
+    struct ly_set xpath;        /**< when/must to check */
+    struct ly_set leafrefs;     /**< to validate leafref's targets */
+    struct ly_set dflts;        /**< set of incomplete default values */
+    ly_bool recompile;          /**< flag whether all the modules need to be recompiled (because of new deviations) */
+};
+
+/**
  * @brief Structure for remembering default values of leaves and leaf-lists. They are resolved at schema compilation
  * end when the whole schema tree is available.
  */
@@ -229,23 +242,48 @@
  * @param[in] prefix_data Format-specific data (see ::ly_resolve_prefix()).
  * @param[in] implement Whether all the non-implemented modules should are implemented or the first
  * non-implemented module, if any, returned in @p mod_p.
+ * @param[in,out] unres Global unres structure of newly implemented modules.
  * @param[out] mod_p Module that is not implemented.
  * @return LY_SUCCESS on success.
  * @return LY_ERR on error.
  */
 LY_ERR lys_compile_expr_implement(const struct ly_ctx *ctx, const struct lyxp_expr *expr, LY_PREFIX_FORMAT format,
-        void *prefix_data, ly_bool implement, const struct lys_module **mod_p);
+        void *prefix_data, ly_bool implement, struct lys_glob_unres *unres, const struct lys_module **mod_p);
+
+/**
+ * @brief Finish compilation of all the global unres sets.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] unres Global unres structure with the sets to resolve.
+ * @return LY_ERR value.
+ */
+LY_ERR lys_compile_unres_glob(struct ly_ctx *ctx, struct lys_glob_unres *unres);
+
+/**
+ * @brief Revert a failed compilation (free new modules, unimplement newly implemented modules).
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] unres Global unres set with newly implemented modules.
+ */
+void lys_compile_unres_glob_revert(struct ly_ctx *ctx, struct lys_glob_unres *unres);
+
+/**
+ * @brief Erase all the global unres sets.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] unres Global unres structure with the sets.
+ */
+void lys_compile_unres_glob_erase(const struct ly_ctx *ctx, struct lys_glob_unres *unres);
 
 /**
  * @brief Recompile the whole context based on the current flags.
  *
  * @param[in] ctx Context to recompile.
- * @param[in] skip Module to skip. If set, recompilation logs normally and stops on error.
- * If not set, recompilation hides any errors and prints just generic messages even though it should always succeed.
+ * @param[in] log Whether to log all the errors.
  * @return LY_SUCCESS on success.
  * @return LY_ERR on error.
  */
-LY_ERR lys_recompile(struct ly_ctx *ctx, const struct lys_module *skip);
+LY_ERR lys_recompile(struct ly_ctx *ctx, ly_bool log);
 
 /**
  * @brief Compile printable schema into a validated schema linking all the references.
@@ -253,8 +291,9 @@
  * @param[in] mod Pointer to the schema structure holding pointers to both schema structure types. The ::lys_module#parsed
  * member is used as input and ::lys_module#compiled is used to hold the result of the compilation.
  * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
+ * @param[in,out] unres Global unres structure for newly implemented modules.
  * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
  */
-LY_ERR lys_compile(struct lys_module *mod, uint32_t options);
+LY_ERR lys_compile(struct lys_module *mod, uint32_t options, struct lys_glob_unres *unres);
 
 #endif /* LY_SCHEMA_COMPILE_H_ */
diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c
index 7c5fea3..8093d86 100644
--- a/src/schema_compile_amend.c
+++ b/src/schema_compile_amend.c
@@ -100,7 +100,7 @@
 
             /* all the modules must be implemented */
             if (!mod->implemented) {
-                ret = lys_set_implemented(mod, NULL);
+                ret = lys_set_implemented_r(mod, NULL, ctx->unres);
                 LY_CHECK_GOTO(ret, cleanup);
             }
         }
@@ -2226,7 +2226,7 @@
 LY_ERR
 lys_precompile_augments_deviations(struct lysc_ctx *ctx)
 {
-    LY_ERR ret = LY_SUCCESS;
+    LY_ERR ret;
     LY_ARRAY_COUNT_TYPE u, v;
     const struct lysp_module *mod_p;
     const struct lysc_node *target;
@@ -2236,12 +2236,12 @@
     uint16_t flags;
     uint32_t idx, opt_prev = ctx->options;
 
-    for (idx = 0; idx < ctx->ctx->implementing.count; ++idx) {
-        if (ctx->cur_mod == ctx->ctx->implementing.objs[idx]) {
+    for (idx = 0; idx < ctx->unres->implementing.count; ++idx) {
+        if (ctx->cur_mod == ctx->unres->implementing.objs[idx]) {
             break;
         }
     }
-    if (idx == ctx->ctx->implementing.count) {
+    if (idx == ctx->unres->implementing.count) {
         /* it was already implemented and all the augments and deviations fully applied */
         return LY_SUCCESS;
     }
@@ -2334,16 +2334,12 @@
         }
     }
 
-    if (!has_dev) {
-        /* no need to recompile any modules */
-        return LY_SUCCESS;
+    if (has_dev) {
+        /* all modules (may) need to be recompiled */
+        ctx->unres->recompile = 1;
     }
 
-    /* recompile all modules except this one */
-    LY_CHECK_GOTO(ret = lys_recompile(ctx->ctx, mod_p->mod), cleanup);
-
-cleanup:
-    return ret;
+    return LY_SUCCESS;
 }
 
 void
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index 17d5f9c..9593d09 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -69,10 +69,10 @@
         return LY_SUCCESS;
     }
 
-    for (i = 0; i < ctx->dflts.count; ++i) {
-        if (((struct lysc_unres_dflt *)ctx->dflts.objs[i])->leaf == leaf) {
+    for (i = 0; i < ctx->unres->dflts.count; ++i) {
+        if (((struct lysc_unres_dflt *)ctx->unres->dflts.objs[i])->leaf == leaf) {
             /* just replace the default */
-            r = ctx->dflts.objs[i];
+            r = ctx->unres->dflts.objs[i];
             lysp_qname_free(ctx->ctx, r->dflt);
             free(r->dflt);
             break;
@@ -84,7 +84,7 @@
         LY_CHECK_ERR_RET(!r, LOGMEM(ctx->ctx), LY_EMEM);
         r->leaf = leaf;
 
-        LY_CHECK_RET(ly_set_add(&ctx->dflts, r, 1, NULL));
+        LY_CHECK_RET(ly_set_add(&ctx->unres->dflts, r, 1, NULL));
     }
 
     r->dflt = malloc(sizeof *r->dflt);
@@ -117,10 +117,10 @@
         return LY_SUCCESS;
     }
 
-    for (i = 0; i < ctx->dflts.count; ++i) {
-        if (((struct lysc_unres_dflt *)ctx->dflts.objs[i])->llist == llist) {
+    for (i = 0; i < ctx->unres->dflts.count; ++i) {
+        if (((struct lysc_unres_dflt *)ctx->unres->dflts.objs[i])->llist == llist) {
             /* just replace the defaults */
-            r = ctx->dflts.objs[i];
+            r = ctx->unres->dflts.objs[i];
             lysp_qname_free(ctx->ctx, r->dflt);
             free(r->dflt);
             r->dflt = NULL;
@@ -134,7 +134,7 @@
         LY_CHECK_ERR_RET(!r, LOGMEM(ctx->ctx), LY_EMEM);
         r->llist = llist;
 
-        LY_CHECK_RET(ly_set_add(&ctx->dflts, r, 1, NULL));
+        LY_CHECK_RET(ly_set_add(&ctx->unres->dflts, r, 1, NULL));
     }
 
     DUP_ARRAY(ctx->ctx, dflts, r->dflts, lysp_qname_dup);
@@ -292,7 +292,7 @@
     if (!(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "when" semantics in a grouping, but repeat the check for different node because
          * of dummy node check */
-        LY_CHECK_RET(ly_set_add(&ctx->xpath, node, 0, NULL));
+        LY_CHECK_RET(ly_set_add(&ctx->unres->xpath, node, 0, NULL));
     }
 
     return LY_SUCCESS;
@@ -2175,7 +2175,7 @@
 
     if ((action->input.musts || action->output.musts) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
         /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->xpath, action, 0, NULL);
+        ret = ly_set_add(&ctx->unres->xpath, action, 0, NULL);
         LY_CHECK_GOTO(ret, cleanup);
     }
 
@@ -2244,7 +2244,7 @@
     COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, lys_compile_must, ret, cleanup);
     if (notif_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->xpath, notif, 0, NULL);
+        ret = ly_set_add(&ctx->unres->xpath, notif, 0, NULL);
         LY_CHECK_GOTO(ret, cleanup);
     }
 
@@ -2324,7 +2324,7 @@
     COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, lys_compile_must, ret, done);
     if (cont_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->xpath, cont, 0, NULL);
+        ret = ly_set_add(&ctx->unres->xpath, cont, 0, NULL);
         LY_CHECK_GOTO(ret, done);
     }
     COMPILE_OP_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, node, lys_compile_action, 0, ret, done);
@@ -2358,13 +2358,13 @@
 
     if ((leaf->type->basetype == LY_TYPE_LEAFREF) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
         /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
-        LY_CHECK_RET(ly_set_add(&ctx->leafrefs, leaf, 0, NULL));
+        LY_CHECK_RET(ly_set_add(&ctx->unres->leafrefs, leaf, 0, NULL));
     } else if ((leaf->type->basetype == LY_TYPE_UNION) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
         LY_ARRAY_COUNT_TYPE u;
         LY_ARRAY_FOR(((struct lysc_type_union *)leaf->type)->types, u) {
             if (((struct lysc_type_union *)leaf->type)->types[u]->basetype == LY_TYPE_LEAFREF) {
                 /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
-                LY_CHECK_RET(ly_set_add(&ctx->leafrefs, leaf, 0, NULL));
+                LY_CHECK_RET(ly_set_add(&ctx->unres->leafrefs, leaf, 0, NULL));
             }
         }
     } else if (leaf->type->basetype == LY_TYPE_EMPTY) {
@@ -2396,7 +2396,7 @@
     COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, lys_compile_must, ret, done);
     if (leaf_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->xpath, leaf, 0, NULL);
+        ret = ly_set_add(&ctx->unres->xpath, leaf, 0, NULL);
         LY_CHECK_GOTO(ret, done);
     }
     if (leaf_p->units) {
@@ -2443,7 +2443,7 @@
     COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, lys_compile_must, ret, done);
     if (llist_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->xpath, llist, 0, NULL);
+        ret = ly_set_add(&ctx->unres->xpath, llist, 0, NULL);
         LY_CHECK_GOTO(ret, done);
     }
     if (llist_p->units) {
@@ -2748,7 +2748,7 @@
     COMPILE_ARRAY_GOTO(ctx, list_p->musts, list->musts, lys_compile_must, ret, done);
     if (list_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "must" semantics in a grouping */
-        LY_CHECK_RET(ly_set_add(&ctx->xpath, list, 0, NULL));
+        LY_CHECK_RET(ly_set_add(&ctx->unres->xpath, list, 0, NULL));
     }
 
     /* keys */
@@ -3035,7 +3035,7 @@
     COMPILE_ARRAY_GOTO(ctx, any_p->musts, any->musts, lys_compile_must, ret, done);
     if (any_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
         /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->xpath, any, 0, NULL);
+        ret = ly_set_add(&ctx->unres->xpath, any, 0, NULL);
         LY_CHECK_GOTO(ret, done);
     }
 
diff --git a/src/tree_data.c b/src/tree_data.c
index 12b853b..f8a9775 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -66,7 +66,7 @@
         *incomplete = 0;
     }
 
-    ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, &err);
+    ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, NULL, &err);
     if (ret == LY_EINCOMPLETE) {
         if (incomplete) {
             *incomplete = 1;
@@ -128,7 +128,7 @@
 
     type = ((struct lysc_node_leaf *)node)->type;
     rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, 0, format, prefix_data,
-            LYD_HINT_SCHEMA, node, &storage, &err);
+            LYD_HINT_SCHEMA, node, &storage, NULL, &err);
     if (rc == LY_EINCOMPLETE) {
         /* actually success since we do not provide the context tree and call validation with
          * LY_TYPE_OPTS_INCOMPLETE_DATA */
@@ -168,7 +168,7 @@
     type = ((struct lysc_node_leaf *)node->schema)->type;
     /* store */
     rc = type->plugin->store(ctx ? ctx : LYD_CTX(node), type, value, value_len, 0, LY_PREF_JSON, NULL,
-            LYD_HINT_DATA, node->schema, &val, &err);
+            LYD_HINT_DATA, node->schema, &val, NULL, &err);
     if (rc == LY_EINCOMPLETE) {
         stored = 1;
 
@@ -1264,7 +1264,7 @@
     /* compile path */
     LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, parent ? parent->schema : NULL, exp, LY_PATH_LREF_FALSE,
             options & LYD_NEW_PATH_OUTPUT ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, LY_PREF_JSON,
-            NULL, &p), cleanup);
+            NULL, NULL, &p), cleanup);
 
     schema = p[LY_ARRAY_COUNT(p) - 1].node;
     if ((schema->nodetype == LYS_LIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE) &&
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 33dd7a5..85ca8bf 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -495,7 +495,7 @@
     /* compile */
     oper = output ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
     ret = ly_path_compile(ctx, NULL, ctx_node, expr, LY_PATH_LREF_FALSE, oper, LY_PATH_TARGET_MANY,
-            LY_PREF_JSON, NULL, &p);
+            LY_PREF_JSON, NULL, NULL, &p);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* resolve */
@@ -529,7 +529,7 @@
     /* compile */
     oper = output ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
     ret = ly_path_compile(ctx, NULL, ctx_node, exp, LY_PATH_LREF_FALSE, oper, LY_PATH_TARGET_MANY,
-            LY_PREF_JSON, NULL, &p);
+            LY_PREF_JSON, NULL, NULL, &p);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* get last node */
@@ -667,29 +667,12 @@
     return LY_SUCCESS;
 }
 
-API LY_ERR
-lys_set_implemented(struct lys_module *mod, const char **features)
+LY_ERR
+lys_set_implemented_r(struct lys_module *mod, const char **features, struct lys_glob_unres *unres)
 {
-    LY_ERR ret = LY_SUCCESS, r;
     struct lys_module *m;
-    uint32_t i, idx;
 
-    LY_CHECK_ARG_RET(NULL, mod, LY_EINVAL);
-
-    if (mod->implemented) {
-        /* mod is already implemented, set the features */
-        r = lys_set_features(mod->parsed, features);
-        if (r == LY_EEXIST) {
-            /* no changes */
-            return LY_SUCCESS;
-        } else if (r) {
-            /* error */
-            return r;
-        }
-
-        /* full recompilation */
-        return lys_recompile(mod->ctx, NULL);
-    }
+    assert(!mod->implemented);
 
     /* we have module from the current context */
     m = ly_ctx_get_module_implemented(mod->ctx, mod->name);
@@ -706,37 +689,52 @@
     LY_CHECK_RET(lys_enable_features(mod->parsed, features));
 
     /* add the module into newly implemented module set */
-    LY_CHECK_RET(ly_set_add(&mod->ctx->implementing, mod, 1, NULL));
+    LY_CHECK_RET(ly_set_add(&unres->implementing, mod, 1, NULL));
 
     /* mark the module implemented, check for collision was already done */
     mod->implemented = 1;
 
     /* compile the schema */
-    ret = lys_compile(mod, 0);
+    return lys_compile(mod, 0, unres);
+}
 
-    if (mod == mod->ctx->implementing.objs[0]) {
-        /* the first module being implemented, consolidate the set */
-        if (ret) {
-            /* failure, full compile revert */
-            for (i = 0; i < mod->ctx->list.count; ++i) {
-                m = mod->ctx->list.objs[i];
-                if (ly_set_contains(&mod->ctx->implementing, m, &idx)) {
-                    assert(m->implemented);
+API LY_ERR
+lys_set_implemented(struct lys_module *mod, const char **features)
+{
+    LY_ERR ret = LY_SUCCESS, r;
+    struct lys_glob_unres unres = {0};
 
-                    /* make the module correctly non-implemented again */
-                    m->implemented = 0;
-                    ly_set_rm_index(&mod->ctx->implementing, idx, NULL);
-                    lys_precompile_augments_deviations_revert(mod->ctx, m);
-                }
-            }
+    LY_CHECK_ARG_RET(NULL, mod, LY_EINVAL);
 
-            /* recompile, do not overwrite return value */
-            lys_recompile(mod->ctx, NULL);
+    if (mod->implemented) {
+        /* mod is already implemented, set the features */
+        r = lys_set_features(mod->parsed, features);
+        if (r == LY_EEXIST) {
+            /* no changes */
+            return LY_SUCCESS;
+        } else if (r) {
+            /* error */
+            return r;
         }
 
-        ly_set_erase(&mod->ctx->implementing, NULL);
+        /* full recompilation */
+        return lys_recompile(mod->ctx, 1);
     }
 
+    /* implement this module and any other required modules, recursively */
+    ret = lys_set_implemented_r(mod, features, &unres);
+    assert(mod == unres.implementing.objs[0]);
+
+    /* the first module being implemented is finished, resolve global unres, consolidate the set */
+    if (!ret) {
+        ret = lys_compile_unres_glob(mod->ctx, &unres);
+    }
+    if (ret) {
+        /* failure, full compile revert */
+        lys_compile_unres_glob_revert(mod->ctx, &unres);
+    }
+
+    lys_compile_unres_glob_erase(mod->ctx, &unres);
     return ret;
 }
 
@@ -751,7 +749,8 @@
     LY_ARRAY_FOR(pmod->imports, u) {
         imp = &pmod->imports[u];
         if (!imp->module) {
-            LY_CHECK_RET(lysp_load_module(PARSER_CTX(pctx), imp->name, imp->rev[0] ? imp->rev : NULL, 0, NULL, &imp->module));
+            LY_CHECK_RET(lysp_load_module(PARSER_CTX(pctx), imp->name, imp->rev[0] ? imp->rev : NULL, 0, NULL,
+                    pctx->unres, &imp->module));
         }
         /* check for importing the same module twice */
         for (v = 0; v < u; ++v) {
@@ -1044,7 +1043,7 @@
 LY_ERR
 lys_create_module(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, ly_bool implement,
         LY_ERR (*custom_check)(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data),
-        void *check_data, const char **features, struct lys_module **module)
+        void *check_data, const char **features, struct lys_glob_unres *unres, struct lys_module **module)
 {
     struct lys_module *mod = NULL, *latest, *mod_dup;
     struct lysp_submodule *submod;
@@ -1056,7 +1055,8 @@
     char *filename, *rev, *dot;
     size_t len;
 
-    LY_CHECK_ARG_RET(ctx, ctx, in, !features || implement, LY_EINVAL);
+    assert(ctx && in && (!features || implement) && unres);
+
     if (module) {
         *module = NULL;
     }
@@ -1067,11 +1067,11 @@
 
     switch (format) {
     case LYS_IN_YIN:
-        ret = yin_parse_module(&yinctx, in, mod);
+        ret = yin_parse_module(&yinctx, in, mod, unres);
         pctx = (struct lys_parser_ctx *)yinctx;
         break;
     case LYS_IN_YANG:
-        ret = yang_parse_module(&yangctx, in, mod);
+        ret = yang_parse_module(&yangctx, in, mod, unres);
         pctx = (struct lys_parser_ctx *)yangctx;
         break;
     default:
@@ -1181,22 +1181,25 @@
         LY_CHECK_GOTO(ret = lys_parsed_add_internal_ietf_netconf_with_defaults(mod->parsed), error);
     }
 
+    /* add the module into newly created module set, will also be freed from there on any error */
+    LY_CHECK_GOTO(ret = ly_set_add(&unres->creating, mod, 1, NULL), error);
+
     /* add into context */
     ret = ly_set_add(&ctx->list, mod, 1, NULL);
-    LY_CHECK_GOTO(ret, error);
+    LY_CHECK_GOTO(ret, cleanup);
     ctx->module_set_id++;
 
     /* resolve includes and all imports */
-    LY_CHECK_GOTO(ret = lys_resolve_import_include(pctx, mod->parsed), error_ctx);
+    LY_CHECK_GOTO(ret = lys_resolve_import_include(pctx, mod->parsed), cleanup);
 
     /* check name collisions */
-    LY_CHECK_GOTO(ret = lysp_check_dup_typedefs(pctx, mod->parsed), error_ctx);
+    LY_CHECK_GOTO(ret = lysp_check_dup_typedefs(pctx, mod->parsed), cleanup);
     /* TODO groupings */
-    LY_CHECK_GOTO(ret = lysp_check_dup_features(pctx, mod->parsed), error_ctx);
-    LY_CHECK_GOTO(ret = lysp_check_dup_identities(pctx, mod->parsed), error_ctx);
+    LY_CHECK_GOTO(ret = lysp_check_dup_features(pctx, mod->parsed), cleanup);
+    LY_CHECK_GOTO(ret = lysp_check_dup_identities(pctx, mod->parsed), cleanup);
 
     /* compile features */
-    LY_CHECK_GOTO(ret = lys_compile_feature_iffeatures(mod->parsed), error_ctx);
+    LY_CHECK_GOTO(ret = lys_compile_feature_iffeatures(mod->parsed), cleanup);
 
     if (!implement) {
         /* pre-compile identities of the module */
@@ -1210,23 +1213,16 @@
         }
     } else {
         /* implement (compile) */
-        LY_CHECK_GOTO(ret = lys_set_implemented(mod, features), error_ctx);
+        LY_CHECK_GOTO(ret = lys_set_implemented_r(mod, features, unres), cleanup);
     }
 
-    if (format == LYS_IN_YANG) {
-        yang_parser_ctx_free(yangctx);
-    } else {
-        yin_parser_ctx_free(yinctx);
-    }
-    if (module) {
-        *module = mod;
-    }
-    return LY_SUCCESS;
+    /* success */
+    goto cleanup;
 
-error_ctx:
-    ly_set_rm(&ctx->list, mod, NULL);
 error:
+    assert(ret);
     lys_module_free(mod, NULL);
+cleanup:
     if (pctx) {
         ly_set_erase(&pctx->tpdfs_nodes, NULL);
     }
@@ -1236,6 +1232,9 @@
         yin_parser_ctx_free(yinctx);
     }
 
+    if (!ret && module) {
+        *module = mod;
+    }
     return ret;
 }
 
@@ -1263,6 +1262,9 @@
 API LY_ERR
 lys_parse(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const char **features, const struct lys_module **module)
 {
+    LY_ERR ret;
+    struct lys_glob_unres unres = {0};
+
     if (module) {
         *module = NULL;
     }
@@ -1274,7 +1276,22 @@
     /* remember input position */
     in->func_start = in->current;
 
-    return lys_create_module(ctx, in, format, 1, NULL, NULL, features, (struct lys_module **)module);
+    ret = lys_create_module(ctx, in, format, 1, NULL, NULL, features, &unres, (struct lys_module **)module);
+    LY_CHECK_GOTO(ret, cleanup);
+
+    /* resolve global unres */
+    ret = lys_compile_unres_glob(ctx, &unres);
+    LY_CHECK_GOTO(ret, cleanup);
+
+cleanup:
+    if (ret) {
+        lys_compile_unres_glob_revert(ctx, &unres);
+    }
+    lys_compile_unres_glob_erase(ctx, &unres);
+    if (ret && module) {
+        *module = NULL;
+    }
+    return ret;
 }
 
 API LY_ERR
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 0211da0..b8fc9e9 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -494,37 +494,32 @@
     const struct lysp_tpdf *typedefs;
     LY_ARRAY_COUNT_TYPE u, v;
     uint32_t i;
-    LY_ERR ret = LY_EVALID;
+    LY_ERR ret = LY_SUCCESS;
 
     /* check name collisions - typedefs and groupings */
     ids_global = lyht_new(8, sizeof(char *), lysp_id_cmp, NULL, 1);
     ids_scoped = lyht_new(8, sizeof(char *), lysp_id_cmp, NULL, 1);
     LY_ARRAY_FOR(mod->typedefs, v) {
-        if (lysp_check_dup_typedef(ctx, NULL, &mod->typedefs[v], ids_global, ids_scoped)) {
-            goto cleanup;
-        }
+        ret = lysp_check_dup_typedef(ctx, NULL, &mod->typedefs[v], ids_global, ids_scoped);
+        LY_CHECK_GOTO(ret, cleanup);
     }
     LY_ARRAY_FOR(mod->includes, v) {
         LY_ARRAY_FOR(mod->includes[v].submodule->typedefs, u) {
-            if (lysp_check_dup_typedef(ctx, NULL, &mod->includes[v].submodule->typedefs[u], ids_global, ids_scoped)) {
-                goto cleanup;
-            }
+            ret = lysp_check_dup_typedef(ctx, NULL, &mod->includes[v].submodule->typedefs[u], ids_global, ids_scoped);
+            LY_CHECK_GOTO(ret, cleanup);
         }
     }
     for (i = 0; i < ctx->tpdfs_nodes.count; ++i) {
         typedefs = lysp_node_typedefs((struct lysp_node *)ctx->tpdfs_nodes.objs[i]);
         LY_ARRAY_FOR(typedefs, u) {
-            if (lysp_check_dup_typedef(ctx, (struct lysp_node *)ctx->tpdfs_nodes.objs[i], &typedefs[u], ids_global, ids_scoped)) {
-                goto cleanup;
-            }
+            ret = lysp_check_dup_typedef(ctx, (struct lysp_node *)ctx->tpdfs_nodes.objs[i], &typedefs[u], ids_global, ids_scoped);
+            LY_CHECK_GOTO(ret, cleanup);
         }
     }
-    ret = LY_SUCCESS;
+
 cleanup:
     lyht_free(ids_global);
     lyht_free(ids_scoped);
-    ly_set_erase(&ctx->tpdfs_nodes, NULL);
-
     return ret;
 }
 
@@ -713,7 +708,8 @@
 
 LY_ERR
 lys_module_localfile(struct ly_ctx *ctx, const char *name, const char *revision, const char **features, ly_bool implement,
-        struct lys_parser_ctx *main_ctx, const char *main_name, ly_bool required, void **result)
+        struct lys_parser_ctx *main_ctx, const char *main_name, ly_bool required, struct lys_glob_unres *unres,
+        void **result)
 {
     struct ly_in *in;
     char *filepath = NULL;
@@ -745,7 +741,7 @@
         ret = lys_parse_submodule(ctx, in, format, main_ctx, lysp_load_module_check, &check_data,
                 (struct lysp_submodule **)&mod);
     } else {
-        ret = lys_create_module(ctx, in, format, implement, lysp_load_module_check, &check_data, features,
+        ret = lys_create_module(ctx, in, format, implement, lysp_load_module_check, &check_data, features, unres,
                 (struct lys_module **)&mod);
 
     }
@@ -763,7 +759,7 @@
 
 LY_ERR
 lysp_load_module(struct ly_ctx *ctx, const char *name, const char *revision, ly_bool implement, const char **features,
-        struct lys_module **mod)
+        struct lys_glob_unres *unres, struct lys_module **mod)
 {
     const char *module_data = NULL;
     LYS_INFORMAT format = LYS_IN_UNKNOWN;
@@ -774,7 +770,7 @@
     struct ly_in *in;
     LY_ERR ret;
 
-    assert(mod);
+    assert(mod && unres);
 
     if (ctx->flags & LY_CTX_ALL_IMPLEMENTED) {
         implement = 1;
@@ -828,7 +824,7 @@
                     LY_CHECK_RET(ly_in_new_memory(module_data, &in));
                     check_data.name = name;
                     check_data.revision = revision;
-                    lys_create_module(ctx, in, format, implement, lysp_load_module_check, &check_data, features, mod);
+                    lys_create_module(ctx, in, format, implement, lysp_load_module_check, &check_data, features, unres, mod);
                     ly_in_free(in, 0);
                     if (module_data_free) {
                         module_data_free((void *)module_data, ctx->imp_clb_data);
@@ -842,7 +838,8 @@
 search_file:
             if (!(ctx->flags & LY_CTX_DISABLE_SEARCHDIRS)) {
                 /* module was not received from the callback or there is no callback set */
-                lys_module_localfile(ctx, name, revision, features, implement, NULL, NULL, ctx_latest ? 0 : 1, (void **)mod);
+                lys_module_localfile(ctx, name, revision, features, implement, NULL, NULL, ctx_latest ? 0 : 1, unres,
+                        (void **)mod);
             }
             if (!*mod && (ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
                 goto search_clb;
@@ -877,9 +874,8 @@
     /*
      * module found, make sure it is implemented if should be
      */
-    if (implement) {
-        /* mark the module implemented, check for collision was already done */
-        ret = lys_set_implemented(*mod, features);
+    if (implement && !(*mod)->implemented) {
+        ret = lys_set_implemented_r(*mod, features, unres);
         if (ret) {
             *mod = NULL;
             return ret;
@@ -961,7 +957,7 @@
         if (!(ctx->flags & LY_CTX_DISABLE_SEARCHDIRS)) {
             /* submodule was not received from the callback or there is no callback set */
             lys_module_localfile(ctx, inc->name, inc->rev[0] ? inc->rev : NULL, NULL, 0, pctx,
-                    pctx->parsed_mod->mod->name, 1, (void **)&submod);
+                    pctx->parsed_mod->mod->name, 1, NULL, (void **)&submod);
         }
         if (!submod && (ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
             goto search_clb;
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 730e3e4..4ee5aac 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -23,6 +23,7 @@
 #include "xml.h"
 
 struct lysc_ctx;
+struct lys_glob_unres;
 
 #define YIN_NS_URI "urn:ietf:params:xml:ns:yang:yin:1"
 
@@ -116,6 +117,7 @@
     struct ly_set tpdfs_nodes;      /**< set of typedef nodes */
     struct ly_set grps_nodes;       /**< set of grouping nodes */
     struct lysp_module *parsed_mod; /**< (sub)module being parsed */
+    struct lys_glob_unres *unres;   /**< global unres structure */
 };
 
 /**
@@ -126,6 +128,7 @@
     struct ly_set tpdfs_nodes;      /**< set of typedef nodes */
     struct ly_set grps_nodes;       /**< set of grouping nodes */
     struct lysp_module *parsed_mod; /**< (sub)module being parsed */
+    struct lys_glob_unres *unres;   /**< global unres structure */
     enum LY_VLOG_ELEM pos_type;     /**< */
     union {
         uint64_t line;              /**< line number */
@@ -147,6 +150,7 @@
     struct ly_set tpdfs_nodes;     /**< set of typedef nodes */
     struct ly_set grps_nodes;      /**< set of grouping nodes */
     struct lysp_module *parsed_mod;/**< (sub)module being parsed */
+    struct lys_glob_unres *unres;   /**< global unres structure */
     struct lyxml_ctx *xmlctx;      /**< context for xml parser */
 };
 
@@ -284,11 +288,12 @@
  * the implemented module in the context is returned despite it might not be of the latest revision, because in this case the module
  * of the latest revision can not be made implemented.
  * @param[in] features All the features to enable if implementing the module.
+ * @param[in] unres Global unres structure for all newly implemented modules.
  * @param[out] mod Parsed module structure.
  * @return LY_ERR value.
  */
 LY_ERR lysp_load_module(struct ly_ctx *ctx, const char *name, const char *revision, ly_bool implement,
-        const char **features, struct lys_module **mod);
+        const char **features, struct lys_glob_unres *unres, struct lys_module **mod);
 
 /**
  * @brief Parse included submodule into the simply parsed YANG module.
@@ -430,6 +435,16 @@
  */
 const char *lys_datatype2str(LY_DATA_TYPE basetype);
 
+/**
+ * @brief Implement a module (just like ::lys_set_implemented()), can be called recursively.
+ *
+ * @param[in] mod Module to implement.
+ * @param[in] features Array of features to enable.
+ * @param[in,out] unres Global unres to add to.
+ * @return LY_ERR value.
+ */
+LY_ERR lys_set_implemented_r(struct lys_module *mod, const char **features, struct lys_glob_unres *unres);
+
 typedef LY_ERR (*lys_custom_check)(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod,
         void *check_data);
 
@@ -445,11 +460,13 @@
  * @param[in] custom_check Callback to check the parsed schema before it is accepted.
  * @param[in] check_data Caller's data to pass to the custom_check callback.
  * @param[in] features Array of features to enable ended with NULL. NULL for all features disabled and '*' for all enabled.
+ * @param[in,out] unres Global unres structure for newly implemented modules.
  * @param[out] module Created module.
  * @return LY_ERR value.
  */
 LY_ERR lys_create_module(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, ly_bool implement,
-        lys_custom_check custom_check, void *check_data, const char **features, struct lys_module **module);
+        lys_custom_check custom_check, void *check_data, const char **features, struct lys_glob_unres *unres,
+        struct lys_module **module);
 
 /**
  * @brief Parse submodule.
@@ -494,12 +511,14 @@
  * @param[in] main_name Main module name in case of loading submodule.
  * @param[in] required Module is required so error (even if the input file not found) are important. If 0, there is some
  * backup and it is actually ok if the input data are not found. However, parser reports errors even in this case.
+ * @param[in,out] unres Global unres structure for newly implemented modules.
  * @param[out] result Parsed YANG schema tree of the requested module (struct lys_module*) or submodule (struct lysp_submodule*).
  * If it is a module, it is already in the context!
  * @return LY_ERR value, in case of LY_SUCCESS, the \arg result is always provided.
  */
 LY_ERR lys_module_localfile(struct ly_ctx *ctx, const char *name, const char *revision, const char **features,
-        ly_bool implement, struct lys_parser_ctx *main_ctx, const char *main_name, ly_bool required, void **result);
+        ly_bool implement, struct lys_parser_ctx *main_ctx, const char *main_name, ly_bool required,
+        struct lys_glob_unres *unres, void **result);
 
 /**
  * @brief Get the @ref ifftokens from the given position in the 2bits array
diff --git a/src/xpath.c b/src/xpath.c
index c8beb28..14738c7 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -1552,7 +1552,7 @@
 
     /* ignore errors, the value may not satisfy schema constraints */
     rc = type->plugin->store(src->ctx, type, str, strlen(str), LY_TYPE_STORE_DYNAMIC, src->format, src->prefix_data,
-            LYD_HINT_DATA, xp_node->node->schema, &val, &err);
+            LYD_HINT_DATA, xp_node->node->schema, &val, NULL, &err);
     ly_err_free(err);
     if (rc) {
         /* invalid value */
@@ -3333,7 +3333,7 @@
         type = ((struct lysc_node_leaf *)scnode)->type;
         if (type->basetype != LY_TYPE_IDENT) {
             rc = type->plugin->store(set->ctx, type, value, strlen(value), 0, set->format, set->prefix_data,
-                    LYD_HINT_DATA, scnode, &storage, &err);
+                    LYD_HINT_DATA, scnode, &storage, NULL, &err);
             if (rc == LY_EINCOMPLETE) {
                 rc = LY_SUCCESS;
             }
@@ -3701,7 +3701,7 @@
 
             /* it was already evaluated on schema, it must succeed */
             rc = ly_path_compile(set->ctx, sleaf->module, (struct lysc_node *)sleaf, lref->path,
-                    LY_PATH_LREF_TRUE, oper, LY_PATH_TARGET_MANY, LY_PREF_SCHEMA_RESOLVED, lref->prefixes, &p);
+                    LY_PATH_LREF_TRUE, oper, LY_PATH_TARGET_MANY, LY_PREF_SCHEMA_RESOLVED, lref->prefixes, NULL, &p);
             assert(!rc);
 
             /* get the target node */
@@ -3810,7 +3810,7 @@
 
             /* store args[1] as ident */
             rc = val->realtype->plugin->store(set->ctx, val->realtype, args[1]->val.str, strlen(args[1]->val.str),
-                    0, set->format, set->prefix_data, LYD_HINT_DATA, leaf->schema, &data, &err);
+                    0, set->format, set->prefix_data, LYD_HINT_DATA, leaf->schema, &data, NULL, &err);
         } else {
             meta = args[0]->val.meta[i].meta;
             val = &meta->value;
@@ -3821,7 +3821,7 @@
 
             /* store args[1] as ident */
             rc = val->realtype->plugin->store(set->ctx, val->realtype, args[1]->val.str, strlen(args[1]->val.str), 0,
-                    set->format, set->prefix_data, LYD_HINT_DATA, meta->parent->schema, &data, &err);
+                    set->format, set->prefix_data, LYD_HINT_DATA, meta->parent->schema, &data, NULL, &err);
         }
 
         if (err) {
diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c
index 8456473..dbf75fe 100644
--- a/tests/utests/data/test_tree_data.c
+++ b/tests/utests/data/test_tree_data.c
@@ -297,7 +297,7 @@
     assert_int_equal(LY_SUCCESS, ly_path_parse(ctx, NULL, path_str, strlen(path_str), LY_PATH_BEGIN_EITHER, LY_PATH_LREF_FALSE,
                                                LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp));
     assert_int_equal(LY_SUCCESS, ly_path_compile(ctx, NULL, NULL, exp, LY_PATH_LREF_FALSE, LY_PATH_OPER_INPUT,
-                                                 LY_PATH_TARGET_SINGLE, LY_PREF_JSON, NULL, &path));
+                                                 LY_PATH_TARGET_SINGLE, LY_PREF_JSON, NULL, NULL, &path));
     term = lyd_target(path, tree);
 
     assert_string_equal(term->schema->name, "d");
diff --git a/tests/utests/schema/test_parser_yang.c b/tests/utests/schema/test_parser_yang.c
index f98777a..78eb373 100644
--- a/tests/utests/schema/test_parser_yang.c
+++ b/tests/utests/schema/test_parser_yang.c
@@ -23,6 +23,7 @@
 #include "common.h"
 #include "in_internal.h"
 #include "parser_internal.h"
+#include "schema_compile.h"
 #include "tree_schema.h"
 #include "tree_schema_internal.h"
 
@@ -879,6 +880,7 @@
     struct lysp_submodule *submod = NULL;
     struct lys_module *m;
     struct ly_in in = {0};
+    struct lys_glob_unres unres = {0};
 
     mod = mod_renew(ctx);
 
@@ -1050,7 +1052,7 @@
     in.current = "module " SCHEMA_BEGINNING "} module q {namespace urn:q;prefixq;}";
     m = calloc(1, sizeof *m);
     m->ctx = ctx->parsed_mod->mod->ctx;
-    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m));
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m, &unres));
     logbuf_assert("Trailing garbage \"module q {names...\" after module, expected end-of-input. Line number 1.");
     yang_parser_ctx_free(ctx_p);
     lys_module_free(m, NULL);
@@ -1058,7 +1060,7 @@
     in.current = "prefix " SCHEMA_BEGINNING "}";
     m = calloc(1, sizeof *m);
     m->ctx = ctx->parsed_mod->mod->ctx;
-    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m));
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m, &unres));
     logbuf_assert("Invalid keyword \"prefix\", expected \"module\" or \"submodule\". Line number 1.");
     yang_parser_ctx_free(ctx_p);
     lys_module_free(m, NULL);
@@ -1066,7 +1068,7 @@
     in.current = "module " SCHEMA_BEGINNING "leaf enum {type enumeration {enum seven { position 7;}}}}";
     m = calloc(1, sizeof *m);
     m->ctx = ctx->parsed_mod->mod->ctx;
-    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m));
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m, &unres));
     logbuf_assert("Invalid keyword \"position\" as a child of \"enum\". Line number 1.");
     yang_parser_ctx_free(ctx_p);
     lys_module_free(m, NULL);
diff --git a/tests/utests/schema/test_parser_yin.c b/tests/utests/schema/test_parser_yin.c
index 287558c..728fe36 100644
--- a/tests/utests/schema/test_parser_yin.c
+++ b/tests/utests/schema/test_parser_yin.c
@@ -24,6 +24,7 @@
 #include "common.h"
 #include "in.h"
 #include "parser_internal.h"
+#include "schema_compile.h"
 #include "tree_schema.h"
 #include "tree_schema_internal.h"
 #include "xml.h"
@@ -4147,6 +4148,7 @@
     struct lys_module *mod;
     struct lys_yin_parser_ctx *yin_ctx = NULL;
     struct ly_in *in = NULL;
+    struct lys_glob_unres unres = {0};
 
     mod = calloc(1, sizeof *mod);
     mod->ctx = st->ctx;
@@ -4172,9 +4174,10 @@
            "</md:annotation>\n"
            "</module>\n";
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
-    assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS);
+    assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_SUCCESS);
     assert_null(mod->parsed->exts->child->next->child);
     assert_string_equal(mod->parsed->exts->child->next->arg, "test");
+    lys_compile_unres_glob_erase(st->ctx, &unres);
     lys_module_free(mod, NULL);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
@@ -4212,7 +4215,8 @@
                 "</list>\n"
             "</module>\n";
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
-    assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS);
+    assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_SUCCESS);
+    lys_compile_unres_glob_erase(st->ctx, &unres);
     lys_module_free(mod, NULL);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
@@ -4227,7 +4231,8 @@
                 "<prefix value=\"foo\"/>\n"
             "</module>\n";
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
-    assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS);
+    assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_SUCCESS);
+    lys_compile_unres_glob_erase(st->ctx, &unres);
     lys_module_free(mod, NULL);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
@@ -4240,7 +4245,7 @@
     data =  "<submodule name=\"example-foo\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
             "</submodule>\n";
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
-    assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_EINVAL);
+    assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_EINVAL);
     logbuf_assert("Input data contains submodule which cannot be parsed directly without its main module.");
     lys_module_free(mod, NULL);
     yin_parser_ctx_free(yin_ctx);
@@ -4255,7 +4260,7 @@
             "</module>"
             "<module>";
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
-    assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_EVALID);
+    assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_EVALID);
     logbuf_assert("Trailing garbage \"<module>\" after module, expected end-of-input. Line number 5.");
     lys_module_free(mod, NULL);
     yin_parser_ctx_free(yin_ctx);
diff --git a/tests/utests/schema/test_schema_common.c b/tests/utests/schema/test_schema_common.c
index dc50517..677a515 100644
--- a/tests/utests/schema/test_schema_common.c
+++ b/tests/utests/schema/test_schema_common.c
@@ -214,61 +214,61 @@
     assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
 
     str = "module a {namespace urn:a; prefix a; typedef binary {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"binary\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef bits {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"bits\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef boolean {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"boolean\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef decimal64 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"decimal64\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef empty {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"empty\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef enumeration {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"enumeration\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef int8 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"int8\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef int16 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"int16\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef int32 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"int32\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef int64 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"int64\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef instance-identifier {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"instance-identifier\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef identityref {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"identityref\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef leafref {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"leafref\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef string {type int8;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"string\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef union {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"union\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef uint8 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"uint8\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef uint16 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"uint16\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef uint32 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"uint32\" of typedef - name collision with a built-in type. Line number 1.");
     str = "module a {namespace urn:a; prefix a; typedef uint64 {type string;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"uint64\" of typedef - name collision with a built-in type. Line number 1.");
 
     str = "module mytypes {namespace urn:types; prefix t; typedef binary_ {type string;} typedef bits_ {type string;} typedef boolean_ {type string;} "
@@ -279,34 +279,34 @@
     assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_SUCCESS);
 
     str = "module a {namespace urn:a; prefix a; typedef test {type string;} typedef test {type int8;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"test\" of typedef - name collision with another top-level type. Line number 1.");
 
     str = "module a {namespace urn:a; prefix a; typedef x {type string;} container c {typedef x {type int8;}}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"x\" of typedef - scoped type collide with a top-level type. Line number 1.");
 
     str = "module a {namespace urn:a; prefix a; container c {container d {typedef y {type int8;}} typedef y {type string;}}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"y\" of typedef - name collision with another scoped type. Line number 1.");
 
     str = "module a {namespace urn:a; prefix a; container c {typedef y {type int8;} typedef y {type string;}}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"y\" of typedef - name collision with sibling type. Line number 1.");
 
     ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type string;}}");
     str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"x\" of typedef - name collision with another top-level type. Line number 1.");
 
     ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule b {belongs-to a {prefix a;} container c {typedef x {type string;}}}");
     str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"x\" of typedef - scoped type collide with a top-level type. Line number 1.");
 
     ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type int8;}}");
     str = "module a {namespace urn:a; prefix a; include b; container c {typedef x {type string;}}}";
-    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EVALID);
+    assert_int_equal(lys_parse_mem(ctx, str, LYS_IN_YANG, NULL), LY_EEXIST);
     logbuf_assert("Invalid name \"x\" of typedef - scoped type collide with a top-level type. Line number 1.");
 
     *state = NULL;
diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
index 94ec823..7c5666f 100644
--- a/tests/utests/schema/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -105,21 +105,28 @@
     struct lys_module *mod = NULL;
     struct lysp_feature *f;
     struct lysc_iffeature *iff;
+    struct lys_glob_unres unres = {0};
 
     str = "module test {namespace urn:test; prefix t;"
           "feature f1;feature f2 {if-feature f1;}}";
     assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
 
-    assert_int_equal(LY_EINVAL, lys_compile(NULL, 0));
+    assert_int_equal(LY_EINVAL, lys_compile(NULL, 0, NULL));
     logbuf_assert("Invalid argument mod (lys_compile()).");
     assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 0, NULL, NULL, NULL, &mod));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 0, NULL, NULL, NULL, &unres, &mod));
+    assert_int_equal(LY_SUCCESS, lys_compile_unres_glob(ctx, &unres));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     assert_int_equal(0, mod->implemented);
-    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0, &unres));
+    assert_int_equal(LY_SUCCESS, lys_compile_unres_glob(ctx, &unres));
+    lys_compile_unres_glob_erase(ctx, &unres);
     assert_null(mod->compiled);
     mod->implemented = 1;
-    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0, &unres));
+    assert_int_equal(LY_SUCCESS, lys_compile_unres_glob(ctx, &unres));
+    lys_compile_unres_glob_erase(ctx, &unres);
     assert_non_null(mod->compiled);
     assert_string_equal("test", mod->name);
     assert_string_equal("urn:test", mod->ns);
@@ -139,15 +146,17 @@
     /* submodules cannot be compiled directly */
     str = "submodule test {belongs-to xxx {prefix x;}}";
     assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
-    assert_int_equal(LY_EINVAL, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, NULL));
+    assert_int_equal(LY_EINVAL, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, NULL));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     logbuf_assert("Input data contains submodule which cannot be parsed directly without its main module.");
 
     /* data definition name collision in top level */
     str = "module aa {namespace urn:aa;prefix aa; leaf a {type string;} container a{presence x;}}";
     assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
-    assert_int_equal(LY_EEXIST, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod));
+    assert_int_equal(LY_EEXIST, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod));
     logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /aa:a");
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
 
     *state = NULL;
@@ -3360,7 +3369,7 @@
             "}"
         "}"
     , LYS_IN_YANG, NULL));
-    logbuf_assert("When condition of \"cont2\" includes a self-reference (referenced by when of \"l\"). /a:cont2");
+    logbuf_assert("When condition of \"val\" includes a self-reference (referenced by when of \"cont2\"). /a:cont/lst/val");
 
     assert_int_equal(LY_EVALID, lys_parse_mem(ctx,
         "module a {"
@@ -3388,7 +3397,7 @@
             "}"
         "}"
     , LYS_IN_YANG, NULL));
-    logbuf_assert("When condition of \"cont2\" includes a self-reference (referenced by when of \"val\"). /a:cont2");
+    logbuf_assert("When condition of \"val\" includes a self-reference (referenced by when of \"cont2\"). /a:cont/lst/val");
 
     assert_int_equal(LY_EVALID, lys_parse_mem(ctx,
         "module a {"
diff --git a/tests/utests/test_context.c b/tests/utests/test_context.c
index a868ebe..89fd762 100644
--- a/tests/utests/test_context.c
+++ b/tests/utests/test_context.c
@@ -275,6 +275,7 @@
     struct ly_in *in;
     const char *str;
     struct lys_module *mod1, *mod2;
+    struct lys_glob_unres unres = {0};
 
     /* invalid arguments */
     assert_int_equal(0, ly_ctx_get_module_set_id(NULL));
@@ -284,7 +285,8 @@
     assert_int_equal(ctx->module_set_id, ly_ctx_get_module_set_id(ctx));
 
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module x {namespace urn:x;prefix x;}", &in));
-    assert_int_equal(LY_EINVAL, lys_create_module(ctx, in, 4, 1, NULL, NULL, NULL, &mod1));
+    assert_int_equal(LY_EINVAL, lys_create_module(ctx, in, 4, 1, NULL, NULL, NULL, &unres, &mod1));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     logbuf_assert("Invalid schema input format.");
 
@@ -302,22 +304,28 @@
     /* name collision of module and submodule */
     ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-30;}");
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module y {namespace urn:y;prefix y;include y;}", &in));
-    assert_int_equal(LY_EVALID, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod1));
+    assert_int_equal(LY_EVALID, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod1));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     logbuf_assert("Name collision between module and submodule of name \"y\". Line number 1.");
 
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module a {namespace urn:a;prefix a;include y;revision 2018-10-30; }", &in));
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod1));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod1));
+    assert_int_equal(LY_SUCCESS, lys_compile_unres_glob(ctx, &unres));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module y {namespace urn:y;prefix y;}", &in));
-    assert_int_equal(LY_EVALID, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod1));
+    assert_int_equal(LY_EVALID, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod1));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     logbuf_assert("Name collision between module and submodule of name \"y\". Line number 1.");
 
     store = 1;
     ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule y {belongs-to b {prefix b;}}");
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module b {namespace urn:b;prefix b;include y;}", &in));
-    assert_int_equal(LY_EVALID, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod1));
+    assert_int_equal(LY_EVALID, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod1));
+    lys_compile_unres_glob_revert(ctx, &unres);
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     logbuf_assert("Name collision between submodules of name \"y\". Line number 1.");
     store = -1;
@@ -326,16 +334,19 @@
     ly_ctx_reset_latests(ctx);
     ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-31;}");
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module a {namespace urn:a;prefix a;include y; revision 2018-10-31;}", &in));
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 0, NULL, NULL, NULL, &mod2));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 0, NULL, NULL, NULL, &unres, &mod2));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     assert_string_equal("2018-10-31", mod2->parsed->includes[0].submodule->revs[0].date);
 
     /* reloading module in case only the compiled module resists in the context */
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module w {namespace urn:w;prefix w;revision 2018-10-24;}", &in));
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 0, NULL, NULL, NULL, &mod1));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 0, NULL, NULL, NULL, &unres, &mod1));
     ly_in_free(in, 0);
     mod1->implemented = 1;
-    assert_int_equal(LY_SUCCESS, lys_compile(mod1, 0));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod1, 0, &unres));
+    assert_int_equal(LY_SUCCESS, lys_compile_unres_glob(ctx, &unres));
+    lys_compile_unres_glob_erase(ctx, &unres);
     assert_non_null(mod1->compiled);
     assert_non_null(mod1->parsed);
 
@@ -354,7 +365,9 @@
 
     assert_int_equal(LY_SUCCESS, ly_in_new_memory("module z {namespace urn:z;prefix z;import w {prefix w;revision-date 2018-10-24;}}", &in));
     ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module w {namespace urn:w;prefix w;revision 2018-10-24;}");
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod2));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod2));
+    assert_int_equal(LY_SUCCESS, lys_compile_unres_glob(ctx, &unres));
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_free(in, 0);
     assert_non_null(mod2);
     assert_non_null(mod1->parsed);
@@ -425,6 +438,7 @@
     const char *str1 = "module a {namespace urn:a;prefix a;revision 2018-10-23;}";
     const char *str2 = "module a {namespace urn:a;prefix a;revision 2018-10-23;revision 2018-10-24;}";
     struct ly_in *in0, *in1, *in2;
+    struct lys_glob_unres unres = {0};
 
     unsigned int index = 0;
     const char *names[] = {"ietf-yang-metadata", "yang", "ietf-inet-types", "ietf-yang-types", "ietf-datastores", "ietf-yang-library", "a", "a", "a"};
@@ -459,16 +473,21 @@
     assert_non_null(ly_ctx_get_module_ns(ctx, "urn:ietf:params:xml:ns:yang:ietf-datastores", "2018-02-14"));
 
     /* select module by revision */
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in1, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in1, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod));
+    assert_int_equal(LY_SUCCESS, lys_compile_unres_glob(ctx, &unres));
+    lys_compile_unres_glob_erase(ctx, &unres);
     /* invalid attempts - implementing module of the same name and inserting the same module */
-    assert_int_equal(LY_EDENIED, lys_create_module(ctx, in2, LYS_IN_YANG, 1, NULL, NULL, NULL, NULL));
+    assert_int_equal(LY_EDENIED, lys_create_module(ctx, in2, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, NULL));
     logbuf_assert("Module \"a\" is already implemented in the context.");
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_reset(in1);
-    assert_int_equal(LY_EEXIST, lys_create_module(ctx, in1, LYS_IN_YANG, 0, NULL, NULL, NULL, NULL));
+    assert_int_equal(LY_EEXIST, lys_create_module(ctx, in1, LYS_IN_YANG, 0, NULL, NULL, NULL, &unres, NULL));
     logbuf_assert("Module \"a\" of revision \"2018-10-23\" is already present in the context.");
     /* insert the second module only as imported, not implemented */
+    lys_compile_unres_glob_erase(ctx, &unres);
     ly_in_reset(in2);
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in2, LYS_IN_YANG, 0, NULL, NULL, NULL, &mod2));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in2, LYS_IN_YANG, 0, NULL, NULL, NULL, &unres, &mod2));
+    lys_compile_unres_glob_erase(ctx, &unres);
     assert_non_null(mod2);
     assert_ptr_not_equal(mod, mod2);
     mod = ly_ctx_get_module_latest(ctx, "a");
@@ -476,15 +495,17 @@
     mod2 = ly_ctx_get_module_latest_ns(ctx, mod->ns);
     assert_ptr_equal(mod, mod2);
     /* work with module with no revision */
-    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in0, LYS_IN_YANG, 0, NULL, NULL, NULL, &mod));
+    assert_int_equal(LY_SUCCESS, lys_create_module(ctx, in0, LYS_IN_YANG, 0, NULL, NULL, NULL, &unres, &mod));
+    lys_compile_unres_glob_erase(ctx, &unres);
     assert_ptr_equal(mod, ly_ctx_get_module(ctx, "a", NULL));
     assert_ptr_not_equal(mod, ly_ctx_get_module_latest(ctx, "a"));
 
     str1 = "submodule b {belongs-to a {prefix a;}}";
     ly_in_free(in1, 0);
     assert_int_equal(LY_SUCCESS, ly_in_new_memory(str1, &in1));
-    assert_int_equal(LY_EINVAL, lys_create_module(ctx, in1, LYS_IN_YANG, 1, NULL, NULL, NULL, &mod));
+    assert_int_equal(LY_EINVAL, lys_create_module(ctx, in1, LYS_IN_YANG, 1, NULL, NULL, NULL, &unres, &mod));
     logbuf_assert("Input data contains submodule which cannot be parsed directly without its main module.");
+    lys_compile_unres_glob_erase(ctx, &unres);
 
     while ((mod = (struct lys_module *)ly_ctx_get_module_iter(ctx, &index))) {
         assert_string_equal(names[index - 1], mod->name);