| File: Lowering\LocalRewriter\LocalRewriter_Field.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp { internal sealed partial class LocalRewriter { public override BoundNode VisitFieldAccess(BoundFieldAccess node) { BoundExpression? rewrittenReceiver = VisitExpression(node.ReceiverOpt); return MakeFieldAccess(node.Syntax, rewrittenReceiver, node.FieldSymbol, node.ConstantValueOpt, node.ResultKind, node.Type, node); } private BoundExpression MakeFieldAccess( SyntaxNode syntax, BoundExpression? rewrittenReceiver, FieldSymbol fieldSymbol, ConstantValue? constantValueOpt, LookupResultKind resultKind, TypeSymbol type, BoundFieldAccess? oldNodeOpt = null) { if (fieldSymbol.ContainingType.IsTupleType) { return MakeTupleFieldAccess(syntax, fieldSymbol, rewrittenReceiver); } BoundExpression result = oldNodeOpt != null ? oldNodeOpt.Update(rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type) : new BoundFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type); if (fieldSymbol.IsFixedSizeBuffer) { // a reference to a fixed buffer is translated into its address result = new BoundAddressOfOperator(syntax, result, type, false); } return result; } /// <summary> /// Converts access to a tuple instance into access into the underlying ValueTuple(s). /// /// For instance, tuple.Item8 /// produces fieldAccess(field=Item1, receiver=fieldAccess(field=Rest, receiver=ValueTuple for tuple)) /// </summary> private BoundExpression MakeTupleFieldAccess( SyntaxNode syntax, FieldSymbol tupleField, BoundExpression? rewrittenReceiver) { var tupleType = tupleField.ContainingType; NamedTypeSymbol currentLinkType = tupleType; FieldSymbol underlyingField = tupleField.TupleUnderlyingField; if ((object)underlyingField == null) { // Use-site error must have been reported elsewhere. return _factory.BadExpression(tupleField.Type); } if (rewrittenReceiver?.Kind == BoundKind.DefaultExpression) { // Optimization: `default((int, string)).Item2` is simply `default(string)` return new BoundDefaultExpression(syntax, tupleField.Type); } if (!TypeSymbol.Equals(underlyingField.ContainingType, currentLinkType, TypeCompareKind.ConsiderEverything2)) { WellKnownMember wellKnownTupleRest = NamedTypeSymbol.GetTupleTypeMember(NamedTypeSymbol.ValueTupleRestPosition, NamedTypeSymbol.ValueTupleRestPosition); var tupleRestField = (FieldSymbol?)NamedTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTupleRest, _diagnostics, syntax); if (tupleRestField is null) { // error tolerance for cases when Rest is missing return _factory.BadExpression(tupleField.Type); } // make nested field accesses to Rest do { FieldSymbol nestedFieldSymbol = tupleRestField.AsMember(currentLinkType); rewrittenReceiver = _factory.Field(rewrittenReceiver, nestedFieldSymbol); currentLinkType = (NamedTypeSymbol)currentLinkType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[NamedTypeSymbol.ValueTupleRestPosition - 1].Type; } while (!TypeSymbol.Equals(underlyingField.ContainingType, currentLinkType, TypeCompareKind.ConsiderEverything2)); } // make a field access for the most local access return _factory.Field(rewrittenReceiver, underlyingField); } private BoundExpression MakeTupleFieldAccessAndReportUseSiteDiagnostics(BoundExpression tuple, SyntaxNode syntax, FieldSymbol field) { // Use default field rather than implicitly named fields since // fields from inferred names are not usable in C# 7.0. field = field.CorrespondingTupleField ?? field; UseSiteInfo<AssemblySymbol> useSiteInfo = field.GetUseSiteInfo(); if (useSiteInfo.DiagnosticInfo?.Severity != DiagnosticSeverity.Error) { useSiteInfo = useSiteInfo.AdjustDiagnosticInfo(null); } _diagnostics.Add(useSiteInfo, syntax); return MakeTupleFieldAccess(syntax, field, tuple); } } }