Repository: aptos-labs/aptos-core (language: python)

Issue:
[Feature Request] Support type annotations for lambda parameters
Currently it is not possible to provide type annotations for lambda parameters. Instead of `|x: T| e` one has to write `|x| { let x:T = x; e }`. Type annotations are required to help the inference algorithm in some occasions. 


Discussion / hints:
This issue is stale because it has been open 45 days with no activity. Remove the `stale` label or comment - otherwise this will be closed in 15 days.
This issue is stale because it has been open 45 days with no activity. Remove the `stale` label or comment - otherwise this will be closed in 15 days.

Fix patch:
diff --git a/third_party/move/move-compiler/src/expansion/ast.rs b/third_party/move/move-compiler/src/expansion/ast.rs
index 257306fbd608b..50cf0b63da498 100644
--- a/third_party/move/move-compiler/src/expansion/ast.rs
+++ b/third_party/move/move-compiler/src/expansion/ast.rs
@@ -426,6 +426,13 @@ pub type LValue = Spanned<LValue_>;
 pub type LValueList_ = Vec<LValue>;
 pub type LValueList = Spanned<LValueList_>;
 
+/// These represent LValues with user-specified explicit types.
+#[derive(Debug, Clone, PartialEq)]
+pub struct TypedLValue_(pub LValue, pub Option<Type>);
+pub type TypedLValue = Spanned<TypedLValue_>;
+pub type TypedLValueList_ = Vec<TypedLValue>;
+pub type TypedLValueList = Spanned<TypedLValueList_>;
+
 pub fn wild_card(loc: Loc) -> LValue {
     let wildcard = sp(loc, Symbol::from("_"));
     let lvalue_ = LValue_::Var(sp(loc, ModuleAccess_::Name(wildcard)), None);
@@ -500,7 +507,7 @@ pub enum Exp_ {
     While(Box<Exp>, Box<Exp>),
     Loop(Box<Exp>),
     Block(Sequence),
-    Lambda(LValueList, Box<Exp>),
+    Lambda(TypedLValueList, Box<Exp>),
     Quant(
         QuantKind,
         LValueWithRangeList,
@@ -1800,6 +1807,23 @@ impl AstDebug for ExpDotted_ {
     }
 }
 
+impl AstDebug for Vec<TypedLValue> {
+    fn ast_debug(&self, w: &mut AstWriter) {
+        w.comma(self, |w, b| b.ast_debug(w));
+    }
+}
+
+impl AstDebug for TypedLValue_ {
+    fn ast_debug(&self, w: &mut AstWriter) {
+        let TypedLValue_(lv, opt_ty) = self;
+        lv.ast_debug(w);
+        if let Some(ty) = opt_ty {
+            w.write(":");
+            ty.ast_debug(w);
+        }
+    }
+}
+
 impl AstDebug for Vec<LValue> {
     fn ast_debug(&self, w: &mut AstWriter) {
         let parens = self.len() != 1;
diff --git a/third_party/move/move-compiler/src/expansion/dependency_ordering.rs b/third_party/move/move-compiler/src/expansion/dependency_ordering.rs
index 92cb3ed239168..9912bd62634ff 100644
--- a/third_party/move/move-compiler/src/expansion/dependency_ordering.rs
+++ b/third_party/move/move-compiler/src/expansion/dependency_ordering.rs
@@ -513,7 +513,9 @@ fn exp(context: &mut Context, sp!(_loc, e_): &E::Exp) {
         },
 
         E::Lambda(ll, e) => {
-            lvalues(context, &ll.value);
+            use crate::expansion::ast::TypedLValue_;
+            let mapped = ll.value.iter().map(|sp!(_, TypedLValue_(lv, _opt_ty))| lv);
+            lvalues(context, mapped);
             exp(context, e)
         },
         E::Quant(_, binds, es_vec, eopt, e) => {
diff --git a/third_party/move/move-compiler/src/expansion/translate.rs b/third_party/move/move-compiler/src/expansion/translate.rs
index c7ea02c5e7f6a..4fec7ef662b1f 100644
--- a/third_party/move/move-compiler/src/expansion/translate.rs
+++ b/third_party/move/move-compiler/src/expansion/translate.rs
@@ -2615,10 +2615,10 @@ fn exp_(context: &mut Context, sp!(loc, pe_): P::Exp) -> E::Exp {
         PE::Loop(ploop) => EE::Loop(exp(context, *ploop)),
         PE::Block(seq) => EE::Block(sequence(context, loc, seq)),
         PE::Lambda(pbs, pe) => {
-            let bs_opt = bind_list(context, pbs);
+            let tbs_opt = typed_bind_list(context, pbs);
             let e = exp_(context, *pe);
-            match bs_opt {
-                Some(bs) => EE::Lambda(bs, Box::new(e)),
+            match tbs_opt {
+                Some(tbs) => EE::Lambda(tbs, Box::new(e)),
                 None => {
                     assert!(context.env.has_errors());
                     EE::UnresolvedError
@@ -2886,6 +2886,24 @@ fn fields<T>(
 // LValues
 //**************************************************************************************************
 
+fn typed_bind_list(
+    context: &mut Context,
+    sp!(loc, pbs_): P::TypedBindList,
+) -> Option<E::TypedLValueList> {
+    let bs_: Option<Vec<E::TypedLValue>> = pbs_
+        .into_iter()
+        .map(|tpb| typed_bind(context, tpb))
+        .collect();
+    Some(sp(loc, bs_?))
+}
+
+fn typed_bind(context: &mut Context, sp!(loc, tpb_): P::TypedBind) -> Option<E::TypedLValue> {
+    let P::TypedBind_(pb, opt_type) = tpb_;
+    let b = bind(context, pb)?;
+    let ot = opt_type.map(|ty| type_(context, ty));
+    Some(sp(loc, E::TypedLValue_(b, ot)))
+}
+
 fn bind_list(context: &mut Context, sp!(loc, pbs_): P::BindList) -> Option<E::LValueList> {
     let bs_: Option<Vec<E::LValue>> = pbs_.into_iter().map(|pb| bind(context, pb)).collect();
     Some(sp(loc, bs_?))
@@ -3234,7 +3252,7 @@ fn unbound_names_exp(unbound: &mut UnboundNames, sp!(_, e_): &E::Exp) {
         EE::Lambda(ls, er) => {
             unbound_names_exp(unbound, er);
             // remove anything in `ls`
-            unbound_names_binds(unbound, ls);
+            unbound_names_typed_binds(unbound, ls);
         },
         EE::Quant(_, rs, trs, cr_opt, er) => {
             unbound_names_exp(unbound, er);
@@ -3311,6 +3329,12 @@ fn unbound_names_binds(unbound: &mut UnboundNames, sp!(_, ls_): &E::LValueList)
         .for_each(|l| unbound_names_bind(unbound, l))
 }
 
+fn unbound_names_typed_binds(unbound: &mut UnboundNames, sp!(_, ls_): &E::TypedLValueList) {
+    ls_.iter()
+        .rev()
+        .for_each(|sp!(_loc, E::TypedLValue_(l, _opt_ty))| unbound_names_bind(unbound, l))
+}
+
 fn unbound_names_binds_with_range(
     unbound: &mut UnboundNames,
     sp!(_, rs_): &E::LValueWithRangeList,
diff --git a/third_party/move/move-compiler/src/naming/translate.rs b/third_party/move/move-compiler/src/naming/translate.rs
index 9080f025707f5..640e235b3605d 100644
--- a/third_party/move/move-compiler/src/naming/translate.rs
+++ b/third_party/move/move-compiler/src/naming/translate.rs
@@ -942,7 +942,7 @@ fn exp_(context: &mut Context, e: E::Exp) -> N::Exp {
         EE::Loop(el) => NE::Loop(exp(context, *el)),
         EE::Block(seq) => NE::Block(sequence(context, seq)),
         EE::Lambda(args, body) => {
-            let bind_opt = bind_list(context, args);
+            let bind_opt = bind_typed_list(context, args);
             match bind_opt {
                 None => {
                     assert!(context.env.has_errors());
@@ -1201,6 +1201,10 @@ fn bind_list(context: &mut Context, ls: E::LValueList) -> Option<N::LValueList>
     lvalue_list(context, LValueCase::Bind, ls)
 }
 
+fn bind_typed_list(context: &mut Context, ls: E::TypedLValueList) -> Option<N::LValueList> {
+    typed_lvalue_list(context, ls)
+}
+
 fn assign_list(context: &mut Context, ls: E::LValueList) -> Option<N::LValueList> {
     lvalue_list(context, LValueCase::Assign, ls)
 }
@@ -1218,6 +1222,30 @@ fn lvalue_list(
     ))
 }
 
+fn typed_lvalue_list(
+    context: &mut Context,
+    sp!(loc, b_): E::TypedLValueList,
+) -> Option<N::LValueList> {
+    let case = LValueCase::Bind;
+    Some(sp(
+        loc,
+        b_.into_iter()
+            .map(|sp!(loc, E::TypedLValue_(inner, opt_ty))| {
+                if opt_ty.is_some() {
+                    context.env.add_diag(diag!(
+                        Syntax::UnsupportedLanguageItem,
+                        (
+                            loc,
+                            "Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond"
+                        )
+                    ))
+                }
+                lvalue(context, case, inner)
+            })
+            .collect::<Option<_>>()?,
+    ))
+}
+
 fn resolve_builtin_function(
     context: &mut Context,
     loc: Loc,
diff --git a/third_party/move/move-compiler/src/parser/ast.rs b/third_party/move/move-compiler/src/parser/ast.rs
index 1bc388c914eb5..bd22eca723c27 100644
--- a/third_party/move/move-compiler/src/parser/ast.rs
+++ b/third_party/move/move-compiler/src/parser/ast.rs
@@ -523,6 +523,13 @@ pub type Bind = Spanned<Bind_>;
 // b1, ..., bn
 pub type BindList = Spanned<Vec<Bind>>;
 
+#[derive(Debug, Clone, PartialEq)]
+pub struct TypedBind_(pub Bind, pub Option<Type>);
+pub type TypedBind = Spanned<TypedBind_>;
+
+// b1 [":" <Type>], ..., bn [":" <Type>]
+pub type TypedBindList = Spanned<Vec<TypedBind>>;
+
 #[derive(Debug, Clone, PartialEq)]
 pub enum BindFieldOrDotDot_ {
     // f : b
@@ -680,8 +687,8 @@ pub enum Exp_ {
 
     // { seq }
     Block(Sequence),
-    // |x1, ..., xn| e
-    Lambda(BindList, Box<Exp>), // spec only
+    // | x1 [: t1], ..., xn [: tn] | e
+    Lambda(TypedBindList, Box<Exp>),
     // forall/exists x1 : e1, ..., xn [{ t1, .., tk } *] [where cond]: en.
     Quant(
         QuantKind,
@@ -1780,6 +1787,7 @@ impl AstDebug for SequenceItem_ {
                 w.write("let ");
                 bs.ast_debug(w);
                 if let Some(ty) = ty_opt {
+                    w.write(":");
                     ty.ast_debug(w)
                 }
             },
@@ -1787,6 +1795,7 @@ impl AstDebug for SequenceItem_ {
                 w.write("let ");
                 bs.ast_debug(w);
                 if let Some(ty) = ty_opt {
+                    w.write(":");
                     ty.ast_debug(w)
                 }
                 w.write(" = ");
@@ -1884,9 +1893,9 @@ impl AstDebug for Exp_ {
                 e.ast_debug(w);
             },
             E::Block(seq) => w.block(|w| seq.ast_debug(w)),
-            E::Lambda(sp!(_, bs), e) => {
+            E::Lambda(sp!(_, tbs), e) => {
                 w.write("|");
-                bs.ast_debug(w);
+                tbs.ast_debug(w);
                 w.write("|");
                 e.ast_debug(w);
             },
@@ -2127,3 +2136,20 @@ impl AstDebug for Bind_ {
         }
     }
 }
+
+impl AstDebug for Vec<TypedBind> {
+    fn ast_debug(&self, w: &mut AstWriter) {
+        w.comma(self, |w, b| b.ast_debug(w));
+    }
+}
+
+impl AstDebug for TypedBind_ {
+    fn ast_debug(&self, w: &mut AstWriter) {
+        let TypedBind_(b, ty_opt) = self;
+        b.ast_debug(w);
+        if let Some(ty) = ty_opt {
+            w.write(":");
+            ty.ast_debug(w)
+        }
+    }
+}
diff --git a/third_party/move/move-compiler/src/parser/syntax.rs b/third_party/move/move-compiler/src/parser/syntax.rs
index e969ac5268a74..1c4aee7141204 100644
--- a/third_party/move/move-compiler/src/parser/syntax.rs
+++ b/third_party/move/move-compiler/src/parser/syntax.rs
@@ -781,6 +781,26 @@ fn parse_bind_field(context: &mut Context) -> Result<(Field, Bind), Box<Diagnost
     Ok((f, arg))
 }
 
+// Parse an optionally typed binding:
+//     TypedBind = Bind ( ":" <Type> )?
+fn parse_typed_bind(context: &mut Context) -> Result<TypedBind, Box<Diagnostic>> {
+    let start_loc = context.tokens.start_loc();
+    let bind = parse_bind(context)?;
+    let ty_opt = if match_token(context.tokens, Tok::Colon)? {
+        Some(parse_type(context)?)
+    } else {
+        None
+    };
+    let end_loc = context.tokens.previous_end_loc();
+    let typed_bind_ = TypedBind_(bind, ty_opt);
+    Ok(spanned(
+        context.tokens.file_hash(),
+        start_loc,
+        end_loc,
+        typed_bind_,
+    ))
+}
+
 // Parse a binding:
 //      Bind =
 //          <Var>
@@ -895,14 +915,14 @@ fn parse_bind_or_dotdot(context: &mut Context) -> Result<BindOrDotDot, Box<Diagn
 
 // Parse a list of bindings for lambda.
 //      LambdaBindList =
-//          "|" Comma<Bind> "|"
-fn parse_lambda_bind_list(context: &mut Context) -> Result<BindList, Box<Diagnostic>> {
+//          "|" Comma<TypedBind> "|"
+fn parse_lambda_bind_list(context: &mut Context) -> Result<TypedBindList, Box<Diagnostic>> {
     let start_loc = context.tokens.start_loc();
     let b = parse_comma_list(
         context,
         Tok::Pipe,
         Tok::Pipe,
-        parse_bind,
+        parse_typed_bind,
         "a variable or structure binding",
     )?;
     let end_loc = context.tokens.previous_end_loc();
diff --git a/third_party/move/move-model/src/builder/exp_builder.rs b/third_party/move/move-model/src/builder/exp_builder.rs
index adf8c6c828fbd..21e7e4369562c 100644
--- a/third_party/move/move-model/src/builder/exp_builder.rs
+++ b/third_party/move/move-model/src/builder/exp_builder.rs
@@ -2262,6 +2262,61 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo
         ExpData::Match(id, discr_exp.into_exp(), translate_arms)
     }
 
+    fn translate_typed_lvalue_list(
+        &mut self,
+        list: &EA::TypedLValueList,
+        expected_type: &Type,
+        expected_order: WideningOrder,
+        match_locals: bool,
+        context: &ErrorMessageContext,
+    ) -> Pattern {
+        // Shortcut for single element case
+        if list.value.len() == 1 {
+            return self.translate_typed_lvalue(
+                list.value.first().unwrap(),
+                expected_type,
+                expected_order,
+                match_locals,
+                context,
+            );
+        }
+        let loc = self.to_loc(&list.loc);
+        // Ensure to maximize precision of expected type for elements
+        let expected_type = self.subs.specialize(expected_type);
+        let elem_expected_types = if let Type::Tuple(tys) = expected_type {
+            tys
+        } else {
+            let vars = self.fresh_type_vars(list.value.len());
+            // Just bind the variables
+            self.check_type_with_order(
+                expected_order,
+                &loc,
+                &Type::Tuple(vars.clone()),
+                &expected_type,
+                context,
+            );
+            vars
+        };
+        if elem_expected_types.len() != list.value.len() {
+            self.error(
+                &loc,
+                &context.arity_mismatch(false, elem_expected_types.len(), list.value.len()),
+            );
+            return self.new_error_pat(&loc);
+        }
+        let mut args = vec![];
+        let mut elem_types = vec![];
+        for (lv, expected) in list.value.iter().zip(elem_expected_types.iter()) {
+            let value =
+                self.translate_typed_lvalue(lv, expected, expected_order, match_locals, context);
+            elem_types.push(self.get_node_type(value.node_id()));
+            args.push(value)
+        }
+        let ty = Type::Tuple(elem_types);
+        let id = self.new_node_id_with_type_loc(&ty, &loc);
+        Pattern::Tuple(id, args)
+    }
+
     fn translate_lvalue_list(
         &mut self,
         list: &EA::LValueList,
@@ -2332,6 +2387,33 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo
         }
     }
 
+    fn translate_typed_lvalue(
+        &mut self,
+        tlv: &EA::TypedLValue,
+        expected_type: &Type,
+        expected_order: WideningOrder,
+        match_locals: bool,
+        context: &ErrorMessageContext,
+    ) -> Pattern {
+        use move_ir_types::sp;
+        let sp!(loc, EA::TypedLValue_(lv, opt_ty)) = tlv;
+        match opt_ty {
+            Some(ty) => {
+                let loc = self.to_loc(loc);
+                let bound_type = self.translate_type(ty);
+                self.check_type_with_order(
+                    expected_order,
+                    &loc,
+                    &bound_type, // is this arg ordering right?
+                    expected_type,
+                    context,
+                );
+                self.translate_lvalue(lv, &bound_type, expected_order, match_locals, context)
+            },
+            None => self.translate_lvalue(lv, expected_type, expected_order, match_locals, context),
+        }
+    }
+
     fn translate_lvalue(
         &mut self,
         lv: &EA::LValue,
@@ -4946,14 +5028,14 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo
     fn translate_lambda(
         &mut self,
         loc: &Loc,
-        args: &EA::LValueList,
+        args: &EA::TypedLValueList,
         body: &EA::Exp,
         expected_type: &Type,
         context: &ErrorMessageContext,
     ) -> ExpData {
         // Translate the argument list
         let arg_type = self.fresh_type_var();
-        let pat = self.translate_lvalue_list(
+        let pat = self.translate_typed_lvalue_list(
             args,
             &arg_type,
             WideningOrder::LeftToRight,


Test patch:
diff --git a/third_party/move/move-compiler-v2/tests/checking-lang-v1/eq_inline_typed.exp b/third_party/move/move-compiler-v2/tests/checking-lang-v1/eq_inline_typed.exp
new file mode 100644
index 0000000000000..7eecb2c8d0891
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/eq_inline_typed.exp
@@ -0,0 +1,18 @@
+
+Diagnostics:
+warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f`
+  ┌─ tests/checking-lang-v1/eq_inline_typed.move:3:20
+  │
+3 │     inline fun foo(f: |&u64|) {
+  │                    ^
+
+// -- Model dump before bytecode pipeline
+module 0x42::m {
+    private inline fun foo(f: |&u64|) {
+        Tuple()
+    }
+    private fun g() {
+        Tuple();
+        Tuple()
+    }
+} // end 0x42::m
diff --git a/third_party/move/move-compiler-v2/tests/checking-lang-v1/eq_inline_typed.move b/third_party/move/move-compiler-v2/tests/checking-lang-v1/eq_inline_typed.move
new file mode 100644
index 0000000000000..fd6c39261d521
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking-lang-v1/eq_inline_typed.move
@@ -0,0 +1,13 @@
+module 0x42::m {
+
+    inline fun foo(f: |&u64|) {
+    }
+
+    fun g() {
+        foo(|v: &u64| {
+            v == &1;
+        });
+    }
+
+
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/break_continue_in_lambda_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/break_continue_in_lambda_typed.exp
new file mode 100644
index 0000000000000..85d0ec7301714
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/break_continue_in_lambda_typed.exp
@@ -0,0 +1,13 @@
+
+Diagnostics:
+error: Break outside of a loop not currently supported in inline functions
+  ┌─ tests/checking/inlining/break_continue_in_lambda_typed.move:3:9
+  │
+3 │         break;
+  │         ^^^^^
+
+error: Break outside of a loop not supported in function-typed arguments (lambda expressions)
+   ┌─ tests/checking/inlining/break_continue_in_lambda_typed.move:40:32
+   │
+40 │                 brk2(|_x: u64| break);
+   │                                ^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/break_continue_in_lambda_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/break_continue_in_lambda_typed.move
new file mode 100644
index 0000000000000..52d85e2156339
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/break_continue_in_lambda_typed.move
@@ -0,0 +1,55 @@
+module 0xc0ffee::m {
+    inline fun brk() {
+        break;
+    }
+
+    inline fun brk2(f: |u64|) {
+        f(2);
+    }
+
+    inline fun brk3() {
+	while (true) {
+            break;
+	}
+    }
+
+    inline fun brk4() {
+	while (true) {
+            continue;
+	}
+    }
+
+    public fun foo(): u64 {
+        let i = 0;
+        while (i < 10) {
+            i = i + 1;
+            if (i == 5) {
+                brk();
+		brk3();
+		brk4();
+            }
+        };
+        i
+    }
+
+    public fun bar(): u64 {
+        let i = 0;
+        while (i < 10) {
+            i = i + 1;
+            if (i == 5) {
+                brk2(|_x: u64| break);
+		brk2(|_x: u64| while (true) { break });
+		brk2(|_x: u64| while (true) { continue });
+            }
+        };
+        i
+    }
+
+    fun broken() {
+	break;
+    }
+
+    fun continued() {
+	continue;
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/cool_inlining_test_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/cool_inlining_test_typed.exp
new file mode 100644
index 0000000000000..9b193b7c044a2
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/cool_inlining_test_typed.exp
@@ -0,0 +1,7 @@
+
+Diagnostics:
+error: no function named `beans` found
+   ┌─ tests/checking/inlining/cool_inlining_test_typed.move:15:22
+   │
+15 │         foo(|_x: u8| beans())
+   │                      ^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/cool_inlining_test_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/cool_inlining_test_typed.move
new file mode 100644
index 0000000000000..530805b4f198a
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/cool_inlining_test_typed.move
@@ -0,0 +1,17 @@
+module 0xc0ffee::cool {
+    public fun beans(): u64 {
+        42
+    }
+}
+
+module 0xc0ffee::m {
+    inline fun foo(f: |u8| u64): u64 {
+        use 0xc0ffee::cool::beans;
+        beans();  // discharge unused use warning
+        f(3)
+    }
+
+    public fun bar(): u64 {
+        foo(|_x: u8| beans())
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_typed.exp
new file mode 100644
index 0000000000000..6e66b076fa40b
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_typed.exp
@@ -0,0 +1,13 @@
+
+Diagnostics:
+error: Currently, a function-typed parameter to an inline function must be a literal lambda expression
+  ┌─ tests/checking/inlining/lambda_param_typed.move:7:15
+  │
+7 │     inline_apply(f, b)
+  │                  ^
+
+error: Currently, a function-typed parameter to an inline function must be a literal lambda expression
+   ┌─ tests/checking/inlining/lambda_param_typed.move:11:16
+   │
+11 │     inline_apply4(f, b)
+   │                   ^
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_typed.move
new file mode 100644
index 0000000000000..98e5b59e65ddb
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_typed.move
@@ -0,0 +1,31 @@
+module 0x42::LambdaParam {
+    public inline fun inline_apply(f: |u64|u64, b: u64) : u64 {
+	f(b)
+    }
+
+    public inline fun inline_apply2(f: |u64|u64, b: u64) : u64 {
+	inline_apply(f, b)
+    }
+
+    public inline fun inline_apply3(f: |u64|u64, b: u64) : u64 {
+	inline_apply4(f, b)
+    }
+
+    public inline fun inline_apply4(_f: |u64|u64, b: u64) : u64 {
+	b
+    }
+
+    fun test_lambda_symbol_param1() {
+	let a = inline_apply2(|x: u64| x, 3);
+	assert!(a == 3, 0);
+    }
+
+    fun test_lambda_symbol_param2() {
+	let a = inline_apply2(|x: u64| x, 3);
+	assert!(a == 3, 0);
+	let b = inline_apply(|x: u64| x, 3);
+	assert!(b == 3, 0);
+	let b = inline_apply3(|x: u64| x, 3);
+	assert!(b == 3, 0);
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_return_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_return_typed.exp
new file mode 100644
index 0000000000000..f52bf7c3477ba
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_return_typed.exp
@@ -0,0 +1,7 @@
+
+Diagnostics:
+error: Return not currently supported in inline functions
+  ┌─ tests/checking/inlining/lambda_return_typed.move:3:2
+  │
+3 │     return f(b)
+  │     ^^^^^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_return_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_return_typed.move
new file mode 100644
index 0000000000000..1ea4d58270306
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_return_typed.move
@@ -0,0 +1,10 @@
+module 0x42::LambdaReturn {
+    public inline fun inline_apply2(f: |u64|u64, b: u64) : u64 {
+	return f(b)
+    }
+
+    fun test_lambda_symbol_param() {
+	let a = inline_apply2(|x: u64| { x }, 3);
+	assert!(a == 3, 0);
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_typed.exp
new file mode 100644
index 0000000000000..11a8de528f5cb
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_typed.exp
@@ -0,0 +1,98 @@
+// -- Model dump before bytecode pipeline
+module 0x42::LambdaTest1 {
+    public inline fun inline_apply(f: |u64|u64,b: u64): u64 {
+        (f)(b)
+    }
+    public inline fun inline_apply1(f: |u64|u64,b: u64): u64 {
+        {
+          let (a: u64, b: u64): (u64, u64) = Tuple(Add<u64>((f)(b), 1), 12);
+          Mul<u64>(a, 12)
+        }
+    }
+    public inline fun inline_mul(a: u64,b: u64): u64 {
+        Mul<u64>(a, b)
+    }
+} // end 0x42::LambdaTest1
+module 0x42::LambdaTest2 {
+    use 0x42::LambdaTest1; // resolved as: 0x42::LambdaTest1
+    use std::vector;
+    public inline fun foreach<T>(v: &vector<#0>,action: |&#0|) {
+        {
+          let i: u64 = 0;
+          loop {
+            if Lt<u64>(i, vector::length<T>(v)) {
+              (action)(vector::borrow<T>(v, i));
+              i: u64 = Add<u64>(i, 1);
+              Tuple()
+            } else {
+              break
+            }
+          }
+        }
+    }
+    public inline fun inline_apply2(g: |u64|u64,c: u64): u64 {
+        Add<u64>({
+          let (b: u64): (u64) = Tuple((g)({
+            let (a: u64, b: u64): (u64, u64) = Tuple(c, 3);
+            Mul<u64>(a, 3)
+          }));
+          {
+            let (a: u64, b: u64): (u64, u64) = Tuple(Add<u64>({
+              let (z: u64): (u64) = Tuple(b);
+              z
+            }, 1), 12);
+            Mul<u64>(a, 12)
+          }
+        }, 2)
+    }
+    public inline fun inline_apply3(g: |u64|u64,c: u64): u64 {
+        Add<u64>(LambdaTest1::inline_apply1(g, LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x: u64| LambdaTest1::inline_apply(|y: u64| y, x), 3))), 4)
+    }
+    public fun test_inline_lambda() {
+        {
+          let product: u64 = 1;
+          {
+            let (v: &vector<u64>): (&vector<u64>) = Tuple(Borrow(Immutable)([Number(1), Number(2), Number(3)]));
+            {
+              let i: u64 = 0;
+              loop {
+                if Lt<u64>(i, vector::length<u64>(v)) {
+                  {
+                    let (e: &u64): (&u64) = Tuple(vector::borrow<u64>(v, i));
+                    product: u64 = {
+                      let (a: u64, b: u64): (u64, u64) = Tuple(product, Deref(e));
+                      Mul<u64>(a, b)
+                    }
+                  };
+                  i: u64 = Add<u64>(i, 1);
+                  Tuple()
+                } else {
+                  break
+                }
+              }
+            }
+          };
+          Tuple()
+        }
+    }
+} // end 0x42::LambdaTest2
+module 0x42::LambdaTest {
+    use 0x42::LambdaTest2; // resolved as: 0x42::LambdaTest2
+    public inline fun inline_apply(f: |u64|u64,b: u64): u64 {
+        (f)(b)
+    }
+    public inline fun inline_apply_test(): u64 {
+        1120
+    }
+    private fun test_lambda() {
+        if false {
+          Tuple()
+        } else {
+          Abort(0)
+        };
+        Tuple()
+    }
+} // end 0x42::LambdaTest
+
+
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_typed.move
new file mode 100644
index 0000000000000..e690fc4ffec92
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_typed.move
@@ -0,0 +1,62 @@
+module 0x42::LambdaTest1 {
+    public inline fun inline_mul(a: u64, b: u64): u64 {
+	a * b
+    }
+
+    public inline fun inline_apply1(f: |u64|u64, b: u64) : u64 {
+	inline_mul(f(b) + 1, inline_mul(3, 4))
+    }
+
+    public inline fun inline_apply(f: |u64|u64, b: u64) : u64 {
+	f(b)
+    }
+}
+
+module 0x42::LambdaTest2 {
+    use 0x42::LambdaTest1;
+    use std::vector;
+
+    public inline fun foreach<T>(v: &vector<T>, action: |&T|) { // expected to be not implemented
+        let i = 0;
+        while (i < vector::length(v)) {
+            action(vector::borrow(v, i));
+            i = i + 1;
+        }
+    }
+
+    public fun test_inline_lambda() {
+	let v = vector[1, 2, 3];
+	let product = 1;
+	foreach(&v, |e: &u64| product = LambdaTest1::inline_mul(product, *e));
+    }
+
+    public inline fun inline_apply2(g: |u64|u64, c: u64) : u64 {
+	LambdaTest1::inline_apply1(|z: u64|z, g(LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x: u64|x, 3)))) + 2
+    }
+
+    public inline fun inline_apply3(g: |u64|u64, c: u64) : u64 {
+	LambdaTest1::inline_apply1(g,
+	    LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x:u64| {
+		LambdaTest1::inline_apply(|y: u64|y, x)
+	    },
+		3))) + 4
+    }
+}
+
+module 0x42::LambdaTest {
+    use 0x42::LambdaTest2;
+
+    public inline fun inline_apply(f: |u64|u64, b: u64) : u64 {
+	f(b)
+    }
+
+    public inline fun inline_apply_test() : u64 {
+	LambdaTest2::inline_apply2(|x: u64| x + 1, 3) +
+	LambdaTest2::inline_apply2(|x: u64| x * x, inline_apply(|y: u64|y, 3))
+    }
+
+    fun test_lambda() {
+	let a = inline_apply_test();
+	assert!(a == 1, 0);
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/return_in_lambda_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/return_in_lambda_typed.exp
new file mode 100644
index 0000000000000..565b1d881cec9
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/return_in_lambda_typed.exp
@@ -0,0 +1,19 @@
+
+Diagnostics:
+error: Return not currently supported in function-typed arguments (lambda expressions)
+   ┌─ tests/checking/inlining/return_in_lambda_typed.move:13:13
+   │
+13 │             return adder(x, y)
+   │             ^^^^^^^^^^^^^^^^^^
+
+error: Return not currently supported in function-typed arguments (lambda expressions)
+   ┌─ tests/checking/inlining/return_in_lambda_typed.move:16:13
+   │
+16 │             return adder(x, y)
+   │             ^^^^^^^^^^^^^^^^^^
+
+error: Return not currently supported in function-typed arguments (lambda expressions)
+   ┌─ tests/checking/inlining/return_in_lambda_typed.move:19:13
+   │
+19 │             return adder(x, y)
+   │             ^^^^^^^^^^^^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/return_in_lambda_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/return_in_lambda_typed.move
new file mode 100644
index 0000000000000..c59650aec4734
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/return_in_lambda_typed.move
@@ -0,0 +1,22 @@
+module 0x42::Test {
+
+    inline fun apply(f:|u64, u64| u64, x: u64, y: u64): u64 {
+        f(x, y)
+    }
+
+    inline fun adder(x: u64, y: u64): u64 {
+        x + y
+    }
+
+    public fun main(): u64 {
+        apply(|x: u64, y: u64| {
+            return adder(x, y)
+        }, 10, 100);
+        apply(|x: u64, y| {
+            return adder(x, y)
+        }, 10, 100);
+        apply(|x, y: u64| {
+            return adder(x, y)
+        }, 10, 100)
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl_typed.exp
new file mode 100644
index 0000000000000..4f7f74661aa59
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl_typed.exp
@@ -0,0 +1,51 @@
+
+Diagnostics:
+warning: Unused parameter `z`. Consider removing or prefixing with an underscore: `_z`
+  ┌─ tests/checking/inlining/shadowing_unused_nodecl_typed.move:6:42
+  │
+6 │     public inline fun quux(f:|u64, u64|, z: u64) {
+  │                                          ^
+
+// -- Model dump before bytecode pipeline
+module 0x42::Test {
+    public inline fun foo(f: |(u64, u64)|,z: u64) {
+        {
+          let (z: u64): (u64) = Tuple(z);
+          (f)(3, 5);
+          Tuple()
+        };
+        Tuple()
+    }
+    public inline fun quux(f: |(u64, u64)|,z: u64) {
+        (f)(3, 5);
+        Tuple()
+    }
+    public fun test_shadowing() {
+        {
+          let _x: u64 = 1;
+          _x: u64 = 3;
+          Tuple();
+          Tuple();
+          if Eq<u64>(_x, 3) {
+            Tuple()
+          } else {
+            Abort(0)
+          }
+        }
+    }
+    public fun test_shadowing2() {
+        {
+          let _x: u64 = 1;
+          _x: u64 = 3;
+          Tuple();
+          if Eq<u64>(_x, 3) {
+            Tuple()
+          } else {
+            Abort(0)
+          }
+        }
+    }
+} // end 0x42::Test
+
+
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl_typed.move
new file mode 100644
index 0000000000000..3191a28a0d3ca
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl_typed.move
@@ -0,0 +1,37 @@
+//# publish
+module 0x42::Test {
+
+    // Ideally, we would have a warning about unused var "z" here, but
+    // we don't check inlined functions until they are inlined.
+    public inline fun quux(f:|u64, u64|, z: u64) {
+        let x = 3;
+	let q = 5;
+        f(x, q);
+    }
+
+    public inline fun foo(f:|u64, u64|, z: u64) {
+        quux(|a: u64, b: u64| f(a, b), z);
+    }
+
+    public fun test_shadowing() {
+        let _x = 1;
+	let z = 4;
+        foo(|y: u64, _q: u64| {
+            _x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, z);
+        assert!(_x == 3, 0)
+    }
+
+    public fun test_shadowing2() {
+        let _x = 1;
+	let z = 4;
+        quux(|y: u64, _q: u64| {
+            _x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, z);
+        assert!(_x == 3, 0)
+    }
+}
+
+//# run 0x42::Test::test_shadowing
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_typed.exp
new file mode 100644
index 0000000000000..2c3a1c4b158bd
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_typed.exp
@@ -0,0 +1,43 @@
+// -- Model dump before bytecode pipeline
+module 0x42::Test {
+    public inline fun foo(f: |(u64, u64)|,z: u64) {
+        {
+          let (_z: u64): (u64) = Tuple(z);
+          (f)(3, 5);
+          Tuple()
+        };
+        Tuple()
+    }
+    public inline fun quux(f: |(u64, u64)|,_z: u64) {
+        (f)(3, 5);
+        Tuple()
+    }
+    public fun test_shadowing() {
+        {
+          let _x: u64 = 1;
+          _x: u64 = 3;
+          Tuple();
+          Tuple();
+          if Eq<u64>(_x, 3) {
+            Tuple()
+          } else {
+            Abort(0)
+          }
+        }
+    }
+    public fun test_shadowing2() {
+        {
+          let _x: u64 = 1;
+          _x: u64 = 3;
+          Tuple();
+          if Eq<u64>(_x, 3) {
+            Tuple()
+          } else {
+            Abort(0)
+          }
+        }
+    }
+} // end 0x42::Test
+
+
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_typed.move
new file mode 100644
index 0000000000000..2366415033c67
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_typed.move
@@ -0,0 +1,35 @@
+//# publish
+module 0x42::Test {
+
+    public inline fun quux(f:|u64, u64|, _z: u64) {
+        let x = 3;
+	let q = 5;
+        f(x, q);
+    }
+
+    public inline fun foo(f:|u64, u64|, z: u64) {
+        quux(|a: u64, b: u64| f(a, b), z);
+    }
+
+    public fun test_shadowing() {
+        let _x = 1;
+	let z = 4;
+        foo(|y: u64, _q: u64| {
+            _x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, z);
+        assert!(_x == 3, 0)
+    }
+
+    public fun test_shadowing2() {
+        let _x = 1;
+	let z = 4;
+        quux(|y: u64, _q: u64| {
+            _x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, z);
+        assert!(_x == 3, 0)
+    }
+}
+
+//# run 0x42::Test::test_shadowing
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining_typed.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining_typed.exp
new file mode 100644
index 0000000000000..f5a5f2de0f028
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining_typed.exp
@@ -0,0 +1,60 @@
+// -- Model dump before bytecode pipeline
+module 0x42::Test {
+    private inline fun apply(v: u64,predicate: |u64|bool): bool {
+        spec {
+          assert Ge($t0, 0);
+        }
+        ;
+        (predicate)(v)
+    }
+    public fun test_apply(x: u64) {
+        {
+          let r1: bool = {
+            let (v: u64): (u64) = Tuple(x);
+            spec {
+              assert Ge(v, 0);
+            }
+            ;
+            {
+              let (v: u64): (u64) = Tuple(v);
+              Ge<u64>(v, 0)
+            }
+          };
+          spec {
+            assert r1;
+          }
+          ;
+          if r1 {
+            Tuple()
+          } else {
+            Abort(1)
+          };
+          {
+            let r2: bool = {
+              let (v: u64): (u64) = Tuple(x);
+              spec {
+                assert Ge(v, 0);
+              }
+              ;
+              {
+                let (v: u64): (u64) = Tuple(v);
+                Neq<u64>(v, 0)
+              }
+            };
+            spec {
+              assert r2;
+            }
+            ;
+            if r2 {
+              Tuple()
+            } else {
+              Abort(2)
+            };
+            Tuple()
+          }
+        }
+    }
+} // end 0x42::Test
+
+
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining_typed.move b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining_typed.move
new file mode 100644
index 0000000000000..060e459a17ef0
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining_typed.move
@@ -0,0 +1,22 @@
+module 0x42::Test {
+    inline fun apply(v: u64, predicate: |u64| bool): bool {
+        spec {
+            assert v >= 0;
+        };
+        predicate(v)
+    }
+
+    public fun test_apply(x: u64) {
+        let r1 = apply(x, |v: u64| v >= 0);
+        spec {
+            assert r1;
+        };
+        assert!(r1, 1);
+
+        let r2 = apply(x, |v: u64| v != 0);
+        spec {
+            assert r2;
+        };
+        assert!(r2, 2);
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/receiver/generic_calls_typed.exp b/third_party/move/move-compiler-v2/tests/checking/receiver/generic_calls_typed.exp
new file mode 100644
index 0000000000000..b396815647805
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/receiver/generic_calls_typed.exp
@@ -0,0 +1,47 @@
+// -- Model dump before bytecode pipeline
+module 0x42::m {
+    struct S {
+        x: #0,
+    }
+    private fun id<T>(self: m::S<#0>): m::S<#0> {
+        self
+    }
+    private inline fun inlined<T>(f: |m::S<#0>|m::S<#0>,s: m::S<#0>) {
+        (f)(s);
+        Tuple()
+    }
+    private fun receiver<T>(self: m::S<#0>,y: #0) {
+        select m::S.x<m::S<T>>(self) = y;
+        Tuple()
+    }
+    private fun receiver_more_generics<T,R>(self: m::S<#0>,_y: #1) {
+        Tuple()
+    }
+    private fun receiver_needs_type_args<T,R>(self: m::S<#0>,_y: #0) {
+        Abort(1)
+    }
+    private fun receiver_ref<T>(self: &m::S<#0>,_y: #0) {
+        Tuple()
+    }
+    private fun receiver_ref_mut<T>(self: &mut m::S<#0>,y: #0) {
+        select m::S.x<&mut m::S<T>>(self) = y
+    }
+    private fun test_call_styles(s: m::S<u64>,x: u64) {
+        m::receiver<u64>(s, x);
+        m::receiver_ref<u64>(Borrow(Immutable)(s), x);
+        m::receiver_ref_mut<u64>(Borrow(Mutable)(s), x);
+        m::receiver_more_generics<u64, u64>(s, 22);
+        m::receiver_needs_type_args<u64, u8>(s, x);
+        Tuple()
+    }
+    private fun test_receiver_inference(s: m::S<u64>) {
+        {
+          let (s: m::S<u64>): (m::S<u64>) = Tuple(s);
+          {
+            let (s: m::S<u64>): (m::S<u64>) = Tuple(s);
+            m::id<u64>(s)
+          };
+          Tuple()
+        }
+    }
+} // end 0x42::m
diff --git a/third_party/move/move-compiler-v2/tests/checking/receiver/generic_calls_typed.move b/third_party/move/move-compiler-v2/tests/checking/receiver/generic_calls_typed.move
new file mode 100644
index 0000000000000..6b5a48ebc7d2a
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/receiver/generic_calls_typed.move
@@ -0,0 +1,49 @@
+module 0x42::m {
+
+    struct S<T> { x: T }
+
+    // Call styles
+
+    fun receiver<T>(self: S<T>, y: T) {
+        self.x = y;
+    }
+
+    fun receiver_ref<T>(self: &S<T>, _y: T) {
+    }
+
+    fun receiver_ref_mut<T>(self: &mut S<T>, y: T) {
+        self.x = y
+    }
+
+    fun receiver_more_generics<T, R>(self: S<T>, _y: R) {
+    }
+
+    fun receiver_needs_type_args<T, R>(self: S<T>, _y: T) {
+        abort 1
+    }
+
+    fun test_call_styles(s: S<u64>, x: u64) {
+        s.receiver(x);
+        s.receiver_ref(x);
+        s.receiver_ref_mut(x);
+        s.receiver_more_generics(22);
+        s.receiver_needs_type_args::<u64, u8>(x);
+    }
+
+    // Inference of receiver function
+
+    inline fun inlined<T>(f: |S<T>|S<T>, s: S<T>) {
+        f(s);
+    }
+
+    fun id<T>(self: S<T>): S<T> {
+        self
+    }
+
+    fun test_receiver_inference(s: S<u64>) {
+        // In the lambda the type of `s` is not known when the expression is checked,
+        // and the receiver function `id` is resolved later when the parameter type is unified
+        // with the lambda expression
+        inlined(|s: S<u64>| s.id(), s)
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/receiver/same_names_typed.exp b/third_party/move/move-compiler-v2/tests/checking/receiver/same_names_typed.exp
new file mode 100644
index 0000000000000..b45494f8c2cf6
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/receiver/same_names_typed.exp
@@ -0,0 +1,37 @@
+// -- Model dump before bytecode pipeline
+module 0x42::b {
+    struct MyOtherList {
+        len: u64,
+    }
+    public fun len(self: &b::MyOtherList): u64 {
+        select b::MyOtherList.len<&b::MyOtherList>(self)
+    }
+} // end 0x42::b
+module 0x42::a {
+    struct MyList {
+        len: u64,
+    }
+    public fun len(self: &a::MyList): u64 {
+        select a::MyList.len<&a::MyList>(self)
+    }
+} // end 0x42::a
+module 0x42::c {
+    use 0x42::a; // resolved as: 0x42::a
+    use 0x42::b; // resolved as: 0x42::b
+    private inline fun foo(f: |(a::MyList, b::MyOtherList)|,x: a::MyList,y: b::MyOtherList) {
+        (f)(x, y)
+    }
+    private fun test(x: a::MyList,y: b::MyOtherList) {
+        {
+          let (x: a::MyList, y: b::MyOtherList): (a::MyList, b::MyOtherList) = Tuple(x, y);
+          {
+            let (x: a::MyList, y: b::MyOtherList): (a::MyList, b::MyOtherList) = Tuple(x, y);
+            if Eq<u64>(Add<u64>(a::len(Borrow(Immutable)(x)), b::len(Borrow(Immutable)(y))), 1) {
+              Tuple()
+            } else {
+              Abort(1)
+            }
+          }
+        }
+    }
+} // end 0x42::c
diff --git a/third_party/move/move-compiler-v2/tests/checking/receiver/same_names_typed.move b/third_party/move/move-compiler-v2/tests/checking/receiver/same_names_typed.move
new file mode 100644
index 0000000000000..dc5b73e4e55ca
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/receiver/same_names_typed.move
@@ -0,0 +1,32 @@
+module 0x42::a {
+
+    struct MyList { len: u64 }
+
+    public fun len(self: &MyList): u64 {
+        self.len
+    }
+}
+
+module 0x42::b {
+
+    struct MyOtherList { len: u64 }
+
+    public fun len(self: &MyOtherList): u64 {
+        self.len
+    }
+}
+
+module 0x42::c {
+    use 0x42::a;
+    use 0x42::b;
+
+    inline fun foo(f: |a::MyList, b::MyOtherList|, x: a::MyList, y: b::MyOtherList) {
+        f(x, y)
+    }
+
+    fun test(x: a::MyList, y: b::MyOtherList) {
+        // In the lambda below, the type of x and y is not known when the
+        // expression is checked.
+        foo(|x: a::MyList, y: b::MyOtherList| { assert!(x.len() + y.len() == 1, 1) }, x, y)
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec_typed.exp b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec_typed.exp
new file mode 100644
index 0000000000000..e3c750934cc8c
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec_typed.exp
@@ -0,0 +1,80 @@
+// -- Model dump before bytecode pipeline
+module 0x42::m {
+    spec {
+      invariant forall a: address: TypeDomain<address>(): Implies(exists<m::S>(a), {
+      let (x: address): (address) = Tuple(a);
+      {
+        let r: bool = {
+          let (a: address): (address) = Tuple(x);
+          Lt(select m::S.f<m::S>({
+            let (a: address): (address) = Tuple(a);
+            global<m::S>(a)
+          }), 10)
+        };
+        r
+      }
+    });
+    }
+
+    struct S {
+        f: u64,
+    }
+    spec {
+      invariant {
+      let (x: u64): (u64) = Tuple(select m::S.f());
+      {
+        let r: bool = {
+          let (x: u64): (u64) = Tuple(x);
+          Gt(x, 0)
+        };
+        r
+      }
+    };
+    }
+
+    private inline fun exec<T,R>(f: |#0|#1,x: #0): #1 {
+        {
+          let r: R = (f)(x);
+          spec {
+            assert Eq<#1>(r, (f)($t1));
+          }
+          ;
+          r
+        }
+    }
+    private fun function_code_spec_block(x: u64): u64 {
+        spec {
+          assert {
+          let (x: u64): (u64) = Tuple($t0);
+          {
+            let r: bool = {
+              let (y: u64): (u64) = Tuple(x);
+              Gt(y, 0)
+            };
+            r
+          }
+        };
+        }
+        ;
+        Add<u64>(x, 1)
+    }
+    private fun function_spec_block(x: u64): u64 {
+        Add<u64>(x, 1)
+    }
+    spec {
+      ensures Eq<u64>(result0(), {
+      let (x: u64): (u64) = Tuple($t0);
+      {
+        let r: num = {
+          let (x: u64): (u64) = Tuple(x);
+          Add(x, 1)
+        };
+        r
+      }
+    });
+    }
+
+    private inline fun get<R>(a: address): &#0 {
+        BorrowGlobal(Immutable)<R>(a)
+    }
+} // end 0x42::m
diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec_typed.move b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec_typed.move
new file mode 100644
index 0000000000000..fcbfc1d52ec19
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec_typed.move
@@ -0,0 +1,33 @@
+module 0x42::m {
+
+    inline fun exec<T, R>(f: |T|R, x: T): R {
+        let r = f(x);
+        spec { assert r == f(x); };
+        r
+    }
+
+    // Function spec block
+    fun function_spec_block(x: u64): u64 {
+        x + 1
+    }
+    spec function_spec_block {
+        ensures result == exec(|x: u64| x + 1, x);
+    }
+
+    // Function code spec block
+    fun function_code_spec_block(x: u64): u64 {
+        spec { assert exec(|y: u64| y > 0, x); };
+        x + 1
+    }
+
+    // Struct spec block
+    struct S has key { f: u64 }
+    spec S { invariant exec(|x: u64| x > 0, f); }
+
+    // Global invariant
+    spec module {
+        invariant forall a: address:
+            exists<S>(a) ==> exec(|a: address| get<S>(a).f < 10, a);
+    }
+    inline fun get<R:key>(a: address): &R { borrow_global<R>(a) }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline_typed.exp b/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline_typed.exp
new file mode 100644
index 0000000000000..c7449303ddf2c
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline_typed.exp
@@ -0,0 +1,18 @@
+
+Diagnostics:
+warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f`
+  ┌─ tests/checking/typing/eq_inline_typed.move:3:20
+  │
+3 │     inline fun foo(f: |&u64|) {
+  │                    ^
+
+// -- Model dump before bytecode pipeline
+module 0x42::m {
+    private inline fun foo(f: |&u64|) {
+        Tuple()
+    }
+    private fun g() {
+        Tuple();
+        Tuple()
+    }
+} // end 0x42::m
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline_typed.move b/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline_typed.move
new file mode 100644
index 0000000000000..fd6c39261d521
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline_typed.move
@@ -0,0 +1,13 @@
+module 0x42::m {
+
+    inline fun foo(f: |&u64|) {
+    }
+
+    fun g() {
+        foo(|v: &u64| {
+            v == &1;
+        });
+    }
+
+
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp
new file mode 100644
index 0000000000000..351d607a7b2b7
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp
@@ -0,0 +1,37 @@
+
+Diagnostics:
+error: expected `|(&T, u64)|_` but found a value of type `|&T|`
+   ┌─ tests/checking/typing/lambda_typed.move:40:13
+   │
+40 │             action(XVector::borrow(v, i), i); // expected to have wrong argument count
+   │             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected `|u64|_` but found a value of type `|&T|`
+   ┌─ tests/checking/typing/lambda_typed.move:48:13
+   │
+48 │             action(i); // expected to have wrong argument type
+   │             ^^^^^^^^^
+
+error: cannot use `()` with an operator which expects a value of type `u64`
+   ┌─ tests/checking/typing/lambda_typed.move:56:21
+   │
+56 │             i = i + action(XVector::borrow(v, i)); // expected to have wrong result type
+   │                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot return `u64` from a function with result type `|integer|`
+   ┌─ tests/checking/typing/lambda_typed.move:61:9
+   │
+61 │         x(1) // expected to be not a function
+   │         ^^^^
+
+error: cannot use `&u64` with an operator which expects a value of type `integer`
+   ┌─ tests/checking/typing/lambda_typed.move:67:43
+   │
+67 │         foreach(&v, |e: &u64| sum = sum + e) // expected to cannot infer type
+   │                                           ^
+
+error: cannot pass `|&u64|u64` to a function which expects argument of type `|&u64|`
+   ┌─ tests/checking/typing/lambda_typed.move:73:21
+   │
+73 │         foreach(&v, |e: &u64| { sum = sum + *e; *e }) // expected to have wrong result type of lambda
+   │                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.move b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.move
new file mode 100644
index 0000000000000..391db99ddd587
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.move
@@ -0,0 +1,110 @@
+module 0x8675309::M {
+    use 0x1::XVector;
+
+    public inline fun foreach<T>(v: &vector<T>, action: |&T|) { // expected to be not implemented
+        let i = 0;
+        while (i < XVector::length(v)) {
+            action(XVector::borrow(v, i));
+            i = i + 1;
+        }
+    }
+
+    public inline fun reduce<R, T>(v: vector<T>, accu: R, reducer: |T, R|R): R {
+        while (!XVector::is_empty(&v)) {
+            accu = reducer(XVector::pop_back(&mut v), accu);
+        };
+        accu
+    }
+
+
+    public fun correct_foreach() {
+        let v = vector[1, 2, 3];
+        let sum = 0;
+        foreach(&v, |e: &u64| sum = sum + *e) // expected to be not implemented
+    }
+
+    public fun correct_reduce(): u64 {
+        let v = vector[1, 2, 3];
+        reduce(v, 0, |t: u64, r: u64| t + r)
+    }
+
+    public fun corrected_nested() {
+        let v = vector[vector[1,2], vector[3]];
+        let sum = 0;
+        foreach(&v, |e: &vector<u64>| sum = sum + reduce(*e, 0, |t: u64, r: u64| t + r));
+    }
+
+    public inline fun wrong_local_call_arg_count<T>(v: &vector<T>, action: |&T|) {
+        let i = 0;
+        while (i < XVector::length(v)) {
+            action(XVector::borrow(v, i), i); // expected to have wrong argument count
+            i = i + 1;
+        }
+    }
+
+    public inline fun wrong_local_call_arg_type<T>(v: &vector<T>, action: |&T|) {
+        let i = 0;
+        while (i < XVector::length(v)) {
+            action(i); // expected to have wrong argument type
+            i = i + 1;
+        }
+    }
+
+    public inline fun wrong_local_call_result_type<T>(v: &vector<T>, action: |&T|) {
+        let i = 0;
+        while (i < XVector::length(v)) {
+            i = i + action(XVector::borrow(v, i)); // expected to have wrong result type
+        }
+    }
+
+    public fun wrong_local_call_no_fun(x: u64) {
+        x(1) // expected to be not a function
+    }
+
+    public fun wrong_lambda_inferred_type() {
+        let v = vector[1, 2, 3];
+        let sum = 0;
+        foreach(&v, |e: &u64| sum = sum + e) // expected to cannot infer type
+    }
+
+    public fun wrong_lambda_result_type() {
+        let v = vector[1, 2, 3];
+        let sum = 0;
+        foreach(&v, |e: &u64| { sum = sum + *e; *e }) // expected to have wrong result type of lambda
+    }
+
+    public fun lambda_not_allowed() {
+        let _x = |i: u64| i + 1; // expected lambda not allowed
+    }
+
+    struct FieldFunNotAllowed {
+        f: |u64|u64, // expected lambda not allowed
+    }
+
+    public fun fun_arg_lambda_not_allowed(x: |u64|) {} // expected lambda not allowed
+
+    public inline fun macro_result_lambda_not_allowed(): |u64| {  // expected lambda not allowed
+        abort (1)
+    }
+    public fun fun_result_lambda_not_allowed(): |u64| {  // expected lambda not allowed
+        abort (1)
+    }
+
+    public fun correct_reduce2(): u64 {
+        let v = vector[1, 2, 3];
+        reduce(v, 0, |t: u64, r| t + r)
+    }
+
+    public fun corrected_nested2() {
+        let v = vector[vector[1,2], vector[3]];
+        let sum = 0;
+        foreach(&v, |e: &vector<u64>| sum = sum + reduce(*e, 0, |t, r: u64| t + r));
+    }
+}
+
+module 0x1::XVector {
+    public fun length<T>(v: &vector<T>): u64 { abort(1) }
+    public fun is_empty<T>(v: &vector<T>): bool { abort(1) }
+    public fun borrow<T>(v: &vector<T>, i: u64): &T { abort(1) }
+    public fun pop_back<T>(v: &mut vector<T>): T { abort(1) }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen.exp
new file mode 100644
index 0000000000000..28c542fa4b1d4
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen.exp
@@ -0,0 +1,25 @@
+
+Diagnostics:
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen.move:38:38
+   │
+38 │         let r = use_mut2_ref(&mut v, |x: &mut u64| *x);
+   │                                      ^^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen.move:53:38
+   │
+53 │         let r = use_mut2_ref(&mut v, |x: &mut u64| *(freeze(x)));
+   │                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen.move:58:37
+   │
+58 │         let r = use_imm_ref(&mut v, |x: &mut u64| *x);
+   │                                     ^^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen.move:73:37
+   │
+73 │         let r = use_imm_ref(&mut v, |x: &mut u64| *(freeze(x)));
+   │                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen.move b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen.move
new file mode 100644
index 0000000000000..df50f25e6d39b
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen.move
@@ -0,0 +1,75 @@
+module 0x8675309::M {
+    use std::vector;
+
+    public inline fun use_mut_ref<T>(v: &mut vector<T>, action: |&mut T|T): T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun use_mut2_ref<T>(v: &mut vector<T>, action: |&T|T): T {
+        return action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun use_imm_ref<T>(v: &mut vector<T>, action: |&T|T): T {
+        return action(vector::borrow(v, 0))
+    }
+
+    public fun consume_mut_mut() {
+        let v = vector[1, 2, 3];
+        let r = use_mut_ref(&mut v, |x: &mut u64| *x);
+    }
+
+    public fun consume_mut_imm() {
+        let v = vector[1, 2, 3];
+        let r = use_mut_ref(&mut v, |x: &u64| *x);
+    }
+
+    public fun consume_mut_untyped() {
+        let v = vector[1, 2, 3];
+        let r = use_mut_ref(&mut v, |x| *x);
+    }
+
+    public fun consume_mut_freeze() {
+        let v = vector[1, 2, 3];
+        let r = use_mut_ref(&mut v, |x: &mut u64| *(freeze(x)));
+    }
+
+    public fun consume_mut2_mut() {
+        let v = vector[1, 2, 3];
+        let r = use_mut2_ref(&mut v, |x: &mut u64| *x);
+    }
+
+    public fun consume_mut2_imm() {
+        let v = vector[1, 2, 3];
+        let r = use_mut2_ref(&mut v, |x: &u64| *x);
+    }
+
+    public fun consume_mut2_untyped() {
+        let v = vector[1, 2, 3];
+        let r = use_mut2_ref(&mut v, |x| *x);
+    }
+
+    public fun consume_mut2_freeze() {
+        let v = vector[1, 2, 3];
+        let r = use_mut2_ref(&mut v, |x: &mut u64| *(freeze(x)));
+    }
+
+    public fun consume_imm_mut() {
+        let v = vector[1, 2, 3];
+        let r = use_imm_ref(&mut v, |x: &mut u64| *x);
+    }
+
+    public fun consume_imm_imm() {
+        let v = vector[1, 2, 3];
+        let r = use_imm_ref(&mut v, |x: &u64| *x);
+    }
+
+    public fun consume_imm_untyped() {
+        let v = vector[1, 2, 3];
+        let r = use_imm_ref(&mut v, |x| *x);
+    }
+
+    public fun consume_imm_freeze() {
+        let v = vector[1, 2, 3];
+        let r = use_imm_ref(&mut v, |x: &mut u64| *(freeze(x)));
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen_result.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen_result.exp
new file mode 100644
index 0000000000000..7c5cd89701bbe
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen_result.exp
@@ -0,0 +1,49 @@
+
+Diagnostics:
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen_result.move:33:38
+   │
+33 │         let r = pass_mut_ref(&mut v, |x: &u64| x);
+   │                                      ^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen_result.move:43:38
+   │
+43 │         let r = pass_mut_ref(&mut v, |x: &mut u64| (freeze(x)));
+   │                                      ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen_result.move:55:39
+   │
+55 │         let r = pass_mut2_ref(&mut v, |x: &u64| x);
+   │                                       ^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen_result.move:65:39
+   │
+65 │         let r = pass_mut2_ref(&mut v, |x: &mut u64| (freeze(x)));
+   │                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_typed_widen_result.move:94:39
+   │
+94 │         let r = pass_mut4_ref(&mut v, |x: &mut u64| x);
+   │                                       ^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+    ┌─ tests/checking/typing/lambda_typed_widen_result.move:109:39
+    │
+109 │         let r = pass_mut4_ref(&mut v, |x: &mut u64| (freeze(x)));
+    │                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+    ┌─ tests/checking/typing/lambda_typed_widen_result.move:116:38
+    │
+116 │         let r = pass_imm_ref(&mut v, |x: &mut u64| x);
+    │                                      ^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+    ┌─ tests/checking/typing/lambda_typed_widen_result.move:131:38
+    │
+131 │         let r = pass_imm_ref(&mut v, |x: &mut u64| (freeze(x)));
+    │                                      ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen_result.move b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen_result.move
new file mode 100644
index 0000000000000..601cab6492a29
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed_widen_result.move
@@ -0,0 +1,133 @@
+module 0x8675309::M {
+    use std::vector;
+
+    public inline fun pass_mut_ref<T>(v: &mut vector<T>, action: |&mut T|&mut T): &mut T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_mut2_ref<T>(v: &mut vector<T>, action: |&mut T|&mut T): &T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_mut3_ref<T>(v: &mut vector<T>, action: |&mut T|&T): &T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_mut4_ref<T>(v: &mut vector<T>, action: |&T|&T): &T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_imm_ref<T>(v: &mut vector<T>, action: |&T|&T): &T {
+        return action(vector::borrow(v, 0))
+    }
+
+    // 1
+
+    public fun consume_mut_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x: &mut u64| x);
+    }
+
+    public fun consume_mut_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x: &u64| x);
+    }
+
+    public fun consume_mut_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x: &mut u64| (freeze(x)));
+    }
+
+    // 2
+
+    public fun consume_mut2_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x: &mut u64| x);
+    }
+
+    public fun consume_mut2_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x: &u64| x);
+    }
+
+    public fun consume_mut2_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut2_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x: &mut u64| (freeze(x)));
+    }
+
+    // 3
+
+    public fun consume_mut3_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x: &mut u64| x);
+    }
+
+    public fun consume_mut3_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x: &u64| x);
+    }
+
+    public fun consume_mut3_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut3_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x: &mut u64| (freeze(x)));
+    }
+
+    // 4
+
+    public fun consume_mut4_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x: &mut u64| x);
+    }
+
+    public fun consume_mut4_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x: &u64| x);
+    }
+
+    public fun consume_mut4_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut4_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x: &mut u64| (freeze(x)));
+    }
+
+    // imm
+
+    public fun consume_imm_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x: &mut u64| x);
+    }
+
+    public fun consume_imm_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x: &u64| x);
+    }
+
+    public fun consume_imm_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x| x);
+    }
+
+    public fun consume_imm_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x: &mut u64| (freeze(x)));
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen.exp
new file mode 100644
index 0000000000000..641f4f0165093
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen.exp
@@ -0,0 +1,13 @@
+
+Diagnostics:
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_widen.move:33:38
+   │
+33 │         let r = use_mut2_ref(&mut v, |x| *(freeze(x)));
+   │                                      ^^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_widen.move:43:37
+   │
+43 │         let r = use_imm_ref(&mut v, |x| *(freeze(x)));
+   │                                     ^^^^^^^^^^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen.move b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen.move
new file mode 100644
index 0000000000000..748d60f38498c
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen.move
@@ -0,0 +1,45 @@
+module 0x8675309::M {
+    use std::vector;
+
+    public inline fun use_mut_ref<T>(v: &mut vector<T>, action: |&mut T|T): T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun use_mut2_ref<T>(v: &mut vector<T>, action: |&T|T): T {
+        return action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun use_imm_ref<T>(v: &mut vector<T>, action: |&T|T): T {
+        return action(vector::borrow(v, 0))
+    }
+
+    public fun consume_mut_mut() {
+        let v = vector[1, 2, 3];
+        let r = use_mut_ref(&mut v, |x| *x);
+    }
+
+    public fun consume_mut_freeze() {
+        let v = vector[1, 2, 3];
+        let r = use_mut_ref(&mut v, |x| *(freeze(x)));
+    }
+
+    public fun consume_mut2_mut() {
+        let v = vector[1, 2, 3];
+        let r = use_mut2_ref(&mut v, |x| *x);
+    }
+
+    public fun consume_mut2_freeze() {
+        let v = vector[1, 2, 3];
+        let r = use_mut2_ref(&mut v, |x| *(freeze(x)));
+    }
+
+    public fun consume_imm_mut() {
+        let v = vector[1, 2, 3];
+        let r = use_imm_ref(&mut v, |x| *x);
+    }
+
+    public fun consume_imm_freeze() {
+        let v = vector[1, 2, 3];
+        let r = use_imm_ref(&mut v, |x| *(freeze(x)));
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen_result.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen_result.exp
new file mode 100644
index 0000000000000..065dfb4facfde
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen_result.exp
@@ -0,0 +1,31 @@
+
+Diagnostics:
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_widen_result.move:43:38
+   │
+43 │         let r = pass_mut_ref(&mut v, |x| (freeze(x)));
+   │                                      ^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+   ┌─ tests/checking/typing/lambda_widen_result.move:65:39
+   │
+65 │         let r = pass_mut2_ref(&mut v, |x| (freeze(x)));
+   │                                       ^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+    ┌─ tests/checking/typing/lambda_widen_result.move:109:39
+    │
+109 │         let r = pass_mut4_ref(&mut v, |x| (freeze(x)));
+    │                                       ^^^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+    ┌─ tests/checking/typing/lambda_widen_result.move:126:38
+    │
+126 │         let r = pass_imm_ref(&mut v, |x| freeze(x));
+    │                                      ^^^^^^^^^^^^^
+
+error: the function takes `&mut` but `&` was provided
+    ┌─ tests/checking/typing/lambda_widen_result.move:136:38
+    │
+136 │         let r = pass_imm_ref(&mut v, |x| (freeze(x)));
+    │                                      ^^^^^^^^^^^^^^^
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen_result.move b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen_result.move
new file mode 100644
index 0000000000000..f49a5c4a2728e
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_widen_result.move
@@ -0,0 +1,138 @@
+module 0x8675309::M {
+    use std::vector;
+
+    public inline fun pass_mut_ref<T>(v: &mut vector<T>, action: |&mut T|&mut T): &mut T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_mut2_ref<T>(v: &mut vector<T>, action: |&mut T|&mut T): &T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_mut3_ref<T>(v: &mut vector<T>, action: |&mut T|&T): &T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_mut4_ref<T>(v: &mut vector<T>, action: |&T|&T): &T {
+        action(vector::borrow_mut(v, 0))
+    }
+
+    public inline fun pass_imm_ref<T>(v: &mut vector<T>, action: |&T|&T): &T {
+        return action(vector::borrow(v, 0))
+    }
+
+    // 1
+
+    public fun consume_mut_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut_ref(&mut v, |x| (freeze(x)));
+    }
+
+    // 2
+
+    public fun consume_mut2_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut2_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut2_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut2_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut2_ref(&mut v, |x| (freeze(x)));
+    }
+
+    // 3
+
+    public fun consume_mut3_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut3_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut3_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut3_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut3_ref(&mut v, |x| (freeze(x)));
+    }
+
+    // 4
+
+    public fun consume_mut4_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut4_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut4_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x| x);
+    }
+
+    public fun consume_mut4_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_mut4_ref(&mut v, |x| (freeze(x)));
+    }
+
+    // imm
+
+    public fun consume_imm_mut() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x| x);
+    }
+
+    public fun consume_imm_imm() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x| x);
+    }
+
+    public fun consume_imm_imm_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x| freeze(x));
+    }
+
+    public fun consume_imm_untyped() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x| x);
+    }
+
+    public fun consume_imm_freeze() {
+        let v = vector[1, 2, 3];
+        let r = pass_imm_ref(&mut v, |x| (freeze(x)));
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param_typed.exp b/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param_typed.exp
new file mode 100644
index 0000000000000..ca98b47e485f2
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param_typed.exp
@@ -0,0 +1,26 @@
+
+Diagnostics:
+warning: Unused anonymous function parameter `x`. Consider removing or prefixing with an underscore: `_x`
+  ┌─ tests/checking/typing/unused_lambda_param_typed.move:7:18
+  │
+7 │         test(0, |x: u64| 1);
+  │                  ^
+
+// -- Model dump before bytecode pipeline
+module 0xc0ffee::m {
+    private inline fun test(p: u64,f: |u64|u64): u64 {
+        (f)(p)
+    }
+    private fun unused_lambda() {
+        1;
+        Tuple()
+    }
+    private fun unused_lambda_suppressed1() {
+        1;
+        Tuple()
+    }
+    private fun unused_lambda_suppressed2() {
+        1;
+        Tuple()
+    }
+} // end 0xc0ffee::m
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param_typed.move b/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param_typed.move
new file mode 100644
index 0000000000000..eb82be0c92b67
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param_typed.move
@@ -0,0 +1,17 @@
+module 0xc0ffee::m {
+    inline fun test(p: u64, f: |u64| u64): u64 {
+        f(p)
+    }
+
+    fun unused_lambda() {
+        test(0, |x: u64| 1);
+    }
+
+    fun unused_lambda_suppressed1() {
+        test(0, |_x: u64| 1);
+    }
+
+    fun unused_lambda_suppressed2() {
+        test(0, |_: u64| 1);
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.exp
new file mode 100644
index 0000000000000..efb4cdee84f64
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.exp
@@ -0,0 +1,64 @@
+
+============ disassembled file-format ==================
+// Move bytecode v7
+module 42.m {
+use 0000000000000000000000000000000000000000000000000000000000000001::vector;
+
+
+struct E<Ty0> has copy, drop, store {
+	key: Ty0
+}
+struct Option<Ty0> has copy, drop, store {
+	vec: vector<Ty0>
+}
+
+public destroy_none<Ty0>(Arg0: Option<Ty0>) /* def_idx: 0 */ {
+B0:
+	0: ImmBorrowLoc[0](Arg0: Option<Ty0>)
+	1: Call is_none<Ty0>(&Option<Ty0>): bool
+	2: BrFalse(4)
+B1:
+	3: Branch(6)
+B2:
+	4: LdU64(262144)
+	5: Abort
+B3:
+	6: MoveLoc[0](Arg0: Option<Ty0>)
+	7: UnpackGeneric[0](Option<Ty0>)
+	8: VecUnpack(2, 0)
+	9: Ret
+}
+public foo<Ty0: drop + store>(Arg0: E<Ty0>, Arg1: &mut Ty0) /* def_idx: 1 */ {
+L2:	loc0: E<Ty0>
+L3:	loc1: Ty0
+L4:	loc2: E<Ty0>
+L5:	loc3: E<Ty0>
+L6:	loc4: u64
+B0:
+	0: MoveLoc[0](Arg0: E<Ty0>)
+	1: StLoc[2](loc0: E<Ty0>)
+	2: MoveLoc[2](loc0: E<Ty0>)
+	3: UnpackGeneric[1](E<Ty0>)
+	4: StLoc[3](loc1: Ty0)
+	5: MoveLoc[3](loc1: Ty0)
+	6: PackGeneric[1](E<Ty0>)
+	7: StLoc[4](loc2: E<Ty0>)
+	8: MoveLoc[4](loc2: E<Ty0>)
+	9: StLoc[5](loc3: E<Ty0>)
+	10: MoveLoc[5](loc3: E<Ty0>)
+	11: UnpackGeneric[1](E<Ty0>)
+	12: LdU64(3)
+	13: StLoc[6](loc4: u64)
+	14: MoveLoc[1](Arg1: &mut Ty0)
+	15: WriteRef
+	16: Ret
+}
+public is_none<Ty0>(Arg0: &Option<Ty0>): bool /* def_idx: 2 */ {
+B0:
+	0: MoveLoc[0](Arg0: &Option<Ty0>)
+	1: ImmBorrowFieldGeneric[0](Option.vec: vector<Ty0>)
+	2: Call vector::is_empty<Ty0>(&vector<Ty0>): bool
+	3: Ret
+}
+}
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.move b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.move
new file mode 100644
index 0000000000000..a38d3de9db2a4
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.move
@@ -0,0 +1,42 @@
+module 0x42::m {
+    use std::vector;
+
+    struct Option<Element> has copy, drop, store {
+        vec: vector<Element>
+    }
+
+    public fun is_none<Element>(t: &Option<Element>): bool {
+        vector::is_empty(&t.vec)
+    }
+
+    public fun destroy_none<Element>(t: Option<Element>) {
+        assert!(is_none(&t), 0x40000);
+        let Option { vec } = t;
+        vector::destroy_empty(vec)
+    }
+
+    struct E<Key> has copy, drop, store {
+        key: Key,
+    }
+
+    public inline fun h<Key: store + drop>(x: E<Key>, v: |Key| E<Key>): E<Key> {
+        let E { key } = x;
+        v(key)
+    }
+
+    public inline fun g<Key: store + drop>(x: E<Key>, v: |E<Key>|) {
+        v(x)
+    }
+
+    public fun foo<Key: store + drop>(
+        data: E<Key>, v: &mut Key) {
+        let f = h(data, |e: Key| {
+            E {key: e}
+        });
+        g(f, |e: E<Key>| {
+            let (E { key }, _x) = (e, 3);
+            *v = key;
+        });
+    }
+
+}
diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.opt.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.opt.exp
new file mode 100644
index 0000000000000..046a3069a091c
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/file-format-generator/unpack_generic_struct_typed.opt.exp
@@ -0,0 +1,47 @@
+
+============ disassembled file-format ==================
+// Move bytecode v7
+module 42.m {
+use 0000000000000000000000000000000000000000000000000000000000000001::vector;
+
+
+struct E<Ty0> has copy, drop, store {
+	key: Ty0
+}
+struct Option<Ty0> has copy, drop, store {
+	vec: vector<Ty0>
+}
+
+public destroy_none<Ty0>(Arg0: Option<Ty0>) /* def_idx: 0 */ {
+B0:
+	0: ImmBorrowLoc[0](Arg0: Option<Ty0>)
+	1: Call is_none<Ty0>(&Option<Ty0>): bool
+	2: BrFalse(7)
+B1:
+	3: MoveLoc[0](Arg0: Option<Ty0>)
+	4: UnpackGeneric[0](Option<Ty0>)
+	5: VecUnpack(2, 0)
+	6: Ret
+B2:
+	7: LdU64(262144)
+	8: Abort
+}
+public foo<Ty0: drop + store>(Arg0: E<Ty0>, Arg1: &mut Ty0) /* def_idx: 1 */ {
+B0:
+	0: MoveLoc[0](Arg0: E<Ty0>)
+	1: UnpackGeneric[1](E<Ty0>)
+	2: PackGeneric[1](E<Ty0>)
+	3: UnpackGeneric[1](E<Ty0>)
+	4: MoveLoc[1](Arg1: &mut Ty0)
+	5: WriteRef
+	6: Ret
+}
+public is_none<Ty0>(Arg0: &Option<Ty0>): bool /* def_idx: 2 */ {
+B0:
+	0: MoveLoc[0](Arg0: &Option<Ty0>)
+	1: ImmBorrowFieldGeneric[0](Option.vec: vector<Ty0>)
+	2: Call vector::is_empty<Ty0>(&vector<Ty0>): bool
+	3: Ret
+}
+}
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.exp b/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.exp
new file mode 100644
index 0000000000000..294f89be7fbf0
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.exp
@@ -0,0 +1,291 @@
+============ initial bytecode ================
+
+[variant baseline]
+fun m::foo(): u64 {
+     var $t0: u64
+     var $t1: vector<u64>
+     var $t2: &mut vector<u64>
+     var $t3: u64
+     var $t4: &mut vector<u64>
+     var $t5: u64
+     var $t6: u64
+     var $t7: &vector<u64>
+     var $t8: bool
+     var $t9: bool
+     var $t10: bool
+     var $t11: &u64
+     var $t12: &u64
+     var $t13: &vector<u64>
+     var $t14: u64
+     var $t15: u64
+     var $t16: u64
+     var $t17: u64
+     var $t18: u64
+     var $t19: u64
+     var $t20: u64
+     var $t21: bool
+     var $t22: bool
+     var $t23: &u64
+     var $t24: &u64
+     var $t25: &vector<u64>
+     var $t26: u64
+     var $t27: u64
+     var $t28: u64
+     var $t29: u64
+     var $t30: u64
+     var $t31: u64
+     var $t32: &u64
+     var $t33: &vector<u64>
+     var $t34: u64
+  0: $t1 := ["1", "2", "3"]
+  1: $t2 := borrow_local($t1)
+  2: $t4 := infer($t2)
+  3: $t5 := 0
+  4: $t7 := freeze_ref(implicit)($t4)
+  5: $t6 := vector::length<u64>($t7)
+  6: label L0
+  7: $t8 := <($t5, $t6)
+  8: if ($t8) goto 9 else goto 27
+  9: label L2
+ 10: $t13 := freeze_ref(implicit)($t4)
+ 11: $t12 := vector::borrow<u64>($t13, $t5)
+ 12: $t11 := infer($t12)
+ 13: $t14 := read_ref($t11)
+ 14: $t15 := 1
+ 15: $t10 := >($t14, $t15)
+ 16: $t9 := !($t10)
+ 17: if ($t9) goto 18 else goto 21
+ 18: label L5
+ 19: goto 31
+ 20: goto 22
+ 21: label L6
+ 22: label L7
+ 23: $t17 := 1
+ 24: $t16 := +($t5, $t17)
+ 25: $t5 := infer($t16)
+ 26: goto 29
+ 27: label L3
+ 28: goto 31
+ 29: label L4
+ 30: goto 6
+ 31: label L1
+ 32: $t18 := infer($t5)
+ 33: $t20 := 1
+ 34: $t19 := +($t5, $t20)
+ 35: $t5 := infer($t19)
+ 36: label L8
+ 37: $t21 := <($t5, $t6)
+ 38: if ($t21) goto 39 else goto 59
+ 39: label L10
+ 40: $t25 := freeze_ref(implicit)($t4)
+ 41: $t24 := vector::borrow<u64>($t25, $t5)
+ 42: $t23 := infer($t24)
+ 43: $t26 := read_ref($t23)
+ 44: $t27 := 1
+ 45: $t22 := >($t26, $t27)
+ 46: if ($t22) goto 47 else goto 53
+ 47: label L13
+ 48: vector::swap<u64>($t4, $t18, $t5)
+ 49: $t29 := 1
+ 50: $t28 := +($t18, $t29)
+ 51: $t18 := infer($t28)
+ 52: goto 54
+ 53: label L14
+ 54: label L15
+ 55: $t31 := 1
+ 56: $t30 := +($t5, $t31)
+ 57: $t5 := infer($t30)
+ 58: goto 61
+ 59: label L11
+ 60: goto 63
+ 61: label L12
+ 62: goto 36
+ 63: label L9
+ 64: $t3 := infer($t18)
+ 65: $t33 := freeze_ref(implicit)($t2)
+ 66: $t34 := 0
+ 67: $t32 := vector::borrow<u64>($t33, $t34)
+ 68: $t0 := read_ref($t32)
+ 69: return $t0
+}
+
+============ after LiveVarAnalysisProcessor: ================
+
+[variant baseline]
+fun m::foo(): u64 {
+     var $t0: u64
+     var $t1: vector<u64>
+     var $t2: &mut vector<u64>
+     var $t3: u64
+     var $t4: &mut vector<u64>
+     var $t5: u64
+     var $t6: u64
+     var $t7: &vector<u64>
+     var $t8: bool
+     var $t9: bool
+     var $t10: bool
+     var $t11: &u64
+     var $t12: &u64
+     var $t13: &vector<u64>
+     var $t14: u64
+     var $t15: u64
+     var $t16: u64
+     var $t17: u64
+     var $t18: u64
+     var $t19: u64
+     var $t20: u64
+     var $t21: bool
+     var $t22: bool
+     var $t23: &u64
+     var $t24: &u64
+     var $t25: &vector<u64>
+     var $t26: u64
+     var $t27: u64
+     var $t28: u64
+     var $t29: u64
+     var $t30: u64
+     var $t31: u64
+     var $t32: &u64
+     var $t33: &vector<u64>
+     var $t34: u64
+     # live vars:
+  0: $t1 := ["1", "2", "3"]
+     # live vars: $t1
+  1: $t2 := borrow_local($t1)
+     # live vars: $t2
+  2: $t4 := infer($t2)
+     # live vars: $t2, $t4
+  3: $t5 := 0
+     # live vars: $t2, $t4, $t5
+  4: $t7 := freeze_ref(implicit)($t4)
+     # live vars: $t2, $t4, $t5, $t7
+  5: $t6 := vector::length<u64>($t7)
+     # live vars: $t2, $t4, $t5, $t6
+  6: label L0
+     # live vars: $t2, $t4, $t5, $t6
+  7: $t8 := <($t5, $t6)
+     # live vars: $t2, $t4, $t5, $t6, $t8
+  8: if ($t8) goto 9 else goto 27
+     # live vars: $t2, $t4, $t5, $t6
+  9: label L2
+     # live vars: $t2, $t4, $t5, $t6
+ 10: $t13 := freeze_ref(implicit)($t4)
+     # live vars: $t2, $t4, $t5, $t6, $t13
+ 11: $t12 := vector::borrow<u64>($t13, $t5)
+     # live vars: $t2, $t4, $t5, $t6, $t12
+ 12: $t11 := infer($t12)
+     # live vars: $t2, $t4, $t5, $t6, $t11
+ 13: $t14 := read_ref($t11)
+     # live vars: $t2, $t4, $t5, $t6, $t14
+ 14: $t15 := 1
+     # live vars: $t2, $t4, $t5, $t6, $t14, $t15
+ 15: $t10 := >($t14, $t15)
+     # live vars: $t2, $t4, $t5, $t6, $t10
+ 16: $t9 := !($t10)
+     # live vars: $t2, $t4, $t5, $t6, $t9
+ 17: if ($t9) goto 18 else goto 21
+     # live vars: $t2, $t4, $t5, $t6
+ 18: label L5
+     # live vars: $t2, $t4, $t5, $t6
+ 19: goto 31
+     # live vars: $t2, $t4, $t5, $t6
+ 20: goto 22
+     # live vars: $t2, $t4, $t5, $t6
+ 21: label L6
+     # live vars: $t2, $t4, $t5, $t6
+ 22: label L7
+     # live vars: $t2, $t4, $t5, $t6
+ 23: $t17 := 1
+     # live vars: $t2, $t4, $t5, $t6, $t17
+ 24: $t16 := +($t5, $t17)
+     # live vars: $t2, $t4, $t6, $t16
+ 25: $t5 := infer($t16)
+     # live vars: $t2, $t4, $t5, $t6
+ 26: goto 29
+     # live vars: $t2, $t4, $t5, $t6
+ 27: label L3
+     # live vars: $t2, $t4, $t5, $t6
+ 28: goto 31
+     # live vars: $t2, $t4, $t5, $t6
+ 29: label L4
+     # live vars: $t2, $t4, $t5, $t6
+ 30: goto 6
+     # live vars: $t2, $t4, $t5, $t6
+ 31: label L1
+     # live vars: $t2, $t4, $t5, $t6
+ 32: $t18 := infer($t5)
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 33: $t20 := 1
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t20
+ 34: $t19 := +($t5, $t20)
+     # live vars: $t2, $t4, $t6, $t18, $t19
+ 35: $t5 := infer($t19)
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 36: label L8
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 37: $t21 := <($t5, $t6)
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t21
+ 38: if ($t21) goto 39 else goto 59
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 39: label L10
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 40: $t25 := freeze_ref(implicit)($t4)
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t25
+ 41: $t24 := vector::borrow<u64>($t25, $t5)
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t24
+ 42: $t23 := infer($t24)
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t23
+ 43: $t26 := read_ref($t23)
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t26
+ 44: $t27 := 1
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t26, $t27
+ 45: $t22 := >($t26, $t27)
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t22
+ 46: if ($t22) goto 47 else goto 53
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 47: label L13
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 48: vector::swap<u64>($t4, $t18, $t5)
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 49: $t29 := 1
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t29
+ 50: $t28 := +($t18, $t29)
+     # live vars: $t2, $t4, $t5, $t6, $t28
+ 51: $t18 := infer($t28)
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 52: goto 54
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 53: label L14
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 54: label L15
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 55: $t31 := 1
+     # live vars: $t2, $t4, $t5, $t6, $t18, $t31
+ 56: $t30 := +($t5, $t31)
+     # live vars: $t2, $t4, $t6, $t18, $t30
+ 57: $t5 := infer($t30)
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 58: goto 61
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 59: label L11
+     # live vars: $t2, $t18
+ 60: goto 63
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 61: label L12
+     # live vars: $t2, $t4, $t5, $t6, $t18
+ 62: goto 36
+     # live vars: $t2, $t18
+ 63: label L9
+     # live vars: $t2, $t18
+ 64: $t3 := infer($t18)
+     # live vars: $t2
+ 65: $t33 := freeze_ref(implicit)($t2)
+     # live vars: $t33
+ 66: $t34 := 0
+     # live vars: $t33, $t34
+ 67: $t32 := vector::borrow<u64>($t33, $t34)
+     # live vars: $t32
+ 68: $t0 := read_ref($t32)
+     # live vars: $t0
+ 69: return $t0
+}
diff --git a/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.move b/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.move
new file mode 100644
index 0000000000000..89bc2d57d9728
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/live-var/mut_inline_typed.move
@@ -0,0 +1,34 @@
+module 0x42::m {
+
+    use 0x1::vector;
+
+    inline fun partition<Element>(
+        v: &mut vector<Element>,
+        pred: |&Element|bool
+    ): u64 {
+        let i = 0;
+        let len = vector::length(v);
+        while (i < len) {
+            if (!pred(vector::borrow(v, i))) break;
+            i = i + 1;
+        };
+        let p = i;
+        i = i + 1;
+        while (i < len) {
+            if (pred(vector::borrow(v, i))) {
+                vector::swap(v, p, i);
+                p = p + 1;
+            };
+            i = i + 1;
+        };
+        p
+    }
+
+    fun foo(): u64 {
+        let v = vector[1,2,3];
+        let r = &mut v;
+        partition(r, |e: &u64| *e > 1);
+        *vector::borrow(r, 0)
+    }
+
+}
diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.exp
new file mode 100644
index 0000000000000..39832e3a20b40
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.exp
@@ -0,0 +1,80 @@
+============ initial bytecode ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+     var $t1: u64
+     var $t2: u64
+     var $t3: u64
+  0: $t2 := 10
+  1: $t1 := infer($t2)
+  2: $t3 := infer($t1)
+  3: $t0 := 3
+  4: return $t0
+}
+
+============ after DeadStoreElimination: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+     var $t1: u64 [unused]
+     var $t2: u64 [unused]
+     var $t3: u64 [unused]
+  0: $t0 := 3
+  1: return $t0
+}
+
+============ after VariableCoalescingAnnotator: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+     var $t1: u64 [unused]
+     var $t2: u64 [unused]
+     var $t3: u64 [unused]
+     # live vars:
+     # events: b:$t0
+  0: $t0 := 3
+     # live vars: $t0
+     # events: e:$t0
+  1: return $t0
+}
+
+============ after VariableCoalescingTransformer: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+     var $t1: u64 [unused]
+     var $t2: u64 [unused]
+     var $t3: u64 [unused]
+  0: $t0 := 3
+  1: return $t0
+}
+
+============ after DeadStoreElimination: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+     var $t1: u64 [unused]
+     var $t2: u64 [unused]
+     var $t3: u64 [unused]
+  0: $t0 := 3
+  1: return $t0
+}
+
+
+============ disassembled file-format ==================
+// Move bytecode v7
+module 42.Test {
+
+
+public test(): u64 /* def_idx: 0 */ {
+B0:
+	0: LdU64(3)
+	1: Ret
+}
+}
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.move b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.move
new file mode 100644
index 0000000000000..9d529bc3acaab
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.move
@@ -0,0 +1,9 @@
+module 0x42::Test {
+    inline fun foo(f:|u64| u64, x: u64): u64 {
+        f(x)
+    }
+
+    public fun test(): u64 {
+        foo(|_: u64| 3, 10)
+    }
+}
diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.opt.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.opt.exp
new file mode 100644
index 0000000000000..fdf29d55e2bf7
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/inlining1_typed.opt.exp
@@ -0,0 +1,62 @@
+============ initial bytecode ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+  0: $t0 := 3
+  1: return $t0
+}
+
+============ after DeadStoreElimination: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+  0: $t0 := 3
+  1: return $t0
+}
+
+============ after VariableCoalescingAnnotator: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+     # live vars:
+     # events: b:$t0
+  0: $t0 := 3
+     # live vars: $t0
+     # events: e:$t0
+  1: return $t0
+}
+
+============ after VariableCoalescingTransformer: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+  0: $t0 := 3
+  1: return $t0
+}
+
+============ after DeadStoreElimination: ================
+
+[variant baseline]
+public fun Test::test(): u64 {
+     var $t0: u64
+  0: $t0 := 3
+  1: return $t0
+}
+
+
+============ disassembled file-format ==================
+// Move bytecode v7
+module 42.Test {
+
+
+public test(): u64 /* def_idx: 0 */ {
+B0:
+	0: LdU64(3)
+	1: Ret
+}
+}
+============ bytecode verification succeeded ========
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam2_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam2_typed.exp
new file mode 100644
index 0000000000000..9387f12a2dcb1
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam2_typed.exp
@@ -0,0 +1,29 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-10:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:22
+-   │
+- 7 │         assert!(foo(|_: u64| 3, |_: u64| 10, 10, 100) == 13, 0);
+-   │                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:34
+-   │
+- 7 │         assert!(foo(|_: u64| 3, |_: u64| 10, 10, 100) == 13, 0);
+-   │                                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 12-12:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam2_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam2_typed.move
new file mode 100644
index 0000000000000..6ef383a7b98a8
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam2_typed.move
@@ -0,0 +1,12 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64| u64, g: |u64| u64, x: u64, _: u64): u64 {
+        f(x) + g(x)
+    }
+
+    public fun test() {
+        assert!(foo(|_: u64| 3, |_: u64| 10, 10, 100) == 13, 0);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam_typed.exp
new file mode 100644
index 0000000000000..6b250eae787df
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam_typed.exp
@@ -0,0 +1,41 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-10:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:22
+-   │
+- 7 │         assert!(foo(|_: u64, _: u64| 3, |_: u64, _: u64| 10, 10, 100) == 13, 0);
+-   │                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:30
+-   │
+- 7 │         assert!(foo(|_: u64, _: u64| 3, |_: u64, _: u64| 10, 10, 100) == 13, 0);
+-   │                              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:42
+-   │
+- 7 │         assert!(foo(|_: u64, _: u64| 3, |_: u64, _: u64| 10, 10, 100) == 13, 0);
+-   │                                          ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:50
+-   │
+- 7 │         assert!(foo(|_: u64, _: u64| 3, |_: u64, _: u64| 10, 10, 100) == 13, 0);
+-   │                                                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 12-12:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam_typed.move
new file mode 100644
index 0000000000000..72091d0cdfb9c
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_noparam_typed.move
@@ -0,0 +1,12 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64, u64| u64, g: |u64, u64| u64, x: u64, _y: u64): u64 {
+        f(x, _y) + g(x, _y)
+    }
+
+    public fun test() {
+        assert!(foo(|_: u64, _: u64| 3, |_: u64, _: u64| 10, 10, 100) == 13, 0);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_typed.exp
new file mode 100644
index 0000000000000..f74668967d29c
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_typed.exp
@@ -0,0 +1,41 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-10:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:22
+-   │
+- 7 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100) == 110, 0);
+-   │                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:30
+-   │
+- 7 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100) == 110, 0);
+-   │                              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:42
+-   │
+- 7 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100) == 110, 0);
+-   │                                          ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:50
+-   │
+- 7 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100) == 110, 0);
+-   │                                                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 12-12:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_typed.move
new file mode 100644
index 0000000000000..da836f0f58d51
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991_typed.move
@@ -0,0 +1,12 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64, u64| u64, g: |u64, u64| u64, x: u64, _y: u64): u64 {
+        f(x, _y) + g(x, _y)
+    }
+
+    public fun test() {
+        assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100) == 110, 0);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991a_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991a_typed.exp
new file mode 100644
index 0000000000000..7539b24f5e319
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991a_typed.exp
@@ -0,0 +1,65 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-14:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:22
+-   │
+- 9 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y,
+-   │                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:30
+-   │
+- 9 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y,
+-   │                              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:42
+-   │
+- 9 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y,
+-   │                                          ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:50
+-   │
+- 9 │         assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y,
+-   │                                                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:10:7
+-    │
+- 10 │         |a: u64, _b: u64| a, |_c: u64, d: u64| d,
+-    │          ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:10:15
+-    │
+- 10 │         |a: u64, _b: u64| a, |_c: u64, d: u64| d,
+-    │                  ^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:10:28
+-    │
+- 10 │         |a: u64, _b: u64| a, |_c: u64, d: u64| d,
+-    │                               ^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:10:37
+-    │
+- 10 │         |a: u64, _b: u64| a, |_c: u64, d: u64| d,
+-    │                                        ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 16-16:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991a_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991a_typed.move
new file mode 100644
index 0000000000000..28f6de500dc78
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991a_typed.move
@@ -0,0 +1,16 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64, u64| u64, g: |u64, u64| u64,
+	h:|u64, u64| u64, i: |u64, u64| u64,
+	x: u64, y: u64): u64 {
+            f(x, y) + g(x, y) + h(x, y) + i(x, y)
+    }
+
+    public fun test() {
+        assert!(foo(|x: u64, _: u64| x, |_: u64, y: u64| y,
+	    |a: u64, _b: u64| a, |_c: u64, d: u64| d,
+	    10, 100) == 220, 0);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991b_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991b_typed.exp
new file mode 100644
index 0000000000000..9c60f12f7e43e
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991b_typed.exp
@@ -0,0 +1,29 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-11:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:22
+-   │
+- 7 │         assert!(foo(|_: u64, y: u64| y,
+-   │                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:30
+-   │
+- 7 │         assert!(foo(|_: u64, y: u64| y,
+-   │                              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 13-13:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991b_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991b_typed.move
new file mode 100644
index 0000000000000..29521a95ac5c6
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991b_typed.move
@@ -0,0 +1,13 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(g: |u64, u64| u64, x: u64, _y: u64): u64 {
+        g(x, _y)
+    }
+
+    public fun test() {
+        assert!(foo(|_: u64, y: u64| y,
+	    10, 100) == 100, 0);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991c_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991c_typed.exp
new file mode 100644
index 0000000000000..49eacd34742fd
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991c_typed.exp
@@ -0,0 +1,41 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-11:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:22
+-   │
+- 7 │         assert!(foo(|_: u64, y: u64, _: u64, q: u64| y + q,
+-   │                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:30
+-   │
+- 7 │         assert!(foo(|_: u64, y: u64, _: u64, q: u64| y + q,
+-   │                              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:38
+-   │
+- 7 │         assert!(foo(|_: u64, y: u64, _: u64, q: u64| y + q,
+-   │                                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:46
+-   │
+- 7 │         assert!(foo(|_: u64, y: u64, _: u64, q: u64| y + q,
+-   │                                              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 13-13:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991c_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991c_typed.move
new file mode 100644
index 0000000000000..71ff4b6e6ebc7
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/bug_10991c_typed.move
@@ -0,0 +1,13 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(g: |u64, u64, u64, u64| u64, x: u64, y: u64, z: u64, q:u64): u64 {
+        g(x, y, z, q)
+    }
+
+    public fun test() {
+        assert!(foo(|_: u64, y: u64, _: u64, q: u64| y + q,
+	    10, 100, 1000, 10000) == 10100, 0);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_some_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_some_typed.exp
new file mode 100644
index 0000000000000..11c5e581bd202
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_some_typed.exp
@@ -0,0 +1,35 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-13:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:15
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z| x*z, |_, y: u64, _| y, 1, 10, 100, 1000);
+-   │                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:23
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z| x*z, |_, y: u64, _| y, 1, 10, 100, 1000);
+-   │                          ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:43
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z| x*z, |_, y: u64, _| y, 1, 10, 100, 1000);
+-   │                                              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 15-15:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_some_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_some_typed.move
new file mode 100644
index 0000000000000..ed65160f1f2b6
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_some_typed.move
@@ -0,0 +1,15 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64, u64, u64| u64, g: |u64, u64, u64| u64, x: u64, _: u64, y: u64, z: u64): u64 {
+	let r1 = f({x = x + 1; x}, {y = y + 1; y}, {z = z + 1; z});
+	let r2 = g({x = x + 1; x}, {y = y + 1; y}, {z  = z + 1 ; z});
+	r1 + r2 + 3*x + 5*y + 7*z
+    }
+
+    public fun test() {
+	let r = foo(|x: u64, _: u64, z| x*z, |_, y: u64, _| y, 1, 10, 100, 1000);
+        assert!(r == 9637, r);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_typed.exp
new file mode 100644
index 0000000000000..8059ac92a5e46
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_typed.exp
@@ -0,0 +1,53 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-13:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:15
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z: u64| x*z, |_: u64, y: u64, _: u64| y, 1, 10, 100, 1000);
+-   │                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:23
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z: u64| x*z, |_: u64, y: u64, _: u64| y, 1, 10, 100, 1000);
+-   │                          ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:31
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z: u64| x*z, |_: u64, y: u64, _: u64| y, 1, 10, 100, 1000);
+-   │                                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:45
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z: u64| x*z, |_: u64, y: u64, _: u64| y, 1, 10, 100, 1000);
+-   │                                                ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:53
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z: u64| x*z, |_: u64, y: u64, _: u64| y, 1, 10, 100, 1000);
+-   │                                                        ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:61
+-   │
+- 9 │     let r = foo(|x: u64, _: u64, z: u64| x*z, |_: u64, y: u64, _: u64| y, 1, 10, 100, 1000);
+-   │                                                                ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 15-15:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_typed.move
new file mode 100644
index 0000000000000..d3f74b0d6d903
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/eval_ignored_param_typed.move
@@ -0,0 +1,15 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64, u64, u64| u64, g: |u64, u64, u64| u64, x: u64, _: u64, y: u64, z: u64): u64 {
+	let r1 = f({x = x + 1; x}, {y = y + 1; y}, {z = z + 1; z});
+	let r2 = g({x = x + 1; x}, {y = y + 1; y}, {z  = z + 1 ; z});
+	r1 + r2 + 3*x + 5*y + 7*z
+    }
+
+    public fun test() {
+	let r = foo(|x: u64, _: u64, z: u64| x*z, |_: u64, y: u64, _: u64| y, 1, 10, 100, 1000);
+        assert!(r == 9637, r);
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/generics_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/generics_typed.exp
new file mode 100644
index 0000000000000..af1df06d30d62
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/generics_typed.exp
@@ -0,0 +1,23 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
++ processed 2 tasks
+= 
+- task 0 'publish'. lines 1-20:
+- Error: error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:14:27
+-    │
+- 14 │         foreach<u64>(&v, |e: &u64| sum = sum + *e);
+-    │                           ^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+= task 1 'run'. lines 22-22:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
++ return values: 6
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/generics_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/generics_typed.move
new file mode 100644
index 0000000000000..15d9a5f191409
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/generics_typed.move
@@ -0,0 +1,22 @@
+//# publish
+module 0x42::Test {
+    use std::vector;
+
+    public inline fun foreach<X>(v: &vector<X>, action: |&X|) {
+        let i = 0;
+        while (i < vector::length(v)) {
+            action(vector::borrow(v, i));
+            i = i + 1;
+        }
+    }
+
+    public fun test(): u64 {
+        let v = vector[1u64, 2, 3];
+        let sum = 0;
+        foreach<u64>(&v, |e: &u64| sum = sum + *e);
+        sum
+    }
+
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/lambda_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/lambda_typed.exp
new file mode 100644
index 0000000000000..b1f5feed168f0
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/lambda_typed.exp
@@ -0,0 +1,29 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
++ processed 2 tasks
+= 
+- task 0 'publish'. lines 1-11:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:16
+-   │
+- 7 │         apply(|x: u64, y: u64| x + y, 1, 2)
+-   │                ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:24
+-   │
+- 7 │         apply(|x: u64, y: u64| x + y, 1, 2)
+-   │                        ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+= task 1 'run'. lines 13-13:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
++ return values: 3
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/lambda_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/lambda_typed.move
new file mode 100644
index 0000000000000..6d28935c398ff
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/lambda_typed.move
@@ -0,0 +1,13 @@
+//# publish
+module 0x42::Test {
+
+    public inline fun apply(f: |u64, u64|u64, x: u64, y: u64): u64 {
+        f(x, y)
+    }
+
+    public fun test(): u64 {
+        apply(|x: u64, y: u64| x + y, 1, 2)
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/masking_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/masking_typed.exp
new file mode 100644
index 0000000000000..0c99da555042f
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/masking_typed.exp
@@ -0,0 +1,41 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
++ processed 2 tasks
+= 
+- task 0 'publish'. lines 1-10:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:14
+-   │
+- 7 │         foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100)
+-   │              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:22
+-   │
+- 7 │         foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100)
+-   │                      ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:34
+-   │
+- 7 │         foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100)
+-   │                                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:42
+-   │
+- 7 │         foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100)
+-   │                                          ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+= task 1 'run'. lines 12-12:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
++ return values: 110
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/masking_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/masking_typed.move
new file mode 100644
index 0000000000000..5681fa39b26b1
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/masking_typed.move
@@ -0,0 +1,12 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64, u64| u64, g: |u64, u64| u64, x: u64, _y: u64): u64 {
+        f(x, _y) + g(x, _y)
+    }
+
+    public fun main(): u64 {
+        foo(|x: u64, _: u64| x, |_: u64, y: u64| y, 10, 100)
+    }
+}
+
+//# run 0x42::Test::main
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.exp
new file mode 100644
index 0000000000000..a4bb458cc6f57
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.exp
@@ -0,0 +1,44 @@
+comparison between v1 and v2 failed:
+= processed 2 tasks
+= 
+= task 0 'publish'. lines 1-29:
+- Error: error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:17:30
++ Error: compilation errors:
++  error: a reference is expected but `_` was provided
++    ┌─ TEMPFILE:24:82
+=    │
+- 17 │         for_each_ref_mut(v, |elem: &mut Elem<K, V>| {
+-    │                              ^^^^^^^^^^^^^^^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
++ 24 │         assert!(elem_for_each_ref(&mut vector[Elem{k:1, v:2}], |x: u64, y: u64| *x + *y) == 3, 0)
++    │                                                                                  ^
+= 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:24:65
++ error: a reference is expected but `_` was provided
++    ┌─ TEMPFILE:24:87
+=    │
+= 24 │         assert!(elem_for_each_ref(&mut vector[Elem{k:1, v:2}], |x: u64, y: u64| *x + *y) == 3, 0)
+-    │                                                                 ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
++    │                                                                                       ^
+= 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:24:73
++ error: cannot pass `|(u64, u64)|integer` to a function which expects argument of type `|(&integer, &mut integer)|u64`
++    ┌─ TEMPFILE:24:64
+=    │
+= 24 │         assert!(elem_for_each_ref(&mut vector[Elem{k:1, v:2}], |x: u64, y: u64| *x + *y) == 3, 0)
+-    │                                                                         ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
++    │                                                                ^^^^^^^^^^^^^^^^^^^^^^^^
+= 
+= 
+= 
+= task 1 'run'. lines 31-31:
+= Error: Function execution failed with VMError: {
+=     major_status: LINKER_ERROR,
+=     sub_status: None,
+=     location: undefined,
+=     indices: redacted,
+=     offsets: redacted,
+= }
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.move
new file mode 100644
index 0000000000000..425abd583731f
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.move
@@ -0,0 +1,31 @@
+//# publish
+module 0x42::Test {
+    use 0x1::vector as V;
+
+    // Can't use that from V because of precompiled import in transactional tests
+    // TODO: we need to fix this
+    public inline fun for_each_ref_mut<Element>(v: &mut vector<Element>, f: |&mut Element|) {
+        let i = 0;
+        while (i < V::length(v)) {
+            f(V::borrow_mut(v, i));
+            i = i + 1
+        }
+    }
+    struct Elem<K, V> has drop { k: K, v: V }
+
+    // Checks a multi-mutality scenario.
+    public inline fun elem_for_each_ref<K,V>(v: &mut vector<Elem<K,V>>, f: |&K, &mut V|u64): u64 {
+        let result = 0;
+        for_each_ref_mut(v, |elem: &mut Elem<K, V>| {
+            let elem: &mut Elem<K, V> = elem; // Checks whether scoping is fine
+            result = result + f(&elem.k, &mut elem.v);
+        });
+        result
+    }
+
+    public fun test() {
+        assert!(elem_for_each_ref(&mut vector[Elem{k:1, v:2}], |x: u64, y: u64| *x + *y) == 3, 0)
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_module_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_module_typed.exp
new file mode 100644
index 0000000000000..c32e5f2c5983d
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_module_typed.exp
@@ -0,0 +1,41 @@
+comparison between v1 and v2 failed:
+- processed 3 tasks
++ processed 3 tasks
+= 
+- task 1 'publish'. lines 8-15:
+- Error: error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE1:12:23
+-    │
+- 12 │         Test1::apply(|x: u64, y: u64| x + y, 1, Test1::apply(|x: u64, y: u64| x * y, 2, 1))
+-    │                       ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE1:12:31
+-    │
+- 12 │         Test1::apply(|x: u64, y: u64| x + y, 1, Test1::apply(|x: u64, y: u64| x * y, 2, 1))
+-    │                               ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE1:12:63
+-    │
+- 12 │         Test1::apply(|x: u64, y: u64| x + y, 1, Test1::apply(|x: u64, y: u64| x * y, 2, 1))
+-    │                                                               ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE1:12:71
+-    │
+- 12 │         Test1::apply(|x: u64, y: u64| x + y, 1, Test1::apply(|x: u64, y: u64| x * y, 2, 1))
+-    │                                                                       ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+= task 2 'run'. lines 17-17:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
++ return values: 3
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_module_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_module_typed.move
new file mode 100644
index 0000000000000..857dec4843233
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_module_typed.move
@@ -0,0 +1,17 @@
+//# publish
+module 0x42::Test1 {
+    public inline fun apply(f: |u64, u64|u64, x: u64, y: u64): u64 {
+        f(x, y)
+    }
+}
+
+//# publish
+module 0x42::Test {
+    use 0x42::Test1;
+
+    public fun test(): u64 {
+        Test1::apply(|x: u64, y: u64| x + y, 1, Test1::apply(|x: u64, y: u64| x * y, 2, 1))
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_typed.exp
new file mode 100644
index 0000000000000..fec36834b3846
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_typed.exp
@@ -0,0 +1,41 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
++ processed 2 tasks
+= 
+- task 0 'publish'. lines 1-11:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:16
+-   │
+- 7 │         apply(|x: u64, y: u64| x + y, 1, apply(|x: u64, y: u64| x * y, 2, 1))
+-   │                ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:24
+-   │
+- 7 │         apply(|x: u64, y: u64| x + y, 1, apply(|x: u64, y: u64| x * y, 2, 1))
+-   │                        ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:49
+-   │
+- 7 │         apply(|x: u64, y: u64| x + y, 1, apply(|x: u64, y: u64| x * y, 2, 1))
+-   │                                                 ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:57
+-   │
+- 7 │         apply(|x: u64, y: u64| x + y, 1, apply(|x: u64, y: u64| x * y, 2, 1))
+-   │                                                         ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+= task 1 'run'. lines 13-13:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
++ return values: 3
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_typed.move
new file mode 100644
index 0000000000000..e31696ac9e662
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/nested_lambda_typed.move
@@ -0,0 +1,13 @@
+//# publish
+module 0x42::Test {
+
+    public inline fun apply(f: |u64, u64|u64, x: u64, y: u64): u64 {
+        f(x, y)
+    }
+
+    public fun test(): u64 {
+        apply(|x: u64, y: u64| x + y, 1, apply(|x: u64, y: u64| x * y, 2, 1))
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/options_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/options_typed.exp
new file mode 100644
index 0000000000000..73a1637536f2e
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/options_typed.exp
@@ -0,0 +1,23 @@
+comparison between v1 and v2 failed:
+- processed 3 tasks
++ processed 3 tasks
+= 
+- task 1 'publish'. lines 15-25:
+- Error: error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE1:21:34
+-    │
+- 21 │         let x = map_opt::map(t, |e: u64| e + 1);
+-    │                                  ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+= task 2 'run'. lines 27-27:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
++ return values: 2
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/options_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/options_typed.move
new file mode 100644
index 0000000000000..943b85da6dff2
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/options_typed.move
@@ -0,0 +1,27 @@
+//# publish
+module 0x42::map_opt {
+    use std::option;
+    /// Maps the content of an option
+    public inline fun map<Element, OtherElement>(t: option::Option<Element>, f: |Element|OtherElement): option::Option<OtherElement> {
+        if (option::is_some(&t)) {
+            option::some(f(option::extract(&mut t)))
+        } else {
+            option::none()
+        }
+    }
+
+}
+
+//# publish
+module 0x42::Test {
+    use std::option;
+    use 0x42::map_opt;
+
+    public fun test(): u64 {
+        let t = option::some(1);
+        let x = map_opt::map(t, |e: u64| e + 1);
+        option::extract(&mut x)
+    }
+}
+
+//# run 0x42::Test::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_param_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_param_typed.exp
new file mode 100644
index 0000000000000..d14795838f0db
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_param_typed.exp
@@ -0,0 +1,43 @@
+comparison between v1 and v2 failed:
+= processed 2 tasks
+= 
+= task 0 'publish'. lines 1-46:
+- Error: error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:11:14
++ warning: Unused assignment to `x`. Consider removing or prefixing with an underscore: `_x`
++    ┌─ TEMPFILE:23:17
+=    │
+- 11 │         foo(|y: u64| {
+-    │              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
++ 23 │         let x = q;
++    │                 ^
+= 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:16:15
+-    │
+- 16 │         foo2(|y: u64| {
+-    │               ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+= 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:24:14
+-    │
+- 24 │         foo(|y: u64| {
+-    │              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+= 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:29:15
+-    │
+- 29 │         foo2(|y: u64| {
+-    │               ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 48-48:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_param_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_param_typed.move
new file mode 100644
index 0000000000000..1ef82d15fcb89
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_param_typed.move
@@ -0,0 +1,48 @@
+//# publish
+module 0x42::Test {
+
+    public inline fun foo(f:|u64|, x:u64) {
+        f(x);
+    }
+
+    public inline fun foo2(f:|u64|, x:u64) {
+        let x = x;
+        f(x);
+    }
+
+    public fun test_shadowing(x: u64) {
+        foo(|y: u64| {
+            x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, 3);
+        assert!(x == 3, 0);
+
+        foo2(|y: u64| {
+            x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, 5);
+        assert!(x == 5, 0)
+    }
+
+    public fun test_shadowing2(q: u64) {
+        let x = q;
+        foo(|y: u64| {
+            x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, 3);
+        assert!(x == 3, 0);
+
+        foo2(|y: u64| {
+            x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        }, 5);
+        assert!(x == 5, 0)
+    }
+
+    fun test_shadowing_entry() {
+        test_shadowing(1);
+        test_shadowing2(1)
+    }
+}
+
+//# run 0x42::Test::test_shadowing_entry
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_typed.exp
new file mode 100644
index 0000000000000..8eeb84f42bddb
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_typed.exp
@@ -0,0 +1,25 @@
+comparison between v1 and v2 failed:
+= processed 2 tasks
+= 
+= task 0 'publish'. lines 1-19:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:14
++ warning: Unused assignment to `x`. Consider removing or prefixing with an underscore: `_x`
++   ┌─ TEMPFILE:8:17
+=   │
+- 9 │         foo(|y: u64| {
+-   │              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
++ 8 │         let x = 1;
++   │                 ^
+= 
+= 
+= 
+- task 1 'run'. lines 21-21:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_typed.move
new file mode 100644
index 0000000000000..37a421b27f40f
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_renamed_typed.move
@@ -0,0 +1,21 @@
+//# publish
+module 0x42::Test {
+
+    public inline fun foo(f:|u64|) {
+        let x = 3;
+        f(x);
+    }
+
+    public fun test_shadowing() {
+        let x = 1;
+        foo(|y: u64| {
+            x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        });
+        assert!(x == 3, 0)
+    }
+
+
+}
+
+//# run 0x42::Test::test_shadowing
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_typed.exp
new file mode 100644
index 0000000000000..880f900af4c5d
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_typed.exp
@@ -0,0 +1,23 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-19:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:9:14
+-   │
+- 9 │         foo(|y: u64| {
+-   │              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 21-21:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_typed.move
new file mode 100644
index 0000000000000..4490f8ee8b68b
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/shadowing_typed.move
@@ -0,0 +1,21 @@
+//# publish
+module 0x42::Test {
+
+    public inline fun foo(f:|u64|) {
+        let _x = 3;
+        f(_x);
+    }
+
+    public fun test_shadowing() {
+        let _x = 1;
+        foo(|y: u64| {
+            _x = y  // We expect this to assign 3 via foo if renaming works correctly. If not it would
+                    // have the value 1.
+        });
+        assert!(_x == 3, 0)
+    }
+
+
+}
+
+//# run 0x42::Test::test_shadowing
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/simple_map_keys_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/simple_map_keys_typed.exp
new file mode 100644
index 0000000000000..4cd3899eb2420
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/simple_map_keys_typed.exp
@@ -0,0 +1,37 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-47:
+- Error: error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:13:29
+-    │
+- 13 │         map_ref(&map.data, |e: &Element<Key, Value>| {
+-    │                             ^^^^^^^^^^^^^^^^^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E04010]: cannot infer type
+-    ┌─ TEMPFILE:14:13
+-    │
+- 13 │         map_ref(&map.data, |e: &Element<Key, Value>| {
+-    │                             - Could not infer the type before field access. Try annotating here
+- 14 │             e.key
+-    │             ^^^^^ Unbound field 'key'
+- 
+- error[E01013]: unsupported language construct
+-    ┌─ TEMPFILE:22:26
+-    │
+- 22 │         for_each_ref(v, |elem: &Element| vector::push_back(&mut result, f(elem)));
+-    │                          ^^^^^^^^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 49-49:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/misc/simple_map_keys_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/simple_map_keys_typed.move
new file mode 100644
index 0000000000000..9c6d4449d6e93
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/misc/simple_map_keys_typed.move
@@ -0,0 +1,49 @@
+//# publish
+module 0x42::simple_map {
+    use 0x1::vector;
+
+    struct SimpleMap<Key, Value> has copy, drop, store {
+        data: vector<Element<Key, Value>>,
+    }
+
+    struct Element<Key, Value> has copy, drop, store {
+        key: Key,
+        value: Value,
+    }
+
+
+    /// Return all keys in the map. This requires keys to be copyable.
+    public fun keys<Key: copy, Value>(map: &SimpleMap<Key, Value>): vector<Key> {
+        map_ref(&map.data, |e: &Element<Key, Value>| {
+            e.key
+        })
+    }
+
+   public inline fun map_ref<Element, NewElement>(
+        v: &vector<Element>,
+        f: |&Element|NewElement
+    ): vector<NewElement> {
+        let result = vector<NewElement>[];
+        for_each_ref(v, |elem: &Element| vector::push_back(&mut result, f(elem)));
+        result
+    }
+
+    public inline fun for_each_ref<Element>(v: &vector<Element>, f: |&Element|) {
+        let i = 0;
+        let len = vector::length(v);
+        while (i < len) {
+            f(vector::borrow(v, i));
+            i = i + 1
+        }
+    }
+
+    public fun run() {
+        let entry = Element{key: 1, value: 2};
+        let data = vector[entry, entry, entry];
+        let map = SimpleMap{data};
+        let keys = keys(&map);
+        assert!(keys == vector[1, 1, 1], 33);
+    }
+}
+
+//# run  0x42::simple_map::run
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.move
new file mode 100644
index 0000000000000..d3893ad8b24fc
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.move
@@ -0,0 +1,13 @@
+//# publish
+module 0xc0ffee::m {
+    inline fun call(f: |u64|u64): u64 {
+        f(2)
+    }
+
+    public fun test(): u64 {
+        let x = 1;
+        x + call(|_x: u64| {x = x + 1; x}) + call(|_x: u64| {x = x + 7; x})
+    }
+}
+
+//# run 0xc0ffee::m::test
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.operator-eval-lang-1.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.operator-eval-lang-1.exp
new file mode 100644
index 0000000000000..4c99c8a28e797
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.operator-eval-lang-1.exp
@@ -0,0 +1,52 @@
+comparison between v1 and v2 failed:
+= processed 2 tasks
+= 
+= task 0 'publish'. lines 1-11:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:8:19
++ Error: compilation errors:
++  error: A sequence within an operand of binary operation `+` can obscure program logic and is not allowed by this compiler.
++   ┌─ TEMPFILE:8:9
+=   │
+= 8 │         x + call(|_x: u64| {x = x + 1; x}) + call(|_x: u64| {x = x + 7; x})
+-   │                   ^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
++   │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   │         │                  │
++   │         │                  non-empty sequence
++   │         binary operation `+`
++   │
++   = To compile this code, either:
++   = 1. upgrade to language version 2.0 or later (which uses strict left-to-right evaluation order),
++   = 2. rewrite the code to remove sequences from directly within binary operations,
++   =    e.g., save intermediate results providing explicit order.
++   = In either of these cases, please ensure to check the code does what you expect it to, because of changed semantics.
+= 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:8:52
++ error: A sequence within an operand of binary operation `+` can obscure program logic and is not allowed by this compiler.
++   ┌─ TEMPFILE:8:9
+=   │
+= 8 │         x + call(|_x: u64| {x = x + 1; x}) + call(|_x: u64| {x = x + 7; x})
+-   │                                                    ^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
++   │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   │         │                                                   │
++   │         │                                                   non-empty sequence
++   │         binary operation `+`
++   │
++   = To compile this code, either:
++   = 1. upgrade to language version 2.0 or later (which uses strict left-to-right evaluation order),
++   = 2. rewrite the code to remove sequences from directly within binary operations,
++   =    e.g., save intermediate results providing explicit order.
++   = In either of these cases, please ensure to check the code does what you expect it to, because of changed semantics.
+= 
+= 
+= 
+= task 1 'run'. lines 13-13:
+= Error: Function execution failed with VMError: {
+=     major_status: LINKER_ERROR,
+=     sub_status: None,
+=     location: undefined,
+=     indices: redacted,
+=     offsets: redacted,
+= }
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.operator-eval-lang-2.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.operator-eval-lang-2.exp
new file mode 100644
index 0000000000000..42fb9148cc13a
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/operator_eval/op_with_side_effect_49_typed.operator-eval-lang-2.exp
@@ -0,0 +1,29 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
++ processed 2 tasks
+= 
+- task 0 'publish'. lines 1-11:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:8:19
+-   │
+- 8 │         x + call(|_x: u64| {x = x + 1; x}) + call(|_x: u64| {x = x + 7; x})
+-   │                   ^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:8:52
+-   │
+- 8 │         x + call(|_x: u64| {x = x + 1; x}) + call(|_x: u64| {x = x + 7; x})
+-   │                                                    ^^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+= task 1 'run'. lines 13-13:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
++ return values: 12
+= 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/optimization/inlining1_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/optimization/inlining1_typed.exp
new file mode 100644
index 0000000000000..c9058684fa8ba
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/optimization/inlining1_typed.exp
@@ -0,0 +1,23 @@
+comparison between v1 and v2 failed:
+- processed 2 tasks
+- 
+- task 0 'publish'. lines 1-14:
+- Error: error[E01013]: unsupported language construct
+-   ┌─ TEMPFILE:7:14
+-   │
+- 7 │         foo(|_: u64| 3, 10)
+-   │              ^^^^^^ Explicit type annotations for lambda parameters are only allowed in Move 2 and beyond
+- 
+- 
+- 
+- task 1 'run'. lines 16-16:
+- Error: Function execution failed with VMError: {
+-     major_status: LINKER_ERROR,
+-     sub_status: None,
+-     location: undefined,
+-     indices: redacted,
+-     offsets: redacted,
+- }
+- 
++ processed 2 tasks
++ 
diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/optimization/inlining1_typed.move b/third_party/move/move-compiler-v2/transactional-tests/tests/optimization/inlining1_typed.move
new file mode 100644
index 0000000000000..e22c531b09c4f
--- /dev/null
+++ b/third_party/move/move-compiler-v2/transactional-tests/tests/optimization/inlining1_typed.move
@@ -0,0 +1,16 @@
+//# publish
+module 0x42::Test {
+    inline fun foo(f:|u64| u64, x: u64): u64 {
+        f(x)
+    }
+
+    public fun test(): u64 {
+        foo(|_: u64| 3, 10)
+    }
+
+    public fun main() {
+        assert!(test() == 3, 5);
+    }
+}
+
+//# run 0x42::Test::main