Skip to content

Commit f1b192f

Browse files
committed
---
yaml --- r: 345583 b: refs/heads/master c: 34adb2a h: refs/heads/master i: 345581: 7780511 345579: a7f259a 345575: a8f2cdd 345567: 3b2cd33
1 parent 060e514 commit f1b192f

File tree

10 files changed

+181
-64
lines changed

10 files changed

+181
-64
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 8af6e75e3ffd93fc97601ae5ecfd1cecb2d544da
2+
refs/heads/master: 34adb2ac74cbd23bb6267360514c2d591057b5c7
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/GenericSignatureBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,11 @@ class GenericSignatureBuilder::FloatingRequirementSource {
14521452
/// Whether this is an explicitly-stated requirement.
14531453
bool isExplicit() const;
14541454

1455+
/// Whether this is a top-level requirement written in source.
1456+
/// FIXME: This is a hack because expandConformanceRequirement()
1457+
/// is too eager; we should remove this once we fix it properly.
1458+
bool isTopLevel() const { return kind == Explicit; }
1459+
14551460
/// Return the "inferred" version of this source, if it isn't already
14561461
/// inferred.
14571462
FloatingRequirementSource asInferred(const TypeRepr *typeRepr) const;

trunk/lib/AST/GenericSignatureBuilder.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5157,8 +5157,18 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementBetweenConcrete(
51575157
}
51585158
} matcher(*this, source, type1, type2, diagnoseMismatch);
51595159

5160-
return matcher.match(type1, type2) ? ConstraintResult::Resolved
5161-
: ConstraintResult::Conflicting;
5160+
if (matcher.match(type1, type2)) {
5161+
// Warn if neither side of the requirement contains a type parameter.
5162+
if (source.isTopLevel() && source.getLoc().isValid()) {
5163+
Diags.diagnose(source.getLoc(),
5164+
diag::requires_no_same_type_archetype,
5165+
type1, type2);
5166+
}
5167+
5168+
return ConstraintResult::Resolved;
5169+
}
5170+
5171+
return ConstraintResult::Conflicting;
51625172
}
51635173

51645174
ConstraintResult GenericSignatureBuilder::addSameTypeRequirement(
@@ -5344,19 +5354,6 @@ GenericSignatureBuilder::addRequirement(const Requirement &req,
53445354
case RequirementKind::SameType: {
53455355
auto secondType = subst(req.getSecondType());
53465356

5347-
// Warn if neither side of the requirement contains a type parameter.
5348-
if (reqRepr &&
5349-
!req.getFirstType()->hasTypeParameter() &&
5350-
!req.getSecondType()->hasTypeParameter() &&
5351-
!req.getFirstType()->hasError() &&
5352-
!req.getSecondType()->hasError()) {
5353-
Diags.diagnose(reqRepr->getSeparatorLoc(),
5354-
diag::requires_no_same_type_archetype,
5355-
req.getFirstType(), req.getSecondType())
5356-
.highlight(reqRepr->getFirstTypeLoc().getSourceRange())
5357-
.highlight(reqRepr->getSecondTypeLoc().getSourceRange());
5358-
}
5359-
53605357
if (inferForModule) {
53615358
inferRequirements(*inferForModule, firstType,
53625359
RequirementRepr::getFirstTypeRepr(reqRepr),

trunk/lib/Sema/TypeCheckType.cpp

Lines changed: 94 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -215,46 +215,69 @@ Type TypeResolution::resolveDependentMemberType(
215215
auto lazyResolver = ctx.getLazyResolver();
216216
if (lazyResolver)
217217
lazyResolver->resolveDeclSignature(concrete);
218-
219-
if (auto typeAlias = dyn_cast<TypeAliasDecl>(concrete)) {
220-
if (auto protocol = dyn_cast<ProtocolDecl>(typeAlias->getDeclContext())) {
221-
// We need to make sure the generic environment of a surrounding protocol
222-
// propagates to the typealias, since the former may not have existed when
223-
// the typealiases type was first computed.
224-
// FIXME: See the comment in the ProtocolDecl case of validateDecl().
225-
if (lazyResolver)
226-
lazyResolver->resolveProtocolEnvironment(protocol);
227-
}
228-
}
229218
if (!concrete->hasInterfaceType())
230219
return ErrorType::get(ctx);
231-
if (baseTy->isTypeParameter()) {
232-
if (auto proto = concrete->getDeclContext()->getSelfProtocolDecl()) {
233-
// Fast path: if there are no type parameters in the concrete type, just
234-
// return it.
235-
if (!concrete->getDeclaredInterfaceType()->hasTypeParameter())
236-
return concrete->getDeclaredInterfaceType();
237220

238-
if (lazyResolver)
239-
lazyResolver->resolveProtocolEnvironment(proto);
221+
if (concrete->getDeclContext()->getSelfClassDecl()) {
222+
// We found a member of a class from a protocol or protocol
223+
// extension.
224+
//
225+
// Get the superclass of the 'Self' type parameter.
226+
baseTy = (baseEquivClass->concreteType
227+
? baseEquivClass->concreteType
228+
: baseEquivClass->superclass);
229+
assert(baseTy);
230+
}
240231

241-
auto subMap = SubstitutionMap::getProtocolSubstitutions(
242-
proto, baseTy, ProtocolConformanceRef(proto));
243-
return concrete->getDeclaredInterfaceType().subst(subMap);
244-
}
232+
return TypeChecker::substMemberTypeWithBase(DC->getParentModule(), concrete,
233+
baseTy);
234+
}
245235

246-
Type baseType = baseEquivClass->concreteType ? baseEquivClass->concreteType
247-
: baseEquivClass->superclass;
236+
Type TypeResolution::resolveSelfAssociatedType(Type baseTy,
237+
DeclContext *DC,
238+
Identifier name) const {
239+
switch (stage) {
240+
case TypeResolutionStage::Structural:
241+
return DependentMemberType::get(baseTy, name);
248242

249-
if (baseType) {
250-
return baseType->getTypeOfMember(DC->getParentModule(), concrete,
251-
concrete->getDeclaredInterfaceType());
252-
}
243+
case TypeResolutionStage::Contextual:
244+
llvm_unreachable("Dependent type after archetype substitution");
253245

254-
llvm_unreachable("shouldn't have a concrete decl here");
246+
case TypeResolutionStage::Interface:
247+
// Handled below.
248+
break;
255249
}
256250

257-
return TypeChecker::substMemberTypeWithBase(DC->getParentModule(), concrete,
251+
assert(stage == TypeResolutionStage::Interface);
252+
auto builder = getGenericSignatureBuilder();
253+
auto baseEquivClass =
254+
builder->resolveEquivalenceClass(
255+
baseTy,
256+
ArchetypeResolutionKind::CompleteWellFormed);
257+
if (!baseEquivClass)
258+
return ErrorType::get(baseTy);
259+
260+
// Look for a nested type with the given name.
261+
auto nestedType = baseEquivClass->lookupNestedType(*builder, name);
262+
assert(nestedType);
263+
264+
// If the nested type has been resolved to an associated type, use it.
265+
if (auto assocType = dyn_cast<AssociatedTypeDecl>(nestedType)) {
266+
return DependentMemberType::get(baseTy, assocType);
267+
}
268+
269+
if (nestedType->getDeclContext()->getSelfClassDecl()) {
270+
// We found a member of a class from a protocol or protocol
271+
// extension.
272+
//
273+
// Get the superclass of the 'Self' type parameter.
274+
baseTy = (baseEquivClass->concreteType
275+
? baseEquivClass->concreteType
276+
: baseEquivClass->superclass);
277+
assert(baseTy);
278+
}
279+
280+
return TypeChecker::substMemberTypeWithBase(DC->getParentModule(), nestedType,
258281
baseTy);
259282
}
260283

@@ -279,6 +302,12 @@ bool TypeResolution::areSameType(Type type1, Type type2) const {
279302

280303
// If we have a generic signature, canonicalize using it.
281304
if (auto genericSig = getGenericSignature()) {
305+
// If both are type parameters, we can use a cheaper check
306+
// that avoids transforming the type and computing anchors.
307+
if (type1->isTypeParameter() &&
308+
type2->isTypeParameter()) {
309+
return genericSig->areSameTypeParameterInContext(type1, type2);
310+
}
282311
return genericSig->getCanonicalTypeInContext(type1)
283312
== genericSig->getCanonicalTypeInContext(type2);
284313
}
@@ -542,20 +571,41 @@ Type TypeChecker::resolveTypeInContext(
542571
selfType = resolution.mapTypeIntoContext(
543572
foundDC->getSelfInterfaceType());
544573

545-
if (selfType->is<GenericTypeParamType>() &&
546-
typeDecl->getDeclContext()->getSelfClassDecl()) {
547-
// We found a member of a class from a protocol or protocol
548-
// extension.
549-
//
550-
// Get the superclass of the 'Self' type parameter.
551-
auto *sig = foundDC->getGenericSignatureOfContext();
552-
if (!sig)
553-
return ErrorType::get(ctx);
554-
auto superclassType = sig->getSuperclassBound(selfType);
555-
if (!superclassType)
556-
return ErrorType::get(ctx);
574+
if (selfType->is<GenericTypeParamType>()) {
575+
if (typeDecl->getDeclContext()->getSelfProtocolDecl()) {
576+
if (isa<AssociatedTypeDecl>(typeDecl) ||
577+
(isa<TypeAliasDecl>(typeDecl) &&
578+
!cast<TypeAliasDecl>(typeDecl)->isGeneric())) {
579+
// FIXME: We should use this lookup method for the Interface
580+
// stage too, but right now that causes problems with
581+
// Sequence.SubSequence vs Collection.SubSequence; the former
582+
// is more canonical, but if we return that instead of the
583+
// latter, we infer the wrong associated type in some cases,
584+
// because we use the Sequence.SubSequence default instead of
585+
// the Collection.SubSequence default, even when the conforming
586+
// type wants to conform to Collection.
587+
if (resolution.getStage() == TypeResolutionStage::Structural) {
588+
return resolution.resolveSelfAssociatedType(
589+
selfType, foundDC, typeDecl->getName());
590+
}
591+
}
592+
}
557593

558-
selfType = superclassType;
594+
// FIXME: Remove this once the above FIXME is addressed.
595+
if (typeDecl->getDeclContext()->getSelfClassDecl()) {
596+
// We found a member of a class from a protocol or protocol
597+
// extension.
598+
//
599+
// Get the superclass of the 'Self' type parameter.
600+
auto *sig = foundDC->getGenericSignatureOfContext();
601+
if (!sig)
602+
return ErrorType::get(ctx);
603+
auto superclassType = sig->getSuperclassBound(selfType);
604+
if (!superclassType)
605+
return ErrorType::get(ctx);
606+
607+
selfType = superclassType;
608+
}
559609
}
560610
}
561611

trunk/lib/Sema/TypeCheckType.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,11 @@ class TypeResolution {
351351
SourceRange baseRange,
352352
ComponentIdentTypeRepr *ref) const;
353353

354+
/// Resolve an unqualified reference to an associated type or type alias
355+
/// in a protocol.
356+
Type resolveSelfAssociatedType(Type baseTy, DeclContext *DC,
357+
Identifier name) const;
358+
354359
/// Determine whether the given two types are equivalent within this
355360
/// type resolution context.
356361
bool areSameType(Type type1, Type type2) const;

trunk/test/Constraints/same_types.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ func structuralSameType3<T, U, V, W>(_: T, _: U, _: V, _: W)
240240
where X1<T, U> == X1<V, W> { }
241241
// expected-error@-1{{same-type requirement makes generic parameters 'T' and 'V' equivalent}}
242242
// expected-error@-2{{same-type requirement makes generic parameters 'U' and 'W' equivalent}}
243+
// expected-warning@-3{{neither type in same-type constraint ('X1<T, U>' or 'X1<V, W>') refers to a generic parameter or associated type}}
243244

244245
protocol P2 {
245246
associatedtype Assoc1
@@ -285,6 +286,7 @@ func test9<T: P6, U: P6>(_ t: T, u: U)
285286
func testMetatypeSameType<T, U>(_ t: T, _ u: U)
286287
where T.Type == U.Type { }
287288
// expected-error@-1{{same-type requirement makes generic parameters 'T' and 'U' equivalent}}
289+
// expected-warning@-2{{neither type in same-type constraint ('T.Type' or 'U.Type') refers to a generic parameter or associated type}}
288290

289291
func testSameTypeCommutativity1<U, T>(_ t: T, _ u: U)
290292
where T.Type == U { } // Equivalent to U == T.Type

trunk/test/Generics/function_decls.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ protocol P {
3838

3939
func f12<T : P>(x: T) -> T.A<Int> {} // expected-error {{cannot specialize non-generic type 'T.A'}}{{29-34=}}
4040

41-
func f13<T : P>(x: T) -> T.B<Int> {} // expected-error {{cannot specialize non-generic type 'P.B' (aka 'Int')}}{{29-34=}}
41+
func f13<T : P>(x: T) -> T.B<Int> {} // expected-error {{cannot specialize non-generic type 'T.B' (aka 'Int')}}{{29-34=}}
4242

4343
func f14<T : P>(x: T) -> T.C<Int> {}
4444

4545
func f15<T : P>(x: T) -> T.D<Int> {}
4646

47-
func f16<T : P>(x: T) -> T.D {} // expected-error {{reference to generic type 'P.D' (aka 'G') requires arguments in <...>}}
47+
func f16<T : P>(x: T) -> T.D {} // expected-error {{reference to generic type 'T.D' (aka 'G') requires arguments in <...>}}
4848

4949
func f17<T : P>(x: T) -> T.E<Int> {}
5050

trunk/test/Generics/protocol_type_aliases.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func requirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, T.C == T.B.X {}
3535
// CHECK-LABEL: .concreteRequirementOnConcreteNestedTypeAlias@
3636
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == τ_0_0.B.A>
3737
func concreteRequirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, S<T.C> == T.B.X {}
38+
// expected-warning@-1 {{neither type in same-type constraint ('S<T.C>' or 'S<T.B.A>') refers to a generic parameter or associated type}}
3839

3940

4041
// Incompatible concrete typealias types are flagged as such

trunk/test/Generics/same_type_constraints.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,7 @@ func resultTypeSuppress<T: P1>() -> StructTakingP1<T> {
376376
typealias NotAnInt = Double
377377

378378
extension X11 where NotAnInt == Int { }
379-
// expected-warning@-1{{neither type in same-type constraint ('NotAnInt' (aka 'Double') or 'Int') refers to a generic parameter or associated type}}
380-
// expected-error@-2{{generic signature requires types 'NotAnInt' (aka 'Double') and 'Int' to be the same}}
379+
// expected-error@-1{{generic signature requires types 'NotAnInt' (aka 'Double') and 'Int' to be the same}}
381380

382381

383382
struct X12<T> { }
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// Reference to associated type from 'where' clause should not be
4+
// ambiguous when there's a typealias with the same name in another
5+
// protocol.
6+
//
7+
// FIXME: The semantics here are still really iffy. There's also a
8+
// case to be made that type aliases in protocol extensions should
9+
// only act as defaults and not as same-type constraints. However,
10+
// if we decide to go down that route, it's important that *both*
11+
// the unqualified (T) and qualified (Self.T) lookups behave the
12+
// same.
13+
protocol P1 {
14+
typealias T = Int // expected-note {{found this candidate}}
15+
}
16+
17+
protocol P2 {
18+
associatedtype T // expected-note {{found this candidate}}
19+
}
20+
21+
// FIXME: This extension's generic signature is still minimized differently from
22+
// the next one. We need to decide if 'T == Int' is a redundant requirement or
23+
// not.
24+
extension P1 where Self : P2, T == Int {
25+
func takeT1(_: T) {}
26+
func takeT2(_: Self.T) {}
27+
}
28+
29+
extension P1 where Self : P2 {
30+
// FIXME: This doesn't make sense -- either both should
31+
// succeed, or both should be ambiguous.
32+
func takeT1(_: T) {} // expected-error {{'T' is ambiguous for type lookup in this context}}
33+
func takeT2(_: Self.T) {}
34+
}
35+
36+
// Same as above, but now we have two visible associated types with the same
37+
// name.
38+
protocol P3 {
39+
associatedtype T
40+
}
41+
42+
// FIXME: This extension's generic signature is still minimized differently from
43+
// the next one. We need to decide if 'T == Int' is a redundant requirement or
44+
// not.
45+
extension P2 where Self : P3, T == Int {
46+
func takeT1(_: T) {}
47+
func takeT2(_: Self.T) {}
48+
}
49+
50+
extension P2 where Self : P3 {
51+
func takeT1(_: T) {}
52+
func takeT2(_: Self.T) {}
53+
}
54+
55+
protocol P4 : P2, P3 {
56+
func takeT1(_: T)
57+
func takeT2(_: Self.T)
58+
}

0 commit comments

Comments
 (0)