Skip to content

Implement experimental module selectors (MyMod::someName) feature #34556

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

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4962754
Use parseDeclNameRef in a few more places
beccadax May 8, 2025
9bea01a
[NFC] Add DeclNameLoc to specialize/dynamicReplacement
beccadax May 9, 2025
3ae0642
Add tok::colon_colon to parser
beccadax May 9, 2025
1b49a11
Parse module selectors in permitted locations
beccadax May 15, 2025
dc9a84d
Parse module selectors on operator references
beccadax May 15, 2025
a4a2755
Allow `::` as an alias for `.` in imports
beccadax May 9, 2025
ec18e47
Parse module selectors in forbidden locations
beccadax May 14, 2025
f7aa3aa
Parse syntactically invalid module selectors early
beccadax May 14, 2025
6a7b1d3
[NFC] Improve some lookup-related doc comments
beccadax May 10, 2025
7e81332
[NFC] Add representations for DeclNameRef/Loc with module selector
beccadax May 10, 2025
0b5ca9a
[NFC] Audit some DeclName➡️DeclNameRef conversions
beccadax May 14, 2025
abe2805
Handle module selectors in qualified lookup
beccadax May 9, 2025
279b433
Root unqualified lookups with module selectors at file scope
beccadax May 15, 2025
5fab496
Handle module selectors in unqualified lookup
beccadax May 15, 2025
229d341
Handle module selectors in UDRE lookups
beccadax May 13, 2025
75d3825
FIXME operators unexpectedly passing
beccadax May 15, 2025
6bf9312
Handle module selectors with local vars right
beccadax May 8, 2025
82d21ef
Improve module selector type lookup diagnostics
beccadax May 10, 2025
8b5c217
Improve module selector expr lookup diagnostics
beccadax May 9, 2025
4df114e
Improve module selector constraint solver diagnostics
beccadax May 15, 2025
0aa18fb
Improve module selector @_dynamicReplacement diagnostics
beccadax May 10, 2025
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
19 changes: 12 additions & 7 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,13 @@ BridgedDeclNameRef_createParsed(BridgedDeclBaseName cBaseName);

class BridgedDeclNameLoc {
const void *_Nullable LocationInfo;
size_t NumArgumentLabels;
uint32_t NumArgumentLabels;
bool HasModuleSelectorLoc;

public:
BridgedDeclNameLoc() : LocationInfo(nullptr), NumArgumentLabels(0) {}
BridgedDeclNameLoc()
: LocationInfo(nullptr), NumArgumentLabels(0), HasModuleSelectorLoc(false)
{}

BRIDGED_INLINE BridgedDeclNameLoc(swift::DeclNameLoc loc);

Expand Down Expand Up @@ -1015,11 +1018,12 @@ BridgedDocumentationAttr BridgedDocumentationAttr_createParsed(

SWIFT_NAME(
"BridgedDynamicReplacementAttr.createParsed(_:atLoc:attrNameLoc:lParenLoc:"
"replacedFunction:rParenLoc:)")
"replacedFunction:replacedFunctionLoc:rParenLoc:)")
BridgedDynamicReplacementAttr BridgedDynamicReplacementAttr_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
BridgedSourceLoc cAttrNameLoc, BridgedSourceLoc cLParenLoc,
BridgedDeclNameRef cReplacedFunction, BridgedSourceLoc cRParenLoc);
BridgedDeclNameRef cReplacedFunction,
BridgedDeclNameLoc cReplacedFunctionLoc, BridgedSourceLoc cRParenLoc);

enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedEffectsKind {
BridgedEffectsKindReadNone,
Expand Down Expand Up @@ -1388,13 +1392,14 @@ enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedSpecializationKind : uint8_t {
};

SWIFT_NAME("BridgedSpecializeAttr.createParsed(_:atLoc:range:whereClause:"
"exported:kind:taretFunction:spiGroups:availableAttrs:)")
"exported:kind:targetFunction:targetFunctionLoc:spiGroups:"
"availableAttrs:)")
BridgedSpecializeAttr BridgedSpecializeAttr_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange, BridgedNullableTrailingWhereClause cWhereClause,
bool exported, BridgedSpecializationKind cKind,
BridgedDeclNameRef cTargetFunction, BridgedArrayRef cSPIGroups,
BridgedArrayRef cAvailableAttrs);
BridgedDeclNameRef cTargetFunction, BridgedDeclNameLoc cTargetFunctionLoc,
BridgedArrayRef cSPIGroups, BridgedArrayRef cAvailableAttrs);

SWIFT_NAME(
"BridgedSPIAccessControlAttr.createParsed(_:atLoc:range:spiGroupName:)")
Expand Down
6 changes: 4 additions & 2 deletions include/swift/AST/ASTBridgingImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ swift::DeclNameRef BridgedDeclNameRef::unbridged() const {

BridgedDeclNameLoc::BridgedDeclNameLoc(swift::DeclNameLoc loc)
: LocationInfo(loc.LocationInfo),
NumArgumentLabels(loc.NumArgumentLabels) {}
NumArgumentLabels(loc.NumArgumentLabels),
HasModuleSelectorLoc(loc.HasModuleSelectorLoc) {}

swift::DeclNameLoc BridgedDeclNameLoc::unbridged() const {
return swift::DeclNameLoc(LocationInfo, NumArgumentLabels);
return swift::DeclNameLoc(LocationInfo, NumArgumentLabels,
HasModuleSelectorLoc);
}

//===----------------------------------------------------------------------===//
Expand Down
28 changes: 22 additions & 6 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1207,19 +1207,22 @@ class DynamicReplacementAttr final
friend class DynamicallyReplacedDeclRequest;

DeclNameRef ReplacedFunctionName;
DeclNameLoc ReplacedFunctionNameLoc;
LazyMemberLoader *Resolver = nullptr;
uint64_t ResolverContextData;

/// Create an @_dynamicReplacement(for:) attribute written in the source.
DynamicReplacementAttr(SourceLoc atLoc, SourceRange baseRange,
DeclNameRef replacedFunctionName,
DeclNameLoc replacedFunctionNameLoc,
SourceRange parenRange);

DynamicReplacementAttr(DeclNameRef name, AbstractFunctionDecl *f)
: DeclAttribute(DeclAttrKind::DynamicReplacement, SourceLoc(),
SourceRange(),
/*Implicit=*/false),
ReplacedFunctionName(name), Resolver(nullptr), ResolverContextData(0) {
ReplacedFunctionName(name), ReplacedFunctionNameLoc(),
Resolver(nullptr), ResolverContextData(0) {
Bits.DynamicReplacementAttr.HasTrailingLocationInfo = false;
}

Expand All @@ -1228,8 +1231,8 @@ class DynamicReplacementAttr final
: DeclAttribute(DeclAttrKind::DynamicReplacement, SourceLoc(),
SourceRange(),
/*Implicit=*/false),
ReplacedFunctionName(name), Resolver(Resolver),
ResolverContextData(Data) {
ReplacedFunctionName(name), ReplacedFunctionNameLoc(),
Resolver(Resolver), ResolverContextData(Data) {
Bits.DynamicReplacementAttr.HasTrailingLocationInfo = false;
}

Expand All @@ -1250,7 +1253,8 @@ class DynamicReplacementAttr final
public:
static DynamicReplacementAttr *
create(ASTContext &Context, SourceLoc AtLoc, SourceLoc DynReplLoc,
SourceLoc LParenLoc, DeclNameRef replacedFunction, SourceLoc RParenLoc);
SourceLoc LParenLoc, DeclNameRef replacedFunction,
DeclNameLoc replacedFunctionNameLoc, SourceLoc RParenLoc);

static DynamicReplacementAttr *create(ASTContext &ctx,
DeclNameRef replacedFunction,
Expand All @@ -1265,6 +1269,10 @@ class DynamicReplacementAttr final
return ReplacedFunctionName;
}

DeclNameLoc getReplacedFunctionNameLoc() const {
return ReplacedFunctionNameLoc;
}

/// Retrieve the location of the opening parentheses, if there is one.
SourceLoc getLParenLoc() const;

Expand Down Expand Up @@ -1752,6 +1760,7 @@ class SpecializeAttr final
GenericSignature specializedSignature;

DeclNameRef targetFunctionName;
DeclNameLoc targetFunctionNameLoc;
LazyMemberLoader *resolver = nullptr;
uint64_t resolverContextData;
size_t numSPIGroups;
Expand All @@ -1762,15 +1771,18 @@ class SpecializeAttr final
SpecializeAttr(SourceLoc atLoc, SourceRange Range,
TrailingWhereClause *clause, bool exported,
SpecializationKind kind, GenericSignature specializedSignature,
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
DeclNameRef targetFunctionName,
DeclNameLoc targetFunctionNameLoc,
ArrayRef<Identifier> spiGroups,
ArrayRef<AvailableAttr *> availabilityAttrs,
size_t typeErasedParamsCount);

public:
static SpecializeAttr *
create(ASTContext &Ctx, SourceLoc atLoc, SourceRange Range,
TrailingWhereClause *clause, bool exported, SpecializationKind kind,
DeclNameRef targetFunctionName, ArrayRef<Identifier> spiGroups,
DeclNameRef targetFunctionName, DeclNameLoc targetFunctionNameLoc,
ArrayRef<Identifier> spiGroups,
ArrayRef<AvailableAttr *> availabilityAttrs,
GenericSignature specializedSignature = nullptr);

Expand Down Expand Up @@ -1849,6 +1861,10 @@ class SpecializeAttr final
return targetFunctionName;
}

DeclNameLoc getTargetFunctionNameLoc() const {
return targetFunctionNameLoc;
}

/// \p forDecl is the value decl that the attribute belongs to.
ValueDecl *getTargetFunctionDecl(const ValueDecl *forDecl) const;

Expand Down
9 changes: 4 additions & 5 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2995,11 +2995,10 @@ class ValueDecl : public Decl {
return Name.getBaseIdentifier();
}

/// Generates a DeclNameRef referring to this declaration with as much
/// specificity as possible.
DeclNameRef createNameRef() const {
return DeclNameRef(Name);
}
/// Generates a DeclNameRef referring to this declaration.
///
/// \param moduleSelector If true, the name ref includes the module name.
DeclNameRef createNameRef(bool moduleSelector = false) const;

/// Retrieve the C declaration name that names this function, or empty
/// string if it has none.
Expand Down
47 changes: 27 additions & 20 deletions include/swift/AST/DeclNameLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,61 +35,69 @@ class DeclNameLoc {

/// Source location information.
///
/// If \c NumArgumentLabels == 0, this is the SourceLoc for the base name.
/// Otherwise, it points to an array of SourceLocs, which contains:
/// If \c NumArgumentLabels == 0 and \c !HasModuleSelectorLoc, this is the
/// SourceLoc for the base name. Otherwise, it points to an array of
/// SourceLocs, which contains:
/// * The base name location
/// * The module selector location
/// * The left parentheses location
/// * The right parentheses location
/// * The locations of each of the argument labels.
const void *LocationInfo;

/// The number of argument labels stored in the name.
unsigned NumArgumentLabels;
uint32_t NumArgumentLabels;
bool HasModuleSelectorLoc;

enum {
BaseNameIndex = 0,
LParenIndex = 1,
RParenIndex = 2,
FirstArgumentLabelIndex = 3,
ModuleSelectorIndex = 1,
LParenIndex = 2,
RParenIndex = 3,
FirstArgumentLabelIndex = 4,
};

/// Retrieve a pointer to either the only source location that was
/// stored or to the array of source locations that was stored.
SourceLoc const * getSourceLocs() const {
if (NumArgumentLabels == 0)
if (NumArgumentLabels == 0 && !HasModuleSelectorLoc)
return reinterpret_cast<SourceLoc const *>(&LocationInfo);

return reinterpret_cast<SourceLoc const *>(LocationInfo);
}

DeclNameLoc(const void *LocationInfo, unsigned NumArgumentLabels)
: LocationInfo(LocationInfo), NumArgumentLabels(NumArgumentLabels) {}
DeclNameLoc(const void *LocationInfo, unsigned NumArgumentLabels,
bool HasModuleSelectorLoc)
: LocationInfo(LocationInfo), NumArgumentLabels(NumArgumentLabels),
HasModuleSelectorLoc(HasModuleSelectorLoc) {}

public:
/// Create an invalid declaration name location.
DeclNameLoc() : DeclNameLoc(nullptr, 0) {}
DeclNameLoc() : DeclNameLoc(nullptr, 0, false) {}

/// Create declaration name location information for a base name.
explicit DeclNameLoc(SourceLoc baseNameLoc)
: DeclNameLoc(baseNameLoc.getOpaquePointerValue(), 0) {}
: DeclNameLoc(baseNameLoc.getOpaquePointerValue(), 0, false) {}

explicit DeclNameLoc(ASTContext &ctx, SourceLoc moduleSelectorLoc,
SourceLoc baseNameLoc)
: DeclNameLoc(baseNameLoc) { }
: DeclNameLoc(ctx, moduleSelectorLoc, baseNameLoc,
SourceLoc(), {}, SourceLoc()) { }

/// Create declaration name location information for a compound
/// name.
DeclNameLoc(ASTContext &ctx, SourceLoc baseNameLoc,
SourceLoc lParenLoc,
ArrayRef<SourceLoc> argumentLabelLocs,
SourceLoc rParenLoc);
SourceLoc rParenLoc)
: DeclNameLoc(ctx, SourceLoc(), baseNameLoc,
lParenLoc, argumentLabelLocs, rParenLoc) { }

DeclNameLoc(ASTContext &ctx, SourceLoc moduleSelectorLoc,
SourceLoc baseNameLoc,
SourceLoc lParenLoc,
ArrayRef<SourceLoc> argumentLabelLocs,
SourceLoc rParenLoc)
: DeclNameLoc(ctx, baseNameLoc, lParenLoc, argumentLabelLocs, rParenLoc) { }
SourceLoc rParenLoc);

/// Whether the location information is valid.
bool isValid() const { return getBaseNameLoc().isValid(); }
Expand Down Expand Up @@ -125,11 +133,12 @@ class DeclNameLoc {
}

SourceLoc getModuleSelectorLoc() const {
return SourceLoc();
if (!HasModuleSelectorLoc) return SourceLoc();
return getSourceLocs()[ModuleSelectorIndex];
}

SourceLoc getStartLoc() const {
return getBaseNameLoc();
return HasModuleSelectorLoc ? getModuleSelectorLoc() : getBaseNameLoc();
}

SourceLoc getEndLoc() const {
Expand All @@ -138,9 +147,7 @@ class DeclNameLoc {

/// Retrieve the complete source range for this declaration name.
SourceRange getSourceRange() const {
if (NumArgumentLabels == 0) return getBaseNameLoc();

return SourceRange(getBaseNameLoc(), getRParenLoc());
return SourceRange(getStartLoc(), getEndLoc());
}
};

Expand Down
19 changes: 19 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ ERROR(forbidden_interpolated_string,none,
ERROR(forbidden_extended_escaping_string,none,
"%0 cannot be an extended escaping string literal", (StringRef))

ERROR(expected_identifier_in_module_selector,none,
"expected identifier in module selector", ())
ERROR(module_selector_not_allowed,none,
"%select{%error|%error|name in %1 declaration|captured variable name|"
"parameter name|generic parameter name|argument label|SPI group|"
"Objective-C name|name of sibling declaration|precedence group name|"
"attribute parameter value|%error}0 cannot be qualified with a module "
"selector",
(uint8_t, StringRef))
NOTE(fixit_remove_module_selector,none,
"remove module selector from this name", ())
NOTE(fixit_capture_with_explicit_name,none,
"explicitly capture into a variable named '%0'",
(StringRef))

//------------------------------------------------------------------------------
// MARK: Lexer diagnostics
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -2183,5 +2198,9 @@ ERROR(nonisolated_nonsending_expected_rparen,PointsToFirstBadToken,
ERROR(nonisolated_nonsending_repeated,none,
"parameter may have at most one 'nonisolated(nonsending)' specifier", ())

ERROR(impossible_parse,none,
"parser entered impossible state; please file a bug report with this "
"source file", ())

#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
10 changes: 10 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,16 @@ ERROR(cannot_find_type_in_cast_expression,none,
"type-casting operator expects a type on its right-hand side (got: %kind0)", (const ValueDecl *))
ERROR(cannot_find_type_in_scope_did_you_mean,none,
"cannot find type %0 in scope; did you mean to use '%1'?", (DeclNameRef, StringRef))
ERROR(type_not_in_module,none,
"type %0 is not imported through module %1", (DeclName, Identifier))
ERROR(decl_not_in_module,none,
"declaration %0 is not imported through module %1", (DeclName, Identifier))
NOTE(note_change_module_selector,none,
"did you mean module %0?", (Identifier))
NOTE(note_remove_module_selector,none,
"did you mean the local declaration?", ())
NOTE(note_add_explicit_self_with_module_selector,none,
"did you mean the member of 'self'?", ())
NOTE(note_typo_candidate_implicit_member,none,
"did you mean the implicitly-synthesized %kindbase0?", (const ValueDecl *))
NOTE(note_remapped_type,none,
Expand Down
Loading