@@ -44,12 +44,87 @@ void swift::registerIDETypeCheckRequestFunctions(Evaluator &evaluator) {
4444 ideTypeCheckRequestFunctions);
4545}
4646
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+
47119static bool isExtensionAppliedInternal (const DeclContext *DC, Type BaseTy,
48120 const ExtensionDecl *ED) {
49121 // We can't do anything if the base type has unbound generic parameters.
50122 // We can't leak type variables into another constraint system.
123+ // For check on specializable archetype see comment on
124+ // ContainsSpecializableArchetype.
51125 if (BaseTy->hasTypeVariable () || BaseTy->hasUnboundGenericType () ||
52- BaseTy->hasUnresolvedType () || BaseTy->hasError ())
126+ BaseTy->hasUnresolvedType () || BaseTy->hasError () ||
127+ ContainsSpecializableArchetype::check (DC, BaseTy))
53128 return true ;
54129
55130 if (!ED->isConstrainedExtension ())
0 commit comments