Skip to content

Commit 61bdbd2

Browse files
committed
Move unsupported super use diagnosis form Parse to Sema
1 parent 7f2b236 commit 61bdbd2

File tree

13 files changed

+213
-117
lines changed

13 files changed

+213
-117
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6689,6 +6689,13 @@ class ParamDecl : public VarDecl {
66896689
DeclContext *Parent,
66906690
ParamSpecifier specifier = ParamSpecifier::Default);
66916691

6692+
static ParamDecl *createParsed(ASTContext &Context, SourceLoc specifierLoc,
6693+
SourceLoc argumentNameLoc,
6694+
Identifier argumentName,
6695+
SourceLoc parameterNameLoc,
6696+
Identifier parameterName, Expr *defaultValue,
6697+
DeclContext *dc);
6698+
66926699
/// Retrieve the argument (API) name for this function parameter.
66936700
Identifier getArgumentName() const {
66946701
return ArgumentNameAndFlags.getPointer();

include/swift/AST/DefaultArgumentKind.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class StringRef;
2727

2828
namespace swift {
2929

30-
class Expr;
31-
3230
/// Describes the kind of default argument a tuple pattern element has.
3331
enum class DefaultArgumentKind : uint8_t {
3432
/// No default argument.
@@ -56,11 +54,6 @@ enum class DefaultArgumentKind : uint8_t {
5654
};
5755
enum { NumDefaultArgumentKindBits = 4 };
5856

59-
/// Determine the kind of a default argument given a parsed expression that has
60-
/// not yet been type-checked.
61-
/// FIXME: Requestify/internalize the computation of the default arg expr and its kind (given a parsed expr) once the old parser no longer needs this.
62-
DefaultArgumentKind getDefaultArgKind(Expr *init);
63-
6457
struct ArgumentAttrs {
6558
DefaultArgumentKind argumentKind;
6659
bool isUnavailableInSwift = false;

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,8 +1344,6 @@ ERROR(expected_identifier_after_dot_expr,none,
13441344
ERROR(expected_identifier_after_super_dot_expr,
13451345
PointsToFirstBadToken,
13461346
"expected identifier or 'init' after super '.' expression", ())
1347-
ERROR(expected_dot_or_subscript_after_super,PointsToFirstBadToken,
1348-
"expected '.' or '[' after 'super'", ())
13491347

13501348
WARNING(await_before_try,none, "'try' must precede 'await'", ())
13511349

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4317,6 +4317,9 @@ ERROR(no_member_of_module,none,
43174317

43184318
// 'super'.
43194319

4320+
ERROR(super_invalid_parent_expr,none,
4321+
"'super' may be used only to access a superclass member, subscript, or "
4322+
"initializer", ())
43204323
ERROR(super_no_superclass,none,
43214324
"'super' cannot be used in %select{|extension of }0class %1 because it "
43224325
"has no superclass",

include/swift/Parse/Parser.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,9 +1593,6 @@ class Parser {
15931593
/// The default argument for this parameter.
15941594
Expr *DefaultArg = nullptr;
15951595

1596-
/// True if this parameter inherits a default argument via '= super'
1597-
bool hasInheritedDefaultArg = false;
1598-
15991596
/// True if we emitted a parse error about this parameter.
16001597
bool isInvalid = false;
16011598

lib/AST/ASTBridging.cpp

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -840,22 +840,10 @@ BridgedParamDecl BridgedParamDecl_createParsed(
840840
BridgedSourceLoc cArgNameLoc, BridgedIdentifier cParamName,
841841
BridgedSourceLoc cParamNameLoc, BridgedNullableTypeRepr opaqueType,
842842
BridgedNullableExpr opaqueDefaultValue) {
843-
auto *declContext = cDeclContext.unbridged();
844-
845-
auto *defaultValue = opaqueDefaultValue.unbridged();
846-
DefaultArgumentKind defaultArgumentKind;
847-
848-
if (declContext->getParentSourceFile()->Kind == SourceFileKind::Interface &&
849-
isa<SuperRefExpr>(defaultValue)) {
850-
defaultValue = nullptr;
851-
defaultArgumentKind = DefaultArgumentKind::Inherited;
852-
} else {
853-
defaultArgumentKind = getDefaultArgKind(defaultValue);
854-
}
855-
856-
auto *paramDecl = new (cContext.unbridged()) ParamDecl(
857-
cSpecifierLoc.unbridged(), cArgNameLoc.unbridged(), cArgName.unbridged(),
858-
cParamNameLoc.unbridged(), cParamName.unbridged(), declContext);
843+
auto *paramDecl = ParamDecl::createParsed(
844+
cContext.unbridged(), cSpecifierLoc.unbridged(), cArgNameLoc.unbridged(),
845+
cArgName.unbridged(), cParamNameLoc.unbridged(), cParamName.unbridged(),
846+
opaqueDefaultValue.unbridged(), cDeclContext.unbridged());
859847

860848
if (auto type = opaqueType.unbridged()) {
861849
paramDecl->setTypeRepr(type);
@@ -899,9 +887,6 @@ BridgedParamDecl BridgedParamDecl_createParsed(
899887
}
900888
}
901889

902-
paramDecl->setDefaultExpr(defaultValue, /*isTypeChecked*/ false);
903-
paramDecl->setDefaultArgumentKind(defaultArgumentKind);
904-
905890
return paramDecl;
906891
}
907892

lib/AST/Decl.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8301,7 +8301,9 @@ ParamDecl *ParamDecl::createImplicit(ASTContext &Context,
83018301
interfaceType, Parent, specifier);
83028302
}
83038303

8304-
DefaultArgumentKind swift::getDefaultArgKind(Expr *init) {
8304+
/// Determine the kind of a default argument for the given expression.
8305+
static DefaultArgumentKind computeDefaultArgumentKind(DeclContext *dc,
8306+
Expr *init) {
83058307
if (!init)
83068308
return DefaultArgumentKind::None;
83078309

@@ -8314,6 +8316,19 @@ DefaultArgumentKind swift::getDefaultArgKind(Expr *init) {
83148316
if (isa<MacroExpansionExpr>(init))
83158317
return DefaultArgumentKind::ExpressionMacro;
83168318

8319+
if (isa<SuperRefExpr>(init)) {
8320+
// The compiler does not synthesize inherited initializers when
8321+
// type-checking Swift module interfaces. Instead, module interfaces are
8322+
// expected to include them explicitly in subclasses. A default argument of
8323+
// '= super' in a parameter of such initializer indicates that the default
8324+
// argument is inherited.
8325+
if (dc->getParentSourceFile()->Kind == SourceFileKind::Interface) {
8326+
return DefaultArgumentKind::Inherited;
8327+
} else {
8328+
return DefaultArgumentKind::Normal;
8329+
}
8330+
}
8331+
83178332
auto magic = dyn_cast<MagicIdentifierLiteralExpr>(init);
83188333
if (!magic)
83198334
return DefaultArgumentKind::Normal;
@@ -8328,6 +8343,30 @@ DefaultArgumentKind swift::getDefaultArgKind(Expr *init) {
83288343
llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch.");
83298344
}
83308345

8346+
ParamDecl *ParamDecl::createParsed(ASTContext &Context, SourceLoc specifierLoc,
8347+
SourceLoc argumentNameLoc,
8348+
Identifier argumentName,
8349+
SourceLoc parameterNameLoc,
8350+
Identifier parameterName, Expr *defaultValue,
8351+
DeclContext *dc) {
8352+
auto *decl =
8353+
new (Context) ParamDecl(specifierLoc, argumentNameLoc, argumentName,
8354+
parameterNameLoc, parameterName, dc);
8355+
8356+
const auto kind = computeDefaultArgumentKind(dc, defaultValue);
8357+
if (kind == DefaultArgumentKind::Inherited) {
8358+
// The 'super' in inherited default arguments is a specifier rather than an
8359+
// expression.
8360+
// TODO: However, we may want to retain its location for diagnostics.
8361+
defaultValue = nullptr;
8362+
}
8363+
8364+
decl->setDefaultExpr(defaultValue, false);
8365+
decl->setDefaultArgumentKind(kind);
8366+
8367+
return decl;
8368+
}
8369+
83318370
/// Retrieve the type of 'self' for the given context.
83328371
Type DeclContext::getSelfTypeInContext() const {
83338372
return mapTypeIntoContext(getSelfInterfaceType());

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,28 +1031,11 @@ void Parser::tryLexRegexLiteral(bool forUnappliedOperator) {
10311031
/// parseExprSuper
10321032
///
10331033
/// expr-super:
1034-
/// expr-super-member
1035-
/// expr-super-init
1036-
/// expr-super-subscript
1037-
/// expr-super-member:
1038-
/// 'super' '.' identifier
1039-
/// expr-super-init:
1040-
/// 'super' '.' 'init'
1041-
/// expr-super-subscript:
1042-
/// 'super' '[' expr ']'
1034+
/// 'super'
10431035
ParserResult<Expr> Parser::parseExprSuper() {
10441036
// Parse the 'super' reference.
10451037
SourceLoc superLoc = consumeToken(tok::kw_super);
10461038

1047-
// 'super.' must be followed by a member ref, explicit initializer ref, or
1048-
// subscript call.
1049-
if (!Tok.isAny(tok::period, tok::period_prefix, tok::code_complete) &&
1050-
!Tok.isFollowingLSquare()) {
1051-
if (!consumeIf(tok::unknown))
1052-
diagnose(Tok, diag::expected_dot_or_subscript_after_super);
1053-
return nullptr;
1054-
}
1055-
10561039
return makeParserResult(new (Context) SuperRefExpr(/*selfDecl=*/nullptr,
10571040
superLoc,
10581041
/*Implicit=*/false));

lib/Parse/ParsePattern.cpp

Lines changed: 10 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,14 @@ void Parser::DefaultArgumentInfo::setFunctionContext(
3737
}
3838
}
3939

40-
static ParserStatus parseDefaultArgument(
41-
Parser &P, Parser::DefaultArgumentInfo *defaultArgs, unsigned argIndex,
42-
Expr *&init, bool &hasInheritedDefaultArg,
43-
Parser::ParameterContextKind paramContext) {
40+
static ParserStatus
41+
parseDefaultArgument(Parser &P, Parser::DefaultArgumentInfo *defaultArgs,
42+
unsigned argIndex, Expr *&init,
43+
Parser::ParameterContextKind paramContext) {
4444
assert(P.Tok.is(tok::equal) ||
4545
(P.Tok.isBinaryOperator() && P.Tok.getText() == "=="));
4646
SourceLoc equalLoc = P.consumeToken();
4747

48-
if (P.SF.Kind == SourceFileKind::Interface) {
49-
// Swift module interfaces don't synthesize inherited initializers and
50-
// instead include them explicitly in subclasses. Since the
51-
// \c DefaultArgumentKind of these initializers is \c Inherited, this is
52-
// represented textually as `= super` in the interface.
53-
54-
// If we're in a module interface and the default argument is exactly
55-
// `super` (i.e. the token after that is `,` or `)` which end a parameter)
56-
// report an inherited default argument to the caller and return.
57-
if (P.Tok.is(tok::kw_super) && P.peekToken().isAny(tok::comma, tok::r_paren)) {
58-
hasInheritedDefaultArg = true;
59-
P.consumeToken(tok::kw_super);
60-
defaultArgs->HasDefaultArgument = true;
61-
return ParserStatus();
62-
}
63-
}
64-
6548
// Enter a fresh default-argument context with a meaningless parent.
6649
// We'll change the parent to the function later after we've created
6750
// that declaration.
@@ -483,9 +466,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
483466
.fixItReplace(EqualLoc, "=");
484467
}
485468

486-
status |= parseDefaultArgument(
487-
*this, defaultArgs, defaultArgIndex, param.DefaultArg,
488-
param.hasInheritedDefaultArg, paramContext);
469+
status |= parseDefaultArgument(*this, defaultArgs, defaultArgIndex,
470+
param.DefaultArg, paramContext);
489471
}
490472

491473
// If we haven't made progress, don't add the parameter.
@@ -547,10 +529,9 @@ mapParsedParameters(Parser &parser,
547529
Identifier argName, SourceLoc argNameLoc,
548530
Identifier paramName, SourceLoc paramNameLoc)
549531
-> ParamDecl * {
550-
auto param = new (ctx) ParamDecl(paramInfo.SpecifierLoc,
551-
argNameLoc, argName,
552-
paramNameLoc, paramName,
553-
parser.CurDeclContext);
532+
auto param = ParamDecl::createParsed(
533+
ctx, paramInfo.SpecifierLoc, argNameLoc, argName, paramNameLoc,
534+
paramName, paramInfo.DefaultArg, parser.CurDeclContext);
554535
param->getAttrs() = paramInfo.Attrs;
555536

556537
bool parsingEnumElt
@@ -713,8 +694,7 @@ mapParsedParameters(Parser &parser,
713694
param.FirstName, param.FirstNameLoc);
714695
}
715696

716-
assert (((!param.DefaultArg &&
717-
!param.hasInheritedDefaultArg) ||
697+
assert ((!param.DefaultArg ||
718698
paramContext == Parser::ParameterContextKind::Function ||
719699
paramContext == Parser::ParameterContextKind::Operator ||
720700
paramContext == Parser::ParameterContextKind::Initializer ||
@@ -723,14 +703,6 @@ mapParsedParameters(Parser &parser,
723703
paramContext == Parser::ParameterContextKind::Macro) &&
724704
"Default arguments are only permitted on the first param clause");
725705

726-
if (param.DefaultArg) {
727-
DefaultArgumentKind kind = getDefaultArgKind(param.DefaultArg);
728-
result->setDefaultArgumentKind(kind);
729-
result->setDefaultExpr(param.DefaultArg, /*isTypeChecked*/ false);
730-
} else if (param.hasInheritedDefaultArg) {
731-
result->setDefaultArgumentKind(DefaultArgumentKind::Inherited);
732-
}
733-
734706
elements.push_back(result);
735707

736708
if (argNames)

lib/Sema/PreCheckExpr.cpp

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,8 @@ namespace {
11061106
VarDecl *getImplicitSelfDeclForSuperContext(SourceLoc Loc) ;
11071107

11081108
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
1109+
auto &diags = Ctx.Diags;
1110+
11091111
// FIXME(diagnostics): `InOutType` could appear here as a result
11101112
// of successful re-typecheck of the one of the sub-expressions e.g.
11111113
// `let _: Int = { (s: inout S) in s.bar() }`. On the first
@@ -1148,11 +1150,39 @@ namespace {
11481150
// Resolve 'super' references.
11491151
if (auto *superRef = dyn_cast<SuperRefExpr>(expr)) {
11501152
auto loc = superRef->getLoc();
1153+
11511154
auto *selfDecl = getImplicitSelfDeclForSuperContext(loc);
11521155
if (selfDecl == nullptr)
1153-
return finish(true, new (Ctx) ErrorExpr(loc));
1156+
return finish(false, new (Ctx) ErrorExpr(loc));
11541157

11551158
superRef->setSelf(selfDecl);
1159+
1160+
const bool isValidSuper = [&]() -> bool {
1161+
auto *parentExpr = Parent.getAsExpr();
1162+
if (!parentExpr) {
1163+
return false;
1164+
}
1165+
1166+
if (isa<UnresolvedDotExpr>(parentExpr) ||
1167+
isa<MemberRefExpr>(parentExpr)) {
1168+
return true;
1169+
} else if (auto *SE = dyn_cast<SubscriptExpr>(parentExpr)) {
1170+
// 'super[]' is valid, but 'x[super]' is not.
1171+
return superRef == SE->getBase();
1172+
}
1173+
1174+
return false;
1175+
}();
1176+
1177+
// NB: This is done along the happy path because presenting this error
1178+
// in a context where 'super' is not legal to begin with is not helpful.
1179+
if (!isValidSuper) {
1180+
// Diagnose and keep going. It is important for source tooling such
1181+
// as code completion that Sema is able to provide type information
1182+
// for 'super' in arbitrary positions inside expressions.
1183+
diags.diagnose(loc, diag::super_invalid_parent_expr);
1184+
}
1185+
11561186
return finish(true, superRef);
11571187
}
11581188

@@ -1193,8 +1223,8 @@ namespace {
11931223
auto *DRE = cast<DeclRefExpr>(refExpr);
11941224
if (accessor->getImplicitSelfDecl() == DRE->getDecl() &&
11951225
!isa_and_nonnull<UnresolvedDotExpr>(Parent.getAsExpr())) {
1196-
Ctx.Diags.diagnose(unresolved->getLoc(),
1197-
diag::invalid_use_of_self_in_init_accessor);
1226+
diags.diagnose(unresolved->getLoc(),
1227+
diag::invalid_use_of_self_in_init_accessor);
11981228
refExpr = new (Ctx) ErrorExpr(unresolved->getSourceRange());
11991229
}
12001230
}
@@ -1240,24 +1270,21 @@ namespace {
12401270
// a member reference, it might be valid to have `&`
12411271
// before all of the parens.
12421272
if (lastInnerParenLoc.isValid()) {
1243-
auto &DE = getASTContext().Diags;
1244-
auto diag = DE.diagnose(expr->getStartLoc(),
1245-
diag::extraneous_address_of);
1273+
auto diag = diags.diagnose(expr->getStartLoc(),
1274+
diag::extraneous_address_of);
12461275
diag.fixItExchange(expr->getLoc(), lastInnerParenLoc);
12471276
}
12481277
return finish(true, expr);
12491278
}
12501279

12511280
if (isa<SubscriptExpr>(parent)) {
1252-
getASTContext().Diags.diagnose(
1253-
expr->getStartLoc(),
1254-
diag::cannot_pass_inout_arg_to_subscript);
1281+
diags.diagnose(expr->getStartLoc(),
1282+
diag::cannot_pass_inout_arg_to_subscript);
12551283
return finish(false, nullptr);
12561284
}
12571285
}
12581286

1259-
getASTContext().Diags.diagnose(expr->getStartLoc(),
1260-
diag::extraneous_address_of);
1287+
diags.diagnose(expr->getStartLoc(), diag::extraneous_address_of);
12611288
return finish(false, nullptr);
12621289
}
12631290

0 commit comments

Comments
 (0)