Skip to content

Commit 4f6e318

Browse files
authored
Merge pull request #83477 from hamishknight/rec-room
2 parents b7a68b0 + fb7f2d0 commit 4f6e318

File tree

17 files changed

+212
-28
lines changed

17 files changed

+212
-28
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,11 @@ ERROR(dynamic_member_lookup_candidate_inaccessible,none,
17351735
"enclosing type",
17361736
(ValueDecl *))
17371737

1738+
ERROR(too_many_dynamic_member_lookups,none,
1739+
"could not find member %0; exceeded the maximum number of nested "
1740+
"dynamic member lookups",
1741+
(DeclNameRef))
1742+
17381743
ERROR(string_index_not_integer,none,
17391744
"String must not be indexed with %0, it has variable size elements",
17401745
(Type))

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,10 @@ namespace swift {
952952
/// (It's arbitrary, but will keep the compiler from taking too much time.)
953953
unsigned SwitchCheckingInvocationThreshold = 200000;
954954

955+
/// The maximum number of `@dynamicMemberLookup`s that can be chained to
956+
/// resolve a member reference.
957+
unsigned DynamicMemberLookupDepthLimit = 100;
958+
955959
/// If true, the time it takes to type-check each function will be dumped
956960
/// to llvm::errs().
957961
bool DebugTimeFunctionBodies = false;

include/swift/Option/FrontendOptions.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,12 @@ def disable_invalid_ephemeralness_as_error :
895895
def switch_checking_invocation_threshold_EQ : Joined<["-"],
896896
"switch-checking-invocation-threshold=">;
897897

898+
def dynamic_member_lookup_depth_limit_EQ
899+
: Joined<["-"], "dynamic-member-lookup-depth-limit=">,
900+
HelpText<
901+
"The maximum number of dynamic member lookups that can be chained "
902+
"to resolve a member reference">;
903+
898904
def enable_new_operator_lookup :
899905
Flag<["-"], "enable-new-operator-lookup">,
900906
HelpText<"Enable the new operator decl and precedencegroup lookup behavior">;

include/swift/Sema/CSFix.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,9 @@ enum class FixKind : uint8_t {
488488
/// the type it's attempting to bind to.
489489
AllowInlineArrayLiteralCountMismatch,
490490

491+
/// Reached the limit of @dynamicMemberLookup depth.
492+
TooManyDynamicMemberLookups,
493+
491494
/// Ignore that a conformance is isolated but is not allowed to be.
492495
IgnoreIsolatedConformance,
493496
};
@@ -3881,6 +3884,33 @@ class AllowInlineArrayLiteralCountMismatch final : public ConstraintFix {
38813884
}
38823885
};
38833886

3887+
class TooManyDynamicMemberLookups : public ConstraintFix {
3888+
DeclNameRef Name;
3889+
3890+
TooManyDynamicMemberLookups(ConstraintSystem &cs, DeclNameRef name,
3891+
ConstraintLocator *locator)
3892+
: ConstraintFix(cs, FixKind::TooManyDynamicMemberLookups, locator),
3893+
Name(name) {}
3894+
3895+
public:
3896+
std::string getName() const override {
3897+
return "too many dynamic member lookups";
3898+
}
3899+
3900+
bool diagnose(const Solution &solution, bool asNote = false) const override;
3901+
3902+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
3903+
return diagnose(*commonFixes.front().first);
3904+
}
3905+
3906+
static TooManyDynamicMemberLookups *
3907+
create(ConstraintSystem &cs, DeclNameRef name, ConstraintLocator *locator);
3908+
3909+
static bool classof(const ConstraintFix *fix) {
3910+
return fix->getKind() == FixKind::TooManyDynamicMemberLookups;
3911+
}
3912+
};
3913+
38843914
class IgnoreIsolatedConformance : public ConstraintFix {
38853915
ProtocolConformance *conformance;
38863916

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,6 +1897,8 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
18971897
Opts.WarnLongExpressionTypeChecking);
18981898
setUnsignedIntegerArgument(OPT_solver_expression_time_threshold_EQ,
18991899
Opts.ExpressionTimeoutThreshold);
1900+
setUnsignedIntegerArgument(OPT_dynamic_member_lookup_depth_limit_EQ,
1901+
Opts.DynamicMemberLookupDepthLimit);
19001902
setUnsignedIntegerArgument(OPT_switch_checking_invocation_threshold_EQ,
19011903
Opts.SwitchCheckingInvocationThreshold);
19021904
setUnsignedIntegerArgument(OPT_debug_constraints_attempt,

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9636,6 +9636,12 @@ bool IncorrectInlineArrayLiteralCount::diagnoseAsError() {
96369636
return true;
96379637
}
96389638

9639+
bool TooManyDynamicMemberLookupsFailure::diagnoseAsError() {
9640+
emitDiagnostic(diag::too_many_dynamic_member_lookups, Name)
9641+
.highlight(getSourceRange());
9642+
return true;
9643+
}
9644+
96399645
bool DisallowedIsolatedConformance::diagnoseAsError() {
96409646
emitDiagnostic(diag::isolated_conformance_with_sendable_simple,
96419647
conformance->getType(),

lib/Sema/CSDiagnostics.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3310,6 +3310,17 @@ class IncorrectInlineArrayLiteralCount final : public FailureDiagnostic {
33103310
bool diagnoseAsError() override;
33113311
};
33123312

3313+
class TooManyDynamicMemberLookupsFailure final : public FailureDiagnostic {
3314+
DeclNameRef Name;
3315+
3316+
public:
3317+
TooManyDynamicMemberLookupsFailure(const Solution &solution, DeclNameRef name,
3318+
ConstraintLocator *locator)
3319+
: FailureDiagnostic(solution, locator), Name(name) {}
3320+
3321+
bool diagnoseAsError() override;
3322+
};
3323+
33133324
/// Diagnose when an isolated conformance is used in a place where one cannot
33143325
/// be, e.g., due to a Sendable or SendableMetatype requirement on the
33153326
/// corresponding type parameter.

lib/Sema/CSFix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,6 +2796,18 @@ bool AllowInlineArrayLiteralCountMismatch::diagnose(const Solution &solution,
27962796
return failure.diagnose(asNote);
27972797
}
27982798

2799+
TooManyDynamicMemberLookups *
2800+
TooManyDynamicMemberLookups::create(ConstraintSystem &cs, DeclNameRef name,
2801+
ConstraintLocator *locator) {
2802+
return new (cs.getAllocator()) TooManyDynamicMemberLookups(cs, name, locator);
2803+
}
2804+
2805+
bool TooManyDynamicMemberLookups::diagnose(const Solution &solution,
2806+
bool asNote) const {
2807+
TooManyDynamicMemberLookupsFailure failure(solution, Name, getLocator());
2808+
return failure.diagnose(asNote);
2809+
}
2810+
27992811
IgnoreIsolatedConformance *
28002812
IgnoreIsolatedConformance::create(ConstraintSystem &cs,
28012813
ConstraintLocator *locator,

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16034,6 +16034,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1603416034
case FixKind::IgnoreOutOfPlaceThenStmt:
1603516035
case FixKind::IgnoreMissingEachKeyword:
1603616036
case FixKind::AllowInlineArrayLiteralCountMismatch:
16037+
case FixKind::TooManyDynamicMemberLookups:
1603716038
case FixKind::IgnoreIsolatedConformance:
1603816039
llvm_unreachable("handled elsewhere");
1603916040
}

lib/Sema/ConstraintLocator.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,17 @@ void LocatorPathElt::dump(raw_ostream &out) const {
545545
/// e.g. `foo[0]` or `\Foo.[0]`
546546
bool ConstraintLocator::isSubscriptMemberRef() const {
547547
auto anchor = getAnchor();
548+
if (!anchor)
549+
return false;
550+
551+
// Look through dynamic member lookup since for a subscript reference the
552+
// dynamic member lookup is also a subscript reference.
548553
auto path = getPath();
554+
using KPDynamicMemberElt = LocatorPathElt::KeyPathDynamicMember;
555+
while (!path.empty() && path.back().is<KPDynamicMemberElt>())
556+
path = path.drop_back();
549557

550-
if (!anchor || path.empty())
558+
if (path.empty())
551559
return false;
552560

553561
return path.back().getKind() == ConstraintLocator::SubscriptMember;

0 commit comments

Comments
 (0)