Skip to content

Commit fcd4c1f

Browse files
authored
Merge pull request #5826 from DougGregor/archetype-builder-same-types
Various fixes to the archetype builder's same-type-to-concrete handling
2 parents 0e340e3 + be791e5 commit fcd4c1f

File tree

8 files changed

+88
-39
lines changed

8 files changed

+88
-39
lines changed

include/swift/AST/ArchetypeBuilder.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,6 @@ class RequirementSource {
8383
///
8484
/// These are dropped when building the GenericSignature.
8585
Inherited,
86-
87-
/// The requirement came from an outer scope.
88-
/// FIXME: eliminate this in favor of keeping requirement sources in
89-
/// GenericSignatures, at least non-canonical ones?
90-
OuterScope,
9186
};
9287

9388
RequirementSource(Kind kind, SourceLoc loc) : StoredKind(kind), Loc(loc) { }
@@ -252,13 +247,8 @@ class ArchetypeBuilder {
252247
void addRequirement(const Requirement &req, RequirementSource source);
253248

254249
/// \brief Add all of a generic signature's parameters and requirements.
255-
///
256-
/// FIXME: Requirements from the generic signature are treated as coming from
257-
/// an outer scope. Setting \c treatRequirementsAsExplicit to true disables
258-
/// this behavior.
259250
void addGenericSignature(GenericSignature *sig,
260-
GenericEnvironment *genericEnv,
261-
bool treatRequirementsAsExplicit = false);
251+
GenericEnvironment *genericEnv);
262252

263253
/// \brief Build the generic signature.
264254
GenericSignature *getGenericSignature();

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,8 +1263,7 @@ ArchetypeBuilder *ASTContext::getOrCreateArchetypeBuilder(
12631263

12641264
// Create a new archetype builder with the given signature.
12651265
auto builder = new ArchetypeBuilder(*mod, Diags);
1266-
builder->addGenericSignature(sig, nullptr,
1267-
/*treatRequirementsAsExplicit=*/true);
1266+
builder->addGenericSignature(sig, nullptr);
12681267

12691268
// Store this archetype builder.
12701269
Impl.ArchetypeBuilders[{sig, mod}]

lib/AST/ArchetypeBuilder.cpp

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ void RequirementSource::dump(llvm::raw_ostream &out,
6161
out << "inferred";
6262
break;
6363

64-
case OuterScope:
65-
out << "outer";
66-
break;
67-
6864
case Inherited:
6965
out << "inherited";
7066
break;
@@ -685,7 +681,6 @@ ArchetypeBuilder::PotentialArchetype::getType(ArchetypeBuilder &builder) {
685681
switch (conforms.second.getKind()) {
686682
case RequirementSource::Explicit:
687683
case RequirementSource::Inferred:
688-
case RequirementSource::OuterScope:
689684
case RequirementSource::Protocol:
690685
case RequirementSource::Redundant:
691686
Protos.push_back(conforms.first);
@@ -993,6 +988,21 @@ bool ArchetypeBuilder::addSuperclassRequirement(PotentialArchetype *T,
993988
});
994989
}
995990

991+
// Make sure the concrete type fulfills the superclass requirement
992+
// of the archetype.
993+
if (T->isConcreteType()) {
994+
Type concrete = T->getConcreteType();
995+
if (!Superclass->isExactSuperclassOf(concrete, getLazyResolver())) {
996+
Diags.diagnose(T->getSameTypeSource().getLoc(),
997+
diag::type_does_not_inherit,
998+
T->getRootParam(), concrete, Superclass)
999+
.highlight(Source.getLoc());
1000+
return true;
1001+
}
1002+
1003+
return false;
1004+
}
1005+
9961006
// Local function to handle the update of superclass conformances
9971007
// when the superclass constraint changes.
9981008
auto updateSuperclassConformances = [&] {
@@ -1257,7 +1267,7 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
12571267
}
12581268

12591269
// Make sure the concrete type fulfills the requirements on the archetype.
1260-
DenseMap<ProtocolDecl *, ProtocolConformance*> conformances;
1270+
DenseMap<ProtocolDecl *, ProtocolConformanceRef> conformances;
12611271
if (!Concrete->is<ArchetypeType>()) {
12621272
for (auto conforms : T->getConformsTo()) {
12631273
auto protocol = conforms.first;
@@ -1270,16 +1280,27 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
12701280
return true;
12711281
}
12721282

1273-
assert(conformance->isConcrete() && "Abstract conformance?");
1274-
conformances[protocol] = conformance->getConcrete();
1283+
conformances.insert({protocol, *conformance});
12751284
}
12761285
}
12771286

12781287
// Record the requirement.
12791288
T->ArchetypeOrConcreteType = NestedType::forConcreteType(Concrete);
12801289
T->SameTypeSource = Source;
12811290

1291+
// Make sure the concrete type fulfills the superclass requirement
1292+
// of the archetype.
1293+
if (T->Superclass) {
1294+
if (!T->Superclass->isExactSuperclassOf(Concrete, getLazyResolver())) {
1295+
Diags.diagnose(Source.getLoc(), diag::type_does_not_inherit,
1296+
T->getRootParam(), Concrete, T->Superclass)
1297+
.highlight(T->SuperclassSource->getLoc());
1298+
return true;
1299+
}
1300+
}
1301+
12821302
// Recursively resolve the associated types to their concrete types.
1303+
RequirementSource nestedSource(RequirementSource::Redundant, Source.getLoc());
12831304
for (auto nested : T->getNestedTypes()) {
12841305
AssociatedTypeDecl *assocType
12851306
= nested.second.front()->getResolvedAssociatedType();
@@ -1288,21 +1309,28 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
12881309
concreteArchetype->getNestedType(nested.first);
12891310
addSameTypeRequirementToConcrete(nested.second.front(),
12901311
witnessType.getValue(),
1291-
Source);
1312+
nestedSource);
12921313
} else {
12931314
assert(conformances.count(assocType->getProtocol()) > 0
12941315
&& "missing conformance?");
1295-
auto witness = conformances[assocType->getProtocol()]
1296-
->getTypeWitness(assocType, getLazyResolver());
1297-
auto witnessType = witness.getReplacement();
1316+
auto conformance = conformances.find(assocType->getProtocol())->second;
1317+
Type witnessType;
1318+
if (conformance.isConcrete()) {
1319+
witnessType = conformance.getConcrete()
1320+
->getTypeWitness(assocType, getLazyResolver())
1321+
.getReplacement();
1322+
} else {
1323+
witnessType = DependentMemberType::get(Concrete, assocType);
1324+
}
1325+
12981326
if (auto witnessPA = resolveArchetype(witnessType)) {
12991327
addSameTypeRequirementBetweenArchetypes(nested.second.front(),
13001328
witnessPA,
1301-
Source);
1329+
nestedSource);
13021330
} else {
13031331
addSameTypeRequirementToConcrete(nested.second.front(),
13041332
witnessType,
1305-
Source);
1333+
nestedSource);
13061334
}
13071335
}
13081336
}
@@ -2010,14 +2038,10 @@ ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
20102038
}
20112039

20122040
void ArchetypeBuilder::addGenericSignature(GenericSignature *sig,
2013-
GenericEnvironment *env,
2014-
bool treatRequirementsAsExplicit) {
2041+
GenericEnvironment *env) {
20152042
if (!sig) return;
20162043

2017-
RequirementSource::Kind sourceKind = treatRequirementsAsExplicit
2018-
? RequirementSource::Explicit
2019-
: RequirementSource::OuterScope;
2020-
2044+
RequirementSource::Kind sourceKind = RequirementSource::Explicit;
20212045
for (auto param : sig->getGenericParams()) {
20222046
addGenericParameter(param);
20232047

@@ -2057,7 +2081,6 @@ static void collectRequirements(ArchetypeBuilder &builder,
20572081
switch (source.getKind()) {
20582082
case RequirementSource::Explicit:
20592083
case RequirementSource::Inferred:
2060-
case RequirementSource::OuterScope:
20612084
// The requirement was explicit and required, keep it.
20622085
break;
20632086

test/Generics/requirement_inference.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class Fox : P1 {
5757
class Box<T : Fox> {
5858
// CHECK-LABEL: .unpack@
5959
// CHECK-NEXT: Requirements:
60-
// CHECK-NEXT: T : Fox [outer]
60+
// CHECK-NEXT: T : Fox [explicit]
6161
func unpack(_ x: X1<T>) {}
6262
}
6363

@@ -136,6 +136,20 @@ func inferSameType2<T : P3, U : P4>(_: T) where U.P4Assoc : P2, T.P3Assoc == U.P
136136
// CHECK-NEXT: Generic signature
137137
func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}
138138

139+
struct X6 : PAssoc {
140+
typealias Assoc = X6
141+
}
142+
143+
// CHECK-LABEL: .inferSameType4@
144+
// CHECK-NEXT: Requirements:
145+
// CHECK-NEXT: T : PAssoc [explicit @
146+
// CHECK-NEXT: T[.PAssoc].Assoc == X6 [explicit
147+
// CHECK-NEXT: T[.PAssoc].Assoc[.PAssoc].Assoc == X6.Assoc [redundant
148+
// CHECK-NEXT: T[.PAssoc].Assoc[.PAssoc].Assoc[.PAssoc].Assoc == X6.Assoc [redundant
149+
// CHECK-NEXT: Generic signature: <T where T : PAssoc, T.Assoc == X6>
150+
// CHECK-NEXT: Canonical generic signature: <τ_0_0 where τ_0_0 : PAssoc, τ_0_0.Assoc == X6>
151+
func inferSameType4<T : PAssoc>(_: T) where T.Assoc : PAssoc, T.Assoc.Assoc : PAssoc, T.Assoc == X6 {}
152+
139153
protocol P5 {
140154
associatedtype Element
141155
}

test/Generics/same_type_constraints.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,18 @@ struct EventHorizon : Timewarp {
318318
func activate<T>(_ t: T) {}
319319

320320
activate(Teleporter<EventHorizon, Beam>())
321+
322+
// rdar://problem/29288428
323+
class C {}
324+
325+
protocol P9 {
326+
associatedtype A
327+
}
328+
329+
struct X7<T: P9> where T.A : C { }
330+
331+
extension X7 where T.A == Int { } // expected-error 2{{'T' requires that 'Int' inherit from 'C'}}
332+
333+
struct X8<T: C> { }
334+
335+
extension X8 where T == Int { } // expected-error 2{{'T' requires that 'Int' inherit from 'C'}}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-parse-verify-swift
2+
// REQUIRES: objc_interop
3+
4+
@objc protocol Q {}
5+
6+
struct X1<T: AnyObject> { }
7+
8+
extension X1 where T == Q { }

test/SILGen/generic_witness.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ struct Canvas<I : Ink> where I.Paint : Pen {
5050

5151
extension Canvas : Medium {}
5252

53-
// CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWuRx15generic_witness3Inkwx5PaintS_3PenrGVS_6Canvasx_S_6MediumS_FS4_4drawuRd__S_6Pencilwd__6StrokezWx7TextureS1__rfT5paintWxS7_S1__6pencilqd___T_ : $@convention(witness_method) <τ_0_0 where τ_0_0 : Ink, τ_0_0.Paint : Pen><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in τ_0_0.Paint, @in τ_1_0, @in_guaranteed Canvas<τ_0_0>) -> ()
54-
// CHECK: [[FN:%.*]] = function_ref @_TFV15generic_witness6Canvas4drawuRd__S_6Pencilwx5Paintzwd__6StrokerfT5paintwxS2_6pencilqd___T_ : $@convention(method) <τ_0_0 where τ_0_0 : Ink, τ_0_0.Paint : Pen><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in τ_0_0.Paint, @in τ_1_0, Canvas<τ_0_0>) -> ()
55-
// CHECK: apply [[FN]]<τ_0_0, τ_1_0, τ_0_0.Paint>({{.*}}) : $@convention(method) <τ_0_0 where τ_0_0 : Ink, τ_0_0.Paint : Pen><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in τ_0_0.Paint, @in τ_1_0, Canvas<τ_0_0>) -> ()
53+
// CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWuRx15generic_witness3Inkwx5PaintS_3PenrGVS_6Canvasx_S_6MediumS_FS4_4drawuRd__S_6Pencilwd__6StrokezWx7TextureS1__rfT5paintWxS7_S1__6pencilqd___T_ : $@convention(witness_method) <τ_0_0 where τ_0_0 : Ink><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in τ_0_0.Paint, @in τ_1_0, @in_guaranteed Canvas<τ_0_0>) -> ()
54+
// CHECK: [[FN:%.*]] = function_ref @_TFV15generic_witness6Canvas4drawuRd__S_6Pencilwx5Paintzwd__6StrokerfT5paintwxS2_6pencilqd___T_ : $@convention(method) <τ_0_0 where τ_0_0 : Ink><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in τ_0_0.Paint, @in τ_1_0, Canvas<τ_0_0>) -> ()
55+
// CHECK: apply [[FN]]<τ_0_0, τ_1_0>({{.*}}) : $@convention(method) <τ_0_0 where τ_0_0 : Ink><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in τ_0_0.Paint, @in τ_1_0, Canvas<τ_0_0>) -> ()
5656
// CHECK: }

test/SILOptimizer/prespecialize.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// CHECK-LABEL: sil [noinline] @_TF13prespecialize4testFTRGSaSi_4sizeSi_T_
1212
//
1313
// function_ref specialized Collection<A where ...>.makeIterator() -> IndexingIterator<A>
14-
// CHECK: function_ref @_TTSgq5GVs14CountableRangeSi_GS_Si_s10Collections___TFesRxs10Collectionwx8IteratorzGVs16IndexingIteratorx_wx8_ElementzWxS0_7Element_rS_12makeIteratorfT_GS1_x_
14+
// CHECK: function_ref @_TTSgq5GVs14CountableRangeSi_GS_Si_s10Collections___TFesRxs10Collectionwx8IteratorzGVs16IndexingIteratorx_rS_12makeIteratorfT_GS1_x_
1515
//
1616
// function_ref specialized IndexingIterator.next() -> A._Element?
1717
// CHECK: function_ref @_TTSgq5GVs14CountableRangeSi_GS_Si_s14_IndexableBases___TFVs16IndexingIterator4nextfT_GSqwx8_Element_

0 commit comments

Comments
 (0)