Skip to content

Commit 28ee60e

Browse files
committed
[CodeComplete] Fix code completion of initialization for variable wrapped by generic property wrapper
If completing the initialization of a variable that’s wrapped in a generic, unbound property wrapper, the expression's type is an `UnboundGenericType`. AFAICT that’s expected and the correct type to assign. We hit the first assertion failure by trying to retrieve that type's substitution map. `UnboundGenericType`s were not handled here, so we crashed. AFAICT we can't get any substitutions out of an unbound generic type, so we should just continue looking into the parent type. We hit the second assertion when trying to retrieve the property wrapper’s backing type, which is null (becuase it couldn't be resolved). However, we haven’t emitted a diagnostic because the variable declaration is perfectly valid. Hence I’m removing the assertion. Fixes rdar://64141399
1 parent e1e0f54 commit 28ee60e

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

lib/AST/Type.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4108,6 +4108,13 @@ TypeBase::getContextSubstitutions(const DeclContext *dc,
41084108
continue;
41094109
}
41104110

4111+
// There are no subtitutions to apply if the type is still unbound,
4112+
// continue looking into the parent.
4113+
if (auto unboundGeneric = baseTy->getAs<UnboundGenericType>()) {
4114+
baseTy = unboundGeneric->getParent();
4115+
continue;
4116+
}
4117+
41114118
// Assert and break to avoid hanging if we get an unexpected baseTy.
41124119
assert(0 && "Bad base type");
41134120
break;

lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,8 @@ PropertyWrapperBackingPropertyTypeRequest::evaluate(
565565
(void)var->getInterfaceType();
566566
if (!binding->isInitializerChecked(index))
567567
TypeChecker::typeCheckPatternBinding(binding, index);
568+
if (binding->isInvalid())
569+
return Type();
568570
} else {
569571
using namespace constraints;
570572
auto dc = var->getInnermostDeclContext();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=COMPLETE_GENERIC -source-filename=%s
2+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=COMPLETE_IN_GENERIC_CONTEXT -source-filename=%s
3+
4+
struct Foo {
5+
static let bar: Foo
6+
}
7+
8+
@propertyWrapper public struct GenericWrapper<Value> {
9+
public var wrappedValue: Value
10+
public var projectedValue: Int
11+
12+
public init(wrappedValue: Value) {
13+
self.wrappedValue = wrappedValue
14+
self.projectedValue = 1
15+
}
16+
}
17+
18+
public struct GenericContext<T> {
19+
@propertyWrapper public struct GenericWrapper<Value> {
20+
public var wrappedValue: Value
21+
public var projectedValue: Int
22+
23+
public init(wrappedValue: Value) {
24+
self.wrappedValue = wrappedValue
25+
self.projectedValue = 1
26+
}
27+
}
28+
}
29+
30+
public struct MyStruct {
31+
@GenericWrapper var someProperty = #^COMPLETE_GENERIC^#
32+
}
33+
public struct MyStruct2 {
34+
@GenericContext<Foo>.GenericWrapper var someProperty2 = #^COMPLETE_IN_GENERIC_CONTEXT^#
35+
}

0 commit comments

Comments
 (0)