diff --git a/manual/luatex-math.tex b/manual/luatex-math.tex
index b19f5823f6adc679862ea599517428e195e59fbb..3c29d9609752deb6e16a6d329e51fa4ef317b66b 100644
--- a/manual/luatex-math.tex
+++ b/manual/luatex-math.tex
@@ -613,6 +613,30 @@ shifts to the left. A \type {\mathnolimitsmode} larger that 15 is considered to
 be a factor for the subscript correction. This feature can be handy when
 experimenting.
 
+\section{Math italic mess}
+
+The \type {\mathitalicsmode} parameter can be set to~1 to force italic correction
+before noads that represent some more complex structure (read: everything
+that is not an ord, bin, rel, open, close, punct or inner).
+
+\starttexdefinition Whatever #1
+    \NC \type{\mathitalicsmode=#1}
+    \NC \mathitalicsmode#1\ruledhbox{$\left|T^1\right|$}
+    \NC \mathitalicsmode#1\ruledhbox{$\left|T\right|$}
+    \NC \mathitalicsmode#1\ruledhbox{$T+1$}
+    \NC \mathitalicsmode#1\ruledhbox{$T{1\over2}$}
+    \NC \mathitalicsmode#1\ruledhbox{$T\sqrt{1}$}
+    \NR \NR
+\stoptexdefinition
+
+\starttabulate[|c|c|c|c|c|c|]
+    \Whatever0
+    \Whatever1
+\stoptabulate
+
+This kind of parameters relate to the fact that italic correction in \OPENTYPE\
+math is bound to fuzzy rules. So, control is the solution.
+
 \section{Math spacing setting}
 
 Besides the parameters mentioned in the previous sections, there are also 64 new
diff --git a/manual/luatex.pdf b/manual/luatex.pdf
index 80b672892462b0f72976e35b39855ee159692ee2..fc22a9e5eaa51d678b303616830d1bf24c671d62 100644
Binary files a/manual/luatex.pdf and b/manual/luatex.pdf differ
diff --git a/source/texk/web2c/luatexdir/tex/commands.w b/source/texk/web2c/luatexdir/tex/commands.w
index bcc46b2c70eee42a13337a9a846df1c6c71a3f73..8a81184dc975d8e5222eaab11c604542d52c165f 100644
--- a/source/texk/web2c/luatexdir/tex/commands.w
+++ b/source/texk/web2c/luatexdir/tex/commands.w
@@ -756,6 +756,7 @@ void initialize_etex_commands(void)
     primitive_luatex("mathdisplayskipmode", assign_int_cmd, int_base + math_display_skip_mode_code, int_base);
     primitive_luatex("mathscriptsmode", assign_int_cmd, int_base + math_scripts_mode_code, int_base);
     primitive_luatex("mathnolimitsmode", assign_int_cmd, int_base + math_nolimits_mode_code, int_base);
+    primitive_luatex("mathitalicsmode", assign_int_cmd, int_base + math_italics_mode_code, int_base);
     primitive_luatex("mathrulesmode", assign_int_cmd, int_base + math_rules_mode_code, int_base);
     primitive_luatex("mathrulesfam", assign_int_cmd, int_base + math_rules_fam_code, int_base);
     primitive_luatex("synctex", assign_int_cmd, int_base + synctex_code, int_base);
diff --git a/source/texk/web2c/luatexdir/tex/dumpdata.w b/source/texk/web2c/luatexdir/tex/dumpdata.w
index 43314b88ede19d41dbfb92b0a69586bd65047919..c7c2accaf157dc2b4d678bcfcfa4e04427e66593 100644
--- a/source/texk/web2c/luatexdir/tex/dumpdata.w
+++ b/source/texk/web2c/luatexdir/tex/dumpdata.w
@@ -23,7 +23,7 @@
 
 /* we start with 907: the sum of the values of the bytes of "don knuth" */
 
-#define FORMAT_ID (907+25)
+#define FORMAT_ID (907+26)
 #if ((FORMAT_ID>=0) && (FORMAT_ID<=256))
 #error Wrong value for FORMAT_ID.
 #endif
diff --git a/source/texk/web2c/luatexdir/tex/equivalents.h b/source/texk/web2c/luatexdir/tex/equivalents.h
index 80f8108393fce15513ef198d716c425d49603995..65102f0866f50978924f75db43b9cad77e4ea4ef 100644
--- a/source/texk/web2c/luatexdir/tex/equivalents.h
+++ b/source/texk/web2c/luatexdir/tex/equivalents.h
@@ -281,12 +281,13 @@ the |number_regs| \.{\\dimen} registers.
 #  define math_nolimits_mode_code 90
 #  define math_rules_mode_code 91
 #  define math_rules_fam_code 92
-#  define synctex_code 93                                               /* is synctex file generation enabled ?  */
-#  define shape_mode_code 94
-#  define first_valid_language_code 95
-#  define hyphenation_bounds_code 96
-#  define math_skip_mode_code 97
-#  define math_pre_display_gap_factor_code 98
+#  define math_italics_mode_code 93
+#  define synctex_code 94                                               /* is synctex file generation enabled ?  */
+#  define shape_mode_code 95
+#  define first_valid_language_code 96
+#  define hyphenation_bounds_code 97
+#  define math_skip_mode_code 98
+#  define math_pre_display_gap_factor_code 99
 
 #  define math_option_code (math_skip_mode_code+1)
 
@@ -648,8 +649,9 @@ extern halfword last_cs_name;
 #define disable_lig_par                    int_par(disable_lig_code)
 #define disable_kern_par                   int_par(disable_kern_code)
 #define disable_space_par                  int_par(disable_space_code)
-#define scripts_mode_par                   int_par(math_scripts_mode_code)
-#define nolimits_mode_par                  int_par(math_nolimits_mode_code)
+#define math_scripts_mode_par              int_par(math_scripts_mode_code)
+#define math_nolimits_mode_par             int_par(math_nolimits_mode_code)
+#define math_italics_mode_par              int_par(math_italics_mode_code)
 #define math_rules_mode_par                int_par(math_rules_mode_code)
 #define math_rules_fam_par                 int_par(math_rules_fam_code)
 
diff --git a/source/texk/web2c/luatexdir/tex/mlist.w b/source/texk/web2c/luatexdir/tex/mlist.w
index 32fd32d4c0eae605ea5fa47629073b45721fc4a9..170dd51d30ad86141411aa0e08c97dea5a4e260b 100644
--- a/source/texk/web2c/luatexdir/tex/mlist.w
+++ b/source/texk/web2c/luatexdir/tex/mlist.w
@@ -2645,11 +2645,13 @@ static scaled make_op(pointer q, int cur_style)
                 small_fam(y) = math_fam(nucleus(q));
                 small_char(y) = math_character(nucleus(q));
                 x = do_delimiter(q, y, text_size, ok_size, false, cur_style, true, NULL, &delta);
-                if (do_new_math(cur_f)) {
-                    /* we never added italic correction */
-                } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) {
-                    /* remove italic correction */
-                    width(x) -= delta;
+                if (delta != 0) {
+                    if (do_new_math(cur_f)) {
+                        /* we never added italic correction */
+                    } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) {
+                        /* remove italic correction */
+                        width(x) -= delta;
+                    }
                 }
             } else {
                 ok_size = height_plus_depth(cur_f, cur_c) + 1;
@@ -2667,7 +2669,7 @@ static scaled make_op(pointer q, int cur_style)
                         /* we never added italic correction */
                     } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) {
                         /* remove italic correction */
-                        width(x) = width(x) - delta;
+                        width(x) -= delta;
                     }
                 }
                 axis_shift = true;
@@ -2681,7 +2683,7 @@ static scaled make_op(pointer q, int cur_style)
                     /* we never added italic correction */
                 } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) {
                     /* remove italic correction */
-                    width(x) = width(x) - delta;
+                    width(x) -= delta;
                 }
             }
             axis_shift = true;
@@ -2710,7 +2712,7 @@ static scaled make_op(pointer q, int cur_style)
                 /*
                     make_scripts(q, p, 0, cur_style, delta, -delta);
                 */
-                int mode = nolimits_mode_par; /* wins */
+                int mode = math_nolimits_mode_par; /* wins */
                 /*
                     for easy configuration ... fonts are somewhat inconsistent and the
                     values for italic correction run from 30 to 60% of the width
@@ -3296,7 +3298,7 @@ static void make_scripts(pointer q, pointer p, scaled it, int cur_style, scaled
         */
         x = clean_box(subscr(q), sub_style(cur_style), cur_style);
         width(x) = width(x) + space_after_script(cur_style);
-        switch (scripts_mode_par) {
+        switch (math_scripts_mode_par) {
             case 1:
                 shift_down = sub_shift_down(cur_style) ;
                 break;
@@ -3346,7 +3348,7 @@ static void make_scripts(pointer q, pointer p, scaled it, int cur_style, scaled
         */
         x = clean_box(supscr(q), sup_style(cur_style), cur_style);
         width(x) = width(x) + space_after_script(cur_style);
-        switch (scripts_mode_par) {
+        switch (math_scripts_mode_par) {
             case 1:
                 shift_up = sup_shift_up(cur_style);
                 break;
@@ -3401,7 +3403,7 @@ static void make_scripts(pointer q, pointer p, scaled it, int cur_style, scaled
             */
             y = clean_box(subscr(q), sub_style(cur_style), cur_style);
             width(y) = width(y) + space_after_script(cur_style);
-            switch (scripts_mode_par) {
+            switch (math_scripts_mode_par) {
                 case 1:
                     shift_down = sub_shift_down(cur_style) ;
                     break;
@@ -3866,6 +3868,7 @@ void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style)
     int t_subtype;                        /* the effective |subtype| of noad |q| during the second pass */
     pointer p = null;
     pointer z = null;
+    halfword nxt ;
     int pen;                              /* a penalty to be inserted */
     scaled max_hl = 0;                    /* maximum height of the list translated so far */
     scaled max_d = 0;                     /* maximum depth of the list translated so far */
@@ -3886,6 +3889,7 @@ void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style)
         */
       RESWITCH:
         delta = 0;
+        nxt = vlink(q);
         switch (type(q)) {
         case simple_noad:
             switch (subtype(q)) {
@@ -4074,8 +4078,42 @@ void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style)
 
         */
         p = check_nucleus_complexity(q, &delta, cur_style);
-
         if ((subscr(q) == null) && (supscr(q) == null)) {
+            /*
+                Adding italic correction here is kind of fuzzy because some
+                characters already have that built in. However, we also add
+                it in the scripts so if it's optional here it also should
+                be there.
+            */
+            if (nxt && (math_italics_mode_par > 0) && (delta != 0)) {
+                if (type(nxt) == simple_noad) {
+                    switch (subtype(nxt)) {
+                        case ord_noad_type:
+                        case bin_noad_type:
+                        case rel_noad_type:
+                        case open_noad_type:
+                        case close_noad_type:
+                        case punct_noad_type:
+                        case inner_noad_type:
+                            delta = 0;
+                            break;
+                        case op_noad_type_normal:
+                        case op_noad_type_limits:
+                        case op_noad_type_no_limits:
+                        case under_noad_type:
+                        case over_noad_type:
+                        case vcenter_noad_type:
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                if (delta != 0) {
+                    pointer d = new_kern(delta);
+                    reset_attributes(d, node_attr(q));
+                    couple_nodes(p,d);
+                }
+            }
             assign_new_hlist(q, p);
         } else {
             /* top, bottom */