Sema: Fix the insertion location for conformances attributes

This commit is contained in:
Anthony Latsis
2025-06-24 08:32:11 +01:00
parent 9488df15e0
commit ad8c52237c
18 changed files with 317 additions and 86 deletions

View File

@@ -216,7 +216,6 @@ void NormalProtocolConformance::setSourceKindAndImplyingConformance(
Bits.NormalProtocolConformance.SourceKind = unsigned(sourceKind);
if (auto implying = implyingConformance) {
ImplyingConformance = implying;
PreconcurrencyLoc = implying->getPreconcurrencyLoc();
Bits.NormalProtocolConformance.Options =
implyingConformance->getOptions().toRaw();
if (getProtocol()->isMarkerProtocol()) {
@@ -515,6 +514,18 @@ TypeExpr *NormalProtocolConformance::getExplicitGlobalActorIsolation() const {
return ctx.getGlobalCache().conformanceExplicitGlobalActorIsolation[this];
}
SourceLoc NormalProtocolConformance::getPreconcurrencyLoc() const {
if (!isPreconcurrency()) {
return SourceLoc();
}
if (!getInheritedTypeRepr()) {
return SourceLoc();
}
return getInheritedTypeRepr()->findAttrLoc(TypeAttrKind::Preconcurrency);
}
bool NormalProtocolConformance::hasExplicitGlobalActorIsolation() const {
return Bits.NormalProtocolConformance.HasExplicitGlobalActor;
}
@@ -805,6 +816,42 @@ void NormalProtocolConformance::resolveValueWitnesses() const {
evaluator::SideEffect());
}
void NormalProtocolConformance::applyConformanceAttribute(
InFlightDiagnostic &diag, std::string attrStr) const {
TypeRepr *inheritedTypeRepr = nullptr;
{
// Look through implied conformances.
auto *conformance = this;
while (conformance->getSourceKind() == ConformanceEntryKind::Implied) {
conformance = conformance->getImplyingConformance();
}
inheritedTypeRepr = conformance->getInheritedTypeRepr();
}
if (!inheritedTypeRepr) {
return;
}
// FIXME: We shouldn't be applying the attribute to all the protocols in a
// composition.
SourceLoc insertionLoc = [&] {
if (auto *attrTypeRepr = dyn_cast<AttributedTypeRepr>(inheritedTypeRepr)) {
// If this is a modifier, append, rather than prepend, it to the
// attribute list. Because e.g. `@unsafe nonisolated P` does parse,
// whereas `nonisolated @unsafe P` does not.
if (attrStr[0] != '@') {
return attrTypeRepr->getTypeRepr()->getStartLoc();
}
}
return inheritedTypeRepr->getStartLoc();
}();
attrStr += " ";
diag.fixItInsert(insertionLoc, attrStr);
}
SpecializedProtocolConformance::SpecializedProtocolConformance(
Type conformingType,
NormalProtocolConformance *genericConformance,