Skip to content

Commit 63bc717

Browse files
authored
Error when one associated type is constrained to another. (#10053)
(...is constrained to be a subtype of another) Previously the compiler would just mark the entry in the inheritance clause invalid and move on without emitting any errors; in certain circumstances in no-asserts builds this could actually lead to everything working "correctly" if all conforming types happened to pick the same concrete type for both associated types. In Swift 4 this can actually be enforced with a same-type requirement, which will guarantee that the two associated types are the same even in generic contexts. This fix avoids assertions and crashes, but the diagnostic is still incorrect, and in the simple case of the inheritance clause it's redundant. Doing something better and possibly even downgrading it to a warning in Swift 3 mode is tracked by rdar://problem/32409449. Initial patch by Slava, fixed up by me.
1 parent 55843a2 commit 63bc717

File tree

5 files changed

+38
-8
lines changed

5 files changed

+38
-8
lines changed

lib/Sema/ITCDecl.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,24 @@ void IterativeTypeChecker::processResolveInheritedClauseEntry(
108108

109109
// Validate the type of this inherited clause entry.
110110
// FIXME: Recursion into existing type checker.
111-
GenericTypeToArchetypeResolver resolver(dc);
112-
if (TC.validateType(*inherited, dc, options, &resolver,
111+
Optional<ProtocolRequirementTypeResolver> protoResolver;
112+
Optional<GenericTypeToArchetypeResolver> archetypeResolver;
113+
GenericTypeResolver *resolver;
114+
if (auto *proto = dyn_cast<ProtocolDecl>(dc)) {
115+
protoResolver.emplace(proto);
116+
resolver = protoResolver.getPointer();
117+
} else {
118+
archetypeResolver.emplace(dc);
119+
resolver = archetypeResolver.getPointer();
120+
}
121+
122+
if (TC.validateType(*inherited, dc, options, resolver,
113123
&unsatisfiedDependency)) {
114124
inherited->setInvalidType(getASTContext());
115125
}
116126

117127
auto type = inherited->getType();
118-
if (!type.isNull())
128+
if (!type.isNull() && !isa<ProtocolDecl>(dc))
119129
inherited->setType(dc->mapTypeOutOfContext(type));
120130
}
121131

test/Sema/circular_decl_checking.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ func TopLevelGenericFunc2<T : TopLevelGenericFunc2>(x: T) -> T { return x} // ex
4343
var TopLevelVar: TopLevelVar? { return nil } // expected-error 2 {{use of undeclared type 'TopLevelVar'}}
4444

4545

46-
protocol AProtocol {
47-
// FIXME: Should produce an error here, but it's currently causing problems.
48-
associatedtype e : e
46+
// FIXME: The first error is redundant, isn't correct in what it states, and
47+
// also should be emitted on the inheritance clause.
48+
protocol AProtocol { // expected-error {{first type 'Self.e' in conformance requirement does not refer to a generic parameter or associated type}}
49+
associatedtype e : e // expected-error {{inheritance from non-protocol, non-class type 'Self.e'}}
4950
}
5051

5152

test/decl/nested/protocol.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,6 @@ class OuterClass {
7272

7373
class OtherGenericClass<T> {
7474
protocol InnerProtocol : OtherGenericClass { }
75-
// expected-error@-1{{protocol 'InnerProtocol' cannot be nested inside another declaration}}
75+
// expected-error@-1{{non-class type 'InnerProtocol' cannot inherit from class 'OtherGenericClass<T>'}}
76+
// expected-error@-2{{protocol 'InnerProtocol' cannot be nested inside another declaration}}
7677
}

test/decl/protocol/req/unsatisfiable.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,21 @@ protocol P3 {
3030
func f<T: P3>(_: T) where T.A == Self.A, T.A: C // expected-error{{instance method requirement 'f' cannot add constraint 'Self.A: C' on 'Self'}}
3131
func g<T: P3>(_: T) where T.A: C, T.A == Self.A // expected-error{{instance method requirement 'g' cannot add constraint 'Self.A: C' on 'Self'}}
3232
}
33+
34+
protocol Base {
35+
associatedtype Assoc
36+
}
37+
38+
// FIXME: The first error is redundant, isn't correct in what it states, and
39+
// also should be emitted on the inheritance clause.
40+
// FIXME: This used to /not/ error in Swift 3. It didn't impose any statically-
41+
// enforced requirements, but the compiler crashed if you used anything but the
42+
// same type.
43+
protocol Sub1: Base { // expected-error {{first type 'Self.Assoc' in conformance requirement does not refer to a generic parameter or associated type}}
44+
associatedtype SubAssoc: Assoc // expected-error {{inheritance from non-protocol, non-class type 'Self.Assoc'}}
45+
}
46+
// FIXME: This error is incorrect in what it states and should be emitted on
47+
// the where-clause.
48+
protocol Sub2: Base { // expected-error {{first type 'Self.Assoc' in conformance requirement does not refer to a generic parameter or associated type}}
49+
associatedtype SubAssoc where SubAssoc: Assoc
50+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
protocol b:Self

0 commit comments

Comments
 (0)