mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
AST: Lazily map archetype superclass into context
We don't really want to support this, at least not yet, but there are ways to sneak it past the diagnostic that are hard to close. Fixes rdar://problem/135348472.
This commit is contained in:
@@ -6580,11 +6580,7 @@ public:
|
||||
bool requiresClass() const;
|
||||
|
||||
/// Retrieve the superclass of this type, if such a requirement exists.
|
||||
Type getSuperclass() const {
|
||||
if (!Bits.ArchetypeType.HasSuperclass) return Type();
|
||||
|
||||
return *getSubclassTrailingObjects<Type>();
|
||||
}
|
||||
Type getSuperclass() const;
|
||||
|
||||
/// Retrieve the layout constraint of this type, if such a requirement exists.
|
||||
LayoutConstraint getLayoutConstraint() const {
|
||||
|
||||
@@ -404,14 +404,6 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
|
||||
// requirements.
|
||||
auto requirements = genericSig->getLocalRequirements(reducedType);
|
||||
|
||||
// Substitute into the superclass.
|
||||
Type superclass = requirements.superclass;
|
||||
if (superclass && superclass->hasTypeParameter()) {
|
||||
superclass = mapTypeIntoContext(superclass);
|
||||
if (superclass->is<ErrorType>())
|
||||
superclass = Type();
|
||||
}
|
||||
|
||||
Type result;
|
||||
|
||||
auto sugaredType = genericSig->getSugaredType(reducedType);
|
||||
@@ -422,11 +414,13 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
|
||||
if (rootGP->isParameterPack()) {
|
||||
result = PackArchetypeType::get(ctx, this, sugaredType,
|
||||
requirements.packShape,
|
||||
requirements.protos, superclass,
|
||||
requirements.protos,
|
||||
requirements.superclass,
|
||||
requirements.layout);
|
||||
} else {
|
||||
result = PrimaryArchetypeType::getNew(ctx, this, sugaredType,
|
||||
requirements.protos, superclass,
|
||||
requirements.protos,
|
||||
requirements.superclass,
|
||||
requirements.layout);
|
||||
}
|
||||
|
||||
@@ -442,7 +436,8 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
|
||||
}
|
||||
|
||||
result = OpaqueTypeArchetypeType::getNew(this, sugaredType,
|
||||
requirements.protos, superclass,
|
||||
requirements.protos,
|
||||
requirements.superclass,
|
||||
requirements.layout);
|
||||
break;
|
||||
}
|
||||
@@ -468,10 +463,12 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
|
||||
protos.push_back(proto);
|
||||
|
||||
result = OpenedArchetypeType::getNew(this, sugaredType, protos,
|
||||
superclass, requirements.layout);
|
||||
requirements.superclass,
|
||||
requirements.layout);
|
||||
} else {
|
||||
result = OpenedArchetypeType::getNew(this, sugaredType,
|
||||
requirements.protos, superclass,
|
||||
requirements.protos,
|
||||
requirements.superclass,
|
||||
requirements.layout);
|
||||
}
|
||||
|
||||
@@ -485,7 +482,8 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
|
||||
}
|
||||
|
||||
result = ElementArchetypeType::getNew(this, sugaredType,
|
||||
requirements.protos, superclass,
|
||||
requirements.protos,
|
||||
requirements.superclass,
|
||||
requirements.layout);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3450,6 +3450,14 @@ bool ArchetypeType::requiresClass() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Type ArchetypeType::getSuperclass() const {
|
||||
if (!Bits.ArchetypeType.HasSuperclass) return Type();
|
||||
|
||||
auto *genericEnv = getGenericEnvironment();
|
||||
return genericEnv->mapTypeIntoContext(
|
||||
*getSubclassTrailingObjects<Type>());
|
||||
}
|
||||
|
||||
Type ArchetypeType::getValueType() const {
|
||||
if (auto gp = getInterfaceType()->getAs<GenericTypeParamType>())
|
||||
return gp->getValueType();
|
||||
@@ -3506,7 +3514,12 @@ static RecursiveTypeProperties archetypeProperties(
|
||||
}
|
||||
}
|
||||
|
||||
if (superclass) properties |= superclass->getRecursiveProperties();
|
||||
if (superclass) {
|
||||
auto superclassProps = superclass->getRecursiveProperties();
|
||||
superclassProps.removeHasTypeParameter();
|
||||
superclassProps.removeHasDependentMember();
|
||||
properties |= superclassProps;
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
44
test/Generics/recursive_superclass.swift
Normal file
44
test/Generics/recursive_superclass.swift
Normal file
@@ -0,0 +1,44 @@
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
// While we disallow explicitly-stated requirements like
|
||||
// `T: C<T>`, there are ways to sneak them past the
|
||||
// diagnostic.
|
||||
//
|
||||
// We could relax the diagnostic eventually by rejecting
|
||||
// the truly invalid cases, where the superclass contains
|
||||
// a member type of a conformance made redundant by the
|
||||
// superclass requirement itself.
|
||||
|
||||
class C<T> {
|
||||
var t: T
|
||||
|
||||
init(t: T) {
|
||||
self.t = t
|
||||
}
|
||||
}
|
||||
|
||||
protocol P1 {
|
||||
associatedtype A: C<B.A>
|
||||
associatedtype B: P1
|
||||
}
|
||||
|
||||
func f<T: P1>(_: T, t: T.A) -> C<T.B.B.B.B.A> {
|
||||
return t.t.t.t
|
||||
}
|
||||
|
||||
protocol P2 {
|
||||
associatedtype A: C<B>
|
||||
associatedtype B
|
||||
}
|
||||
|
||||
extension P2 where Self == A {
|
||||
func f() -> C<B> {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
extension P2 where Self == A, A == B {
|
||||
func g() -> C<Self> {
|
||||
return self
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user