Index: lauxlib.h
===================================================================
--- lauxlib.h	(revision 19392)
+++ lauxlib.h	(working copy)
@@ -65,6 +65,8 @@
 LUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);
 LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
 
+LUALIB_API void (luaL_checkrawset) (lua_State *L, int tbl);
+
 LUALIB_API void (luaL_where) (lua_State *L, int lvl);
 LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
 
Index: ltm.cxx
===================================================================
--- ltm.cxx	(revision 19392)
+++ ltm.cxx	(working copy)
@@ -29,8 +29,9 @@
 
 void luaT_init (lua_State *L) {
   static const char *const luaT_eventname[] = {  /* ORDER TM */
-    "__index", "__newindex",
+    "__index", "__newindex", "__usedindex",
     "__gc", "__mode", "__eq",
+    "__rawset",
     "__add", "__sub", "__mul", "__div", "__mod",
     "__pow", "__unm", "__len", "__lt", "__le",
     "__concat", "__call"
Index: lvm.cxx
===================================================================
--- lvm.cxx	(revision 19392)
+++ lvm.cxx	(working copy)
@@ -138,16 +138,19 @@
     if (ttistable(t)) {  /* `t' is a table? */
       Table *h = hvalue(t);
       TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
-      if (!ttisnil(oldval) ||  /* result is no nil? */
-          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
+      /* oldval is nil=> look for newindex, oldval is not nil => look for usedindex */
+      tm = ttisnil(oldval) ? fasttm(L, h->metatable, TM_NEWINDEX)
+                           : fasttm(L, h->metatable, TM_USEDINDEX);
+      if (tm == NULL) { /* no tag method, set the value */
         setobj2t(L, oldval, val);
         luaC_barriert(L, h, val);
         return;
       }
       /* else will try the tag method */
     }
-    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
+    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) {
       luaG_typeerror(L, t, "index");
+    }
     if (ttisfunction(tm)) {
       callTM(L, tm, t, key, val);
       return;
Index: lbaselib.cxx
===================================================================
--- lbaselib.cxx	(revision 19392)
+++ lbaselib.cxx	(working copy)
@@ -176,6 +176,7 @@
 
 static int luaB_rawset (lua_State *L) {
   luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawset(L, 1);
   luaL_checkany(L, 2);
   luaL_checkany(L, 3);
   lua_settop(L, 3);
Index: ltm.h
===================================================================
--- ltm.h	(revision 19392)
+++ ltm.h	(working copy)
@@ -18,9 +18,11 @@
 typedef enum {
   TM_INDEX,
   TM_NEWINDEX,
+  TM_USEDINDEX,
   TM_GC,
   TM_MODE,
   TM_EQ,  /* last tag method with `fast' access */
+  TM_RAWSET,
   TM_ADD,
   TM_SUB,
   TM_MUL,
Index: lauxlib.cxx
===================================================================
--- lauxlib.cxx	(revision 19392)
+++ lauxlib.cxx	(working copy)
@@ -137,6 +137,26 @@
 }
 
 
+LUALIB_API void luaL_checkrawset (lua_State *L, int tbl) {
+  if (luaL_getmetafield(L, tbl, "__rawset")) {
+    const int type = lua_type(L, -1);
+    switch (type) {
+      case LUA_TSTRING: {
+        luaL_error(L, "__rawset: %s", lua_tostring(L, -1));
+        break;
+      }
+      case LUA_TBOOLEAN: {
+        if (!lua_toboolean(L, -1)) {
+          luaL_error(L, "blocked by (__rawset == false)");
+        }
+        break;
+      }
+    }
+    lua_pop(L, 1);
+  }
+}
+
+
 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
   if (!lua_checkstack(L, space))
     luaL_error(L, "stack overflow (%s)", mes);
Index: ltablib.cxx
===================================================================
--- ltablib.cxx	(revision 19392)
+++ ltablib.cxx	(working copy)
@@ -77,6 +77,7 @@
 
 static int setn (lua_State *L) {
   luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawset(L, 1);
 #ifndef luaL_setn
   luaL_setn(L, 1, luaL_checkint(L, 2));
 #else
@@ -90,6 +91,7 @@
 static int tinsert (lua_State *L) {
   int e = aux_getn(L, 1) + 1;  /* first empty element */
   int pos;  /* where to insert new element */
+  luaL_checkrawset(L, 1);
   switch (lua_gettop(L)) {
     case 2: {  /* called with only 2 arguments */
       pos = e;  /* insert new element at the end */
@@ -118,6 +120,7 @@
 static int tremove (lua_State *L) {
   int e = aux_getn(L, 1);
   int pos = luaL_optint(L, 2, e);
+  luaL_checkrawset(L, 1);
   if (!(1 <= pos && pos <= e))  /* position is outside bounds? */
    return 0;  /* nothing to remove */
   luaL_setn(L, 1, e - 1);  /* t.n = n-1 */
@@ -255,6 +258,7 @@
 
 static int sort (lua_State *L) {
   int n = aux_getn(L, 1);
+  luaL_checkrawset(L, 1);
   luaL_checkstack(L, 40, "");  /* assume array is smaller than 2^40 */
   if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */
     luaL_checktype(L, 2, LUA_TFUNCTION);
