--- /dev/null
+// CS0023: The `?' operator cannot be applied to operand of type `T'
+// Line: 11
+
+class C2<T>
+{
+ C2<T> i;
+ T field;
+
+ public void Foo ()
+ {
+ var x = i?.field;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0023: The `?' operator cannot be applied to operand of type `T'
+// Line: 13
+
+interface IFoo<T>
+{
+ T Call ();
+}
+
+class C1
+{
+ U Foo<T, U> (IFoo<T> t)
+ {
+ return t?.Call ();
+ }
+}
--- /dev/null
+// CS0023: The `?' operator cannot be applied to operand of type `T'
+// Line: 8
+
+class X
+{
+ static void Bug<T>(System.Func<T> func)
+ {
+ var r = func?.Invoke ();
+ }
+}
\ No newline at end of file
if (conditionalAccess) {
if (!ec.ConditionalAccess.Statement) {
- if (ec.ConditionalAccess.Type.IsNullableType)
- Nullable.LiftedNull.Create (ec.ConditionalAccess.Type, Location.Null).Emit (ec);
- else
+ var t = ec.ConditionalAccess.Type;
+ if (t.IsNullableType)
+ Nullable.LiftedNull.Create (t, Location.Null).Emit (ec);
+ else {
ec.EmitNull ();
+
+ if (t.IsGenericParameter)
+ ec.Emit (OpCodes.Unbox_Any, t);
+ }
}
ec.Emit (OpCodes.Br, ec.ConditionalAccess.EndLabel);
void ResolveConditionalAccessReceiver (ResolveContext rc)
{
- // LAMESPEC: Not sure why this is explicitly disalloed with very odd error message
+ // LAMESPEC: Not sure why this is explicitly disallowed with very odd error message
if (!rc.HasSet (ResolveContext.Options.DontSetConditionalAccessReceiver) && method_group.HasConditionalAccess ()) {
Error_OperatorCannotBeApplied (rc, loc, "?", method_group.Type);
}
return false;
}
- protected static TypeSpec LiftMemberType (ResolveContext rc, TypeSpec type)
+ protected TypeSpec LiftMemberType (ResolveContext rc, TypeSpec type)
{
+ var tps = type as TypeParameterSpec;
+ if (tps != null && !(tps.IsReferenceType || tps.IsValueType)) {
+ Error_OperatorCannotBeApplied (rc, loc, "?", type);
+ }
+
return TypeSpec.IsValueType (type) && !type.IsNullableType ?
Nullable.NullableInfo.MakeType (rc.Module, type) :
type;
{
}
- public ExpressionStatement ResolveStatement (BlockContext ec)
+ public virtual ExpressionStatement ResolveStatement (BlockContext ec)
{
Expression e = Resolve (ec);
if (e == null)
}
}
+ bool statement_resolve;
+ public override ExpressionStatement ResolveStatement (BlockContext bc)
+ {
+ statement_resolve = true;
+ var es = base.ResolveStatement (bc);
+ statement_resolve = false;
+
+ return es;
+ }
+
protected override Expression DoResolve (ResolveContext rc)
{
ResolveConditionalAccessReceiver (rc);
var method = mg.BestCandidate;
type = mg.BestCandidateReturnType;
- if (conditional_access_receiver)
+ if (conditional_access_receiver && !statement_resolve)
type = LiftMemberType (ec, type);
if (arguments == null && method.DeclaringType.BuiltinType == BuiltinTypeSpec.Type.Object && method.Name == Destructor.MetadataName) {
--- /dev/null
+using System;
+
+interface IFoo<T>
+{
+ T Call ();
+}
+
+class C1
+{
+ public void Foo<T> (IFoo<T> t) where T : class
+ {
+ t?.Call ();
+ var x = t?.Call ();
+ }
+
+ public void Foo2<T> (IFoo<T> t)
+ {
+ t?.Call ();
+ }
+}
+
+class C2<T> where T : class
+{
+ C2<T> i;
+ T field;
+
+ public void Foo ()
+ {
+ var x = i?.field;
+ }
+}
+
+class Program
+{
+ static void Test<T>(Func<T> func) where T : struct
+ {
+ var r = func?.Invoke ();
+ }
+
+ static void Test2<T>(Func<T> func)
+ {
+ func?.Invoke ();
+ }
+
+ static void Main()
+ {
+ new C1 ().Foo<Program> (null);
+ new C1 ().Foo2<Program> (null);
+
+ new C2<string> ().Foo ();
+
+ Test (() => 1);
+ Test (() => 2);
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="test-null-operator-04.cs">
+ <type name="C1">
+ <method name="Void Foo[T](IFoo`1[T])" attrs="134">
+ <size>38</size>
+ </method>
+ <method name="Void Foo2[T](IFoo`1[T])" attrs="134">
+ <size>17</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="C2`1[T]">
+ <method name="Void Foo()" attrs="134">
+ <size>33</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="Program">
+ <method name="Void Test[T](System.Func`1[T])" attrs="145">
+ <size>31</size>
+ </method>
+ <method name="Void Test2[T](System.Func`1[T])" attrs="145">
+ <size>17</size>
+ </method>
+ <method name="Void Main()" attrs="145">
+ <size>102</size>
+ </method>
+ <method name="Int32 <Main>m__0()" attrs="145">
+ <size>9</size>
+ </method>
+ <method name="Int32 <Main>m__1()" attrs="145">
+ <size>9</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-null-operator-05.cs">
<type name="CI">
<method name="Void set_Item(System.String, System.String)" attrs="2182">