Skip to content

Fix regression with inout in enum and subscript signatures #17020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsCommon.def
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ NOTE(profile_read_error,none,
ERROR(generic_signature_not_minimal,none,
"generic requirement '%0' is redundant in %1", (StringRef, StringRef))

ERROR(attr_only_on_parameters, none,
"'%0' may only be used on parameters", (StringRef))

#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG
Expand Down
2 changes: 0 additions & 2 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1309,8 +1309,6 @@ ERROR(attr_interpolated_string,none,

ERROR(attr_only_at_non_local_scope, none,
"attribute '%0' can only be used in a non-local scope", (StringRef))
ERROR(attr_only_on_parameters_parse, none,
"'%0' may only be used on parameters", (StringRef))

// Access control
ERROR(attr_access_expected_set,none,
Expand Down
6 changes: 2 additions & 4 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2298,12 +2298,10 @@ ERROR(property_behavior_conformance_broken,none,

ERROR(attr_only_one_decl_kind,none,
"%0 may only be used on '%1' declarations", (DeclAttribute,StringRef))
ERROR(attr_only_on_parameters,none,
"%0 may only be used on parameters", (StringRef))
ERROR(attr_not_on_variadic_parameters,none,
"%0 must not be used on variadic parameters", (StringRef))
"'%0' must not be used on variadic parameters", (StringRef))
ERROR(attr_not_on_subscript_parameters,none,
"%0 must not be used on subscript parameters", (StringRef))
"'%0' must not be used on subscript parameters", (StringRef))

ERROR(override_final,none,
"%0 overrides a 'final' %1", (DescriptiveDeclKind, DescriptiveDeclKind))
Expand Down
5 changes: 3 additions & 2 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4366,8 +4366,9 @@ ParamDecl::ParamDecl(Specifier specifier,
/*IsCaptureList*/false, parameterNameLoc, parameterName, ty, dc),
ArgumentName(argumentName), ArgumentNameLoc(argumentNameLoc),
SpecifierLoc(specifierLoc) {
assert(specifier != Specifier::Var &&
"'var' cannot appear on parameters; you meant 'inout'");

assert(specifier != Specifier::Var &&
"'var' cannot appear on parameters; you meant 'inout'");
Bits.ParamDecl.IsTypeLocImplicit = false;
Bits.ParamDecl.defaultArgumentKind =
static_cast<unsigned>(DefaultArgumentKind::None);
Expand Down
2 changes: 1 addition & 1 deletion lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5617,7 +5617,7 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
// argument label
auto *paramDecl =
new (Impl.SwiftContext) ParamDecl(
VarDecl::Specifier::Let, SourceLoc(), SourceLoc(), argNames.front(),
VarDecl::Specifier::Default, SourceLoc(), SourceLoc(), argNames.front(),
SourceLoc(), argNames.front(), Impl.SwiftContext.TheEmptyTupleType,
dc);
paramDecl->setInterfaceType(Impl.SwiftContext.TheEmptyTupleType);
Expand Down
2 changes: 1 addition & 1 deletion lib/Parse/ParsePattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ mapParsedParameters(Parser &parser,
Identifier argName, SourceLoc argNameLoc,
Identifier paramName, SourceLoc paramNameLoc)
-> ParamDecl * {
auto param = new (ctx) ParamDecl(paramInfo.SpecifierKind,
auto param = new (ctx) ParamDecl(VarDecl::Specifier::Default,
paramInfo.SpecifierLoc,
argNameLoc, argName,
paramNameLoc, paramName, Type(),
Expand Down
2 changes: 1 addition & 1 deletion lib/Parse/ParseType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
Tok.getRawText().equals("__owned")))) {
// Type specifier should already be parsed before here. This only happens
// for construct like 'P1 & inout P2'.
diagnose(Tok.getLoc(), diag::attr_only_on_parameters_parse, Tok.getText());
diagnose(Tok.getLoc(), diag::attr_only_on_parameters, Tok.getRawText());
consumeToken();
}

Expand Down
20 changes: 6 additions & 14 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2193,11 +2193,7 @@ Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr,
options -= TypeResolutionFlags::ImmediateFunctionInput;
options -= TypeResolutionFlags::FunctionInput;
options -= TypeResolutionFlags::TypeAliasUnderlyingType;
// FIXME: Until we remove the IUO type from the type system, we
// need to continue to parse IUOs in SIL tests so that we can
// match the types we generate from the importer.
if (!options.contains(TypeResolutionFlags::SILMode))
options -= TypeResolutionFlags::AllowIUO;
options -= TypeResolutionFlags::AllowIUO;

Type inputTy = resolveType(repr->getArgsTypeRepr(),
options | TypeResolutionFlags::ImmediateFunctionInput);
Expand Down Expand Up @@ -2712,13 +2708,13 @@ Type TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
StringRef name;
switch (repr->getKind()) {
case TypeReprKind::InOut:
name = "'inout'";
name = "inout";
break;
case TypeReprKind::Shared:
name = "'__shared'";
name = "__shared";
break;
case TypeReprKind::Owned:
name = "'__owned'";
name = "__owned";
break;
default:
llvm_unreachable("unknown SpecifierTypeRepr kind");
Expand Down Expand Up @@ -2863,11 +2859,7 @@ Type TypeResolver::resolveTupleType(TupleTypeRepr *repr,
auto elementOptions = options;
if (repr->isParenType()) {
// We also want to disallow IUO within even a paren.
// FIXME: Until we remove the IUO type from the type system, we
// need to continue to parse IUOs in SIL tests so that we can
// match the types we generate from the importer.
if (!options.contains(TypeResolutionFlags::SILMode))
elementOptions -= TypeResolutionFlags::AllowIUO;
elementOptions -= TypeResolutionFlags::AllowIUO;

// If we have a single ParenType, don't clear the context bits; we
// still want to parse the type contained therein as if it were in
Expand All @@ -2876,7 +2868,7 @@ Type TypeResolver::resolveTupleType(TupleTypeRepr *repr,
// `FunctionInput` so that e.g. ((foo: Int)) -> Int is considered a
// tuple argument rather than a labeled Int argument.
if (isImmediateFunctionInput) {
elementOptions -= TypeResolutionFlags::ImmediateFunctionInput;
elementOptions = withoutContext(elementOptions, true);
elementOptions |= TypeResolutionFlags::FunctionInput;
}
} else {
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ withoutContext(TypeResolutionOptions options, bool preserveSIL = false) {
options -= TypeResolutionFlags::FunctionInput;
options -= TypeResolutionFlags::VariadicFunctionInput;
options -= TypeResolutionFlags::EnumCase;
options -= TypeResolutionFlags::SubscriptParameters;
options -= TypeResolutionFlags::ImmediateOptionalTypeArgument;
options -= TypeResolutionFlags::AllowIUO;
if (!preserveSIL) options -= TypeResolutionFlags::SILType;
Expand Down
6 changes: 3 additions & 3 deletions test/attr/attr_autoclosure.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %target-typecheck-verify-swift

// Simple case.
var fn : @autoclosure () -> Int = 4 // expected-error {{@autoclosure may only be used on parameters}} expected-error {{cannot convert value of type 'Int' to specified type '() -> Int'}}
var fn : @autoclosure () -> Int = 4 // expected-error {{'@autoclosure' may only be used on parameters}} expected-error {{cannot convert value of type 'Int' to specified type '() -> Int'}}

@autoclosure func func1() {} // expected-error {{attribute can only be applied to types, not declarations}}

Expand All @@ -15,7 +15,7 @@ func func4(fp : @autoclosure () -> Int) {func4(fp: 0)}
func func6(_: @autoclosure () -> Int) {func6(0)}

// autoclosure + inout doesn't make sense.
func func8(_ x: inout @autoclosure () -> Bool) -> Bool { // expected-error {{@autoclosure may only be used on parameters}}
func func8(_ x: inout @autoclosure () -> Bool) -> Bool { // expected-error {{'@autoclosure' may only be used on parameters}}
}

func func9(_ x: @autoclosure (Int) -> Bool) {} // expected-error {{argument type of @autoclosure parameter must be '()'}}
Expand Down Expand Up @@ -157,7 +157,7 @@ func callAutoclosureWithNoEscape_3(_ fn: @autoclosure () -> Int) {
takesAutoclosure(fn()) // ok
}

// expected-error @+1 {{@autoclosure must not be used on variadic parameters}}
// expected-error @+1 {{'@autoclosure' must not be used on variadic parameters}}
func variadicAutoclosure(_ fn: @autoclosure () -> ()...) {
for _ in fn {}
}
3 changes: 3 additions & 0 deletions test/decl/enum/enumtest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,7 @@ func useSynthesizedMember() {
enum Lens<T> {
case foo(inout T) // expected-error {{'inout' may only be used on parameters}}
case bar(inout T, Int) // expected-error {{'inout' may only be used on parameters}}

case baz((inout T) -> ()) // ok
case quux((inout T, inout T) -> ()) // ok
}
17 changes: 17 additions & 0 deletions test/decl/subscript/subscripting.swift
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,20 @@ struct SR2575 {

SR2575().subscript()
// expected-error@-1 {{value of type 'SR2575' has no property or method named 'subscript'; did you mean to use the subscript operator?}} {{9-10=}} {{10-19=}} {{19-20=[}} {{20-21=]}}

// SR-7890

struct InOutSubscripts {
subscript(x1: inout Int) -> Int { return 0 }
// expected-error@-1 {{'inout' must not be used on subscript parameters}}

subscript(x2: inout Int, y2: inout Int) -> Int { return 0 }
// expected-error@-1 2{{'inout' must not be used on subscript parameters}}

subscript(x3: (inout Int) -> ()) -> Int { return 0 } // ok
subscript(x4: (inout Int, inout Int) -> ()) -> Int { return 0 } // ok

subscript(inout x5: Int) -> Int { return 0 }
// expected-error@-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}
// expected-error@-2 {{'inout' must not be used on subscript parameters}}
}