diff options
Diffstat (limited to 'mcs/gmcs/generic.cs')
-rw-r--r-- | mcs/gmcs/generic.cs | 87 |
1 files changed, 66 insertions, 21 deletions
diff --git a/mcs/gmcs/generic.cs b/mcs/gmcs/generic.cs index d52299761d6..8d0c4b03d8b 100644 --- a/mcs/gmcs/generic.cs +++ b/mcs/gmcs/generic.cs @@ -1495,7 +1495,7 @@ namespace Mono.CSharp { is_class = is_struct = false; } } else { - is_class = atype.IsClass || atype.IsInterface; + is_class = atype.IsClass; is_struct = atype.IsValueType && !TypeManager.IsNullableType (atype); } @@ -1526,16 +1526,26 @@ namespace Mono.CSharp { // The class constraint comes next. // if (gc.HasClassConstraint) { - if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint)) + if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint)) { + Error_TypeMustBeConvertible (atype, gc.ClassConstraint, ptype); return false; + } } // // Now, check the interface constraints. // foreach (Type it in gc.InterfaceConstraints) { - if (!CheckConstraint (ec, ptype, aexpr, it)) + Type itype; + if (it.IsGenericParameter) + itype = atypes [it.GenericParameterPosition]; + else + itype = it; + + if (!CheckConstraint (ec, ptype, aexpr, itype)) { + Error_TypeMustBeConvertible (atype, itype, ptype); return false; + } } // @@ -1590,11 +1600,7 @@ namespace Mono.CSharp { ctype = atypes [pos]; } - if (Convert.ImplicitStandardConversionExists (ec, expr, ctype)) - return true; - - Error_TypeMustBeConvertible (expr.Type, ctype, ptype); - return false; + return Convert.ImplicitStandardConversionExists (ec, expr, ctype); } bool HasDefaultConstructor (EmitContext ec, Type atype) @@ -2685,8 +2691,7 @@ namespace Mono.CSharp { if (expr == null) return null; - if (!(expr is IMemoryLocation)) - temp = new LocalTemporary (ec, expr.Type); + temp = new LocalTemporary (ec, expr.Type); info = new NullableInfo (expr.Type); type = info.UnderlyingType; @@ -2706,6 +2711,11 @@ namespace Mono.CSharp { ec.ig.EmitCall (OpCodes.Call, info.HasValue, null); } + public void Store (EmitContext ec) + { + create_temp (ec); + } + void create_temp (EmitContext ec) { if ((temp != null) && !has_temp) { @@ -2740,14 +2750,35 @@ namespace Mono.CSharp { public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { - source.Emit (ec); - ec.ig.Emit (OpCodes.Newobj, info.Constructor); + InternalWrap wrap = new InternalWrap (source, info, loc); + ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false); + } + + protected class InternalWrap : Expression + { + public Expression expr; + public NullableInfo info; + + public InternalWrap (Expression expr, NullableInfo info, Location loc) + { + this.expr = expr; + this.info = info; + this.loc = loc; - if (leave_copy) - ec.ig.Emit (OpCodes.Dup); + type = info.Type; + eclass = ExprClass.Value; + } - Expression empty = new EmptyExpression (expr.Type); - ((IAssignMethod) expr).EmitAssign (ec, empty, false, prepare_for_load); + public override Expression DoResolve (EmitContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + ec.ig.Emit (OpCodes.Newobj, info.Constructor); + } } } @@ -2951,7 +2982,8 @@ namespace Mono.CSharp { { public readonly Binary.Operator Oper; - Expression left, right, underlying, null_value, bool_wrap; + Expression left, right, original_left, original_right; + Expression underlying, null_value, bool_wrap; Unwrap left_unwrap, right_unwrap; bool is_equality, is_comparision, is_boolean; @@ -2959,8 +2991,8 @@ namespace Mono.CSharp { Location loc) { this.Oper = op; - this.left = left; - this.right = right; + this.left = original_left = left; + this.right = original_right = right; this.loc = loc; } @@ -2980,8 +3012,16 @@ namespace Mono.CSharp { return null; } - if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr) || - (Oper == Binary.Operator.LogicalAnd) || (Oper == Binary.Operator.LogicalOr)) && + if ((Oper == Binary.Operator.LogicalAnd) || + (Oper == Binary.Operator.LogicalOr)) { + Binary.Error_OperatorCannotBeApplied ( + loc, Binary.OperName (Oper), + original_left.GetSignatureForError (), + original_right.GetSignatureForError ()); + return null; + } + + if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr)) && ((left.Type == TypeManager.bool_type) && (right.Type == TypeManager.bool_type))) { Expression empty = new EmptyExpression (TypeManager.bool_type); bool_wrap = new Wrap (empty, loc).Resolve (ec); @@ -3214,6 +3254,11 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { + if (left_unwrap != null) + left_unwrap.Store (ec); + if (right_unwrap != null) + right_unwrap.Store (ec); + if (is_boolean) { EmitBoolean (ec); return; |