diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index e15f887f81a5a..5d7e47f29e65c 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -164,6 +164,9 @@ class Evaluator { /// is treated as a stack and is used to detect cycles. llvm::SetVector activeRequests; + /// A set of active requests that have been diagnosed for a cycle. + llvm::DenseSet diagnosedActiveCycles; + /// A cache that stores the results of requests. evaluator::RequestCache cache; @@ -344,7 +347,17 @@ class Evaluator { recorder.beginRequest(); - auto result = getRequestFunction()(request, *this); + auto result = [&]() -> typename Request::OutputType { + auto reqResult = getRequestFunction()(request, *this); + + // If we diagnosed a cycle for this request, we want to only use the + // default value to ensure we return a consistent result. + if (!diagnosedActiveCycles.empty() && + diagnosedActiveCycles.erase(activeReq)) { + return defaultValueFn(); + } + return reqResult; + }(); recorder.endRequest(request); diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index d4fd6dc357baa..352af26fe472f 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -120,6 +120,10 @@ class GenericSignature { ArrayRef requirements, bool isKnownCanonical = false); + /// Create a new placeholder generic signature from a set of generic + /// parameters. This is necessary for recovery in invalid cases. + static GenericSignature forInvalid(ArrayRef params); + /// Produce a new generic signature which drops all of the marker /// protocol conformance requirements associated with this one. GenericSignature withoutMarkerProtocols() const; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 07b932e8c75f3..155ab58b8a684 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3618,15 +3618,11 @@ static Type replacingTypeVariablesAndPlaceholders(Type ty) { Type ErrorType::get(Type originalType) { // The original type is only used for printing/debugging, and we don't support // solver-allocated ErrorTypes. As such, fold any type variables and - // placeholders into bare ErrorTypes, which print as placeholders. - // - // FIXME: If the originalType is itself an ErrorType we ought to be flattening - // it, but that's currently load-bearing as it avoids crashing for recursive - // generic signatures such as in `0120-rdar34184392.swift`. To fix this we - // ought to change the evaluator to ensure the outer step of a request cycle - // returns the same default value as the inner step such that we don't end up - // with conflicting generic signatures on encountering a cycle. + // placeholders into ErrorTypes. If we have a top-level one, we can return + // that directly. originalType = replacingTypeVariablesAndPlaceholders(originalType); + if (isa(originalType.getPointer())) + return originalType; ASSERT(originalType); ASSERT(!originalType->getRecursiveProperties().isSolverAllocated() && @@ -6007,6 +6003,25 @@ GenericSignature::get(ArrayRef params, return newSig; } +GenericSignature +GenericSignature::forInvalid(ArrayRef params) { + ASSERT(!params.empty()); + auto &ctx = params.front()->getASTContext(); + + // Add same type requirements that make each of the generic parameters + // concrete error types. This helps avoid downstream diagnostics and is + // handled the same as if the user wrote e.g ``. + SmallVector requirements; + for (auto *param : params) { + if (param->isValue()) + continue; + + requirements.emplace_back(RequirementKind::SameType, param, + ErrorType::get(ctx)); + } + return GenericSignature::get(params, requirements); +} + GenericEnvironment *GenericEnvironment::forPrimary(GenericSignature signature) { auto &ctx = signature->getASTContext(); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index ea76f64a38cb6..8b24c6e4b830d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1643,8 +1643,7 @@ bool GenericContext::isComputingGenericSignature() const { /// If we hit a cycle while building the generic signature, we can't return /// nullptr, since this breaks invariants elsewhere. Instead, build a dummy -/// signature where everything is Copyable and Escapable, to avoid spurious -/// downstream diagnostics concerning move-only types. +/// invalid signature to avoid spurious downstream diagnostics. static GenericSignature getPlaceholderGenericSignature( ASTContext &ctx, const DeclContext *DC) { SmallVector gpLists; @@ -1660,22 +1659,13 @@ static GenericSignature getPlaceholderGenericSignature( gpLists[i]->setDepth(i); SmallVector genericParams; - SmallVector requirements; - for (auto *gpList : gpLists) { for (auto *genericParam : *gpList) { auto type = genericParam->getDeclaredInterfaceType(); genericParams.push_back(type->castTo()); - - for (auto ip : InvertibleProtocolSet::allKnown()) { - auto proto = ctx.getProtocol(getKnownProtocolKind(ip)); - requirements.emplace_back(RequirementKind::Conformance, type, - proto->getDeclaredInterfaceType()); - } } } - - return GenericSignature::get(genericParams, requirements); + return GenericSignature::forInvalid(genericParams); } GenericSignature GenericContext::getGenericSignature() const { @@ -2700,10 +2690,16 @@ bool PatternBindingDecl::hasStorage() const { const PatternBindingEntry * PatternBindingDecl::getCheckedPatternBindingEntry(unsigned i) const { - return evaluateOrDefault( + auto result = evaluateOrDefault( getASTContext().evaluator, PatternBindingEntryRequest{const_cast(this), i}, nullptr); + + // If we ran into a cycle, we can still return the entry. + if (!result) + return &getPatternList()[i]; + + return result; } void PatternBindingDecl::setPattern(unsigned i, Pattern *P, @@ -7392,8 +7388,7 @@ bool ProtocolDecl::existentialConformsToSelf() const { } bool ProtocolDecl::hasSelfOrAssociatedTypeRequirements() const { - // Because we will have considered all the protocols in a cyclic hierarchy by - // the time the cycle is hit. + // Be conservative and avoid diagnosing if we hit a cycle. const bool resultForCycle = false; return evaluateOrDefault(getASTContext().evaluator, diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index 7632e2e581fed..dcc1c55423f4f 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -155,8 +155,12 @@ void Evaluator::diagnoseCycle(const ActiveRequest &request) { request.diagnoseCycle(cycleDiags.getDiags()); for (const auto &step : llvm::reverse(activeRequests)) { - if (step == request) + if (step == request) { + // Note that we diagnosed a cycle for the outermost step to ensure it + // also returns a cyclic result. + diagnosedActiveCycles.insert(step); return; + } step.noteCycleStep(cycleDiags.getDiags()); } diff --git a/lib/AST/RequirementMachine/RequirementMachineRequests.cpp b/lib/AST/RequirementMachine/RequirementMachineRequests.cpp index c80d68b91e765..28ec01d43c5ec 100644 --- a/lib/AST/RequirementMachine/RequirementMachineRequests.cpp +++ b/lib/AST/RequirementMachine/RequirementMachineRequests.cpp @@ -750,26 +750,6 @@ AbstractGenericSignatureRequest::evaluate( } } -/// If completion fails, build a dummy generic signature where everything is -/// Copyable and Escapable, to avoid spurious downstream diagnostics -/// concerning move-only types. -static GenericSignature getPlaceholderGenericSignature( - ASTContext &ctx, ArrayRef genericParams) { - SmallVector requirements; - for (auto param : genericParams) { - if (param->isValue()) - continue; - - for (auto ip : InvertibleProtocolSet::allKnown()) { - auto proto = ctx.getProtocol(getKnownProtocolKind(ip)); - requirements.emplace_back(RequirementKind::Conformance, param, - proto->getDeclaredInterfaceType()); - } - } - - return GenericSignature::get(genericParams, requirements); -} - GenericSignatureWithError InferredGenericSignatureRequest::evaluate( Evaluator &evaluator, @@ -996,7 +976,7 @@ InferredGenericSignatureRequest::evaluate( diag::requirement_machine_completion_rule, rule); - auto result = getPlaceholderGenericSignature(ctx, genericParams); + auto result = GenericSignature::forInvalid(genericParams); if (rewriteCtx.getDebugOptions().contains(DebugFlags::Timers)) { rewriteCtx.endTimer("InferredGenericSignatureRequest"); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index f2c724e6db31c..c1787e3456353 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1917,9 +1917,6 @@ static Type replacePlaceholderType(PlaceholderType *placeholder, return Type(gp); }); - if (isa(replacement.getPointer())) - return ErrorType::get(ctx); - // For completion, we want to produce an archetype instead of an ErrorType // for a top-level generic parameter. // FIXME: This is pretty weird, we're producing a contextual type outside of @@ -1930,8 +1927,8 @@ static Type replacePlaceholderType(PlaceholderType *placeholder, return GP->getDecl()->getInnermostDeclContext()->mapTypeIntoContext(GP); } // Return an ErrorType with the replacement as the original type. Note that - // if we failed to replace a type variable with a generic parameter in a - // dependent member, `ErrorType::get` will fold it away. + // if we failed to replace a type variable with a generic parameter, + // `ErrorType::get` will fold it away. return ErrorType::get(replacement); } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 04e5950f6c59f..9d3c4fe2310e2 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -893,7 +893,8 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD, return hadError; } -bool TypeChecker::typeCheckForEachPreamble(DeclContext *dc, ForEachStmt *stmt) { +bool TypeChecker::typeCheckForEachPreamble(DeclContext *dc, ForEachStmt *stmt, + bool skipWhere) { auto &Context = dc->getASTContext(); FrontendStatsTracer statsTracer(Context.Stats, "typecheck-for-each", stmt); PrettyStackTraceStmt stackTrace(Context, "type-checking-for-each", stmt); @@ -902,18 +903,20 @@ bool TypeChecker::typeCheckForEachPreamble(DeclContext *dc, ForEachStmt *stmt) { if (!typeCheckTarget(target)) return true; - if (auto *where = stmt->getWhere()) { - auto boolType = dc->getASTContext().getBoolType(); - if (!boolType) - return true; + if (!skipWhere) { + if (auto *where = stmt->getWhere()) { + auto boolType = dc->getASTContext().getBoolType(); + if (!boolType) + return true; - SyntacticElementTarget whereClause(where, dc, {boolType, CTP_Condition}, - /*isDiscarded=*/false); - auto result = typeCheckTarget(whereClause); - if (!result) - return true; + SyntacticElementTarget whereClause(where, dc, {boolType, CTP_Condition}, + /*isDiscarded=*/false); + auto result = typeCheckTarget(whereClause); + if (!result) + return true; - stmt->setWhere(result->getAsExpr()); + stmt->setWhere(result->getAsExpr()); + } } // Check to see if the sequence expr is throwing (in async context), diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 3f5b32c24845b..3cb4d453ad98c 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1156,6 +1156,15 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, getOrCreateRequirementEnvironment(reqEnvCache, dc, reqSig, proto, covariantSelf, conformance); + auto reqSubMap = reqEnvironment.getRequirementToWitnessThunkSubs(); + + Type selfTy = proto->getSelfInterfaceType().subst(reqSubMap); + if (selfTy->hasError()) { + return RequirementMatch(witness, MatchKind::WitnessInvalid, + witnessType, reqEnvironment, + /*optionalAdjustments*/ {}); + } + // Set up the constraint system for matching. auto setup = [&]() -> std::tuple, Type, Type, Type, Type> { @@ -1163,10 +1172,6 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, // the required type and the witness type. cs.emplace(dc, ConstraintSystemFlags::AllowFixes); - auto reqSubMap = reqEnvironment.getRequirementToWitnessThunkSubs(); - - Type selfTy = proto->getSelfInterfaceType().subst(reqSubMap); - // Open up the type of the requirement. reqLocator = cs->getConstraintLocator(req, ConstraintLocator::ProtocolRequirement); diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 430d699fe3e94..253a37aea5626 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1463,7 +1463,15 @@ class StmtChecker : public StmtVisitor { } Stmt *visitForEachStmt(ForEachStmt *S) { - TypeChecker::typeCheckForEachPreamble(DC, S); + // If we're performing IDE inspection, we also want to skip the where + // clause if we're leaving the body unchecked. + // FIXME: This is a hack to avoid cycles through NamingPatternRequest when + // doing lazy type-checking, we ought to fix the request to be granular in + // the type-checking work it kicks. + bool skipWhere = LeaveBraceStmtBodyUnchecked && + Ctx.SourceMgr.hasIDEInspectionTargetBuffer(); + + TypeChecker::typeCheckForEachPreamble(DC, S, skipWhere); // Type-check the body of the loop. auto sourceFile = DC->getParentSourceFile(); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 680de34d68218..e9fcf14459e9e 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -235,6 +235,13 @@ Type TypeResolution::resolveDependentMemberType( // Record the type we found. repr->setValue(nestedType, nullptr); } else { + // If we have a concrete equivalence to an error type, avoid diagnosing the + // missing member. + if (auto concreteBase = genericSig->getConcreteType(baseTy)) { + if (concreteBase->hasError()) + return ErrorType::get(baseTy); + } + // Resolve the base to a potential archetype. // Perform typo correction. TypoCorrectionResults corrections(repr->getNameRef(), repr->getNameLoc()); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index e6808789e603b..f0ab3ea2ecf75 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -799,7 +799,8 @@ bool typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned patternNumber, /// together. /// /// \returns true if a failure occurred. -bool typeCheckForEachPreamble(DeclContext *dc, ForEachStmt *stmt); +bool typeCheckForEachPreamble(DeclContext *dc, ForEachStmt *stmt, + bool skipWhereClause); /// Compute the set of captures for the given closure. void computeCaptures(AbstractClosureExpr *ACE); diff --git a/test/Constraints/same_types.swift b/test/Constraints/same_types.swift index 44e52f6e9b647..c61f79c2b8dc7 100644 --- a/test/Constraints/same_types.swift +++ b/test/Constraints/same_types.swift @@ -282,15 +282,11 @@ protocol P2 { } // CHECK-LABEL: same_types.(file).structuralSameTypeRecursive1@ -// CHECK-NEXT: Generic signature: +// CHECK-NEXT: Generic signature: >, U == <>> // expected-error@+2 {{cannot build rewrite system for generic signature; concrete type nesting limit exceeded}} // expected-note@+1 {{τ_0_0.[P2:Assoc1].[concrete: ((((((((((((((((((((((((((((((((τ_0_0.[P2:Assoc1], τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1), τ_0_1)] => τ_0_0.[P2:Assoc1]}} -func structuralSameTypeRecursive1(_: T, _: U) - where T.Assoc1 == Tuple2 - // expected-error@-1 {{'Assoc1' is not a member type of type 'T'}} - // expected-error@-2 {{'Assoc1' is not a member type of type 'T'}} -{ } +func structuralSameTypeRecursive1(_: T, _: U) where T.Assoc1 == Tuple2 {} protocol P3 { } diff --git a/test/Generics/invalid.swift b/test/Generics/invalid.swift index 3bf1d0be1b44c..3736d569c0271 100644 --- a/test/Generics/invalid.swift +++ b/test/Generics/invalid.swift @@ -154,3 +154,13 @@ func errorMessageVariants(x: X, x2: X = X()) -> X { let _: X.Foo = X.Foo() // expected-error {{cannot convert parent type 'X' to expected type 'X'}} return x // expected-error {{cannot convert return expression of type 'X' to return type 'X'}} } + +protocol P2 { + func foo() +} + +// Make sure we don't diagnose the conformance failure or 'T.K'. +struct HasInvalidSameType: P2 where T == Undefined, T.K == Int { + // expected-error@-1 {{cannot find type 'Undefined' in scope}} + func foo() {} +} diff --git a/test/IDE/complete_loop.swift b/test/IDE/complete_loop.swift index 5ec4b45325b49..77a1085a0df4e 100644 --- a/test/IDE/complete_loop.swift +++ b/test/IDE/complete_loop.swift @@ -1,72 +1,64 @@ -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_1 | %FileCheck %s -check-prefix=LOOP_1 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_2 > %t.loop2.txt -// RUN: %FileCheck %s -check-prefix=LOOP_2 < %t.loop2.txt -// RUN: %FileCheck %s -check-prefix=LOOP_2_NEGATIVE < %t.loop2.txt -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_3 | %FileCheck %s -check-prefix=LOOP_3 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_4 | %FileCheck %s -check-prefix=LOOP_4 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_5 | %FileCheck %s -check-prefix=LOOP_5 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_6 | %FileCheck %s -check-prefix=LOOP_6 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_7 | %FileCheck %s -check-prefix=LOOP_6 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LOOP_8 | %FileCheck %s -check-prefix=LOOP_8 +// FIXME: Fails with non-source-ordering +// RUN: %batch-code-completion -source-order-completion class Gen { - func IntGen() -> Int { return 0 } - func IntOpGen() -> Int? {return 0} - func IntSeqGen() -> [Int] {return [0]} + func IntGen() -> Int { return 0 } + func IntOpGen() -> Int? {return 0} + func IntSeqGen() -> [Int] {return [0]} } class C { - func f1(_ Seq : [Int], I : Int, G : Gen) { - for i in #^LOOP_1^# - } -// LOOP_1-DAG: Decl[LocalVar]/Local/TypeRelation[Convertible]: Seq[#[Int]#]{{; name=.+$}} -// LOOP_1-DAG: Decl[LocalVar]/Local: I[#Int#]{{; name=.+$}} -// LOOP_1-DAG: Decl[LocalVar]/Local: G[#Gen#]{{; name=.+$}} -// LOOP_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f1({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} -// LOOP_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f2({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} + func f1(_ Seq : [Int], I : Int, G : Gen) { + for i in #^LOOP_1^# + } + // LOOP_1-DAG: Decl[LocalVar]/Local/TypeRelation[Convertible]: Seq[#[Int]#]{{; name=.+$}} + // LOOP_1-DAG: Decl[LocalVar]/Local: I[#Int#]{{; name=.+$}} + // LOOP_1-DAG: Decl[LocalVar]/Local: G[#Gen#]{{; name=.+$}} + // LOOP_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f1({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} + // LOOP_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f2({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} - func f2(_ Seq : [Int], I : Int, G: Gen) { - for i in #^LOOP_2^# { + func f2(_ Seq : [Int], I : Int, G: Gen) { + for i in #^LOOP_2?check=LOOP_2;check=LOOP_2_NEGATIVE^# { - } - } -// LOOP_2-DAG: Decl[LocalVar]/Local/TypeRelation[Convertible]: Seq[#[Int]#]{{; name=.+$}} -// LOOP_2-DAG: Decl[LocalVar]/Local: I[#Int#]{{; name=.+$}} -// LOOP_2-DAG: Decl[LocalVar]/Local: G[#Gen#]{{; name=.+$}} -// LOOP_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f1({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} -// LOOP_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f2({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} + } + } + // LOOP_2-DAG: Decl[LocalVar]/Local/TypeRelation[Convertible]: Seq[#[Int]#]{{; name=.+$}} + // LOOP_2-DAG: Decl[LocalVar]/Local: I[#Int#]{{; name=.+$}} + // LOOP_2-DAG: Decl[LocalVar]/Local: G[#Gen#]{{; name=.+$}} + // LOOP_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f1({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} + // LOOP_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: f2({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]{{; name=.+$}} -// LOOP_2_NEGATIVE-NOT: TypeRelation[{{.*}}]: SequenceType[#SequenceType#]; + // LOOP_2_NEGATIVE-NOT: TypeRelation[{{.*}}]: SequenceType[#SequenceType#]; - func f3(_ G : Gen) { - for i in G.#^LOOP_3^# - } + func f3(_ G : Gen) { + for i in G.#^LOOP_3^# + } -// LOOP_3-DAG: Decl[InstanceMethod]/CurrNominal: IntGen()[#Int#]{{; name=.+$}} -// LOOP_3-DAG: Decl[InstanceMethod]/CurrNominal: IntOpGen()[#Int?#]{{; name=.+$}} -// LOOP_3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntSeqGen()[#[Int]#]{{; name=.+$}} + // LOOP_3-DAG: Decl[InstanceMethod]/CurrNominal: IntGen()[#Int#]{{; name=.+$}} + // LOOP_3-DAG: Decl[InstanceMethod]/CurrNominal: IntOpGen()[#Int?#]{{; name=.+$}} + // LOOP_3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntSeqGen()[#[Int]#]{{; name=.+$}} - func f4(_ G : Gen) { - for i in G.#^LOOP_4^# { + func f4(_ G : Gen) { + for i in G.#^LOOP_4^# { - } - } + } + } -// LOOP_4-DAG: Decl[InstanceMethod]/CurrNominal: IntGen()[#Int#]{{; name=.+$}} -// LOOP_4-DAG: Decl[InstanceMethod]/CurrNominal: IntOpGen()[#Int?#]{{; name=.+$}} -// LOOP_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntSeqGen()[#[Int]#]{{; name=.+$}} + // LOOP_4-DAG: Decl[InstanceMethod]/CurrNominal: IntGen()[#Int#]{{; name=.+$}} + // LOOP_4-DAG: Decl[InstanceMethod]/CurrNominal: IntOpGen()[#Int?#]{{; name=.+$}} + // LOOP_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntSeqGen()[#[Int]#]{{; name=.+$}} func f5(_ a: [C]) { do { for user in a { user.#^LOOP_5^# -// LOOP_5-DAG: Keyword[self]/CurrNominal: self[#C#]; -// LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f1({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]; -// LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f2({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]; -// LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f3({#(G): Gen#})[#Void#]; -// LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f4({#(G): Gen#})[#Void#]; -// LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f5({#(a): [C]#})[#Void#]; + // LOOP_5-DAG: Keyword[self]/CurrNominal: self[#C#]; + // LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f1({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]; + // LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f2({#(Seq): [Int]#}, {#I: Int#}, {#G: Gen#})[#Void#]; + // LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f3({#(G): Gen#})[#Void#]; + // LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f4({#(G): Gen#})[#Void#]; + // LOOP_5-DAG: Decl[InstanceMethod]/CurrNominal: f5({#(a): [C]#})[#Void#]; } } catch {} } @@ -76,14 +68,29 @@ class C { do { for value #^LOOP_6^# } +// LOOP_6: Begin completions, 1 items +// LOOP_6-CHECK-NEXT: Keyword[in]/None: in; name=in + do { for value #^LOOP_7^# 1..<7 {} } -// LOOP_6: Begin completions, 1 items -// LOOP_6-CHECK-NEXT: Keyword[in]/None: in; name=in +// LOOP_7: Begin completions // Pack Iteration do { for t in #^LOOP_8^# {} } // LOOP_8-DAG: Keyword[repeat]/None: repeat; name=repeat + +do { + struct S { + var foo: Bool + } + func bar(_ xs: [S]) { + // Make sure we can resolve 'x' here without causing a request cycle. + for x in xs where x.foo { + x.#^LOOP_9^# + // LOOP_9-DAG: Decl[InstanceVar]/CurrNominal: foo[#Bool#]; name=foo + } + } +} diff --git a/test/Index/circular.swift b/test/Index/circular.swift index 1c819956444be..44d29e5b785dd 100644 --- a/test/Index/circular.swift +++ b/test/Index/circular.swift @@ -28,17 +28,17 @@ class Cycle2_C: Cycle2_B {} // CHECK: RelBase | class/Swift | Cycle2_C | {{[^ ]*}} class TestCase1: XCTestCase {} -// CHECK: [[@LINE-1]]:7 | class(test)/Swift | TestCase1 | {{[^ ]*}} | Def | rel: 0 +// CHECK: [[@LINE-1]]:7 | class/Swift | TestCase1 | {{[^ ]*}} | Def | rel: 0 // CHECK: [[@LINE-2]]:18 | class/Swift | XCTestCase | {{[^ ]*}} | Ref,RelBase | rel: 1 -// CHECK: RelBase | class(test)/Swift | TestCase1 | {{[^ ]*}} +// CHECK: RelBase | class/Swift | TestCase1 | {{[^ ]*}} class XCTestCase: TestCase1 {} // CHECK: [[@LINE-1]]:7 | class/Swift | XCTestCase | {{[^ ]*}} | Def | rel: 0 -// CHECK: [[@LINE-2]]:19 | class(test)/Swift | TestCase1 | {{[^ ]*}} | Ref,RelBase | rel: 1 +// CHECK: [[@LINE-2]]:19 | class/Swift | TestCase1 | {{[^ ]*}} | Ref,RelBase | rel: 1 // CHECK: RelBase | class/Swift | XCTestCase | {{[^ ]*}} class TestCase2: TestCase1 {} -// CHECK: [[@LINE-1]]:7 | class(test)/Swift | TestCase2 | {{[^ ]*}} | Def | rel: 0 -// CHECK: [[@LINE-2]]:18 | class(test)/Swift | TestCase1 | {{[^ ]*}} | Ref,RelBase | rel: 1 -// CHECK: RelBase | class(test)/Swift | TestCase2 | {{[^ ]*}} +// CHECK: [[@LINE-1]]:7 | class/Swift | TestCase2 | {{[^ ]*}} | Def | rel: 0 +// CHECK: [[@LINE-2]]:18 | class/Swift | TestCase1 | {{[^ ]*}} | Ref,RelBase | rel: 1 +// CHECK: RelBase | class/Swift | TestCase2 | {{[^ ]*}} protocol SelfCycleP: SelfCycleP {} // CHECK: [[@LINE-1]]:10 | protocol/Swift | SelfCycleP | {{[^ ]*}} | Def | rel: 0 diff --git a/test/attr/attr_specialize.swift b/test/attr/attr_specialize.swift index 745cfd5ed19a3..6363d2857e8ac 100644 --- a/test/attr/attr_specialize.swift +++ b/test/attr/attr_specialize.swift @@ -55,8 +55,6 @@ class G { @_specialize(where T == S) // expected-error@-1 {{cannot build rewrite system for generic signature; concrete type nesting limit exceeded}} // expected-note@-2 {{failed rewrite rule is τ_0_0.[concrete: S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] => τ_0_0}} - // expected-error@-3 {{too few generic parameters are specified in '_specialize' attribute (got 0, but expected 1)}} - // expected-note@-4 {{missing constraint for 'T' in '_specialize' attribute}} @_specialize(where T == Int, U == Int) // expected-error{{cannot find type 'U' in scope}} func noGenericParams() {} diff --git a/test/decl/circularity.swift b/test/decl/circularity.swift index 1f5c25ea73d78..a30289c162116 100644 --- a/test/decl/circularity.swift +++ b/test/decl/circularity.swift @@ -98,7 +98,7 @@ protocol P1 { } class C4 { - required init(x: Int) {} + required init(x: Int) {} // expected-note {{'required' initializer is declared in superclass here}} } class D4 : C4, P1 { // expected-note@:7 {{through reference here}} @@ -107,7 +107,7 @@ class D4 : C4, P1 { // expected-note@:7 {{through reference here}} // expected-note@-2:17 {{through reference here}} super.init(x: x) } -} +} // expected-error {{'required' initializer 'init(x:)' must be provided by subclass of 'C4'}} // https://github.com/apple/swift/issues/54662 // N.B. This used to compile in 5.1. diff --git a/test/decl/protocol/req/recursion.swift b/test/decl/protocol/req/recursion.swift index 8a42e5de71128..0581faa0d4de0 100644 --- a/test/decl/protocol/req/recursion.swift +++ b/test/decl/protocol/req/recursion.swift @@ -11,10 +11,8 @@ extension SomeProtocol where T == Optional { } // rdar://problem/19840527 class X where T == X { -// expected-error@-1 {{cannot build rewrite system for generic signature; concrete type nesting limit exceeded}} -// expected-note@-2 {{failed rewrite rule is τ_0_0.[concrete: X>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] => τ_0_0}} -// expected-error@-3 {{generic class 'X' has self-referential generic requirements}} - var type: T { return Swift.type(of: self) } // expected-error{{cannot convert return expression of type 'X.Type' to return type 'T'}} +// expected-error@-1 {{generic class 'X' has self-referential generic requirements}} + var type: T { return Swift.type(of: self) } } // FIXME: The "associated type 'Foo' is not a member type of 'Self'" diagnostic diff --git a/test/type/explicit_existential_cyclic_protocol.swift b/test/type/explicit_existential_cyclic_protocol.swift index f4de772c2b5df..399ff54f26148 100644 --- a/test/type/explicit_existential_cyclic_protocol.swift +++ b/test/type/explicit_existential_cyclic_protocol.swift @@ -3,9 +3,8 @@ // REQUIRES: swift_feature_ExistentialAny -// 'HasSelfOrAssociatedTypeRequirementsRequest' should evaluate to false in -// the event of a cycle because we will have considered all the protocols in a -// cyclic hierarchy by the time the cycle is hit. +// 'HasSelfOrAssociatedTypeRequirementsRequest' evaluates to false in the event +// of a cycle. do { do { protocol P1 : P2 {} @@ -30,6 +29,6 @@ do { // expected-explicit-any-error@-2 1 {{protocol 'P2' refines itself}} let _: P2 - // expected-warning@-1 {{use of protocol 'P2' as a type must be written 'any P2'}} + // expected-explicit-any-warning@-1 {{use of protocol 'P2' as a type must be written 'any P2'}} } } diff --git a/validation-test/compiler_crashers_2_fixed/0161-issue-49119.swift b/validation-test/compiler_crashers_2_fixed/0161-issue-49119.swift index 4fa6d4843dcd8..f848a412abdac 100644 --- a/validation-test/compiler_crashers_2_fixed/0161-issue-49119.swift +++ b/validation-test/compiler_crashers_2_fixed/0161-issue-49119.swift @@ -13,5 +13,4 @@ extension Type: P where Param: P, Param.A == Type { // expected-error@-3 {{type 'Type' does not conform to protocol 'P'}} // expected-note@-4 {{add stubs for conformance}} typealias A = Param - // expected-note@-1 {{possibly intended match 'Type.A' (aka 'Param') does not conform to 'P'}} } diff --git a/validation-test/compiler_crashers_2/aa9ebb248dabc27b.swift b/validation-test/compiler_crashers_2_fixed/aa9ebb248dabc27b.swift similarity index 84% rename from validation-test/compiler_crashers_2/aa9ebb248dabc27b.swift rename to validation-test/compiler_crashers_2_fixed/aa9ebb248dabc27b.swift index bb2c80f046613..1a4544780c063 100644 --- a/validation-test/compiler_crashers_2/aa9ebb248dabc27b.swift +++ b/validation-test/compiler_crashers_2_fixed/aa9ebb248dabc27b.swift @@ -1,4 +1,4 @@ // {"kind":"typecheck","signature":"swift::ConformanceChecker::resolveWitnessViaDerivation(swift::ValueDecl*)","signatureAssert":"Assertion failed: (Conformance->getWitnessUncached(requirement).getDecl() == match.Witness && \"Deduced different witnesses?\"), function recordWitness"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s class a : Codable { b = a( diff --git a/validation-test/compiler_crashers_2/dcd4ff250d0bde99.swift b/validation-test/compiler_crashers_2_fixed/dcd4ff250d0bde99.swift similarity index 84% rename from validation-test/compiler_crashers_2/dcd4ff250d0bde99.swift rename to validation-test/compiler_crashers_2_fixed/dcd4ff250d0bde99.swift index f77e93bd8f8d2..9c6fb28ff0c27 100644 --- a/validation-test/compiler_crashers_2/dcd4ff250d0bde99.swift +++ b/validation-test/compiler_crashers_2_fixed/dcd4ff250d0bde99.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"swift::ValueDecl::isObjC() const","signatureAssert":"Assertion failed: (!LazySemanticInfo.isObjCComputed || LazySemanticInfo.isObjC == value), function setIsObjC"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop protocol a @objc protocol b : c diff --git a/validation-test/compiler_crashers_2/dfe03ade76b34fdb.swift b/validation-test/compiler_crashers_2_fixed/dfe03ade76b34fdb.swift similarity index 88% rename from validation-test/compiler_crashers_2/dfe03ade76b34fdb.swift rename to validation-test/compiler_crashers_2_fixed/dfe03ade76b34fdb.swift index 023c7b70a9203..aecceeefe97af 100644 --- a/validation-test/compiler_crashers_2/dfe03ade76b34fdb.swift +++ b/validation-test/compiler_crashers_2_fixed/dfe03ade76b34fdb.swift @@ -1,4 +1,4 @@ // {"kind":"typecheck","signature":"swift::ASTContext::getSpecializedConformance(swift::Type, swift::NormalProtocolConformance*, swift::SubstitutionMap)","signatureAssert":"Assertion failed: (substitutions.getGenericSignature().getCanonicalSignature() == generic->getGenericSignature().getCanonicalSignature()), function getSpecializedConformance"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s protocol a{ < } protocol b { associatedtype c : a where d == Self } class e : a where f : b, f.c == e diff --git a/validation-test/compiler_crashers_2_fixed/issue-52031.swift b/validation-test/compiler_crashers_2_fixed/issue-52031.swift index 02b29a9299135..8cfb45ab08edf 100644 --- a/validation-test/compiler_crashers_2_fixed/issue-52031.swift +++ b/validation-test/compiler_crashers_2_fixed/issue-52031.swift @@ -13,9 +13,6 @@ extension S: P where N: P { static func f(_ x: X) -> S where A == X, X.A == N { // expected-error@-1 {{cannot build rewrite system for generic signature; rule length limit exceeded}} // expected-note@-2 {{τ_0_0.[P:A].[P:A].[P:A].[P:A].[P:A].[concrete: S>>>>>] => τ_0_0.[P:A].[P:A].[P:A].[P:A].[P:A] [subst↓]}} - // expected-error@-3 {{'A' is not a member type of type 'X'}} - // expected-error@-4 {{'A' is not a member type of type 'X'}} return S() - // expected-error@-1 {{'A' is not a member type of type 'X'}} } }