patch 8.2.0920: writing viminfo fails with a circular reference

Problem:    Writing viminfo fails with a circular reference.
Solution:   Use copyID to detect the cycle. (closes #6217)
diff --git a/src/testdir/test_viminfo.vim b/src/testdir/test_viminfo.vim
index b4708f5..8650598 100644
--- a/src/testdir/test_viminfo.vim
+++ b/src/testdir/test_viminfo.vim
@@ -91,6 +91,28 @@
   set viminfo-=!
 endfunc
 
+func Test_global_vars_with_circular_reference()
+  let g:MY_GLOBAL_LIST = []
+  call add(g:MY_GLOBAL_LIST, g:MY_GLOBAL_LIST)
+  let g:MY_GLOBAL_DICT = {}
+  let g:MY_GLOBAL_DICT['self'] = g:MY_GLOBAL_DICT
+
+  set viminfo='100,<50,s10,h,!,nviminfo
+  wv! Xviminfo
+  call assert_equal(v:errmsg, '')
+
+  unlet g:MY_GLOBAL_LIST
+  unlet g:MY_GLOBAL_DICT
+
+  rv! Xviminfo
+  call assert_equal(v:errmsg, '')
+  call assert_true(!exists('g:MY_GLOBAL_LIST'))
+  call assert_true(!exists('g:MY_GLOBAL_DICT'))
+
+  call delete('Xviminfo')
+  set viminfo-=!
+endfunc
+
 func Test_cmdline_history()
   call histdel(':')
   call test_settime(11)
diff --git a/src/version.c b/src/version.c
index 3620745..c400df4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    920,
+/**/
     919,
 /**/
     918,
diff --git a/src/viminfo.c b/src/viminfo.c
index b014d7f..4f26348 100644
--- a/src/viminfo.c
+++ b/src/viminfo.c
@@ -1337,8 +1337,34 @@
 		    case VAR_STRING:  s = "STR"; break;
 		    case VAR_NUMBER:  s = "NUM"; break;
 		    case VAR_FLOAT:   s = "FLO"; break;
-		    case VAR_DICT:    s = "DIC"; break;
-		    case VAR_LIST:    s = "LIS"; break;
+		    case VAR_DICT:
+			  {
+			      dict_T	*di = this_var->di_tv.vval.v_dict;
+			      int	copyID = get_copyID();
+
+			      s = "DIC";
+			      if (di != NULL && !set_ref_in_ht(
+						 &di->dv_hashtab, copyID, NULL)
+				      && di->dv_copyID == copyID)
+				  // has a circular reference, can't turn the
+				  // value into a string
+				  continue;
+			      break;
+			  }
+		    case VAR_LIST:
+			  {
+			      list_T	*l = this_var->di_tv.vval.v_list;
+			      int	copyID = get_copyID();
+
+			      s = "LIS";
+			      if (l != NULL && !set_ref_in_list_items(
+							       l, copyID, NULL)
+				      && l->lv_copyID == copyID)
+				  // has a circular reference, can't turn the
+				  // value into a string
+				  continue;
+			      break;
+			  }
 		    case VAR_BLOB:    s = "BLO"; break;
 		    case VAR_BOOL:    s = "XPL"; break;  // backwards compat.
 		    case VAR_SPECIAL: s = "XPL"; break;