mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Sema: Try to bind extensions without expanding macros
Macro expansion can call typeCheckExpr(), which performs qualified lookups. So if we expand macros while binding extensions, these qualified lookups can fail because they cannot find members of extensions that have not been bound yet. To fix this, try binding extensions without performing macro expansion first. If any extensions remain at the end, we fall back to the old behavior, and try to bind them again, this time performing macro expansion. Fixes rdar://149798059.
This commit is contained in:
@@ -191,12 +191,14 @@ ModuleDecl *TypeChecker::getStdlibModule(const DeclContext *dc) {
|
||||
}
|
||||
|
||||
void swift::bindExtensions(ModuleDecl &mod) {
|
||||
bool excludeMacroExpansions = true;
|
||||
|
||||
// Utility function to try and resolve the extended type without diagnosing.
|
||||
// If we succeed, we go ahead and bind the extension. Otherwise, return false.
|
||||
auto tryBindExtension = [&](ExtensionDecl *ext) -> bool {
|
||||
assert(!ext->canNeverBeBound() &&
|
||||
"Only extensions that can ever be bound get here.");
|
||||
if (auto nominal = ext->computeExtendedNominal()) {
|
||||
if (auto nominal = ext->computeExtendedNominal(excludeMacroExpansions)) {
|
||||
nominal->addExtension(ext);
|
||||
return true;
|
||||
}
|
||||
@@ -228,20 +230,28 @@ void swift::bindExtensions(ModuleDecl &mod) {
|
||||
visitTopLevelDecl(D);
|
||||
}
|
||||
|
||||
// Phase 2 - repeatedly go through the worklist and attempt to bind each
|
||||
// extension there, removing it from the worklist if we succeed.
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
auto tryBindExtensions = [&]() {
|
||||
// Phase 2 - repeatedly go through the worklist and attempt to bind each
|
||||
// extension there, removing it from the worklist if we succeed.
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
auto last = std::remove_if(worklist.begin(), worklist.end(),
|
||||
tryBindExtension);
|
||||
if (last != worklist.end()) {
|
||||
worklist.erase(last, worklist.end());
|
||||
changed = true;
|
||||
}
|
||||
} while(changed);
|
||||
auto last = std::remove_if(worklist.begin(), worklist.end(),
|
||||
tryBindExtension);
|
||||
if (last != worklist.end()) {
|
||||
worklist.erase(last, worklist.end());
|
||||
changed = true;
|
||||
}
|
||||
} while(changed);
|
||||
};
|
||||
|
||||
tryBindExtensions();
|
||||
|
||||
// If that fails, try again, but this time expand macros.
|
||||
excludeMacroExpansions = false;
|
||||
tryBindExtensions();
|
||||
|
||||
// Any remaining extensions are invalid. They will be diagnosed later by
|
||||
// typeCheckDecl().
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user