Skip to content

Commit b053eae

Browse files
committed
Sema: Tweak assertion in CustomAttrTypeRequest to allow generic typealiases
If the typealias here is generic, we return an UnboundGenericType where getAnyNominal() returns nullptr. This would fail by returning an ErrorType to the caller without diagnosing anything. This was a regression after some recent refactoring to remove code duplication and some TypeLoc usages, because one of the copies of this code did not have this check, so it happened to work for property wrappers. Relax the check by looking through a TypeAliasDecl explicitly. I believe we can't end up here anyway, because if the type was not a nominal we would fail earlier in CustomAttrNominalRequest, and we wouldn't attempt to compute the type of the property wrapper at all. However it's better to keep the assertion in place just in case. Fixes https://bugs.swift.org/browse/SR-14143 / rdar://problem/73888684.
1 parent 1b2ef54 commit b053eae

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4029,12 +4029,26 @@ Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr,
40294029
};
40304030
}
40314031

4032-
ASTContext &ctx = dc->getASTContext();
40334032
const auto type = TypeResolution::forContextual(dc, options, unboundTyOpener)
40344033
.resolveType(attr->getTypeRepr());
40354034

4036-
// We always require the type to resolve to a nominal type.
4037-
if (!type->getAnyNominal()) {
4035+
// We always require the type to resolve to a nominal type. If the type was
4036+
// not a nominal type, we should have already diagnosed an error via
4037+
// CustomAttrNominalRequest.
4038+
auto checkType = [](Type type) -> bool {
4039+
while (auto *genericDecl = type->getAnyGeneric()) {
4040+
if (isa<NominalTypeDecl>(genericDecl))
4041+
return true;
4042+
4043+
auto *aliasDecl = cast<TypeAliasDecl>(genericDecl);
4044+
type = aliasDecl->getUnderlyingType();
4045+
}
4046+
4047+
return false;
4048+
};
4049+
4050+
if (!checkType(type)) {
4051+
ASTContext &ctx = dc->getASTContext();
40384052
assert(ctx.Diags.hadAnyError());
40394053
return ErrorType::get(ctx);
40404054
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// https://bugs.swift.org/browse/SR-14143
4+
5+
@propertyWrapper
6+
struct SomeLongFooName<Holder, T> {
7+
var wrappedValue: T
8+
9+
init(wrappedValue: T) {
10+
self.wrappedValue = wrappedValue
11+
}
12+
}
13+
14+
15+
struct Bar {
16+
typealias Foo<T> = SomeLongFooName<Self, T>
17+
18+
@Foo var baz: Bool = false
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
@propertyWrapper
4+
struct SomeStruct<T> {
5+
var wrappedValue: T
6+
7+
init(wrappedValue: T) {
8+
self.wrappedValue = wrappedValue
9+
}
10+
}
11+
12+
typealias Invalid1<T> = (T) -> ()
13+
typealias Invalid2<T> = SomeStruct<T>.Type
14+
typealias Invalid3 = SomeStruct<Bool>.Type
15+
16+
struct Bar {
17+
@Invalid1 var badWrapper1: Bool = false // expected-error {{unknown attribute 'Invalid1'}}
18+
@Invalid2 var badWrapper2: Bool = false // expected-error {{unknown attribute 'Invalid2'}}
19+
@Invalid3 var badWrapper3: Bool = false // expected-error {{unknown attribute 'Invalid3'}}
20+
}

0 commit comments

Comments
 (0)