diff --git a/parse.y b/parse.y
index 915db67..0a93ead 100644
--- a/parse.y
+++ b/parse.y
@@ -10311,6 +10311,17 @@ rb_intern_str(VALUE str)
return intern_str(rb_str_dup(str));
}
+ID
+rb_interned_str(VALUE str)
+{
+ st_data_t id;
+
+ if (st_lookup(global_symbols.sym_id, str, &id))
+ return (ID)id;
+
+ return (ID)0;
+}
+
VALUE
rb_id2str(ID id)
{
diff --git a/string.c b/string.c
index 04984f0..12f7487 100644
--- a/string.c
+++ b/string.c
@@ -7196,6 +7196,61 @@ rb_str_intern(VALUE s)
/*
* call-seq:
+ * str.interned -> symbol
+ *
+ * Returns the Symbol corresponding to str, returning
+ * nil if it did not previously exist. See Symbol#id2name.
+ *
+ * x = :banana
+ * "banana".interned #=> :banana
+ * "mango".interned #=> nil
+ *
+ */
+
+VALUE
+rb_str_interned(VALUE s)
+{
+ VALUE str = RB_GC_GUARD(s);
+ ID id;
+
+ id = rb_interned_str(str);
+ if (id == ID(0))
+ return Qnil;
+
+ return ID2SYM(id);
+}
+
+
+/*
+ * call-seq:
+ * str.to_existing_sym -> symbol
+ *
+ * Returns the Symbol corresponding to str, raising an
+ * ArgumentError if it did not previously exist.
+ * See Symbol#id2name.
+ *
+ * x = :banana
+ * "banana".to_existing_sym #=> :banana
+ * "mango".to_existing_sym #=> ArgumentError
+ *
+ */
+
+VALUE
+rb_str_to_existing_sym(VALUE s)
+{
+ VALUE str = RB_GC_GUARD(s);
+ ID id;
+
+ id = rb_interned_str(str);
+ if (id == ID(0))
+ rb_raise(rb_eArgError, "undefined symbol :'%s'", StringValuePtr(str));
+
+ return ID2SYM(id);
+}
+
+
+/*
+ * call-seq:
* str.ord -> integer
*
* Return the Integer ordinal of a one-character string.
@@ -8238,6 +8293,8 @@ Init_String(void)
rb_define_method(rb_cString, "crypt", rb_str_crypt, 1);
rb_define_method(rb_cString, "intern", rb_str_intern, 0);
rb_define_method(rb_cString, "to_sym", rb_str_intern, 0);
+ rb_define_method(rb_cString, "interned", rb_str_interned, 0);
+ rb_define_method(rb_cString, "to_existing_sym", rb_str_interned_err, 0);
rb_define_method(rb_cString, "ord", rb_str_ord, 0);
rb_define_method(rb_cString, "include?", rb_str_include, 1);