@@ -3700,6 +3700,35 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
3700
3700
}
3701
3701
}
3702
3702
3703
+ static void recordConformanceDependency (DeclContext *DC,
3704
+ NominalTypeDecl *Adoptee,
3705
+ ProtocolConformance *Conformance,
3706
+ bool InExpression) {
3707
+ if (!Conformance)
3708
+ return ;
3709
+
3710
+ auto *topLevelContext = DC->getModuleScopeContext ();
3711
+ auto *SF = dyn_cast<SourceFile>(topLevelContext);
3712
+ if (!SF)
3713
+ return ;
3714
+
3715
+ auto *tracker = SF->getReferencedNameTracker ();
3716
+ if (!tracker)
3717
+ return ;
3718
+
3719
+ if (SF->getParentModule () !=
3720
+ Conformance->getDeclContext ()->getParentModule ())
3721
+ return ;
3722
+
3723
+ auto &Context = DC->getASTContext ();
3724
+
3725
+ // FIXME: 'deinit' is being used as a dummy identifier here. Really we
3726
+ // don't care about /any/ of the type's members, only that it conforms to
3727
+ // the protocol.
3728
+ tracker->addUsedMember ({Adoptee, Context.Id_deinit },
3729
+ DC->isCascadingContextForLookup (InExpression));
3730
+ }
3731
+
3703
3732
#pragma mark Protocol conformance checking
3704
3733
void ConformanceChecker::checkConformance () {
3705
3734
assert (!Conformance->isComplete () && " Conformance is already complete" );
@@ -3715,6 +3744,12 @@ void ConformanceChecker::checkConformance() {
3715
3744
// Resolve all of the type witnesses.
3716
3745
resolveTypeWitnesses ();
3717
3746
3747
+ // Ensure the conforming type is used.
3748
+ //
3749
+ // FIXME: This feels like the wrong place for this, but if we don't put
3750
+ // it here, extensions don't end up depending on the extended type.
3751
+ recordConformanceDependency (DC, Adoptee->getAnyNominal (), Conformance, false );
3752
+
3718
3753
// If we complain about any associated types, there is no point in continuing.
3719
3754
// FIXME: Not really true. We could check witnesses that don't involve the
3720
3755
// failed associated types.
@@ -4156,38 +4191,14 @@ bool TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto,
4156
4191
SourceLoc ComplainLoc) {
4157
4192
bool InExpression = options.contains (ConformanceCheckFlags::InExpression);
4158
4193
4159
- const DeclContext *topLevelContext = DC->getModuleScopeContext ();
4160
4194
auto recordDependency = [=](ProtocolConformance *conformance = nullptr ) {
4161
- if (options.contains (ConformanceCheckFlags::SuppressDependencyTracking))
4162
- return ;
4163
-
4164
- // Record that we depend on the type's conformance.
4165
- auto *constSF = dyn_cast<SourceFile>(topLevelContext);
4166
- if (!constSF)
4167
- return ;
4168
- auto *SF = const_cast <SourceFile *>(constSF);
4169
-
4170
- auto *tracker = SF->getReferencedNameTracker ();
4171
- if (!tracker)
4172
- return ;
4173
-
4174
- // We only care about intra-module dependencies.
4175
- if (conformance)
4176
- if (SF->getParentModule () !=
4177
- conformance->getDeclContext ()->getParentModule ())
4178
- return ;
4179
-
4180
- if (auto nominal = T->getAnyNominal ()) {
4181
- // FIXME: 'deinit' is being used as a dummy identifier here. Really we
4182
- // don't care about /any/ of the type's members, only that it conforms to
4183
- // the protocol.
4184
- tracker->addUsedMember ({nominal, Context.Id_deinit },
4185
- DC->isCascadingContextForLookup (InExpression));
4186
- }
4195
+ if (!options.contains (ConformanceCheckFlags::SuppressDependencyTracking))
4196
+ if (auto nominal = T->getAnyNominal ())
4197
+ recordConformanceDependency (DC, nominal, conformance, InExpression);
4187
4198
};
4188
4199
4189
4200
// Look up conformance in the module.
4190
- Module *M = topLevelContext ->getParentModule ();
4201
+ Module *M = DC ->getParentModule ();
4191
4202
auto lookupResult = M->lookupConformance (T, Proto, this );
4192
4203
if (!lookupResult) {
4193
4204
if (ComplainLoc.isValid ())
@@ -4206,7 +4217,7 @@ bool TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto,
4206
4217
} else {
4207
4218
if (Conformance)
4208
4219
*Conformance = nullptr ;
4209
- recordDependency (nullptr );
4220
+ recordDependency ();
4210
4221
}
4211
4222
4212
4223
// If we're using this conformance, note that.
0 commit comments