+ if (eclass != ExprClass.Invalid)
+ return this;
+
+ unwrap = Unwrap.Create (Expr, ec);
+ if (unwrap == null)
+ return null;
+
+ Expression res = base.ResolveOperator (ec, unwrap);
+ if (res != this) {
+ if (user_operator == null)
+ return res;
+ } else {
+ res = Expr = LiftExpression (ec, Expr);
+ }
+
+ if (res == null)
+ return null;
+
+ eclass = ExprClass.Value;
+ type = res.Type;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ Label is_null_label = ig.DefineLabel ();
+ Label end_label = ig.DefineLabel ();
+
+ unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brfalse, is_null_label);
+
+ NullableInfo ni = new NullableInfo (type);
+
+ if (user_operator != null) {
+ user_operator.Emit (ec);
+ } else {
+ EmitOperator (ec, ni.UnderlyingType);
+ }
+
+ ig.Emit (OpCodes.Newobj, ni.Constructor);
+ ig.Emit (OpCodes.Br_S, end_label);
+
+ ig.MarkLabel (is_null_label);
+ LiftedNull.Create (type, loc).Emit (ec);
+
+ ig.MarkLabel (end_label);
+ }
+
+ Expression LiftExpression (EmitContext ec, Expression expr)
+ {
+ TypeExpr lifted_type = new NullableType (expr.Type, expr.Location);
+ lifted_type = lifted_type.ResolveAsTypeTerminal (ec, false);
+ if (lifted_type == null)
+ return null;
+
+ expr.Type = lifted_type.Type;
+ return expr;
+ }
+
+ protected override Expression ResolveEnumOperator (EmitContext ec, Expression expr)
+ {
+ expr = base.ResolveEnumOperator (ec, expr);
+ if (expr == null)
+ return null;
+
+ Expr = LiftExpression (ec, Expr);
+ return LiftExpression (ec, expr);
+ }
+
+ protected override Expression ResolveUserOperator (EmitContext ec, Expression expr)
+ {
+ expr = base.ResolveUserOperator (ec, expr);
+ if (expr == null)
+ return null;
+
+ //
+ // When a user operator is of non-nullable type
+ //
+ if (Expr is Unwrap) {
+ user_operator = LiftExpression (ec, expr);
+ return user_operator;
+ }
+
+ return expr;