../../mcs/support.cs
../../mcs/typemanager.cs
../../mcs/typespec.cs
+../../mcs/tuples.cs
../../mcs/visit.cs
../../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
../../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
--- /dev/null
+// CS0029: Cannot implicitly convert type `int' to `(long, bool)'
+// Line: 8
+
+class C
+{
+ static void Test ()
+ {
+ System.ValueTuple<long, bool> arg = 1;
+ }
+}
--- /dev/null
+// CS0815: An implicitly typed local variable declaration cannot be initialized with `(int, method group)'
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = (1, Main);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0826: The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = new [] { (1, Main) };
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0827: An anonymous type property `Prop' cannot be initialized with `(int, method group)'
+// Line: 9
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = new {
+ Prop = (1, Main)
+ };
+ }
+}
\ No newline at end of file
+++ /dev/null
-// CS1026: Unexpected symbol `;', expecting `)'
-// Line: 10
-
-using System;
-
-class Test {
- static void Main ()
- {
- string uri = "http://localhost/";
- int default_port = (uri.StartsWith ("http://") ? 80 : -1;
- }
-}
-// CS1525: Unexpected symbol `==', expecting `type'
+// CS1525: Unexpected symbol `==', expecting `(' or `type'
// Line: 8
class A
-// CS1525: Unexpected symbol `1', expecting `type'
+// CS1525: Unexpected symbol `1', expecting `(' or `type'
// Line: 4
class M : 1
-// CS1525: Unexpected symbol `)', expecting `[', `out', `params', `ref', `this', or `type'
+// CS1525: Unexpected symbol `)', expecting `(', `[', `out', `params', `ref', `this', or `type'
// Line: 6
class TestClass
--- /dev/null
+// CS1026: Unexpected symbol `;', expecting `)' or `,'
+// Line: 10
+
+using System;
+
+class Test {
+ static void Main ()
+ {
+ string uri = "http://localhost/";
+ int default_port = (uri.StartsWith ("http://") ? 80 : -1;
+ }
+}
-// CS1525: Unexpected symbol `this', expecting `[', `{', or `type'
+// CS1525: Unexpected symbol `this', expecting `(', `[', `{', or `type'
// Line: 8
class M
--- /dev/null
+// CS1644: Feature `tuples' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 7
+// Compiler options: -langversion:6
+
+class Class
+{
+ static (int, bool) Foo ()
+ {
+ return;
+ }
+}
--- /dev/null
+// CS1644: Feature `tuples' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 9
+// Compiler options: -langversion:6
+
+class Class
+{
+ static void Main ()
+ {
+ var t = (a: 1, b: 2);
+ }
+}
--- /dev/null
+// CS8123: The tuple element name `a' is ignored because a different name or no name is specified by the target type `(int, int)'
+// Line: 9
+// Compiler options: -warnaserror
+
+class C
+{
+ public static void Main ()
+ {
+ (int tt1, int tt2) t = (a: 1, 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8123: The tuple element name `b' is ignored because a different name or no name is specified by the target type `(long, string)'
+// Line: 9
+// Compiler options: -warnaserror
+
+static class X
+{
+ static (long a, string x) Test ()
+ {
+ return (b: 1, "");
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8124: Tuple must contain at least two elements
+// Line: 6
+
+class X
+{
+ static (int) Foo ()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8125: The tuple element name `Item22' can only be used at position 22
+// Line: 6
+
+class C
+{
+ static void Test ((int Item22, int b) arg)
+ {
+ }
+}
--- /dev/null
+// CS8126: The tuple element name `Rest' is reserved
+// Line: 6
+
+class C
+{
+ static void Test ((int Rest, int b) arg)
+ {
+ }
+}
--- /dev/null
+// CS8127: The tuple element name `a' is a duplicate
+// Line: 6
+
+class C
+{
+ static (int a, int a) Test ()
+ {
+ return null;
+ }
+}
--- /dev/null
+// CS8129:
+// Line:
+
+using System;
+
+class C
+{
+ static void Main ()
+ {
+ long x;
+ string y;
+ (x, y) = new C ();
+ }
+
+ public static void Deconstruct (out int a, out string b)
+ {
+ a = 1;
+ b = "hello";
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side
+// Line: 9
+
+class C
+{
+ public static void Main ()
+ {
+ int x, y;
+ (x, y) = null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8132:
+// Line: 8
+
+class C
+{
+ public static void Main ()
+ {
+ var (t, u, v) = (1, 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8133: Cannot deconstruct dynamic objects
+// Line: 9
+
+class C
+{
+ public static void Test (dynamic d)
+ {
+ int x, y;
+ (x, y) = d;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8135: Tuple literal `(int, method group)' cannot be converted to type `object'
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ object m = (1, Main);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8138: Do not use `System.Runtime.CompilerServices.TupleElementNamesAttribute' directly. Use the tuple syntax instead
+// Line: 7
+
+using System;
+using System.Runtime.CompilerServices;
+
+[TupleElementNames (new[] { "a", "b" })]
+public class C
+{
+}
--- /dev/null
+// CS8139: `D.M()': cannot change return type tuple element names when overriding inherited member `C.M()'
+// Line: 14
+
+class C
+{
+ public virtual (int a, int b) M ()
+ {
+ throw null;
+ }
+}
+
+class D : C
+{
+ public override (int, int) M ()
+ {
+ throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8139: `D.M((int, int))': cannot change tuple element names when overriding inherited member `C.M((int, int))'
+// Line: 13
+
+class C
+{
+ public virtual void M ((int, int) arg)
+ {
+ }
+}
+
+class D : C
+{
+ public override void M ((int c, int d) arg)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8139: `D.Prop': cannot change return type tuple element names when overriding inherited member `C.Prop'
+// Line: 14
+
+class C
+{
+ public virtual (int a, int b) Prop {
+ get {
+ throw null;
+ }
+ }
+}
+
+class D : C
+{
+ public override (int c, int d) Prop {
+ get {
+ throw null;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8139: `D.M()': cannot change return type tuple element names when overriding inherited member `C.M()'
+// Line: 14
+
+class C
+{
+ public virtual (int a, int b) M ()
+ {
+ throw null;
+ }
+}
+
+class D : C
+{
+ public override (int c, int d) M ()
+ {
+ throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8141:
+// Line: 11
+
+public interface I<T>
+{
+ int this[T arg] { get; set; }
+}
+
+public class C : I<(int a, int b)>
+{
+ public int this[(int c, int d) arg] {
+ get {
+ return 1;
+ }
+ set {
+
+ }
+ }
+}
--- /dev/null
+// CS8141:
+// Line: 9
+
+public interface I<T>
+{
+ T Test ();
+}
+
+public class C : I<(int a, int b)>
+{
+ public (int c, int d) Test ()
+ {
+ return (1, 2);
+ }
+}
--- /dev/null
+// CS8142: A partial method declaration and partial method implementation must both use the same tuple element names
+// Line: 11
+
+partial class X
+{
+ partial void Foo ((int a, int b) arg);
+}
+
+partial class X
+{
+ partial void Foo ((int c, int d) arg)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8143: An expression tree cannot contain a tuple literal
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+ public static void Main ()
+ {
+ Expression<Func<object>> l = () => (-1, 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8144:
+// Line: 12
+
+using System;
+using System.Linq.Expressions;
+
+class X
+{
+ public static void Main ()
+ {
+ (byte b, short d) t = (0, 0);
+ Expression<Func<(int a, int aa)>> e = () => t;
+ }
+}
--- /dev/null
+// CS8181: Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead
+// Line: 8
+
+class C
+{
+ static void Main ()
+ {
+ var x = new (long, int) () {
+ Item1 = 1
+ };
+ }
+}
--- /dev/null
+// CS8210: A tuple literal cannot not contain a value of type `void'
+// Line: 8
+
+class XX
+{
+ public static void Main ()
+ {
+ var m = (1, Main ());
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS8307: The first operand of an `as' operator may not be a tuple literal without a natural type
+// Line: 8
+
+class X
+{
+ public static void Main ()
+ {
+ var g = (1, Main) as object;
+ }
+}
\ No newline at end of file
# Operators
cs0457-2.cs
cs0457.cs
+
+cs8129.cs NO ERROR
+cs8132.cs NO ERROR
+cs8141.cs
+cs8141-2.cs
+cs8144.cs
return System.Linq.Expressions.Expression.Assign (target_object, source_object);
}
+
protected virtual Expression ResolveConversions (ResolveContext ec)
{
source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location);
Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
}
+ public void Error_MisusedTupleAttribute ()
+ {
+ Report.Error (8138, loc, "Do not use `{0}' directly. Use the tuple syntax instead", GetSignatureForError ());
+ }
+
void Error_AttributeEmitError (string inner)
{
Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
}
if (!IsConditionallyExcluded (ctor.DeclaringType)) {
+ if (Type == predefined.TupleElementNames) {
+ Error_MisusedTupleAttribute ();
+ return;
+ }
+
try {
foreach (Attributable target in targets)
target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
// New in .NET 4.5
public readonly PredefinedStateMachineAttribute AsyncStateMachine;
+ // New in .NET 4.7
+ public readonly PredefinedTupleElementNamesAttribute TupleElementNames;
+
//
// Optional types which are used as types and for member lookup
//
CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
+ TupleElementNames = new PredefinedTupleElementNamesAttribute (module, "System.Runtime.CompilerServices", "TupleElementNamesAttribute");
+
// TODO: Should define only attributes which are used for comparison
const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
return tctor != null;
}
}
+
+ public class PredefinedTupleElementNamesAttribute : PredefinedAttribute
+ {
+ MethodSpec tctor;
+
+ public PredefinedTupleElementNamesAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
+ {
+ }
+
+ public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
+ {
+ var cab = CreateCustomAttributeBuilder (type, loc);
+ if (cab != null)
+ builder.SetCustomAttribute (cab);
+ }
+
+ CustomAttributeBuilder CreateCustomAttributeBuilder (TypeSpec type, Location loc)
+ {
+ if (tctor == null) {
+ tctor = module.PredefinedMembers.TupleElementNamesAttributeCtor.Resolve (loc);
+ if (tctor == null)
+ return null;
+ }
+
+ var names = new List<string> (type.TypeArguments.Length);
+ BuildStringElements (type, names);
+ return new CustomAttributeBuilder ((ConstructorInfo)tctor.GetMetaInfo (), new object [] { names.ToArray () });
+ }
+
+ //
+ // Returns an array of names when any element of the type is
+ // tuple with named element. The array is built for top level
+ // type therefore it can contain multiple tuple types
+ //
+ // Example: Func<(int, int), int, (int a, int b)[]>
+ // Output: { null, null, "a", "b" }
+ //
+ static void BuildStringElements (TypeSpec type, List<string> names)
+ {
+ while (type is ArrayContainer) {
+ type = ((ArrayContainer)type).Element;
+ }
+
+ var nts = type as NamedTupleSpec;
+ if (nts != null) {
+ names.AddRange (nts.Elements);
+ } else {
+ for (int i = 0; i < type.Arity; ++i) {
+ names.Add (null);
+ }
+ }
+
+ foreach (var ta in type.TypeArguments) {
+ BuildStringElements (ta, names);
+ }
+ }
+ }
}
public override void Emit ()
{
+ if (Interfaces != null) {
+ foreach (var iface in Interfaces) {
+ if (iface.HasNamedTupleElement) {
+ throw new NotImplementedException ("named tuples for .interfaceimpl");
+ }
+ }
+ }
+
if (OptAttributes != null)
OptAttributes.Emit ();
if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
- if (base_type != null && base_type.HasDynamicElement) {
- Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+ if (base_type != null) {
+ if (base_type.HasDynamicElement)
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+ if (base_type.HasNamedTupleElement)
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (TypeBuilder, base_type, Location);
}
}
ok = false;
}
- var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
+ var base_member_type = ((IInterfaceMemberSpec)base_member).MemberType;
if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
Report.SymbolRelatedToPreviousError (base_member);
if (this is PropertyBasedMember) {
GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
}
ok = false;
+ } else if (!NamedTupleSpec.CheckOverrideName (MemberType, base_member_type)) {
+ // CSC: Should be different error code
+ Report.Error (8139, Location, "`{0}': cannot change return type tuple element names when overriding inherited member `{1}'",
+ GetSignatureForError (), base_member.GetSignatureForError ());
+ ok = false;
+ }
+
+ var base_params = base_member as IParametersMember;
+ if (base_params != null) {
+ if (!NamedTupleSpec.CheckOverrideName ((IParametersMember)this, base_params)) {
+ Report.Error (8139, Location, "`{0}': cannot change tuple element names when overriding inherited member `{1}'",
+ GetSignatureForError (), base_member.GetSignatureForError ());
+ ok = false;
+ }
}
return ok;
return null;
}
+ static Expression ImplicitTupleLiteralConversion (ResolveContext rc, Expression source, TypeSpec targetType, Location loc)
+ {
+ var targetTypeArgument = targetType.TypeArguments;
+ if (source.Type.Arity != targetTypeArgument.Length)
+ return null;
+
+ var namedTarget = targetType as NamedTupleSpec;
+ var tupleLiteral = source as TupleLiteral;
+ Expression instance;
+
+ if (tupleLiteral == null && !ExpressionAnalyzer.IsInexpensiveLoad (source)) {
+ var expr_variable = LocalVariable.CreateCompilerGenerated (source.Type, rc.CurrentBlock, loc);
+ source = new CompilerAssign (expr_variable.CreateReferenceExpression (rc, loc), source, loc);
+ instance = expr_variable.CreateReferenceExpression (rc, loc);
+ } else {
+ instance = null;
+ }
+
+ var converted = new List<Expression> (targetType.Arity);
+ for (int i = 0; i < targetType.Arity; ++i) {
+ Expression elementSrc;
+ if (tupleLiteral != null) {
+ elementSrc = tupleLiteral.Elements [i].Expr;
+
+ if (namedTarget != null) {
+ var elementSrcName = tupleLiteral.Elements [i].Name;
+ if (elementSrcName != null && elementSrcName != namedTarget.Elements [i]) {
+ rc.Report.Warning (8123, 1, loc,
+ "The tuple element name `{0}' is ignored because a different name or no name is specified by the target type `{1}'",
+ elementSrcName, namedTarget.GetSignatureForErrorWithNames ());
+ }
+ }
+ } else {
+ elementSrc = new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)).Resolve (rc);
+ }
+
+ var res = ImplicitConversionStandard (rc, elementSrc, targetTypeArgument [i], loc);
+ if (res == null)
+ return null;
+
+ converted.Add (res);
+ }
+
+ return new TupleLiteralConversion (source, targetType, converted, loc);
+ }
+
+ static bool ImplicitTupleLiteralConversionExists (Expression source, TypeSpec targetType)
+ {
+ if (source.Type.Arity != targetType.Arity)
+ return false;
+
+ var srcTypeArgument = source.Type.TypeArguments;
+ var targetTypeArgument = targetType.TypeArguments;
+
+ var tupleLiteralElements = (source as TupleLiteral)?.Elements;
+
+ for (int i = 0; i < targetType.Arity; ++i) {
+ var elementType = srcTypeArgument [i];
+
+ if (tupleLiteralElements != null) {
+ if (!ImplicitStandardConversionExists (tupleLiteralElements[i].Expr, targetTypeArgument [i])) {
+ return false;
+ }
+ } else {
+ if (!ImplicitStandardConversionExists (new EmptyExpression (srcTypeArgument [i]), targetTypeArgument [i])) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
//
// Full version of implicit conversion
//
if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
return true;
-
+
+ if (expr_type.IsTupleType && target_type.IsTupleType)
+ return ImplicitTupleLiteralConversionExists (expr, target_type);
+
//
// Implicit Constant Expression Conversions
//
return c;
}
+ if (expr_type.IsTupleType) {
+ if (target_type.IsTupleType)
+ return ImplicitTupleLiteralConversion (ec, expr, target_type, loc);
+
+ if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (expr_type))
+ return null;
+ }
+
e = ImplicitNumericConversion (expr, expr_type, target_type);
if (e != null)
return e;
/// ImplicitConversion. If there is no implicit conversion, then
/// an error is signaled
/// </summary>
- static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
+ public static Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
TypeSpec target_type, Location loc)
{
Expression e = ImplicitConversion (ec, source, target_type, loc);
if (e != null)
return e;
- source.Error_ValueCannotBeConverted (ec, target_type, false);
+ if (target_type != InternalType.ErrorType)
+ source.Error_ValueCannotBeConverted (ec, target_type, false);
return null;
}
%token GENERIC_DIMENSION
%token DEFAULT_COLON
%token OPEN_BRACKET_EXPR
+%token OPEN_PARENS_DECONSTRUCT
// Make the parser go into eval mode parsing (statements and compilation units).
%token EVAL_STATEMENT_PARSER
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, Argument.AType.Out);
lbag.AddLocation ($$, GetLocation($2));
}
-
;
named_argument_expr
$$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2);
}
| builtin_type_expression
+ | OPEN_PARENS tuple_elements CLOSE_PARENS opt_nullable
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var a = (Tuple<TypeArguments, List<string>>) $2;
+ if (a.Item1.Count < 2) {
+ report.Error (8124, GetLocation ($1), "Tuple must contain at least two elements");
+ }
+
+ $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+
+ if ($4 != null)
+ $$ = new ComposedCast ((FullNamedExpression) $$, (ComposedTypeSpecifier) $4);
+ }
+ ;
+
+tuple_elements
+ : tuple_element tuple_element_name
+ {
+ var type_args = new TypeArguments ();
+ type_args.Add ((FullNamedExpression) $1);
+
+ var names = new List<string> (2);
+ var lt = (LocatedToken) $2;
+ names.Add (lt?.Value);
+
+ $$ = Tuple.Create (type_args, names);
+ }
+ | tuple_elements COMMA tuple_element tuple_element_name
+ {
+ var a = (Tuple<TypeArguments, List<string>>) $1;
+ a.Item1.Add ((FullNamedExpression) $3);
+ var lt = (LocatedToken) $4;
+ a.Item2.Add (lt?.Value);
+ $$ = a;
+ }
+ ;
+
+tuple_element_name
+ : /* empty */
+ | IDENTIFIER
+ ;
+
+tuple_element
+ : parameter_type
;
void_invalid
literal
: boolean_literal
+ | tuple_literal
| LITERAL
| NULL { $$ = new NullLiteral (GetLocation ($1)); }
;
| FALSE { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); }
;
+tuple_literal
+ : OPEN_PARENS tuple_literal_elements CLOSE_PARENS
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ $$ = new TupleLiteral ((List<TupleLiteralElement>)$2, GetLocation ($1));
+ }
+ ;
+
+tuple_literal_elements
+ : tuple_literal_element COMMA tuple_literal_element
+ {
+ $$ = new List<TupleLiteralElement> () {
+ (TupleLiteralElement) $1, (TupleLiteralElement) $3
+ };
+ }
+ | tuple_literal_elements COMMA tuple_literal_element
+ {
+ var list = (List<TupleLiteralElement>)$1;
+ list.Add ((TupleLiteralElement) $3);
+ }
+ ;
+
+tuple_literal_element
+ : expression
+ {
+ $$ = new TupleLiteralElement ((Expression) $1);
+ }
+ | IDENTIFIER COLON expression
+ {
+ var lt = (LocatedToken) $1;
+ $$ = new TupleLiteralElement (lt.Value, (Expression) $3, lt.Location);
+ }
+ ;
+
interpolated_string
: INTERPOLATED_STRING interpolations INTERPOLATED_STRING_END
{
$$ = new Unary (Unary.Operator.AddressOf, null, GetLocation ($1));
}
- ;
multiplicative_expression
: prefixed_unary_expression
{
$$ = new WildcardPattern (GetLocation ($1));
}
- | pattern_expr_invocation
+/* | pattern_expr_invocation */
| pattern_property
;
+/*
pattern_expr_invocation
: type_name_expression OPEN_PARENS opt_pattern_list CLOSE_PARENS
{
$$ = new RecursivePattern ((ATypeNameExpression) $1, (Arguments) $3, GetLocation ($2));
}
;
+*/
pattern_property
: type_name_expression OPEN_BRACE pattern_property_list CLOSE_BRACE
}
;
+/*
opt_pattern_list
- : /* empty */
+ : // empty
{
$$ = new Arguments (0);
}
}
;
+
pattern_argument
: pattern
{
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3);
}
;
+*/
shift_expression
: additive_expression
$$ = new CompoundAssign (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3);
lbag.AddLocation ($$, GetLocation ($2));
}
+ | OPEN_PARENS_DECONSTRUCT deconstruct_exprs CLOSE_PARENS ASSIGN expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var exprs = (List<Expression>) $2;
+ $$ = new TupleDeconstruct (exprs, (Expression) $5, GetLocation ($4));
+ }
+ ;
+
+deconstruct_exprs
+ : expression COMMA expression
+ {
+ $$ = new List<Expression> () {
+ (Expression) $1,
+ (Expression) $3
+ };
+ }
+ | deconstruct_exprs COMMA expression
+ {
+ var src = (List<Expression>) $1;
+ src.Add ((Expression) $3);
+ $$ = src;
+ }
;
lambda_parameter_list
variable_type_simple
: type_name_expression opt_nullable
{
- // Ok, the above "primary_expression" is there to get rid of
- // both reduce/reduce and shift/reduces in the grammar, it should
- // really just be "type_name". If you use type_name, a reduce/reduce
- // creeps up. If you use namespace_or_type_name (which is all we need
- // really) two shift/reduces appear.
- //
-
- // So the super-trick is that primary_expression
- // can only be either a SimpleName or a MemberAccess.
- // The MemberAccess case arises when you have a fully qualified type-name like :
- // Foo.Bar.Blah i;
- // SimpleName is when you have
- // Blah i;
-
var expr = (ATypeNameExpression) $1;
if ($2 == null) {
if (expr.Name == "var" && expr is SimpleName)
$$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2);
}
| builtin_type_expression
+ | tuple_type opt_nullable
+ {
+ if ($2 == null)
+ $$ = $1;
+ else
+ $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2);
+ }
| void_invalid
;
-
+
+tuple_type
+ : OPEN_PARENS tuple_type_elements CLOSE_PARENS
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (GetLocation ($1), "tuples");
+
+ var a = (Tuple<TypeArguments, List<string>>) $2;
+
+ $$ = new TupleTypeExpr (a.Item1, a.Item2, GetLocation ($1));
+ }
+ ;
+
+tuple_type_elements
+ : variable_type IDENTIFIER /* opt_identifier */ COMMA variable_type IDENTIFIER /* opt_identifier */
+ {
+ var type_args = new TypeArguments ();
+
+ type_args.Add ((FullNamedExpression) $1);
+ type_args.Add ((FullNamedExpression) $4);
+
+ var names = new List<string> (2);
+ var lt = (LocatedToken) $2;
+ names.Add (lt?.Value);
+ lt = (LocatedToken) $5;
+ names.Add (lt?.Value);
+
+ $$ = Tuple.Create (type_args, names);
+ }
+ | tuple_type_elements COMMA variable_type IDENTIFIER /* opt_identifier */
+ {
+ var a = (Tuple<TypeArguments, List<string>>) $1;
+ a.Item1.Add ((FullNamedExpression) $3);
+ var lt = (LocatedToken) $4;
+ a.Item2.Add (lt?.Value);
+ $$ = a;
+ }
+ ;
+
pointer_stars
: pointer_star
| pointer_star pointer_stars
return "]";
case Token.OPEN_PARENS_CAST:
case Token.OPEN_PARENS_LAMBDA:
+ case Token.OPEN_PARENS_DECONSTRUCT:
case Token.OPEN_PARENS:
return "(";
case Token.CLOSE_PARENS:
}
//
- // Open parens micro parser. Detects both lambda and cast ambiguity.
+ // Open parens micro parser
//
int TokenizeOpenParens ()
{
int bracket_level = 0;
bool is_type = false;
bool can_be_type = false;
+ bool at_least_one_comma = false;
while (true) {
ptoken = current_token;
if (current_token == Token.ARROW)
return Token.OPEN_PARENS_LAMBDA;
+ //
+ // Expression inside parens is deconstruct expression, (a, x.y) = ...
+ //
+ if (current_token == Token.ASSIGN && at_least_one_comma)
+ return Token.OPEN_PARENS_DECONSTRUCT;
+
//
// Expression inside parens is single type, (int[])
//
if (bracket_level == 0) {
bracket_level = 100;
can_be_type = is_type = false;
+ at_least_one_comma = true;
}
continue;
}
return false;
+ case Token.OPEN_PARENS:
+ if (!parsing_generic_declaration)
+ return false;
+
+ while (true) {
+ switch (token ()) {
+ case Token.COMMA:
+ // tuple declaration after <
+ return true;
+ case Token.OP_GENERICS_GT:
+ case Token.EOF:
+ return false;
+ }
+ }
+
default:
return false;
}
case Token.DEFAULT:
case Token.DELEGATE:
case Token.OP_GENERICS_GT:
+ case Token.REFVALUE:
return Token.OPEN_PARENS;
}
MissingDependency = 1 << 5,
HasDynamicElement = 1 << 6,
ConstraintsChecked = 1 << 7,
+ HasNamedTupleElement = 1 << 8,
IsAccessor = 1 << 9, // Method is an accessor
IsGeneric = 1 << 10, // Member contains type arguments
GenericIterateInterface = 1 << 21,
GenericTask = 1 << 22,
InterfacesImported = 1 << 23,
+ Tuple = 1 << 24
}
//
StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected |
StateFlags.Obsolete | StateFlags.Obsolete_Undetected |
StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected |
- StateFlags.HasDynamicElement;
+ StateFlags.HasDynamicElement | StateFlags.HasNamedTupleElement;
protected Modifiers modifiers;
public StateFlags state;
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Target == AttributeTargets.ReturnValue) {
- if (return_attributes == null)
- return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
-
+ CreateReturnBuilder ();
return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
}
}
+ ReturnParameter CreateReturnBuilder ()
+ {
+ return return_attributes ?? (return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location));
+ }
+
protected override bool DoDefineMembers ()
{
var builtin_types = Compiler.BuiltinTypes;
}
}
- if (ReturnType.Type != null) {
- if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
- } else if (ReturnType.Type.HasDynamicElement) {
- return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType.Type, Location);
+ var rtype = ReturnType.Type;
+ if (rtype != null) {
+ if (rtype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
+ } else if (rtype.HasDynamicElement) {
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, rtype, Location);
+ }
+
+ if (rtype.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, rtype, Location);
}
ConstraintChecker.Check (this, ReturnType.Type, ReturnType.Location);
PropertyAccess,
EventAccess,
IndexerAccess,
- Nothing,
+ Nothing,
}
/// <remarks>
return MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
}
+ if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+ var ntuple = queried_type as NamedTupleSpec;
+ if (ntuple != null) {
+ var ms = ntuple.FindElement (rc, name, loc);
+ if (ms != null)
+ return ExprClassFromMemberInfo (ms, loc);
+ }
+ }
+
return null;
}
{
}
- public bool InferType (ResolveContext ec, Expression right_side)
+ public bool InferType (ResolveContext ec, Expression rhs)
{
if (type != null)
throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
- type = right_side.Type;
- if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
+ type = rhs.Type;
+
+ if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || (rhs is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
ec.Report.Error (815, loc,
"An implicitly typed local variable declaration cannot be initialized with `{0}'",
type.GetSignatureForError ());
eclass = ExprClass.Value;
TypeSpec etype = expr.Type;
+ if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (etype)) {
+ ec.Report.Error (8307, expr.Location, "The first operand of an `as' operator may not be a tuple literal without a natural type");
+ type = InternalType.ErrorType;
+ return this;
+ }
+
if (type == null) {
type = InternalType.ErrorType;
return this;
return DoResolveInvocation (rc);
}
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+ {
+ var sn = expr as SimpleName;
+ if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
+ throw new NotImplementedException ("var deconstruct");
+ }
+
+ return base.DoResolveLValue (rc, right_side);
+ }
+
Expression DoResolveInvocation (ResolveContext ec)
{
Expression member_expr;
protected override Expression DoResolve (ResolveContext ec)
{
+ if (RequestedType is TupleTypeExpr) {
+ ec.Report.Error (8181, loc, "Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead.");
+ }
+
type = RequestedType.ResolveAsType (ec);
if (type == null)
return null;
array_element_type = best_type_inference.InferredTypeArguments[0];
best_type_inference = null;
- if (array_element_type == null ||
- array_element_type == InternalType.NullLiteral || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
- arguments.Count != rank.Dimension) {
+ if (array_element_type == null || InternalType.HasNoType (array_element_type) || arguments.Count != rank.Dimension) {
ec.Report.Error (826, loc,
"The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
return null;
}
type = e.Type;
- if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
+ if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || type.IsPointer || (e is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
Error_InvalidInitializer (ec, type.GetSignatureForError ());
return null;
}
Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location);
}
+ if (member_type.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (FieldBuilder, member_type, Location);
+ }
+
if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder);
if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
}
}
-#endregion
+ #endregion
public FieldInfo GetMetaInfo ()
{
foreach (var arg in targs) {
if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
state |= StateFlags.HasDynamicElement;
- break;
+ }
+
+ if (arg.HasNamedTupleElement) {
+ state |= StateFlags.HasNamedTupleElement;
}
}
}
}
+ public override bool IsTupleType {
+ get {
+ return (open_type.state & StateFlags.Tuple) != 0;
+ }
+ }
+
//
// Types used to inflate the generic type
//
bound.Type == InternalType.ThrowExpr)
return;
+ if (bound.Type.IsTupleType && TupleLiteral.ContainsNoTypeElement (bound.Type))
+ return;
+
var a = bounds [index];
if (a == null) {
a = new List<BoundInfo> (2);
if (t.Name[0] == '<')
continue;
- var it = CreateType (t, null, new DynamicTypeReader (t), true);
+ var it = CreateType (t, null, new AttributesTypeInfoReader (t), true);
if (it == null)
continue;
public abstract class MetadataImporter
{
//
- // Dynamic types reader with additional logic to reconstruct a dynamic
- // type using DynamicAttribute values
+ // Types reader with additional logic to reconstruct extra
+ // type information encoded in custom attributes values
//
- protected struct DynamicTypeReader
+ protected struct AttributesTypeInfoReader
{
static readonly bool[] single_attribute = { true };
- public int Position;
- bool[] flags;
+ public int DynamicPosition;
+ bool[] dynamicFlags;
+
+ public int TuplePosition;
+ string[] tupleNames;
// There is no common type for CustomAttributeData and we cannot
// use ICustomAttributeProvider
//
// A member provider which can be used to get CustomAttributeData
//
- public DynamicTypeReader (object provider)
+ public AttributesTypeInfoReader (object provider)
{
- Position = 0;
- flags = null;
+ DynamicPosition = 0;
+ TuplePosition = 0;
+ dynamicFlags = null;
+ tupleNames = null;
this.provider = provider;
}
if (provider != null)
ReadAttribute ();
- return flags != null && Position < flags.Length && flags[Position];
+ return dynamicFlags != null && DynamicPosition < dynamicFlags.Length && dynamicFlags [DynamicPosition];
}
//
if (provider != null)
ReadAttribute ();
- return flags != null;
+ return dynamicFlags != null;
+ }
+
+ public bool HasNamedTupleAttribute ()
+ {
+ if (provider != null)
+ ReadAttribute ();
+
+ return tupleNames != null;
+ }
+
+ public IList<string> GetNamedTupleElements (int length)
+ {
+ if (TuplePosition == 0 && length == tupleNames.Length)
+ return tupleNames;
+
+ for (int i = TuplePosition; i < length + TuplePosition; ++i) {
+ if (tupleNames [i] != null) {
+ var res = new string [length];
+ Array.Copy (tupleNames, TuplePosition, res, 0, length);
+ return res;
+ }
+ }
+
+ //
+ // Current range can be just padding
+ //
+ return null;
}
IList<CustomAttributeData> GetCustomAttributes ()
if (cad.Count > 0) {
foreach (var ca in cad) {
var dt = ca.Constructor.DeclaringType;
- if (dt.Name != "DynamicAttribute" || dt.Namespace != CompilerServicesNamespace)
+ if (dt.Namespace != CompilerServicesNamespace)
continue;
- if (ca.ConstructorArguments.Count == 0) {
- flags = single_attribute;
- break;
- }
+ switch (dt.Name) {
+ case "DynamicAttribute":
+ if (ca.ConstructorArguments.Count == 0) {
+ dynamicFlags = single_attribute;
+ break;
+ }
- var arg_type = ca.ConstructorArguments[0].ArgumentType;
+ var arg_type = ca.ConstructorArguments [0].ArgumentType;
- if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
- var carg = (IList<CustomAttributeTypedArgument>) ca.ConstructorArguments[0].Value;
- flags = new bool[carg.Count];
- for (int i = 0; i < flags.Length; ++i) {
- if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean)
- flags[i] = (bool) carg[i].Value;
+ if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
+ var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+ dynamicFlags = new bool [carg.Count];
+ for (int i = 0; i < dynamicFlags.Length; ++i) {
+ if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.Boolean)
+ dynamicFlags [i] = (bool)carg [i].Value;
+ }
+ }
+
+ break;
+ case "TupleElementNamesAttribute":
+ if (ca.ConstructorArguments.Count != 1)
+ break;
+
+ var tuple_arg_type = ca.ConstructorArguments [0].ArgumentType;
+ if (tuple_arg_type.IsArray && MetaType.GetTypeCode (tuple_arg_type.GetElementType ()) == TypeCode.String) {
+ var carg = (IList<CustomAttributeTypedArgument>)ca.ConstructorArguments [0].Value;
+ tupleNames = new string [carg.Count];
+ for (int i = 0; i < tupleNames.Length; ++i) {
+ if (MetaType.GetTypeCode (carg [i].ArgumentType) == TypeCode.String)
+ tupleNames [i] = (string)carg [i].Value;
+ }
}
break;
TypeSpec field_type;
try {
- field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi), declaringType);
+ field_type = ImportType (fi.FieldType, new AttributesTypeInfoReader (fi), declaringType);
//
// Private field has private type which is not fixed buffer
if (add.Modifiers != remove.Modifiers)
throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
- var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei), declaringType);
+ var event_type = ImportType (ei.EventHandlerType, new AttributesTypeInfoReader (ei), declaringType);
var definition = new ImportedMemberDefinition (ei, event_type, this);
return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove);
}
var type = tparams[pos];
int index = pos - first;
- tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false);
+ tspec[index] = (TypeParameterSpec) CreateType (type, new AttributesTypeInfoReader (), false);
}
return tspec;
}
- TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype)
+ TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, AttributesTypeInfoReader dtype)
{
- ++dtype.Position;
+ ++dtype.DynamicPosition;
var tspec = new TypeSpec [tparams.Length - first];
for (int pos = first; pos < tparams.Length; ++pos) {
TypeSpec spec;
if (type.HasElementType) {
var element = type.GetElementType ();
- ++dtype.Position;
+ ++dtype.DynamicPosition;
spec = ImportType (element, dtype, null);
if (!type.IsArray) {
if (spec == null)
return null;
- ++dtype.Position;
+ ++dtype.DynamicPosition;
tspec[index] = spec;
}
returnType = module.Compiler.BuiltinTypes.Void;
} else {
var mi = (MethodInfo)mb;
- returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter), declaringType);
+ returnType = ImportType (mi.ReturnType, new AttributesTypeInfoReader (mi.ReturnParameter), declaringType);
//
// Detect operators and destructors
// Strip reference wrapping
//
var el = p.ParameterType.GetElementType ();
- types[i] = ImportType (el, new DynamicTypeReader (p), parent); // TODO: 1-based positio to be csc compatible
+ types[i] = ImportType (el, new AttributesTypeInfoReader (p), parent); // TODO: 1-based positio to be csc compatible
} else if (i == 0 && method.IsStatic && (parent.Modifiers & Modifiers.METHOD_EXTENSION) != 0 &&
HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
mod = Parameter.Modifier.This;
- types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+ types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
} else {
- types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
+ types[i] = ImportType (p.ParameterType, new AttributesTypeInfoReader (p), parent);
if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
public TypeSpec CreateType (MetaType type)
{
- return CreateType (type, new DynamicTypeReader (), true);
+ return CreateType (type, new AttributesTypeInfoReader (), true);
}
public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType)
{
- return CreateType (type, declaringType, new DynamicTypeReader (type), false);
+ return CreateType (type, declaringType, new AttributesTypeInfoReader (type), false);
}
- TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType)
+ TypeSpec CreateType (MetaType type, AttributesTypeInfoReader dtype, bool canImportBaseType)
{
TypeSpec declaring_type;
if (type.IsNested && !type.IsGenericParameter)
- declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true);
+ declaring_type = CreateType (type.DeclaringType, new AttributesTypeInfoReader (type.DeclaringType), true);
else
declaring_type = null;
return CreateType (type, declaring_type, dtype, canImportBaseType);
}
- protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType)
+ protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, AttributesTypeInfoReader dtype, bool canImportBaseType)
{
TypeSpec spec;
if (import_cache.TryGetValue (type, out spec)) {
return null;
if (declaringType == null) {
// Simple case, no nesting
- spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
+ spec = CreateType (type_def, null, new AttributesTypeInfoReader (), canImportBaseType);
spec = spec.MakeGenericType (module, targs);
} else {
//
}
}
+ if (spec.IsTupleType && dtype.HasNamedTupleAttribute ()) {
+ var names = dtype.GetNamedTupleElements (spec.Arity);
+ if (names != null)
+ return NamedTupleSpec.MakeType (module, (InflatedTypeSpec) spec, names);
+
+ dtype.TuplePosition += spec.Arity;
+ }
+
// Don't add generic type with dynamic arguments, they can interfere with same type
// using object type arguments
if (!spec.HasDynamicElement) {
else if (type.BaseType != null) {
TypeSpec base_type;
if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType)
- base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true);
+ base_type = CreateType (type.BaseType, new AttributesTypeInfoReader (type), true);
else
base_type = CreateType (type.BaseType);
if (t.Name[0] == '<')
continue;
- var it = CreateType (t, null, new DynamicTypeReader (t), true);
+ var it = CreateType (t, null, new AttributesTypeInfoReader (t), true);
if (it == null)
continue;
public TypeSpec ImportType (MetaType type)
{
- return ImportType (type, new DynamicTypeReader (type), null);
+ return ImportType (type, new AttributesTypeInfoReader (type), null);
}
- TypeSpec ImportType (MetaType type, DynamicTypeReader dtype, TypeSpec currentType)
+ TypeSpec ImportType (MetaType type, AttributesTypeInfoReader dtype, TypeSpec currentType)
{
if (type.HasElementType) {
var element = type.GetElementType ();
- ++dtype.Position;
+ ++dtype.DynamicPosition;
var spec = ImportType (element, dtype, currentType);
if (type.IsArray)
<Compile Include="field.cs" />\r
<Compile Include="typespec.cs" />\r
<Compile Include="visit.cs" />\r
+ <Compile Include="tuples.cs" />\r
</ItemGroup>\r
<ItemGroup Label="IKVM.Reflection">\r
<Compile Include="..\..\external\ikvm\reflect\*.cs">\r
support.cs
typemanager.cs
typespec.cs
+tuples.cs
visit.cs
../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
}
return false;
}
+
+ var pm_member = (MethodCore)member;
+ if (!NamedTupleSpec.CheckOverrideName (pm, pm_member) || !NamedTupleSpec.CheckOverrideName (pm.MemberType, pm_member.MemberType)) {
+ Report.Error (8142, member.Location,
+ "A partial method declaration and partial method implementation must both use the same tuple element names");
+ }
}
}
public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
{
if (a.Target == AttributeTargets.ReturnValue) {
- if (return_attributes == null)
- return_attributes = new ReturnParameter (this, MethodBuilder, Location);
-
- return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
+ CreateReturnBuilder ().ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
return new EmitContext (this, ig, MemberType, sourceMethod);
}
+ ReturnParameter CreateReturnBuilder ()
+ {
+ return return_attributes ?? (return_attributes = new ReturnParameter (this, MethodBuilder, Location));
+ }
+
public override bool Define ()
{
if (!base.Define ())
explicit_name = null;
} else {
- MethodData = new MethodData (this, ModFlags, flags, this, base_method);
+ MethodData = new MethodData (this, ModFlags, flags, this);
if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
return false;
Module.PredefinedAttributes.DebuggerStepThrough.EmitAttribute (MethodBuilder);
if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- return_attributes = new ReturnParameter (this, MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
} else if (ReturnType.HasDynamicElement) {
- return_attributes = new ReturnParameter (this, MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
+ }
+
+ if (ReturnType.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
}
if (OptAttributes != null)
protected Modifiers modifiers;
protected MethodAttributes flags;
protected TypeSpec declaring_type;
- protected MethodSpec parent_method;
SourceMethodBuilder debug_builder;
string full_name;
this.method = method;
}
- public MethodData (InterfaceMemberBase member,
- Modifiers modifiers, MethodAttributes flags,
- IMethodData method,
- MethodSpec parent_method)
- : this (member, modifiers, flags, method)
- {
- this.parent_method = parent_method;
- }
-
public bool Define (TypeDefinition container, string method_full_name)
{
PendingImplementation pending = container.PendingImplementations;
}
}
}
+
+ if (!NamedTupleSpec.CheckOverrideName (member.MemberType, implementing.ReturnType)) {
+ container.Compiler.Report.Error (8141, method.Location,
+ "The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
+ member.GetSignatureForError (), implementing.GetSignatureForError ());
+ }
+
+ var p_member = method as IParametersMember;
+ var p_implementing = implementing as IParametersMember;
+ if (p_member != null && p_implementing != null && !NamedTupleSpec.CheckOverrideName (p_member, p_implementing)) {
+ container.Compiler.Report.Error (8141, method.Location,
+ "The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
+ member.GetSignatureForError (), implementing.GetSignatureForError ());
+ }
}
}
} else {
}
} else {
//
- // Setting implementin to null inside this block will trigger a more
+ // Setting implementing to null inside this block will trigger a more
// verbose error reporting for missing interface implementations
//
if (implementing.DeclaringType.IsInterface) {
}
if (a.Target == AttributeTargets.ReturnValue) {
- if (return_attributes == null)
- return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
-
+ CreateReturnBuilder ();
return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
return;
}
throw new NotSupportedException ();
}
+ ReturnParameter CreateReturnBuilder ()
+ {
+ return return_attributes ?? (return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location));
+ }
+
public virtual void Emit (TypeDefinition parent)
{
method_data.Emit (parent);
Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
} else if (ReturnType.HasDynamicElement) {
- return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
- Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
+ Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
+ }
+
+ if (ReturnType.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
}
if (OptAttributes != null)
} else if (parameter_type.HasDynamicElement) {
pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
}
+
+ if (parameter_type.HasNamedTupleElement) {
+ pa.TupleElementNames.EmitAttribute (builder, parameter_type, Location);
+ }
}
}
Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
}
+ if (member_type.HasNamedTupleElement) {
+ Module.PredefinedAttributes.TupleElementNames.EmitAttribute (PropertyBuilder, member_type, Location);
+ }
+
ConstraintChecker.Check (this, member_type, type_expr.Location);
first.Emit (Parent);
3021, 3022, 3023, 3024, 3026, 3027,
4014, 4024, 4025, 4026,
7035, 7080, 7081, 7082, 7095,
- 8009, 8094
+ 8009, 8094, 8123
};
public Report (CompilerContext context, ReportPrinter printer)
public readonly PredefinedType FormattableString;
public readonly PredefinedType FormattableStringFactory;
+ // C# 7.0
+ public readonly PredefinedType[] Tuples;
+
public PredefinedTypes (ModuleContainer module)
{
TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
IFormattable.Define ();
FormattableString.Define ();
+
+ Tuples = new PredefinedType [8];
+ for (int i = 0; i < Tuples.Length; i++) {
+ var pt = new PredefinedType (module, MemberKind.Struct, "System", "ValueTuple", i + 1);
+ Tuples [i] = pt;
+ if (pt.Define ())
+ pt.TypeSpec.IsTupleType = true;
+ }
}
}
public readonly PredefinedMember<FieldSpec> StructLayoutCharSet;
public readonly PredefinedMember<FieldSpec> StructLayoutSize;
public readonly PredefinedMember<MethodSpec> TypeGetTypeFromHandle;
+ public readonly PredefinedMember<MethodSpec> TupleElementNamesAttributeCtor;
public PredefinedMembers (ModuleContainer module)
{
MemberFilter.Field ("Size", btypes.Int));
TypeGetTypeFromHandle = new PredefinedMember<MethodSpec> (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle);
+
+ TupleElementNamesAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.TupleElementNames,
+ MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
+ ArrayContainer.MakeType (module, btypes.String))));
}
}
}
}
+ public bool HasNamedTupleElement {
+ get {
+ return (state & StateFlags.HasNamedTupleElement) != 0;
+ }
+ }
+
//
// Returns a list of all interfaces including
// interfaces from base type or base interfaces
}
}
+ //
+ // Returns true for instances of any System.ValueTuple<......> type
+ //
+ public virtual bool IsTupleType {
+ get {
+ return (state & StateFlags.Tuple) != 0;
+ }
+ set {
+ state = value ? state | StateFlags.Tuple : state & ~StateFlags.Tuple;
+ }
+ }
+
// TODO: Should probably do
// IsGenericType -- recursive
// HasTypeParameter -- non-recursive
if (IsNested) {
s = DeclaringType.GetSignatureForError ();
} else if (MemberDefinition is AnonymousTypeClass) {
- return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
+ return ((AnonymousTypeClass)MemberDefinition).GetSignatureForError ();
+ } else if (IsTupleType) {
+ return FormatTupleSignature ();
} else {
s = MemberDefinition.Namespace;
}
return s + Name + GetTypeNameSignature ();
}
+ string FormatTupleSignature ()
+ {
+ var sb = new StringBuilder ();
+ sb.Append ("(");
+ for (int i = 0; i < TypeArguments.Length; ++i) {
+ if (i != 0)
+ sb.Append (", ");
+
+ sb.Append (TypeArguments[i].GetSignatureForError ());
+ }
+ sb.Append (")");
+
+ return sb.ToString ();
+ }
+
public string GetSignatureForErrorIncludingAssemblyName ()
{
var imported = MemberDefinition.DeclaringAssembly as ImportedAssemblyDefinition;
}
#endregion
+
+ public static bool HasNoType (TypeSpec type)
+ {
+ return type == AnonymousMethod || type == MethodGroup || type == NullLiteral || type == ThrowExpr;
+ }
}
//
{
}
-class C
+class B<T>
+{
+}
+
+class C : B<dynamic>
{
public C (dynamic d)
{
if (t.GetConstructors ()[0].GetCustomAttributes (ca, false).Length != 0)
return 21;
+ if (t.GetCustomAttributes (ca, false).Length != 1)
+ return 22;
+
// Transformations
DynamicAttribute da;
da = t.GetMember ("t")[0].GetCustomAttributes (ca, false)[0] as DynamicAttribute;
gtest-230.cs
test-pattern-02.cs
+test-pattern-04.cs
+test-pattern-05.cs
+test-pattern-07.cs
--- /dev/null
+using System;
+
+static class X
+{
+ static (int, string) Test1 ()
+ {
+ return ValueTuple.Create (1, "2");
+ }
+
+ static void Test2 ((int Item1, int Item2) arg)
+ {
+ }
+
+ static void Test3 ((int a, string b) arg)
+ {
+ }
+
+ static (int a, string b) Test4 ()
+ {
+ return ValueTuple.Create (1, "x");
+ }
+
+ static int Main ()
+ {
+ var res = Test1 ();
+ if (res.Item1 != 1) {
+ return 1;
+ }
+
+ if (res.Item2 != "2") {
+ return 2;
+ }
+
+ ValueTuple<int, string> res2 = res;
+
+ Test3 (ValueTuple.Create (1, "2"));
+
+ var res3 = Test4 ();
+ if (res3.Item1 != 1)
+ return 3;
+
+ if (res3.a != 1)
+ return 4;
+
+ if (res3.Item2 != "x")
+ return 5;
+
+ if (res3.b != "x")
+ return 6;
+
+ return 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+class TupleConversions
+{
+ public static void Main ()
+ {
+ object oarg = 4;
+ (sbyte v1, long v2) t1 = (-1, 2);
+ var t2 = (-1, 2);
+
+ IComparable o = (x1: "a", x2: 1.ToString ());
+
+ var arg = (x1: 1, x2: 1.ToString ());
+ if (arg.x2 != "1")
+ return;
+
+ Foo ((x1: (oarg, 'v'), x2: 1.ToString ()));
+
+ Test3 (ValueTuple.Create (1, "2"));
+
+ (int v1, string v2) y = (1, null);
+
+ (int v1, Action v2) y2 = (1, Main);
+ (int v1, Action v2) y3 = (ValueTuple<int, Action>) (1, Main);
+
+ (string v1, object v2) b = ("a", "b");
+
+ (int v1, long v2)? x = null;
+ }
+
+ static void Foo<T> (T arg)
+ {
+ }
+
+ static void Test3 ((long a, object b) arg)
+ {
+ }
+}
--- /dev/null
+using System;
+using System.Linq.Expressions;
+
+class TupleDeconstruct
+{
+ public static int Main ()
+ {
+// var (xx, yy) = (1, 2);
+// if (xx != 1)
+// return 1;
+
+// if (yy != 2)
+// return 2;
+
+ int x, y;
+ (x, y) = (1, 2);
+ if (x != 1)
+ return 1;
+
+ if (y != 2)
+ return 2;
+
+// var (l1, l2) = ('a', 'b');
+
+// var cwd = new ClassWithDeconstruct ();
+// var (m1, m2) = cwd;
+
+// (string, string) ss = cwd; // Error
+
+ return 0;
+ }
+
+ static void Test2 ()
+ {
+ var c = new C ();
+ (c.Prop1, c.Prop2) = (1, 2);
+ }
+
+ static void var1 (object o1, object o2)
+ {
+ }
+
+ static void TestCustom ()
+ {
+ return;
+ }
+}
+
+class ClassWithDeconstruct
+{
+ public void Deconstruct (out string f, out string s)
+ {
+ f = "a";
+ s = "z";
+ }
+}
+
+class C
+{
+ public int Prop1 { get; set; }
+ public int Prop2 { get; set; }
+}
\ No newline at end of file
--- /dev/null
+// Compiler options: -t:library
+
+using System;
+using System.Collections.Generic;
+
+public class X
+{
+ public static (int a, string, bool b, object) Test1 ()
+ {
+ return ValueTuple.Create (1, "2", true, new X ());
+ }
+
+ public static (int x, (int x2, string y2), bool z) Field;
+}
--- /dev/null
+// Compiler options: -r:test-tuple-04-lib.dll
+
+class Test
+{
+ public static int Main ()
+ {
+ var x = X.Test1 ();
+ if (x.b != true)
+ return 1;
+
+ var z = X.Field;
+ if (z.z != false)
+ return 2;
+
+ return 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+//
+// tuple names attribute decoration
+//
+
+using System;
+using System.Collections;
+using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+using System.Linq;
+
+interface I<T>
+{
+}
+
+class B<T>
+{
+}
+
+class C // : B<(int a, int b)> // TODO: I<(a, b)
+{
+ public C((int a, int b) d)
+ {
+ }
+
+ public (int a, int b) a;
+ public (int, (int a, int b)) c;
+
+ public (int a, int b) Prop { set; get; }
+ public (int a, int b) Prop2 { set { } }
+
+ public (int a, int b)? this[(int a, int b) d] { set { } get { return null; } }
+
+ public (int a, int b)? Method(ref (int a, int b) d)
+ {
+ return null;
+ }
+
+ public (int a, int b)[] t;
+ public (int a, int b)[,] t2;
+ // TODO: public Func<(int a, int b), int, (int c, int d)[]> v;
+ // public I<(int a, int b)>[] iface;
+ // TODO: public Action<(long, (long u, long))[], object, (int a, int b)> d2;
+ public (((int aa1, int aa2) a1, (int, int) a2) x1, ((int cc1, int cc2) b1, (int dd1, int dd2) b2) x2) d3;
+}
+
+delegate (int a, int b) Del((int a, int b) d);
+
+class Test
+{
+ public static int Main()
+ {
+ Type t = typeof(C);
+ Type ca = typeof(TupleElementNamesAttribute);
+ TupleElementNamesAttribute da;
+
+ if (t.GetMember("a")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 1;
+
+ if (t.GetMember("c")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 3;
+
+ if (t.GetMember("Prop")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 4;
+
+ if (t.GetMember("get_Prop")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 5;
+
+ if (t.GetMethod("get_Prop").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+ return 6;
+
+ if (t.GetMember("set_Prop")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 7;
+
+ if (t.GetMethod("set_Prop").ReturnParameter.GetCustomAttributes(ca, false).Length != 0)
+ return 8;
+
+ if (t.GetMethod("set_Prop").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 9;
+
+ if (t.GetMember("Prop2")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 10;
+
+ if (t.GetMember("set_Prop2")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 11;
+
+ if (t.GetMember("Item")[0].GetCustomAttributes(ca, false).Length != 1)
+ return 12;
+
+ if (t.GetMethod("get_Item").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+ return 13;
+
+ if (t.GetMethod("get_Item").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 14;
+
+ if (t.GetMethod("set_Item").ReturnParameter.GetCustomAttributes(ca, false).Length != 0)
+ return 15;
+
+ if (t.GetMethod("set_Item").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 16;
+
+ if (t.GetMethod("set_Item").GetParameters()[1].GetCustomAttributes(ca, false).Length != 1)
+ return 17;
+
+ if (t.GetMember("Method")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 18;
+
+ var res = t.GetMethod("Method").GetParameters()[0].GetCustomAttributes(ca, false);
+ if (res.Length != 1)
+ return 19;
+
+ da = res[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 190;
+ if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ return 191;
+
+ if (t.GetConstructors()[0].GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 20;
+
+ if (t.GetConstructors()[0].GetCustomAttributes(ca, false).Length != 0)
+ return 21;
+
+ // if (t.GetCustomAttributes(ca, false).Length != 1)
+ // return 22;
+
+ // Transformations
+ da = t.GetMember("t")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 40;
+
+ if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ return 41;
+
+ da = t.GetMember("t2")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 42;
+
+ if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ return 43;
+
+ //da = t.GetMember("v")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ //if (da == null)
+ // return 44;
+
+ //if (!da.TransformNames.SequenceEqual(new string[] { "a", "b", "c", "d" }))
+ // return 45;
+
+ //da = t.GetMember("iface")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ //if (da == null)
+ // return 46;
+
+ //if (!da.TransformNames.SequenceEqual(new string[] { "a", "b" }))
+ // return 47;
+
+ //da = t.GetMember("d2")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ //if (da == null)
+ // return 48;
+ //if (!da.TransformNames.SequenceEqual(new string[] { null, null, "u", null, "a", "b" }))
+ // return 49;
+
+ da = t.GetMember("d3")[0].GetCustomAttributes(ca, false)[0] as TupleElementNamesAttribute;
+ if (da == null)
+ return 50;
+ if (!da.TransformNames.SequenceEqual(new string[] { "x1", "x2", "a1", "a2", "aa1", "aa2", null, null, "b1", "b2", "cc1", "cc2", "dd1", "dd2" }))
+ return 51;
+
+ t = typeof(Del);
+
+ if (t.GetMember("Invoke")[0].GetCustomAttributes(ca, false).Length != 0)
+ return 100;
+
+ if (t.GetMethod("Invoke").GetParameters()[0].GetCustomAttributes(ca, false).Length != 1)
+ return 101;
+
+ if (t.GetMethod("Invoke").ReturnParameter.GetCustomAttributes(ca, false).Length != 1)
+ return 102;
+
+ Console.WriteLine("ok");
+ return 0;
+ }
+}
</type>
<type name="Test">
<method name="Int32 Main()" attrs="150">
- <size>1292</size>
+ <size>1316</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
<size>0</size>
</method>
</type>
+ <type name="B`1[T]">
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
</test>
<test name="dtest-002.cs">
<type name="C">
</method>
</type>
</test>
- <test name="test-pattern-04.cs">
- <type name="RecursivePattern">
- <method name="Int32 Main()" attrs="145">
- <size>750</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="C1">
- <method name="Boolean op_Is(C1, Int32 ByRef)" attrs="2198">
- <size>13</size>
- </method>
- <method name="Boolean op_Is(C1, C1 ByRef, C1 ByRef)" attrs="2198">
- <size>16</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="S">
- <method name="Boolean op_Is(S, System.Nullable`1[System.Int32] ByRef, System.Decimal ByRef)" attrs="2198">
- <size>34</size>
- </method>
- </type>
- </test>
- <test name="test-pattern-05.cs">
- <type name="RecursiveNamedPattern">
- <method name="Int32 Main()" attrs="150">
- <size>204</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="C">
- <method name="Boolean op_Is(C, Int64 ByRef, System.String ByRef)" attrs="2198">
- <size>22</size>
- </method>
- <method name="Boolean op_Is(C)" attrs="2198">
- <size>10</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- </test>
<test name="test-pattern-06.cs">
<type name="RecursiveNamedPattern">
<method name="Int32 Main()" attrs="150">
</method>
</type>
</test>
- <test name="test-pattern-07.cs">
- <type name="PropertyPattern">
- <method name="Int32 Main()" attrs="145">
- <size>684</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="X">
- <method name="System.Object get_Field()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_Field(System.Object)" attrs="2182">
- <size>8</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="Y">
- <method name="Char get_Prop()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_Prop(Char)" attrs="2182">
- <size>8</size>
- </method>
- <method name="Boolean op_Is(Y, Int32 ByRef)" attrs="2198">
- <size>13</size>
- </method>
- <method name="Void .ctor()" attrs="6278">
- <size>7</size>
- </method>
- </type>
- <type name="X">
- <method name="System.Object get_Value()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_Value(System.Object)" attrs="2182">
- <size>8</size>
- </method>
- </type>
- <type name="<PatternMatchingHelper>">
- <method name="Boolean NumberMatcher(System.Object, System.Object, Boolean)" attrs="150">
- <size>69</size>
- </method>
- </type>
- <type name="X">
- <method name="System.Nullable`1[System.Int64] get_NullableValue()" attrs="2182">
- <size>14</size>
- </method>
- <method name="Void set_NullableValue(System.Nullable`1[System.Int64])" attrs="2182">
- <size>8</size>
- </method>
- </type>
- </test>
<test name="test-pragma-unrecognized.cs">
<type name="C">
<method name="Void Main()" attrs="150">
</method>
</type>
</test>
+ <test name="test-tuple-01.cs">
+ <type name="X">
+ <method name="System.ValueTuple`2[System.Int32,System.String] Test1()" attrs="145">
+ <size>20</size>
+ </method>
+ <method name="Void Test2(System.ValueTuple`2[System.Int32,System.Int32])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void Test3(System.ValueTuple`2[System.Int32,System.String])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="System.ValueTuple`2[System.Int32,System.String] Test4()" attrs="145">
+ <size>40</size>
+ </method>
+ <method name="Int32 Main()" attrs="145">
+ <size>210</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-02.cs">
+ <type name="TupleConversions">
+ <method name="Void Main()" attrs="150">
+ <size>314</size>
+ </method>
+ <method name="Void Foo[T](T)" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void Test3(System.ValueTuple`2[System.Int64,System.Object])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-03.cs">
+ <type name="TupleDeconstruct">
+ <method name="Int32 Main()" attrs="150">
+ <size>42</size>
+ </method>
+ <method name="Void Test2()" attrs="145">
+ <size>22</size>
+ </method>
+ <method name="Void var1(System.Object, System.Object)" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void TestCustom()" attrs="145">
+ <size>7</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="ClassWithDeconstruct">
+ <method name="Void Deconstruct(System.String ByRef, System.String ByRef)" attrs="134">
+ <size>16</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="C">
+ <method name="Int32 get_Prop1()" attrs="2182">
+ <size>14</size>
+ </method>
+ <method name="Void set_Prop1(Int32)" attrs="2182">
+ <size>8</size>
+ </method>
+ <method name="Int32 get_Prop2()" attrs="2182">
+ <size>14</size>
+ </method>
+ <method name="Void set_Prop2(Int32)" attrs="2182">
+ <size>8</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-04.cs">
+ <type name="Test">
+ <method name="Int32 Main()" attrs="150">
+ <size>60</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-tuple-05.cs">
+ <type name="B`1[T]">
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="C">
+ <method name="Void set_Prop(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+ <size>28</size>
+ </method>
+ <method name="System.ValueTuple`2[System.Int32,System.Int32] get_Prop()" attrs="2182">
+ <size>34</size>
+ </method>
+ <method name="Void set_Prop2(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+ <size>2</size>
+ </method>
+ <method name="Void set_Item(System.ValueTuple`2[System.Int32,System.Int32], System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]])" attrs="2182">
+ <size>2</size>
+ </method>
+ <method name="System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]] get_Item(System.ValueTuple`2[System.Int32,System.Int32])" attrs="2182">
+ <size>18</size>
+ </method>
+ <method name="System.Nullable`1[System.ValueTuple`2[System.Int32,System.Int32]] Method(System.ValueTuple`2[System.Int32,System.Int32] ByRef)" attrs="134">
+ <size>18</size>
+ </method>
+ <method name="Void .ctor(ValueTuple`2)" attrs="6278">
+ <size>8</size>
+ </method>
+ </type>
+ <type name="Del">
+ <method name="System.ValueTuple`2[System.Int32,System.Int32] Invoke(System.ValueTuple`2[System.Int32,System.Int32])" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="System.IAsyncResult BeginInvoke(System.ValueTuple`2[System.Int32,System.Int32], System.AsyncCallback, System.Object)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="System.ValueTuple`2[System.Int32,System.Int32] EndInvoke(System.IAsyncResult)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="Void .ctor(Object, IntPtr)" attrs="6278">
+ <size>0</size>
+ </method>
+ </type>
+ <type name="Test">
+ <method name="Int32 Main()" attrs="150">
+ <size>1338</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-var-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">