diff --git a/include/swift/Sema/Constraint.h b/include/swift/Sema/Constraint.h index 54e780d2c7a0f..5e7b688d38662 100644 --- a/include/swift/Sema/Constraint.h +++ b/include/swift/Sema/Constraint.h @@ -186,14 +186,12 @@ enum class ConstraintKind : char { /// constraint. OneWayBindParam, /// If there is no contextual info e.g. `_ = { 42 }` default first type - /// to a second type (inferred closure type). This is effectively a - /// `Defaultable` constraint which a couple of differences: + /// to a second type. This is effectively a `Defaultable` constraint + /// which one significant difference: /// - /// - References inferred closure type and all of the outer parameters - /// referenced by closure body. /// - Handled specially by binding inference, specifically contributes /// to the bindings only if there are no contextual types available. - DefaultClosureType, + FallbackType, /// The first type represents a result of an unresolved member chain, /// and the second type is its base type. This constraint acts almost /// like `Equal` but also enforces following semantics: @@ -701,7 +699,7 @@ class Constraint final : public llvm::ilist_node, case ConstraintKind::OptionalObject: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PackElementOf: case ConstraintKind::SameShape: diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 5a54d3fd8ae2d..711dd131d2189 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4847,11 +4847,12 @@ class ConstraintSystem { TypeMatchOptions flags, ConstraintLocatorBuilder locator); - /// Attempt to simplify the given defaultable closure type constraint. - SolutionKind simplifyDefaultClosureTypeConstraint( - Type closureType, Type inferredType, - ArrayRef referencedOuterParameters, - TypeMatchOptions flags, ConstraintLocatorBuilder locator); + /// Attempt to simplify the given fallback type constraint. + SolutionKind + simplifyFallbackTypeConstraint(Type defaultableType, Type fallbackType, + ArrayRef referencedVars, + TypeMatchOptions flags, + ConstraintLocatorBuilder locator); /// Attempt to simplify a property wrapper constraint. SolutionKind simplifyPropertyWrapperConstraint(Type wrapperType, Type wrappedValueType, diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 0c8c28b70c337..8d3fdd6e1e555 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -452,7 +452,7 @@ void BindingSet::inferTransitiveBindings( // Infer transitive defaults. for (const auto &def : bindings.Defaults) { - if (def.getSecond()->getKind() == ConstraintKind::DefaultClosureType) + if (def.getSecond()->getKind() == ConstraintKind::FallbackType) continue; addDefault(def.second); @@ -1510,7 +1510,7 @@ void PotentialBindings::infer(Constraint *constraint) { } case ConstraintKind::Defaultable: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: // Do these in a separate pass. if (CS.getFixedTypeRecursive(constraint->getFirstType(), true) ->getAs() == TypeVar) { @@ -1634,7 +1634,7 @@ void PotentialBindings::retract(Constraint *constraint) { break; case ConstraintKind::Defaultable: - case ConstraintKind::DefaultClosureType: { + case ConstraintKind::FallbackType: { Defaults.erase(constraint); break; } @@ -2075,11 +2075,10 @@ bool TypeVarBindingProducer::computeNext() { if (NumTries == 0) { // Add defaultable constraints (if any). for (auto *constraint : DelayedDefaults) { - if (constraint->getKind() == ConstraintKind::DefaultClosureType) { - // If there are no other possible bindings for this closure - // let's default it to the type inferred from its parameters/body, - // otherwise we should only attempt contextual types as a - // top-level closure type. + if (constraint->getKind() == ConstraintKind::FallbackType) { + // If there are no other possible bindings for this variable + // let's default it to the fallback type, otherwise we should + // only attempt contextual types. if (!ExploredTypes.empty()) continue; } diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index eee49f6fc7280..ee74264f6bd66 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2921,9 +2921,9 @@ namespace { SmallVector referencedVars{ collectVarRefs.varRefs.begin(), collectVarRefs.varRefs.end()}; - CS.addUnsolvedConstraint(Constraint::create( - CS, ConstraintKind::DefaultClosureType, closureType, inferredType, - locator, referencedVars)); + CS.addUnsolvedConstraint( + Constraint::create(CS, ConstraintKind::FallbackType, closureType, + inferredType, locator, referencedVars)); CS.setClosureType(closure, inferredType); return closureType; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 1a82aad8d528b..7ad87912d2447 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2284,7 +2284,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2, case ConstraintKind::BridgingConversion: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PropertyWrapper: case ConstraintKind::SyntacticElement: @@ -2643,7 +2643,7 @@ static bool matchFunctionRepresentations(FunctionType::ExtInfo einfo1, case ConstraintKind::ValueWitness: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PropertyWrapper: case ConstraintKind::SyntacticElement: @@ -3161,7 +3161,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, case ConstraintKind::BridgingConversion: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PropertyWrapper: case ConstraintKind::SyntacticElement: @@ -6814,7 +6814,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, case ConstraintKind::ValueWitness: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PropertyWrapper: case ConstraintKind::SyntacticElement: @@ -10950,18 +10950,18 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyDefaultableConstraint( return SolutionKind::Solved; } -ConstraintSystem::SolutionKind -ConstraintSystem::simplifyDefaultClosureTypeConstraint( - Type closureType, Type inferredType, - ArrayRef referencedOuterParameters, - TypeMatchOptions flags, ConstraintLocatorBuilder locator) { - closureType = getFixedTypeRecursive(closureType, flags, /*wantRValue=*/true); +ConstraintSystem::SolutionKind ConstraintSystem::simplifyFallbackTypeConstraint( + Type defaultableType, Type fallbackType, + ArrayRef referencedVars, TypeMatchOptions flags, + ConstraintLocatorBuilder locator) { + defaultableType = + getFixedTypeRecursive(defaultableType, flags, /*wantRValue=*/true); - if (closureType->isTypeVariableOrMember()) { + if (defaultableType->isTypeVariableOrMember()) { if (flags.contains(TMF_GenerateConstraints)) { addUnsolvedConstraint(Constraint::create( - *this, ConstraintKind::DefaultClosureType, closureType, inferredType, - getConstraintLocator(locator), referencedOuterParameters)); + *this, ConstraintKind::FallbackType, defaultableType, fallbackType, + getConstraintLocator(locator), referencedVars)); return SolutionKind::Solved; } @@ -15014,7 +15014,7 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first, case ConstraintKind::Conjunction: case ConstraintKind::KeyPath: case ConstraintKind::KeyPathApplication: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::SyntacticElement: llvm_unreachable("Use the correct addConstraint()"); } @@ -15546,12 +15546,12 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { /*flags*/ None, constraint.getLocator()); - case ConstraintKind::DefaultClosureType: - return simplifyDefaultClosureTypeConstraint(constraint.getFirstType(), - constraint.getSecondType(), - constraint.getTypeVariables(), - /*flags*/ None, - constraint.getLocator()); + case ConstraintKind::FallbackType: + return simplifyFallbackTypeConstraint(constraint.getFirstType(), + constraint.getSecondType(), + constraint.getTypeVariables(), + /*flags*/ None, + constraint.getLocator()); case ConstraintKind::PropertyWrapper: return simplifyPropertyWrapperConstraint(constraint.getFirstType(), diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp index a6d98b18f4fde..0e0b4c3971a9d 100644 --- a/lib/Sema/Constraint.cpp +++ b/lib/Sema/Constraint.cpp @@ -99,7 +99,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, llvm_unreachable("Wrong constructor for member constraint"); case ConstraintKind::Defaultable: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: assert(!First.isNull()); assert(!Second.isNull()); break; @@ -164,7 +164,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, Type Third, case ConstraintKind::Conjunction: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PropertyWrapper: case ConstraintKind::SyntacticElement: @@ -314,7 +314,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const { case ConstraintKind::Defaultable: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PropertyWrapper: case ConstraintKind::BindTupleOfFunctionParams: @@ -470,8 +470,8 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm, case ConstraintKind::OpenedExistentialOf: Out << " opened archetype of "; break; case ConstraintKind::OneWayEqual: Out << " one-way bind to "; break; case ConstraintKind::OneWayBindParam: Out << " one-way bind param to "; break; - case ConstraintKind::DefaultClosureType: - Out << " closure can default to "; + case ConstraintKind::FallbackType: + Out << " can fallback to "; break; case ConstraintKind::UnresolvedMemberChainBase: Out << " unresolved member chain base "; @@ -742,7 +742,7 @@ gatherReferencedTypeVars(Constraint *constraint, case ConstraintKind::SelfObjectOfProtocol: case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: - case ConstraintKind::DefaultClosureType: + case ConstraintKind::FallbackType: case ConstraintKind::UnresolvedMemberChainBase: case ConstraintKind::PropertyWrapper: case ConstraintKind::BindTupleOfFunctionParams: diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 632c9ef72690b..2afd78535ac20 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1031,7 +1031,7 @@ Type ConstraintSystem::openPackExpansionType(PackExpansionType *expansion, // This constraint is important to make sure that pack expansion always // has a binding and connect pack expansion var to any type variables // that appear in pattern and shape types. - addUnsolvedConstraint(Constraint::create(*this, ConstraintKind::Defaultable, + addUnsolvedConstraint(Constraint::create(*this, ConstraintKind::FallbackType, expansionVar, openedPackExpansion, expansionLoc)); @@ -7391,7 +7391,7 @@ bool TypeVarBindingProducer::requiresOptionalAdjustment( PotentialBinding TypeVarBindingProducer::getDefaultBinding(Constraint *constraint) const { assert(constraint->getKind() == ConstraintKind::Defaultable || - constraint->getKind() == ConstraintKind::DefaultClosureType); + constraint->getKind() == ConstraintKind::FallbackType); auto type = constraint->getSecondType(); Binding binding{type, BindingKind::Exact, constraint}; diff --git a/test/Constraints/pack-expansion-expressions.swift b/test/Constraints/pack-expansion-expressions.swift index 12f7d93c54ec1..de7e50a2abc6b 100644 --- a/test/Constraints/pack-expansion-expressions.swift +++ b/test/Constraints/pack-expansion-expressions.swift @@ -560,3 +560,45 @@ func configure( repeat item[keyPath: (each configuration).0] = (each configuration).1 return item } + +// rdar://110819621 - generic parameter is bound before pack expansion type which result in inference failures +func test_that_expansions_are_bound_early() { + struct Data { + let prop: Int? + } + + struct Value { + init(_ body: (repeat each T) -> Bool) {} + } + + func compute( + root: Root, + keyPath: KeyPath, + other: Value) -> Bool { true } + + func test_keypath(v: Int) { + let _: Value = Value({ + compute( + root: $0, + keyPath: \.prop, + other: v + ) + }) // Ok + + let _: Value = Value({ + compute( + root: $0, + keyPath: \.prop, + other: v + ) + }) // Ok + } + + func equal(_: Value, _: Value) -> Bool {} + + func test_equality(i: Int) { + let _: Value = Value({ + equal($0.prop, i) // Ok + }) + } +} diff --git a/unittests/Sema/ConstraintSimplificationTests.cpp b/unittests/Sema/ConstraintSimplificationTests.cpp index c8c3271cc815b..d596e5317fe1e 100644 --- a/unittests/Sema/ConstraintSimplificationTests.cpp +++ b/unittests/Sema/ConstraintSimplificationTests.cpp @@ -111,7 +111,7 @@ TEST_F(SemaTest, TestClosureInferenceFromOptionalContext) { auto *closureTy = cs.createTypeVariable(closureLoc, /*options=*/0); cs.addUnsolvedConstraint(Constraint::create( - cs, ConstraintKind::DefaultClosureType, closureTy, defaultTy, + cs, ConstraintKind::FallbackType, closureTy, defaultTy, cs.getConstraintLocator(closure), /*referencedVars=*/{})); auto contextualTy =