@@ -44,12 +44,87 @@ void swift::registerIDETypeCheckRequestFunctions(Evaluator &evaluator) {
44
44
ideTypeCheckRequestFunctions);
45
45
}
46
46
47
+ // / Consider the following example
48
+ // /
49
+ // / \code
50
+ // / protocol FontStyle {}
51
+ // / struct FontStyleOne: FontStyle {}
52
+ // / extension FontStyle where Self == FontStyleOne {
53
+ // / static var one: FontStyleOne { FontStyleOne() }
54
+ // / }
55
+ // / func foo<T: FontStyle>(x: T) {}
56
+ // /
57
+ // / func case1() {
58
+ // / foo(x: .#^COMPLETE^#) // extension should be considered applied here
59
+ // / }
60
+ // / func case2<T: FontStyle>(x: T) {
61
+ // / x.#^COMPLETE_2^# // extension should not be considered applied here
62
+ // / }
63
+ // / \endcode
64
+ // / We want to consider the extension applied in the first case but not the
65
+ // / second case. In the first case the constraint `T: FontStyle` from the
66
+ // / definition of `foo` should be considered an 'at-least' constraint and any
67
+ // / additional constraints on `T` (like `T == FonstStyleOne`) can be
68
+ // / fulfilled by picking a more specialized version of `T`.
69
+ // / However, in the second case, `T: FontStyle` should be considered an
70
+ // / 'at-most' constraint and we can't make the assumption that `x` has a more
71
+ // / specialized type.
72
+ // /
73
+ // / After type-checking we cannot easily differentiate the two cases. In both
74
+ // / we have a unresolved dot completion on a primary archetype that
75
+ // / conforms to `FontStyle`.
76
+ // /
77
+ // / To tell them apart, we apply the following heuristic: If the primary
78
+ // / archetype refers to a generic parameter that is not visible in the current
79
+ // / decl context (i.e. the current decl context is not a child context of the
80
+ // / parameter's decl context), it is not the type of a variable visible
81
+ // / in the current decl context. Hence, we must be in the first case and
82
+ // / consider all extensions applied, otherwise we should only consider those
83
+ // / extensions applied whose requirements are fulfilled.
84
+ class ContainsSpecializableArchetype : public TypeWalker {
85
+ const DeclContext *DC;
86
+ bool Result = false ;
87
+ ContainsSpecializableArchetype (const DeclContext *DC) : DC(DC) {}
88
+
89
+ Action walkToTypePre (Type T) override {
90
+ if (auto *Archetype = T->getAs <ArchetypeType>()) {
91
+ if (auto *GenericTypeParam =
92
+ Archetype->mapTypeOutOfContext ()->getAs <GenericTypeParamType>()) {
93
+ if (auto GenericTypeParamDecl = GenericTypeParam->getDecl ()) {
94
+ bool ParamMaybeVisibleInCurrentContext =
95
+ (DC == GenericTypeParamDecl->getDeclContext () ||
96
+ DC->isChildContextOf (GenericTypeParamDecl->getDeclContext ()));
97
+ if (!ParamMaybeVisibleInCurrentContext) {
98
+ Result = true ;
99
+ return Action::Stop;
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return Action::Continue;
105
+ }
106
+
107
+ public:
108
+ static bool check (const DeclContext *DC, Type T) {
109
+ if (!T->hasArchetype ()) {
110
+ // Fast path, we don't have an archetype to check.
111
+ return false ;
112
+ }
113
+ ContainsSpecializableArchetype Checker (DC);
114
+ T.walk (Checker);
115
+ return Checker.Result ;
116
+ }
117
+ };
118
+
47
119
static bool isExtensionAppliedInternal (const DeclContext *DC, Type BaseTy,
48
120
const ExtensionDecl *ED) {
49
121
// We can't do anything if the base type has unbound generic parameters.
50
122
// We can't leak type variables into another constraint system.
123
+ // For check on specializable archetype see comment on
124
+ // ContainsSpecializableArchetype.
51
125
if (BaseTy->hasTypeVariable () || BaseTy->hasUnboundGenericType () ||
52
- BaseTy->hasUnresolvedType () || BaseTy->hasError ())
126
+ BaseTy->hasUnresolvedType () || BaseTy->hasError () ||
127
+ ContainsSpecializableArchetype::check (DC, BaseTy))
53
128
return true ;
54
129
55
130
if (!ED->isConstrainedExtension ())
0 commit comments