Skip to content

Commit

Permalink
Merge pull request dotnet#8030 from VSadov/refReturns
Browse files Browse the repository at this point in the history
Ref returns and Locals
  • Loading branch information
VSadov committed Feb 19, 2016
2 parents f445f43 + c734932 commit 453bdae
Show file tree
Hide file tree
Showing 230 changed files with 13,005 additions and 1,248 deletions.
9 changes: 5 additions & 4 deletions Roslyn.sln
Original file line number Diff line number Diff line change
Expand Up @@ -374,27 +374,28 @@ Global
src\Compilers\Core\CommandLine\CommandLine.projitems*{ad6f474e-e6d4-4217-91f3-b7af1be31ccc}*SharedItemsImports = 13
src\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.projitems*{e8f0baa5-7327-43d1-9a51-644e81ae55f1}*SharedItemsImports = 13
src\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{d0bc9be7-24f6-40ca-8dc6-fcb93bd44b34}*SharedItemsImports = 13
src\Compilers\Core\CommandLine\CommandLine.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
src\Compilers\Server\ServerShared\ServerShared.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{e58ee9d7-1239-4961-a0c1-f9ec3952c4c1}*SharedItemsImports = 4
src\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.projitems*{a1bcd0ce-6c2f-4f8c-9a48-d9d93928e26d}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{9508f118-f62e-4c16-a6f4-7c3b56e166ad}*SharedItemsImports = 4
src\Compilers\Server\ServerShared\ServerShared.projitems*{9508f118-f62e-4c16-a6f4-7c3b56e166ad}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{9508f118-f62e-4c16-a6f4-7c3b56e166ad}*SharedItemsImports = 4
src\ExpressionEvaluator\CSharp\Source\ResultProvider\CSharpResultProvider.projitems*{bf9dac1e-3a5e-4dc3-bb44-9a64e0d4e9d4}*SharedItemsImports = 4
src\ExpressionEvaluator\CSharp\Source\ResultProvider\CSharpResultProvider.projitems*{bf9dac1e-3a5e-4dc3-bb44-9a64e0d4e9d3}*SharedItemsImports = 4
src\Compilers\Core\SharedCollections\SharedCollections.projitems*{afde6bea-5038-4a4a-a88e-dbd2e4088eed}*SharedItemsImports = 4
src\ExpressionEvaluator\Core\Source\ResultProvider\ResultProvider.projitems*{fa0e905d-ec46-466d-b7b2-3b5557f9428c}*SharedItemsImports = 4
src\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{1ee8cad3-55f9-4d91-96b2-084641da9a6c}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{7ad4fe65-9a30-41a6-8004-aa8f89bcb7f3}*SharedItemsImports = 4
src\Compilers\Core\SharedCollections\SharedCollections.projitems*{1ee8cad3-55f9-4d91-96b2-084641da9a6c}*SharedItemsImports = 4
src\Compilers\Core\MSBuildTask\Shared\MSBuildTask.Shared.projitems*{7ad4fe65-9a30-41a6-8004-aa8f89bcb7f3}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{7ad4fe65-9a30-41a6-8004-aa8f89bcb7f3}*SharedItemsImports = 4
src\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems*{3973b09a-4fbf-44a5-8359-3d22ceb71f71}*SharedItemsImports = 4
src\ExpressionEvaluator\Core\Source\ResultProvider\ResultProvider.projitems*{bedc5a4a-809e-4017-9cfd-6c8d4e1847f0}*SharedItemsImports = 4
src\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems*{b501a547-c911-4a05-ac6e-274a50dff30e}*SharedItemsImports = 4
src\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.projitems*{2523d0e6-df32-4a3e-8ae0-a19bffae2ef6}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{4b45ca0c-03a0-400f-b454-3d4bcb16af38}*SharedItemsImports = 4
src\Compilers\Core\SharedCollections\SharedCollections.projitems*{c1930979-c824-496b-a630-70f5369a636f}*SharedItemsImports = 13
src\Compilers\Core\CommandLine\CommandLine.projitems*{d874349c-8bb3-4bdc-8535-2d52ccca1198}*SharedItemsImports = 4
src\Compilers\Core\MSBuildTask\Shared\MSBuildTask.Shared.projitems*{d874349c-8bb3-4bdc-8535-2d52ccca1198}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{d874349c-8bb3-4bdc-8535-2d52ccca1198}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{e3cd2895-76a8-4d11-a316-ea67cb5ea42c}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
14 changes: 12 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,9 @@ internal enum BindValueKind : byte
CompoundAssignment,

/// <summary>
/// Expression is an out parameter.
/// Expression is passed as a ref or out parameter or assigned to a byref variable.
/// </summary>
OutParameter,
RefOrOut,

/// <summary>
/// Expression is the operand of an address-of operation (&amp;).
Expand All @@ -711,6 +711,16 @@ internal enum BindValueKind : byte
/// Expression is the receiver of a fixed buffer field access
/// </summary>
FixedReceiver,

/// <summary>
/// Expression is assigned by reference.
/// </summary>
RefAssign,

/// <summary>
/// Expression is returned by reference.
/// </summary>
RefReturn,
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ private static ImmutableArray<Symbol> PerformCrefOverloadResolution(ArrayBuilder
// These are ignored by this specific MemberSignatureComparer.
containingType: null,
name: null,
refKind: RefKind.None,
returnType: null,
returnTypeCustomModifiers: ImmutableArray<CustomModifier>.Empty,
explicitInterfaceImplementations: ImmutableArray<MethodSymbol>.Empty);
Expand All @@ -752,6 +753,7 @@ private static ImmutableArray<Symbol> PerformCrefOverloadResolution(ArrayBuilder
// These are ignored by this specific MemberSignatureComparer.
containingType: null,
name: null,
refKind: RefKind.None,
type: null,
typeCustomModifiers: ImmutableArray<CustomModifier>.Empty,
isStatic: false,
Expand Down
75 changes: 55 additions & 20 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,10 @@ private static bool RequiresGettingValue(BindValueKind kind)
case BindValueKind.IncrementDecrement:
return true;

case BindValueKind.OutParameter:
case BindValueKind.RefOrOut:
case BindValueKind.AddressOf:
case BindValueKind.Assignment:
case BindValueKind.RefReturn:
return false;

default:
Expand All @@ -267,9 +268,31 @@ private static bool RequiresSettingValue(BindValueKind kind)

case BindValueKind.CompoundAssignment:
case BindValueKind.IncrementDecrement:
case BindValueKind.OutParameter:
case BindValueKind.RefOrOut:
case BindValueKind.AddressOf:
case BindValueKind.Assignment:
case BindValueKind.RefReturn:
return true;

default:
throw ExceptionUtilities.UnexpectedValue(kind);
}
}

private static bool RequiresAddressableValue(BindValueKind kind)
{
switch (kind)
{
case BindValueKind.RValue:
case BindValueKind.RValueOrMethodGroup:
case BindValueKind.CompoundAssignment:
case BindValueKind.IncrementDecrement:
case BindValueKind.Assignment:
return false;

case BindValueKind.RefOrOut:
case BindValueKind.AddressOf:
case BindValueKind.RefReturn:
return true;

default:
Expand Down Expand Up @@ -297,6 +320,7 @@ internal BoundExpression BindValueAllowArgList(ExpressionSyntax node, Diagnostic

internal BoundExpression BindVariableOrAutoPropInitializer(
EqualsValueClauseSyntax initializerOpt,
RefKind refKind,
TypeSymbol varType,
DiagnosticBag diagnostics)
{
Expand All @@ -305,7 +329,9 @@ internal BoundExpression BindVariableOrAutoPropInitializer(
return null;
}

var initializer = BindPossibleArrayInitializer(initializerOpt.Value, varType, diagnostics);
BindValueKind valueKind;
IsInitializerRefKindValid(initializerOpt, initializerOpt, refKind, diagnostics, out valueKind);
var initializer = BindPossibleArrayInitializer(initializerOpt.Value, varType, valueKind, diagnostics);
return GenerateConversionForAssignment(varType, initializer, diagnostics);
}

Expand Down Expand Up @@ -615,7 +641,7 @@ private BoundExpression BindRefValue(RefValueExpressionSyntax node, DiagnosticBa
private BoundExpression BindMakeRef(MakeRefExpressionSyntax node, DiagnosticBag diagnostics)
{
// __makeref(x) requires that x be a variable, and not be of a restricted type.
BoundExpression argument = this.BindValue(node.Expression, diagnostics, BindValueKind.OutParameter);
BoundExpression argument = this.BindValue(node.Expression, diagnostics, BindValueKind.RefOrOut);

bool hasErrors = argument.HasAnyErrors;

Expand Down Expand Up @@ -1040,6 +1066,23 @@ private bool IsBindingImplicitlyTypedLocal(LocalSymbol symbol)
return false;
}

private bool IsBadLocalOrParameterCapture(Symbol symbol, RefKind refKind)
{
if (refKind != RefKind.None)
{
var containingMethod = this.ContainingMemberOrLambda as MethodSymbol;
if ((object)containingMethod != null && (object)symbol.ContainingSymbol != (object)containingMethod)
{
// Not expecting symbol from constructed method.
Debug.Assert(!symbol.ContainingSymbol.Equals(containingMethod));

// Captured in a lambda.
return containingMethod.MethodKind == MethodKind.AnonymousFunction || containingMethod.MethodKind == MethodKind.LocalFunction; // false in EE evaluation method
}
}
return false;
}

private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, DiagnosticBag diagnostics, LookupResultKind resultKind, bool isError)
{
// Events are handled later as we don't know yet if we are binding to the event or it's backing field.
Expand Down Expand Up @@ -1174,6 +1217,11 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag
}
else
{
if (IsBadLocalOrParameterCapture(localSymbol, localSymbol.RefKind))
{
Error(diagnostics, ErrorCode.ERR_AnonDelegateCantUseLocal, node, localSymbol);
}

type = localSymbol.Type;
}

Expand All @@ -1183,23 +1231,10 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag
case SymbolKind.Parameter:
{
var parameter = (ParameterSymbol)symbol;
if (parameter.RefKind != RefKind.None)
{
var containingMethod = this.ContainingMemberOrLambda as MethodSymbol;
if (((object)containingMethod != null) &&
((object)parameter.ContainingSymbol != (object)containingMethod))
{
// Not expecting parameter from constructed method.
Debug.Assert(!parameter.ContainingSymbol.Equals(containingMethod));

// Captured in a lambda.
if (containingMethod.MethodKind == MethodKind.AnonymousFunction || containingMethod.MethodKind == MethodKind.LocalFunction) // false in EE evaluation method
if (IsBadLocalOrParameterCapture(parameter, parameter.RefKind))
{
Error(diagnostics, ErrorCode.ERR_AnonDelegateCantUse, node, parameter.Name);
}
}
}

return new BoundParameter(node, parameter, hasErrors: isError);
}

Expand Down Expand Up @@ -1816,7 +1851,7 @@ private bool BindArgumentAndName(
{
case BoundKind.PropertyAccess:
case BoundKind.IndexerAccess:
return CheckIsVariable(argumentSyntax, arg, BindValueKind.OutParameter, false, diagnostics);
return CheckIsVariable(argumentSyntax, arg, BindValueKind.RefOrOut, false, diagnostics);
}
}

Expand All @@ -1839,7 +1874,7 @@ private bool BindArgumentAndName(
{
Debug.Assert(argumentSyntax is ArgumentSyntax || argumentSyntax is AttributeArgumentSyntax);

BindValueKind valueKind = refKind == RefKind.None ? BindValueKind.RValue : BindValueKind.OutParameter;
BindValueKind valueKind = refKind == RefKind.None ? BindValueKind.RValue : BindValueKind.RefOrOut;

// Bind argument and verify argument matches rvalue or out param requirements.
BoundExpression argument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ private static BoundFieldInitializer BindFieldInitializer(Binder binder, FieldSy
}

var collisionDetector = new LocalScopeBinder(binder);
var boundInitValue = collisionDetector.BindVariableOrAutoPropInitializer(equalsValueClauseNode, fieldSymbol.GetFieldType(fieldsBeingBound), initializerDiagnostics);
var boundInitValue = collisionDetector.BindVariableOrAutoPropInitializer(equalsValueClauseNode, RefKind.None, fieldSymbol.GetFieldType(fieldsBeingBound), initializerDiagnostics);

if (isImplicitlyTypedField)
{
Expand Down
3 changes: 1 addition & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2136,12 +2136,11 @@ internal bool IsNonMoveableVariable(BoundExpression expr, out Symbol accessedLoc
{
BoundLocal localAccess = (BoundLocal)expr;
LocalSymbol localSymbol = localAccess.LocalSymbol;
Debug.Assert(localSymbol.RefKind == RefKind.None);
accessedLocalOrParameterOpt = localSymbol;
// NOTE: The spec says that this is moveable if it is captured by an anonymous function,
// but that will be reported separately and error-recovery is better if we say that
// such locals are not moveable.
return true;
return localSymbol.RefKind == RefKind.None;
}
case BoundKind.PointerIndirectionOperator: //Covers ->, since the receiver will be one of these.
case BoundKind.PointerElementAccess:
Expand Down
8 changes: 4 additions & 4 deletions src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ private UnboundLambda MakePairLambda(CSharpSyntaxNode node, QueryTranslationStat
var x1Expression = new BoundParameter(node, lambdaSymbol.Parameters[0]) { WasCompilerGenerated = true };
var x2Expression = new BoundParameter(node, lambdaSymbol.Parameters[1]) { WasCompilerGenerated = true };
var construction = MakePair(node, x1.Name, x1Expression, x2.Name, x2Expression, state, d);
return lambdaBodyBinder.CreateBlockFromExpression(node, ImmutableArray<LocalSymbol>.Empty, null, construction, d);
return lambdaBodyBinder.CreateBlockFromExpression(node, ImmutableArray<LocalSymbol>.Empty, RefKind.None, construction, null, d);
};

var result = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x1, x2), node, bodyFactory);
Expand Down Expand Up @@ -593,7 +593,7 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Diagnos

// The bound block represents a closure scope for transparent identifiers captured in the let clause.
// Such closures shall be associated with the lambda body expression.
return lambdaBodyBinder.CreateBlockFromExpression(let.Expression, lambdaBodyBinder.Locals, null, construction, d);
return lambdaBodyBinder.CreateBlockFromExpression(let.Expression, lambdaBodyBinder.Locals, RefKind.None, construction, null, d);
};

var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x), let.Expression, bodyFactory);
Expand Down Expand Up @@ -659,7 +659,7 @@ private UnboundLambda MakeQueryUnboundLambda(RangeVariableMap qvm, ImmutableArra
{
return MakeQueryUnboundLambda(expression, new QueryUnboundLambdaState(this, qvm, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) =>
{
return lambdaBodyBinder.BindLambdaExpressionAsBlock(expression, diagnostics);
return lambdaBodyBinder.BindLambdaExpressionAsBlock(RefKind.None, expression, diagnostics);
}));
}

Expand All @@ -672,7 +672,7 @@ private UnboundLambda MakeQueryUnboundLambdaWithCast(RangeVariableMap qvm, Range
// We transform the expression from "expr" to "expr.Cast<castTypeOpt>()".
boundExpression = lambdaBodyBinder.MakeQueryInvocation(expression, boundExpression, "Cast", castTypeSyntax, castType, diagnostics);

return lambdaBodyBinder.CreateBlockFromExpression(expression, lambdaBodyBinder.Locals, expression, boundExpression, diagnostics);
return lambdaBodyBinder.CreateBlockFromExpression(expression, lambdaBodyBinder.Locals, RefKind.None, boundExpression, expression, diagnostics);
}));
}

Expand Down
Loading

0 comments on commit 453bdae

Please sign in to comment.