Skip to content

Commit 50471e1

Browse files
authored
Merge pull request #6406 from slavapestov/small-sema-fixes
Small Sema fixes
2 parents 035e179 + 867a956 commit 50471e1

13 files changed

+95
-31
lines changed

lib/AST/ArchetypeBuilder.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,6 +1993,17 @@ static void collectRequirements(ArchetypeBuilder &builder,
19931993
if (auto concreteTy = type.dyn_cast<Type>()) {
19941994
// Maybe we were equated to a concrete type...
19951995
repTy = concreteTy;
1996+
1997+
// Drop requirements involving concrete types containing
1998+
// unresolved associated types.
1999+
if (repTy.findIf([](Type t) -> bool {
2000+
if (auto *depTy = dyn_cast<DependentMemberType>(t.getPointer()))
2001+
if (depTy->getAssocType() == nullptr)
2002+
return true;
2003+
return false;
2004+
})) {
2005+
return;
2006+
}
19962007
} else {
19972008
// ...or to a dependent type.
19982009
repTy = type.get<ArchetypeBuilder::PotentialArchetype *>()

lib/AST/Module.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -610,16 +610,18 @@ TypeBase::gatherAllSubstitutions(Module *module,
610610
llvm_unreachable("Not a nominal or bound generic type");
611611
}
612612

613+
auto *genericEnv = gpContext->getGenericEnvironmentOfContext();
614+
613615
// Add forwarding substitutions from the outer context if we have
614616
// a type nested inside a generic function.
615617
auto *parentDC = gpContext;
616618
while (parentDC->isTypeContext())
617619
parentDC = parentDC->getParent();
618-
if (auto *outerEnv = parentDC->getGenericEnvironmentOfContext()) {
619-
for (auto gp : outerEnv->getGenericParams()) {
620+
if (auto *outerSig = parentDC->getGenericSignatureOfContext()) {
621+
for (auto gp : outerSig->getGenericParams()) {
620622
auto result = substitutions.insert(
621623
{gp->getCanonicalType()->castTo<GenericTypeParamType>(),
622-
outerEnv->mapTypeIntoContext(gp)});
624+
genericEnv->mapTypeIntoContext(gp)});
623625
assert(result.second);
624626
}
625627
}

lib/Sema/ITCDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ void IterativeTypeChecker::processResolveInheritedClauseEntry(
112112
&unsatisfiedDependency)) {
113113
inherited->setInvalidType(getASTContext());
114114
}
115+
116+
auto type = inherited->getType();
117+
if (!type.isNull())
118+
inherited->setType(dc->mapTypeOutOfContext(type));
115119
}
116120

117121
bool IterativeTypeChecker::breakCycleForResolveInheritedClauseEntry(

lib/Sema/TypeCheckDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3464,6 +3464,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
34643464
: TC(TC), IsFirstPass(IsFirstPass), IsSecondPass(IsSecondPass) {}
34653465

34663466
void visit(Decl *decl) {
3467+
PrettyStackTraceDecl StackTrace("type-checking", decl);
34673468

34683469
DeclVisitor<DeclChecker>::visit(decl);
34693470

@@ -6570,7 +6571,6 @@ bool TypeChecker::isAvailabilitySafeForConformance(
65706571
}
65716572

65726573
void TypeChecker::typeCheckDecl(Decl *D, bool isFirstPass) {
6573-
PrettyStackTraceDecl StackTrace("type-checking", D);
65746574
checkForForbiddenPrefix(D);
65756575
bool isSecondPass =
65766576
!isFirstPass && D->getDeclContext()->isModuleScopeContext();
@@ -6756,6 +6756,8 @@ void TypeChecker::validateDecl(ValueDecl *D) {
67566756
if (D->isBeingValidated())
67576757
return;
67586758

6759+
PrettyStackTraceDecl StackTrace("validating", D);
6760+
67596761
if (hasEnabledForbiddenTypecheckPrefix())
67606762
checkForForbiddenPrefix(D);
67616763

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,9 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
340340
// existential type, because we have no way to represent such types.
341341
//
342342
// This is diagnosed further on down in resolveNestedIdentTypeComponent().
343-
if (type->isExistentialType()) {
343+
if (type->isExistentialType() &&
344+
(isa<TypeAliasDecl>(typeDecl) ||
345+
isa<AssociatedTypeDecl>(typeDecl))) {
344346
auto memberType = typeDecl->getInterfaceType()->getRValueInstanceType();
345347

346348
if (memberType->hasTypeParameter()) {

lib/Sema/TypeCheckType.cpp

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -221,38 +221,41 @@ findDeclContextForType(TypeChecker &TC,
221221

222222
bool needsBaseType = (ownerDC->isTypeContext() &&
223223
!isa<GenericTypeParamDecl>(typeDecl));
224-
NominalTypeDecl *ownerNominal = nullptr;
225-
if (needsBaseType) {
226-
ownerNominal = ownerDC->getAsNominalTypeOrNominalTypeExtensionContext();
224+
NominalTypeDecl *ownerNominal =
225+
ownerDC->getAsNominalTypeOrNominalTypeExtensionContext();
227226

228-
// We might have an invalid extension that didn't resolve.
229-
if (ownerNominal == nullptr)
230-
return std::make_tuple(nullptr, nullptr, false);
231-
}
227+
// We might have an invalid extension that didn't resolve.
228+
if (needsBaseType && ownerNominal == nullptr)
229+
return std::make_tuple(nullptr, nullptr, false);
232230

231+
// First, check for containment in one of our parent contexts.
233232
for (auto parentDC = fromDC; !parentDC->isModuleContext();
234233
parentDC = parentDC->getParent()) {
234+
auto parentNominal =
235+
parentDC->getAsNominalTypeOrNominalTypeExtensionContext();
235236

236-
// If we're not computing a base type, we just have to check for
237-
// containment in one of our parent contexts.
238-
if (!needsBaseType) {
239-
if (ownerDC == parentDC)
240-
return std::make_tuple(ownerDC, nullptr, true);
237+
if (ownerDC == parentDC)
238+
return std::make_tuple(parentDC, parentNominal, true);
241239

242-
// FIXME: Horrible hack. Don't allow us to reference a generic parameter
243-
// or from a context outside a ProtocolDecl.
244-
if (isa<ProtocolDecl>(parentDC) && isa<GenericTypeParamDecl>(typeDecl))
245-
return std::make_tuple(nullptr, nullptr, false);
240+
// FIXME: Horrible hack. Don't allow us to reference a generic parameter
241+
// from a context outside a ProtocolDecl.
242+
if (isa<ProtocolDecl>(parentDC) && isa<GenericTypeParamDecl>(typeDecl))
243+
return std::make_tuple(nullptr, nullptr, false);
244+
}
246245

247-
continue;
248-
}
246+
if (!needsBaseType) {
247+
assert(false && "Should have found non-type context by now");
248+
return std::make_tuple(nullptr, nullptr, false);
249+
}
249250

251+
// Now, search the supertypes or refined protocols of each parent
252+
// context.
253+
for (auto parentDC = fromDC; !parentDC->isModuleContext();
254+
parentDC = parentDC->getParent()) {
250255
// For the next steps we need our parentDC to be a type context
251256
if (!parentDC->isTypeContext())
252257
continue;
253258

254-
// Search the type of this context and its supertypes (if its a
255-
// class) or refined protocols (if its a protocol).
256259
llvm::SmallPtrSet<const NominalTypeDecl *, 8> visited;
257260
llvm::SmallVector<const NominalTypeDecl *, 8> stack;
258261

@@ -314,9 +317,9 @@ findDeclContextForType(TypeChecker &TC,
314317
}
315318
}
316319

317-
// FIXME: Horrible hack. Don't allow us to reference an associated type
318-
// from a context outside a ProtocolDecl.
319-
if (isa<ProtocolDecl>(parentDC) && isa<AssociatedTypeDecl>(typeDecl))
320+
// FIXME: Horrible hack. Don't allow us to reference a generic parameter
321+
// or associated type from a context outside a ProtocolDecl.
322+
if (isa<ProtocolDecl>(parentDC) && isa<AbstractTypeParamDecl>(typeDecl))
320323
return std::make_tuple(nullptr, nullptr, false);
321324
}
322325

test/Generics/invalid.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,13 @@ func takesAny(_ a: Any) {}
7979
func badDiagnostic3() {
8080
takesAny(Deli.self) // expected-error {{argument type 'Deli<_>.Type' does not conform to expected type 'Any'}}
8181
}
82+
83+
// Crash with missing nested type inside concrete type
84+
class OuterGeneric<T> {
85+
class InnerGeneric<U> where U:OuterGeneric<T.NoSuchType> {
86+
// expected-error@-1 {{'NoSuchType' is not a member type of 'T'}}
87+
func method() {
88+
_ = method
89+
}
90+
}
91+
}

test/decl/nested/protocol.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,22 @@ protocol Racoon {
4141
}
4242
}
4343

44+
enum SillyRawEnum : SillyProtocol.InnerClass {}
45+
// expected-error@-1 {{raw type 'SillyProtocol.InnerClass' is not expressible by any literal}}
46+
// expected-error@-2 {{'SillyRawEnum' declares raw type 'SillyProtocol.InnerClass', but does not conform to RawRepresentable and conformance could not be synthesized}}
47+
48+
protocol SillyProtocol {
49+
class InnerClass<T> {} // expected-error {{type 'InnerClass' cannot be nested in protocol 'SillyProtocol'}}
50+
}
51+
4452
enum OuterEnum {
4553
protocol C {} // expected-error{{protocol 'C' cannot be nested inside another declaration}}
4654
// expected-note@-1{{'C' previously declared here}}
4755
case C(C) // expected-error{{invalid redeclaration of 'C'}}
4856
}
4957

58+
class OuterClass<T> {
59+
protocol InnerProtocol : OuterClass { }
60+
// expected-error@-1{{protocol 'InnerProtocol' cannot be nested inside another declaration}}
61+
// expected-error@-2{{non-class type 'InnerProtocol' cannot inherit from class 'OuterClass<T>'}}
62+
}

test/decl/nested/type_in_function.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,15 @@ func f5<T, U>(x: T, y: U) {
7979
typealias U = Int
8080
}
8181
}
82+
83+
// Issue with gatherAllSubstitutions().
84+
struct OuterGenericStruct<A> {
85+
class MiddleNonGenericClass {
86+
func nonGenericFunction() {
87+
class InnerGenericClass<T> : MiddleNonGenericClass {
88+
// expected-error@-1 {{type 'InnerGenericClass' cannot be nested in generic function 'nonGenericFunction'}}
89+
override init() { super.init() }
90+
}
91+
}
92+
}
93+
}

test/decl/nested/type_in_type.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ class OuterGenericClass<T> {
104104
super.init()
105105
}
106106
}
107+
108+
class Middle {
109+
class Inner1<T> {}
110+
class Inner2<T> : Middle where T: Inner1<Int> {}
111+
}
107112
}
108113

109114
// <rdar://problem/12895793>

validation-test/compiler_crashers/28415-swift-iterativetypechecker-processtypechecksuperclass.swift renamed to validation-test/compiler_crashers_fixed/28415-swift-iterativetypechecker-processtypechecksuperclass.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
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 -typecheck
8+
// RUN: not %target-swift-frontend %s -typecheck
99
// REQUIRES: asserts
1010
class B<a>{
1111
protocol c:a

validation-test/compiler_crashers/28458-resultreplacement-istypeparameter-cant-be-dependent.swift renamed to validation-test/compiler_crashers_fixed/28458-resultreplacement-istypeparameter-cant-be-dependent.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
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
// REQUIRES: asserts
1010
protocol C{struct D:C{enum A{case J(f}typealias F=Self}typealias f typealias F
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
class B<T>{class a{var:{class B<T>:a

0 commit comments

Comments
 (0)