patch 9.1.0548: it's not possible to get a unique id for some vars

Problem:  it's not possible to get a unique id for some vars
Solution: Add the id() Vim script function, which returns a unique
          identifier for object, dict, list, job, blob or channel
          variables (Ernie Rael)

fixes: #14374
closes: #15145

Signed-off-by: Ernie Rael <errael@raelity.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 635b7b2..9c3d7a9 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -309,6 +309,7 @@
 hlset({list})			Number	set highlight group attributes
 hostname()			String	name of the machine Vim is running on
 iconv({expr}, {from}, {to})	String	convert encoding of {expr}
+id({item})			String	get address of item as a string
 indent({lnum})			Number	indent of line {lnum}
 index({object}, {expr} [, {start} [, {ic}]])
 				Number	index in {object} where {expr} appears
@@ -5618,6 +5619,34 @@
 		Return type: |String|
 
 
+id({item})							    *id()*
+		The result is a unique String associated with the {item} and
+		not with the {item}'s contents. It is only valid while the
+		{item} exists and is referenced. It is valid only in the
+		instance of vim that produces the result. The whole idea is
+		that `id({item})` does not change if the contents of {item}
+		changes. This is useful as a `key` for creating an identity
+		dictionary, rather than one based on equals.
+
+		This operation does not reference {item} and there is no
+		function to convert the `id` to the {item}. It may be useful to
+		have a map of `id` to {item}. The following >
+		    var referenceMap: dict<any>
+		    var id = item->id()
+		    referenceMap[id] = item
+<		prevents {item} from being garbage collected and provides a
+		way to get the {item} from the `id`.
+
+		{item} may be a List, Dictionary, Object, Job, Channel or
+		Blob. If the item is not a permitted type, or it is a null
+		value, then an empty String is returned.
+
+		Can also be used as a |method|: >
+			GetItem()->id()
+<
+		Return type: |String|
+
+
 indent({lnum})							*indent()*
 		The result is a Number, which is indent of line {lnum} in the
 		current buffer.  The indent is counted in spaces, the value
diff --git a/runtime/doc/tags b/runtime/doc/tags
index be71710..adbc145 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -8302,6 +8302,7 @@
 iconize	starting.txt	/*iconize*
 iconv()	builtin.txt	/*iconv()*
 iconv-dynamic	mbyte.txt	/*iconv-dynamic*
+id()	builtin.txt	/*id()*
 ident-search	tips.txt	/*ident-search*
 idl-syntax	syntax.txt	/*idl-syntax*
 idl.vim	syntax.txt	/*idl.vim*
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 922e80a..765eab5 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -1408,6 +1408,8 @@
 
 	wordcount()		get byte/word/char count of buffer
 
+	id()			get unique string for item to use as a key
+
 	luaeval()		evaluate |Lua| expression
 	mzeval()		evaluate |MzScheme| expression
 	perleval()		evaluate Perl expression (|+perl|)
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 43de269..86ec020 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2024 Jul 08
+*version9.txt*  For Vim version 9.1.  Last change: 2024 Jul 09
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41593,6 +41593,8 @@
 |foreach()|		apply function to List items
 |getregion()|		get a region of text from a buffer
 |getregionpos()|	get a list of positions for a region
+|id()|			get unique identifier for a Dict, List, Object,
+			Channel or Blob variable
 |matchbufline()|	all the matches of a pattern in a buffer
 |matchstrlist()|	all the matches of a pattern in a List of strings
 |popup_setbuf()|	switch to a different buffer in a popup