private SourceLocalSymbol( Symbol containingSymbol, Binder scopeBinder, bool allowRefKind, TypeSyntax typeSyntax, SyntaxToken identifierToken, LocalDeclarationKind declarationKind) { Debug.Assert(identifierToken.Kind() != SyntaxKind.None); Debug.Assert(declarationKind != LocalDeclarationKind.None); Debug.Assert(scopeBinder != null); this._scopeBinder = scopeBinder; this._containingSymbol = containingSymbol; this._identifierToken = identifierToken; this._typeSyntax = allowRefKind ? typeSyntax.SkipRef(out this._refKind) : typeSyntax; this._declarationKind = declarationKind; // create this eagerly as it will always be needed for the EnsureSingleDefinition _locations = ImmutableArray.Create<Location>(identifierToken.GetLocation()); }
private TypeSymbol BindVariableType(CSharpSyntaxNode declarationNode, DiagnosticBag diagnostics, TypeSyntax typeSyntax, ref bool isConst, out bool isVar, out AliasSymbol alias) { Debug.Assert( declarationNode.Kind() == SyntaxKind.SingleVariableDesignation || declarationNode.Kind() == SyntaxKind.VariableDeclaration || declarationNode.Kind() == SyntaxKind.DeclarationExpression); // If the type is "var" then suppress errors when binding it. "var" might be a legal type // or it might not; if it is not then we do not want to report an error. If it is, then // we want to treat the declaration as an explicitly typed declaration. RefKind refKind; TypeSymbol declType = BindType(typeSyntax.SkipRef(out refKind), diagnostics, out isVar, out alias); Debug.Assert((object)declType != null || isVar); if (isVar) { // There are a number of ways in which a var decl can be illegal, but in these // cases we should report an error and then keep right on going with the inference. if (isConst) { Error(diagnostics, ErrorCode.ERR_ImplicitlyTypedVariableCannotBeConst, declarationNode); // Keep processing it as a non-const local. isConst = false; } // In the dev10 compiler the error recovery semantics for the illegal case // "var x = 10, y = 123.4;" are somewhat undesirable. // // First off, this is an error because a straw poll of language designers and // users showed that there was no consensus on whether the above should mean // "double x = 10, y = 123.4;", taking the best type available and substituting // that for "var", or treating it as "var x = 10; var y = 123.4;" -- since there // was no consensus we decided to simply make it illegal. // // In dev10 for error recovery in the IDE we do an odd thing -- we simply take // the type of the first variable and use it. So that is "int x = 10, y = 123.4;". // // This seems less than ideal. In the error recovery scenario it probably makes // more sense to treat that as "var x = 10; var y = 123.4;" and do each inference // separately. if (declarationNode.Parent.Kind() == SyntaxKind.LocalDeclarationStatement && ((VariableDeclarationSyntax)declarationNode).Variables.Count > 1 && !declarationNode.HasErrors) { Error(diagnostics, ErrorCode.ERR_ImplicitlyTypedVariableMultipleDeclarator, declarationNode); } } else { // In the native compiler when given a situation like // // D[] x; // // where D is a static type we report both that D cannot be an element type // of an array, and that D[] is not a valid type for a local variable. // This seems silly; the first error is entirely sufficient. We no longer // produce additional errors for local variables of arrays of static types. if (declType.IsStatic) { Error(diagnostics, ErrorCode.ERR_VarDeclIsStaticClass, typeSyntax, declType); } if (isConst && !declType.CanBeConst()) { Error(diagnostics, ErrorCode.ERR_BadConstType, typeSyntax, declType); // Keep processing it as a non-const local. isConst = false; } } return declType; }