Skip to content

[Parser] Check let/var context when fix-it moving attributes from type to decl #65748

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 1 commit into from
May 10, 2023
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
13 changes: 10 additions & 3 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4034,13 +4034,20 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
if (justChecking) return makeParserError();

// If this is the first attribute, and if we are on a simple decl, emit a
// fixit to move the attribute. Otherwise, we don't have the location of
// the @ sign, or we don't have confidence that the fixit will be right.
// fixit to move or just remove the attribute. Otherwise, we don't have
// the location of the @ sign, or we don't have confidence that the fixit
// will be right.
if (!Attributes.empty() || StructureMarkers.empty() ||
StructureMarkers.back().Kind != StructureMarkerKind::Declaration ||
StructureMarkers.back().Loc.isInvalid() ||
peekToken().is(tok::equal)) {
diagnose(Tok, diag::decl_attribute_applied_to_type);
} else if (InBindingPattern != PatternBindingState::NotInBinding ||
StructureMarkers.back().Kind !=
StructureMarkerKind::Declaration) {
// In let/var/inout pattern binding declaration context or in non-decl,
// so we can only suggest a remove fix-it.
diagnose(Tok, diag::decl_attribute_applied_to_type)
.fixItRemove(SourceRange(Attributes.AtLoc, Tok.getLoc()));
} else {
// Otherwise, this is the first type attribute and we know where the
// declaration is. Emit the same diagnostic, but include a fixit to
Expand Down
18 changes: 18 additions & 0 deletions test/attr/attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,21 @@ enum E1 {
}

@_custom func testCustomAttribute() {} // expected-error {{unknown attribute '_custom'}}

// https://github.com/apple/swift/issues/65705
struct GI65705<A> {}
struct I65705 {
let m1: @discardableResult () -> Int // expected-error {{attribute can only be applied to declarations, not types}} {{11-30=}} {{none}}
var m2: @discardableResult () -> Int // expected-error {{attribute can only be applied to declarations, not types}} {{11-30=}} {{none}}
let m3: GI65705<@discardableResult () -> Int> // expected-error{{attribute can only be applied to declarations, not types}} {{19-37=}} {{none}}

func f1(_: inout @discardableResult Int) {} // expected-error {{attribute can only be applied to declarations, not types}} {{20-39=}} {{3-3=@discardableResult }} {{none}}
func f2(_: @discardableResult Int) {} // expected-error {{attribute can only be applied to declarations, not types}} {{14-33=}} {{3-3=@discardableResult }} {{none}}

func stmt(_ a: Int?) {
if let _: @discardableResult Int = a { // expected-error {{attribute can only be applied to declarations, not types}} {{15-34=}}
}
if var _: @discardableResult Int = a { // expected-error {{attribute can only be applied to declarations, not types}} {{15-34=}}
}
}
}