internal BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyntax nodeOpt, LocalDeclarationKind localKind, DiagnosticBag diagnostics, out ImmutableArray<BoundLocalDeclaration> declarations) { if (nodeOpt == null) { declarations = ImmutableArray<BoundLocalDeclaration>.Empty; return null; } var typeSyntax = nodeOpt.Type; AliasSymbol alias; bool isVar; TypeSymbol declType = BindType(typeSyntax, diagnostics, out isVar, out alias); Debug.Assert((object)declType != null || isVar); var variables = nodeOpt.Variables; int count = variables.Count; Debug.Assert(count > 0); if (isVar && count > 1) { // 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. Error(diagnostics, ErrorCode.ERR_ImplicitlyTypedVariableMultipleDeclarator, nodeOpt); } var declarationArray = new BoundLocalDeclaration[count]; for (int i = 0; i < count; i++) { var variableDeclarator = variables[i]; var declaration = BindVariableDeclaration(localKind, isVar, variableDeclarator, typeSyntax, declType, alias, diagnostics); declarationArray[i] = declaration; } declarations = declarationArray.AsImmutableOrNull(); return (count == 1) ? (BoundStatement)declarations[0] : new BoundMultipleLocalDeclarations(nodeOpt, declarations); }
private BoundStatement BindDeclarationStatement(LocalDeclarationStatementSyntax node, DiagnosticBag diagnostics) { var typeSyntax = node.Declaration.Type; bool isConst = node.IsConst; bool isVar; AliasSymbol alias; TypeSymbol declType = BindVariableType(node, diagnostics, typeSyntax, ref isConst, isVar: out isVar, alias: out alias); // UNDONE: "possible expression" feature for IDE LocalDeclarationKind kind = LocalDeclarationKind.RegularVariable; if (isConst) { kind = LocalDeclarationKind.Constant; } var variableList = node.Declaration.Variables; int variableCount = variableList.Count; if (variableCount == 1) { return BindVariableDeclaration(kind, isVar, variableList[0], typeSyntax, declType, alias, diagnostics, node); } else { BoundLocalDeclaration[] boundDeclarations = new BoundLocalDeclaration[variableCount]; int i = 0; foreach (var variableDeclaratorSyntax in variableList) { boundDeclarations[i++] = BindVariableDeclaration(kind, isVar, variableDeclaratorSyntax, typeSyntax, declType, alias, diagnostics); } return new BoundMultipleLocalDeclarations(node, boundDeclarations.AsImmutableOrNull()); } }
private BoundStatement BindDeclarationStatement(LocalDeclarationStatementSyntax node, DiagnosticBag diagnostics) { var typeSyntax = node.Declaration.Type; bool isConst = node.IsConst; bool isFixed = node.IsFixed; // 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. bool isVar; AliasSymbol alias; TypeSymbol declType = BindType(typeSyntax, 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 (isFixed) { Error(diagnostics, ErrorCode.ERR_ImplicitlyTypedLocalCannotBeFixed, node); } if (isConst) { Error(diagnostics, ErrorCode.ERR_ImplicitlyTypedVariableCannotBeConst, node); // 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 (node.Declaration.Variables.Count > 1 && !node.HasErrors) { Error(diagnostics, ErrorCode.ERR_ImplicitlyTypedVariableMultipleDeclarator, node); } } 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 (isFixed && !(declType is PointerTypeSymbol)) { Error(diagnostics, ErrorCode.ERR_BadFixedInitType, node); } if (isConst && !declType.CanBeConst()) { Error(diagnostics, ErrorCode.ERR_BadConstType, typeSyntax, declType); // Keep processing it as a non-const local. isConst = false; } } // UNDONE: "possible expression" feature for IDE LocalDeclarationKind kind = LocalDeclarationKind.Variable; if (isFixed) { kind = LocalDeclarationKind.Fixed; } if (isConst) { kind = LocalDeclarationKind.Constant; } var variableList = node.Declaration.Variables; int variableCount = variableList.Count; if (variableCount == 1) { return BindVariableDeclaration(kind, isVar, variableList[0], typeSyntax, declType, alias, diagnostics, node); } else { BoundLocalDeclaration[] boundDeclarations = new BoundLocalDeclaration[variableCount]; int i = 0; foreach (var variableDeclaratorSyntax in variableList) { boundDeclarations[i++] = BindVariableDeclaration(kind, isVar, variableDeclaratorSyntax, typeSyntax, declType, alias, diagnostics); } return new BoundMultipleLocalDeclarations(node, boundDeclarations.AsImmutableOrNull()); } }