if (t.IsGenericParameter)
return dargs [t.GenericParameterPosition];
if (t.IsGenericType) {
+ Type[] args = t.GetGenericArguments ();
+ Type[] inflated = new Type [args.Length];
+
+ for (int i = 0; i < args.Length; i++)
+ inflated [i] = inflate (args [i]);
+
t = t.GetGenericTypeDefinition ();
- t = t.MakeGenericType (dargs);
+ t = t.MakeGenericType (inflated);
}
return t;
}
}
- MethodGroupExpr mg = Expression.MemberLookup (
- containerType, atype, ".ctor", MemberTypes.Constructor,
+ TypeParameter tparam = TypeManager.LookupTypeParameter (atype);
+ if (tparam != null)
+ return tparam.HasConstructorConstraint;
+
+ MemberList list = TypeManager.FindMembers (
+ atype, MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance |
- BindingFlags.DeclaredOnly, loc)
- as MethodGroupExpr;
+ BindingFlags.DeclaredOnly, null, null);
- if (!atype.IsAbstract && (mg != null) && mg.IsInstance) {
- foreach (MethodBase mb in mg.Methods) {
- ParameterData pd = TypeManager.GetParameterData (mb);
- if (pd.Count == 0)
- return true;
- }
+ if (atype.IsAbstract || (list == null))
+ return false;
+
+ foreach (MethodBase mb in list) {
+ ParameterData pd = TypeManager.GetParameterData (mb);
+ if ((pd.Count == 0) && mb.IsPublic && !mb.IsStatic)
+ return true;
}
return false;
return generic_nullable_type == DropGenericTypeArguments (t);
}
+ public static bool IsNullableTypeOf (Type t, Type nullable)
+ {
+ if (!IsNullableType (t))
+ return false;
+
+ return GetTypeArguments (t) [0] == nullable;
+ }
+
public static bool IsNullableValueType (Type t)
{
if (!IsNullableType (t))
public abstract class Nullable
{
- protected sealed class NullableInfo
+ public sealed class NullableInfo
{
public readonly Type Type;
public readonly Type UnderlyingType;
}
}
- protected class Unwrap : Expression, IMemoryLocation, IAssignMethod
+ public class Unwrap : Expression, IMemoryLocation, IAssignMethod
{
Expression expr;
NullableInfo info;
LocalTemporary temp;
bool has_temp;
- public Unwrap (Expression expr, Location loc)
+ protected Unwrap (Expression expr)
{
this.expr = expr;
- this.loc = loc;
+ this.loc = expr.Location;
+ }
+
+ public static Unwrap Create (Expression expr, EmitContext ec)
+ {
+ return new Unwrap (expr).Resolve (ec) as Unwrap;
}
public override Expression DoResolve (EmitContext ec)
}
}
- protected class Wrap : Expression
+ public class Wrap : Expression
{
Expression expr;
NullableInfo info;
- public Wrap (Expression expr, Location loc)
+ protected Wrap (Expression expr)
{
this.expr = expr;
- this.loc = loc;
+ this.loc = expr.Location;
+ }
+
+ public static Wrap Create (Expression expr, EmitContext ec)
+ {
+ return new Wrap (expr).Resolve (ec) as Wrap;
}
public override Expression DoResolve (EmitContext ec)
if (expr == null)
return null;
- unwrap = (Unwrap) new Unwrap (expr, loc).Resolve (ec);
+ unwrap = Unwrap.Create (expr, ec);
if (unwrap == null)
return null;
if (underlying == null)
return null;
- wrap = new Wrap (underlying, loc).Resolve (ec);
+ wrap = Wrap.Create (underlying, ec);
if (wrap == null)
return null;
public override Expression DoResolve (EmitContext ec)
{
if (TypeManager.IsNullableType (left.Type)) {
- left_unwrap = new Unwrap (left, loc);
- left = left_unwrap.Resolve (ec);
+ left = left_unwrap = Unwrap.Create (left, ec);
if (left == null)
return null;
}
if (TypeManager.IsNullableType (right.Type)) {
- right_unwrap = new Unwrap (right, loc);
- right = right_unwrap.Resolve (ec);
+ right = right_unwrap = Unwrap.Create (right, ec);
if (right == null)
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);
+ bool_wrap = Wrap.Create (empty, ec);
null_value = new NullableLiteral (bool_wrap.Type, loc).Resolve (ec);
type = bool_wrap.Type;
if (underlying == null)
return null;
- underlying = new Wrap (underlying, loc).Resolve (ec);
+ underlying = Wrap.Create (underlying, ec);
if (underlying == null)
return null;
{
ILGenerator ig = ec.ig;
- Label left_not_null_label = ig.DefineLabel ();
- Label false_label = ig.DefineLabel ();
- Label true_label = ig.DefineLabel ();
- Label end_label = ig.DefineLabel ();
-
- bool false_label_used = false;
- bool true_label_used = false;
+ // Given 'X? x;' for any value type X: 'x != null' is the same as 'x.HasValue'
+ if (left is NullLiteral) {
+ if (right_unwrap == null)
+ throw new InternalErrorException ();
+ right_unwrap.EmitCheck (ec);
+ if (Oper == Binary.Operator.Equality) {
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Ceq);
+ }
+ return;
+ }
- if (left_unwrap != null) {
+ if (right is NullLiteral) {
+ if (left_unwrap == null)
+ throw new InternalErrorException ();
left_unwrap.EmitCheck (ec);
- if (right is NullLiteral) {
- if (Oper == Binary.Operator.Equality) {
- true_label_used = true;
- ig.Emit (OpCodes.Brfalse, true_label);
- } else {
- false_label_used = true;
- ig.Emit (OpCodes.Brfalse, false_label);
- }
- } else if (right_unwrap != null) {
- ig.Emit (OpCodes.Dup);
- ig.Emit (OpCodes.Brtrue, left_not_null_label);
- right_unwrap.EmitCheck (ec);
+ if (Oper == Binary.Operator.Equality) {
+ ig.Emit (OpCodes.Ldc_I4_0);
ig.Emit (OpCodes.Ceq);
- if (Oper == Binary.Operator.Inequality) {
- ig.Emit (OpCodes.Ldc_I4_0);
- ig.Emit (OpCodes.Ceq);
- }
- ig.Emit (OpCodes.Br, end_label);
-
- ig.MarkLabel (left_not_null_label);
- ig.Emit (OpCodes.Pop);
- } else {
- if (Oper == Binary.Operator.Equality) {
- false_label_used = true;
- ig.Emit (OpCodes.Brfalse, false_label);
- } else {
- true_label_used = true;
- ig.Emit (OpCodes.Brfalse, true_label);
- }
}
+ return;
}
- if (right_unwrap != null) {
+ Label both_have_value_label = ig.DefineLabel ();
+ Label end_label = ig.DefineLabel ();
+
+ if (left_unwrap != null && right_unwrap != null) {
+ Label dissimilar_label = ig.DefineLabel ();
+
+ left_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Dup);
right_unwrap.EmitCheck (ec);
- if (left is NullLiteral) {
- if (Oper == Binary.Operator.Equality) {
- true_label_used = true;
- ig.Emit (OpCodes.Brfalse, true_label);
- } else {
- false_label_used = true;
- ig.Emit (OpCodes.Brfalse, false_label);
- }
- } else {
- if (Oper == Binary.Operator.Equality) {
- false_label_used = true;
- ig.Emit (OpCodes.Brfalse, false_label);
- } else {
- true_label_used = true;
- ig.Emit (OpCodes.Brfalse, true_label);
- }
- }
- }
+ ig.Emit (OpCodes.Bne_Un, dissimilar_label);
- bool left_is_null = left is NullLiteral;
- bool right_is_null = right is NullLiteral;
- if (left_is_null || right_is_null) {
- if (((Oper == Binary.Operator.Equality) && (left_is_null == right_is_null)) ||
- ((Oper == Binary.Operator.Inequality) && (left_is_null != right_is_null))) {
- true_label_used = true;
- ig.Emit (OpCodes.Br, true_label);
- } else {
- false_label_used = true;
- ig.Emit (OpCodes.Br, false_label);
- }
- } else {
- underlying.Emit (ec);
+ ig.Emit (OpCodes.Brtrue, both_have_value_label);
+
+ // both are null
+ if (Oper == Binary.Operator.Equality)
+ ig.Emit (OpCodes.Ldc_I4_1);
+ else
+ ig.Emit (OpCodes.Ldc_I4_0);
ig.Emit (OpCodes.Br, end_label);
- }
- ig.MarkLabel (false_label);
- if (false_label_used) {
- ig.Emit (OpCodes.Ldc_I4_0);
- if (true_label_used)
- ig.Emit (OpCodes.Br, end_label);
+ ig.MarkLabel (dissimilar_label);
+ ig.Emit (OpCodes.Pop);
+ } else if (left_unwrap != null) {
+ left_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brtrue, both_have_value_label);
+ } else if (right_unwrap != null) {
+ right_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brtrue, both_have_value_label);
+ } else {
+ throw new InternalErrorException ("shouldn't get here");
}
- ig.MarkLabel (true_label);
- if (true_label_used)
+ // one is null while the other isn't
+ if (Oper == Binary.Operator.Equality)
+ ig.Emit (OpCodes.Ldc_I4_0);
+ else
ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Br, end_label);
+
+ ig.MarkLabel (both_have_value_label);
+ underlying.Emit (ec);
ig.MarkLabel (end_label);
}
public override Expression DoResolve (EmitContext ec)
{
- unwrap = new Unwrap (expr, loc);
- expr = unwrap.Resolve (ec);
- if (expr == null)
+ unwrap = Unwrap.Create (expr, ec);
+ if (unwrap == null)
return null;
if (unwrap.Type != TypeManager.bool_type)
if (TypeManager.IsNullableType (ltype)) {
NullableInfo info = new NullableInfo (ltype);
- unwrap = (Unwrap) new Unwrap (left, loc).Resolve (ec);
+ unwrap = Unwrap.Create (left, ec);
if (unwrap == null)
return null;
if (expr == null)
return null;
- unwrap = (Unwrap) new Unwrap (expr, loc).Resolve (ec);
+ unwrap = Unwrap.Create (expr, ec);
if (unwrap == null)
return null;