Skip to content

Commit f549f35

Browse files
committed
IRGen: Fix crash when emitting type nested inside constrained extension
getFormalTypeInContext() was using the context archetypes of the original parent type, and not the extension.
1 parent 7d41e79 commit f549f35

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

lib/IRGen/GenValueWitness.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,17 +419,14 @@ static Address getArgAsBuffer(IRGenFunction &IGF,
419419
return Address(arg, getFixedBufferAlignment(IGF.IGM));
420420
}
421421

422-
/// Given an abstract type --- a type possibly expressed in terms of
423-
/// unbound generic types --- return the formal type within the type's
424-
/// primary defining context.
425-
static CanType getFormalTypeInContext(CanType abstractType) {
422+
static CanType getFormalTypeInContext(CanType abstractType, DeclContext *dc) {
426423
// Map the parent of any non-generic nominal type.
427424
if (auto nominalType = dyn_cast<NominalType>(abstractType)) {
428425
// If it doesn't have a parent, or the parent doesn't need remapping,
429426
// do nothing.
430427
auto abstractParentType = nominalType.getParent();
431428
if (!abstractParentType) return abstractType;
432-
auto parentType = getFormalTypeInContext(abstractParentType);
429+
auto parentType = getFormalTypeInContext(abstractParentType, dc);
433430
if (abstractParentType == parentType) return abstractType;
434431

435432
// Otherwise, rebuild the type.
@@ -438,14 +435,24 @@ static CanType getFormalTypeInContext(CanType abstractType) {
438435

439436
// Map unbound types into their defining context.
440437
} else if (auto ugt = dyn_cast<UnboundGenericType>(abstractType)) {
441-
return ugt->getDecl()->getDeclaredTypeInContext()->getCanonicalType();
438+
return dc->mapTypeIntoContext(ugt->getDecl()->getDeclaredInterfaceType())
439+
->getCanonicalType();
442440

443441
// Everything else stays the same.
444442
} else {
445443
return abstractType;
446444
}
447445
}
448446

447+
/// Given an abstract type --- a type possibly expressed in terms of
448+
/// unbound generic types --- return the formal type within the type's
449+
/// primary defining context.
450+
static CanType getFormalTypeInContext(CanType abstractType) {
451+
if (auto nominal = abstractType.getAnyNominal())
452+
return getFormalTypeInContext(abstractType, nominal);
453+
return abstractType;
454+
}
455+
449456
/// Get the next argument and use it as the 'self' type metadata.
450457
static void getArgAsLocalSelfTypeMetadata(IRGenFunction &IGF,
451458
llvm::Function::arg_iterator &it,

test/IRGen/nested_generics.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,16 @@ public class OuterGenericClass<T> {
7979
}
8080
}
8181
}
82+
83+
// This used to crash while emitting value witnesses.
84+
85+
public struct Fish<Water> {}
86+
87+
public protocol Wet {}
88+
89+
extension Fish where Water : Wet {
90+
public enum Fillet {
91+
case grilled
92+
case fried
93+
}
94+
}

0 commit comments

Comments
 (0)