Skip to content

Commit 1b1963e

Browse files
committed
Sema: Remove 'inferred result type requires explicit coercion' diagnostic
1 parent ef6630f commit 1b1963e

File tree

8 files changed

+16
-404
lines changed

8 files changed

+16
-404
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7344,16 +7344,6 @@ WARNING(backdeployed_opaque_result_not_supported,none,
73447344
// MARK: Implicit opening of existential types
73457345
//------------------------------------------------------------------------------
73467346

7347-
ERROR(result_requires_explicit_coercion,none,
7348-
"inferred result type %0 requires explicit coercion due to "
7349-
"loss of generic requirements",
7350-
(Type))
7351-
7352-
NOTE(candidate_result_requires_explicit_coercion,none,
7353-
"inferred result type %0 requires explicit coercion due to "
7354-
"loss of generic requirements",
7355-
(Type))
7356-
73577347
ERROR(concurrency_task_to_thread_model_custom_executor,none,
73587348
"custom executors are not permitted within %0", (StringRef))
73597349
ERROR(concurrency_task_to_thread_model_async_main,none,

include/swift/Sema/CSFix.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3410,40 +3410,6 @@ class IgnoreDefaultExprTypeMismatch : public AllowArgumentMismatch {
34103410
}
34113411
};
34123412

3413-
class AddExplicitExistentialCoercion final : public ConstraintFix {
3414-
Type ErasedResultType;
3415-
3416-
AddExplicitExistentialCoercion(ConstraintSystem &cs, Type erasedResultTy,
3417-
ConstraintLocator *locator,
3418-
FixBehavior fixBehavior)
3419-
: ConstraintFix(cs, FixKind::AddExplicitExistentialCoercion, locator,
3420-
fixBehavior),
3421-
ErasedResultType(erasedResultTy) {}
3422-
3423-
public:
3424-
std::string getName() const override {
3425-
return "add explicit existential type coercion";
3426-
}
3427-
3428-
bool diagnose(const Solution &solution, bool asNote = false) const override;
3429-
3430-
static bool
3431-
isRequired(ConstraintSystem &cs, Type resultTy,
3432-
ArrayRef<std::pair<TypeVariableType *, OpenedArchetypeType *>>
3433-
openedExistentials,
3434-
ConstraintLocatorBuilder locator);
3435-
3436-
static bool
3437-
isRequired(ConstraintSystem &cs, Type resultTy,
3438-
llvm::function_ref<llvm::Optional<Type>(TypeVariableType *)>
3439-
findExistentialType,
3440-
ConstraintLocatorBuilder locator);
3441-
3442-
static AddExplicitExistentialCoercion *create(ConstraintSystem &cs,
3443-
Type resultTy,
3444-
ConstraintLocator *locator);
3445-
};
3446-
34473413
class RenameConflictingPatternVariables final
34483414
: public ConstraintFix,
34493415
private llvm::TrailingObjects<RenameConflictingPatternVariables,

lib/Sema/CSDiagnostics.cpp

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9124,61 +9124,6 @@ bool DefaultExprTypeMismatch::diagnoseAsError() {
91249124
return true;
91259125
}
91269126

9127-
bool MissingExplicitExistentialCoercion::diagnoseAsError() {
9128-
auto diagnostic = emitDiagnostic(diag::result_requires_explicit_coercion,
9129-
ErasedResultType);
9130-
fixIt(diagnostic);
9131-
return true;
9132-
}
9133-
9134-
bool MissingExplicitExistentialCoercion::diagnoseAsNote() {
9135-
auto diagnostic = emitDiagnostic(
9136-
diag::candidate_result_requires_explicit_coercion, ErasedResultType);
9137-
fixIt(diagnostic);
9138-
return true;
9139-
}
9140-
9141-
bool MissingExplicitExistentialCoercion::fixItRequiresParens() const {
9142-
auto anchor = getAsExpr(getRawAnchor());
9143-
9144-
// If it's a member reference an an existential metatype, let's
9145-
// use the parent "call" expression.
9146-
if (auto *UDE = dyn_cast_or_null<UnresolvedDotExpr>(anchor))
9147-
anchor = findParentExpr(UDE);
9148-
9149-
if (!anchor)
9150-
return false;
9151-
9152-
const auto &solution = getSolution();
9153-
return llvm::any_of(
9154-
solution.OpenedExistentialTypes,
9155-
[&anchor](const auto &openedExistential) {
9156-
if (auto openedLoc = simplifyLocatorToAnchor(openedExistential.first)) {
9157-
return anchor == getAsExpr(openedLoc);
9158-
}
9159-
return false;
9160-
});
9161-
}
9162-
9163-
void MissingExplicitExistentialCoercion::fixIt(
9164-
InFlightDiagnostic &diagnostic) const {
9165-
9166-
if (ErasedResultType->hasTypeParameter())
9167-
return;
9168-
9169-
bool requiresParens = fixItRequiresParens();
9170-
9171-
auto callRange = getSourceRange();
9172-
9173-
if (requiresParens)
9174-
diagnostic.fixItInsert(callRange.Start, "(");
9175-
9176-
auto printOpts = PrintOptions::forDiagnosticArguments();
9177-
diagnostic.fixItInsertAfter(callRange.End,
9178-
"as " + ErasedResultType->getString(printOpts) +
9179-
(requiresParens ? ")" : ""));
9180-
}
9181-
91829127
bool ConflictingPatternVariables::diagnoseAsError() {
91839128
for (auto *var : Vars) {
91849129
emitDiagnosticAt(var->getStartLoc(),

lib/Sema/CSFix.cpp

Lines changed: 0 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,259 +2485,6 @@ IgnoreDefaultExprTypeMismatch::create(ConstraintSystem &cs, Type argType,
24852485
IgnoreDefaultExprTypeMismatch(cs, argType, paramType, locator);
24862486
}
24872487

2488-
bool AddExplicitExistentialCoercion::diagnose(const Solution &solution,
2489-
bool asNote) const {
2490-
MissingExplicitExistentialCoercion failure(solution, ErasedResultType,
2491-
getLocator(), fixBehavior);
2492-
return failure.diagnose(asNote);
2493-
}
2494-
2495-
bool AddExplicitExistentialCoercion::isRequired(
2496-
ConstraintSystem &cs, Type resultTy,
2497-
llvm::function_ref<llvm::Optional<Type>(TypeVariableType *)>
2498-
findExistentialType,
2499-
ConstraintLocatorBuilder locator) {
2500-
using ExistentialTypeFinder =
2501-
llvm::function_ref<llvm::Optional<Type>(TypeVariableType *)>;
2502-
2503-
struct CoercionChecker : public TypeWalker {
2504-
bool RequiresCoercion = false;
2505-
2506-
ConstraintSystem &cs;
2507-
ExistentialTypeFinder GetExistentialType;
2508-
2509-
CoercionChecker(ConstraintSystem &cs,
2510-
ExistentialTypeFinder getExistentialType)
2511-
: cs(cs), GetExistentialType(getExistentialType) {}
2512-
2513-
Action walkToTypePre(Type componentTy) override {
2514-
// In cases where result references a member type, we need to check
2515-
// whether such type would is resolved to concrete or not.
2516-
if (auto *member = componentTy->getAs<DependentMemberType>()) {
2517-
auto memberBaseTy = getBaseTypeOfDependentMemberChain(member);
2518-
2519-
auto typeVar = memberBaseTy->getAs<TypeVariableType>();
2520-
if (!typeVar)
2521-
return Action::SkipChildren;
2522-
2523-
// If the base is an opened existential type, let's see whether
2524-
// erase would produce an existential in this case and if so,
2525-
// we need to check whether any requirements are going to be lost
2526-
// in process.
2527-
2528-
auto existentialType = GetExistentialType(typeVar);
2529-
if (!existentialType)
2530-
return Action::SkipChildren;
2531-
2532-
auto erasedMemberTy = typeEraseOpenedExistentialReference(
2533-
Type(member), *existentialType, typeVar, TypePosition::Covariant);
2534-
2535-
// If result is an existential type and the base has `where` clauses
2536-
// associated with its associated types, the call needs a coercion.
2537-
if (erasedMemberTy->isExistentialType() &&
2538-
hasConstrainedAssociatedTypes(member, *existentialType)) {
2539-
RequiresCoercion = true;
2540-
return Action::Stop;
2541-
}
2542-
2543-
if (erasedMemberTy->isExistentialType() &&
2544-
erasedMemberTy->hasTypeParameter()) {
2545-
RequiresCoercion = true;
2546-
return Action::Stop;
2547-
}
2548-
2549-
return Action::SkipChildren;
2550-
}
2551-
2552-
// The case where there is a direct access to opened existential type
2553-
// e.g. `$T` or `[$T]`.
2554-
if (auto *typeVar = componentTy->getAs<TypeVariableType>()) {
2555-
if (auto existentialType = GetExistentialType(typeVar)) {
2556-
RequiresCoercion |= hasAnyConstrainedAssociatedTypes(
2557-
(*existentialType)->getExistentialLayout());
2558-
return RequiresCoercion ? Action::Stop : Action::SkipChildren;
2559-
}
2560-
}
2561-
2562-
return Action::Continue;
2563-
}
2564-
2565-
private:
2566-
/// Check whether the given member type has any of its associated
2567-
/// types constrained by requirements associated with the given
2568-
/// existential type.
2569-
static bool hasConstrainedAssociatedTypes(DependentMemberType *member,
2570-
Type existentialTy) {
2571-
auto layout = existentialTy->getExistentialLayout();
2572-
for (auto *protocol : layout.getProtocols()) {
2573-
auto requirementSig = protocol->getRequirementSignature();
2574-
if (hasConstrainedAssociatedTypes(member,
2575-
requirementSig.getRequirements()))
2576-
return true;
2577-
}
2578-
return false;
2579-
}
2580-
2581-
/// Check whether the given member type has any of its associated
2582-
/// types constrained by the given requirement set.
2583-
static bool
2584-
hasConstrainedAssociatedTypes(DependentMemberType *member,
2585-
ArrayRef<Requirement> requirements) {
2586-
for (const auto &req : requirements) {
2587-
switch (req.getKind()) {
2588-
case RequirementKind::SameShape:
2589-
llvm_unreachable("Same-shape requirement not supported here");
2590-
2591-
case RequirementKind::Superclass:
2592-
case RequirementKind::Conformance:
2593-
case RequirementKind::Layout: {
2594-
if (isAnchoredOn(req.getFirstType(), member->getAssocType()))
2595-
return true;
2596-
break;
2597-
}
2598-
2599-
case RequirementKind::SameType: {
2600-
auto lhsTy = req.getFirstType();
2601-
auto rhsTy = req.getSecondType();
2602-
2603-
if (isAnchoredOn(lhsTy, member->getAssocType()) ||
2604-
isAnchoredOn(rhsTy, member->getAssocType()))
2605-
return true;
2606-
2607-
break;
2608-
}
2609-
}
2610-
}
2611-
2612-
return false;
2613-
}
2614-
2615-
/// Check whether any of the protocols mentioned in the given
2616-
/// existential layout have constraints associated with their
2617-
/// associated types via a `where` clause, for example:
2618-
/// `associatedtype A: P where A.B == Int`
2619-
static bool hasAnyConstrainedAssociatedTypes(ExistentialLayout layout) {
2620-
for (auto *protocol : layout.getProtocols()) {
2621-
auto requirementSig = protocol->getRequirementSignature();
2622-
for (const auto &req : requirementSig.getRequirements()) {
2623-
switch (req.getKind()) {
2624-
case RequirementKind::SameShape:
2625-
llvm_unreachable("Same-shape requirement not supported here");
2626-
2627-
case RequirementKind::Conformance:
2628-
case RequirementKind::Layout:
2629-
case RequirementKind::Superclass: {
2630-
if (getMemberChainDepth(req.getFirstType()) > 1)
2631-
return true;
2632-
break;
2633-
}
2634-
2635-
case RequirementKind::SameType:
2636-
auto lhsTy = req.getFirstType();
2637-
auto rhsTy = req.getSecondType();
2638-
2639-
if (getMemberChainDepth(lhsTy) > 1 ||
2640-
getMemberChainDepth(rhsTy) > 1)
2641-
return true;
2642-
2643-
break;
2644-
}
2645-
}
2646-
}
2647-
return false;
2648-
}
2649-
2650-
/// Check whether the given type is a dependent member type and
2651-
/// is anchored on the given associated type e.g. type is `A.B.C`
2652-
/// and associated type is `A.B`.
2653-
static bool isAnchoredOn(Type type, AssociatedTypeDecl *assocTy,
2654-
unsigned depth = 0) {
2655-
if (auto *member = type->getAs<DependentMemberType>()) {
2656-
if (member->getAssocType() == assocTy)
2657-
return depth > 0;
2658-
2659-
return isAnchoredOn(member->getBase(), assocTy, depth + 1);
2660-
}
2661-
2662-
return false;
2663-
}
2664-
2665-
static unsigned getMemberChainDepth(Type type, unsigned currDepth = 0) {
2666-
if (auto *memberTy = type->getAs<DependentMemberType>())
2667-
return getMemberChainDepth(memberTy->getBase(), currDepth + 1);
2668-
return currDepth;
2669-
}
2670-
2671-
static Type getBaseTypeOfDependentMemberChain(DependentMemberType *member) {
2672-
if (!member->getBase())
2673-
return member;
2674-
2675-
auto base = member->getBase();
2676-
2677-
if (auto *DMT = base->getAs<DependentMemberType>())
2678-
return getBaseTypeOfDependentMemberChain(DMT);
2679-
2680-
return base;
2681-
}
2682-
};
2683-
2684-
// First, let's check whether coercion is already there.
2685-
if (auto *anchor = getAsExpr(locator.getAnchor())) {
2686-
// If this is erasure related to `Self`, let's look through
2687-
// the call, if any.
2688-
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
2689-
// If this is an implicit `makeIterator` call, let's skip the check.
2690-
if (UDE->isImplicit() &&
2691-
cs.getContextualTypePurpose(UDE->getBase()) == CTP_ForEachSequence)
2692-
return false;
2693-
2694-
auto parentExpr = cs.getParentExpr(anchor);
2695-
if (parentExpr && isa<CallExpr>(parentExpr))
2696-
anchor = parentExpr;
2697-
}
2698-
2699-
auto *parent = cs.getParentExpr(anchor);
2700-
// Support both `as` and `as!` coercions.
2701-
if (parent &&
2702-
(isa<CoerceExpr>(parent) || isa<ForcedCheckedCastExpr>(parent)))
2703-
return false;
2704-
}
2705-
2706-
CoercionChecker check(cs, findExistentialType);
2707-
resultTy.walk(check);
2708-
2709-
return check.RequiresCoercion;
2710-
}
2711-
2712-
bool AddExplicitExistentialCoercion::isRequired(
2713-
ConstraintSystem &cs, Type resultTy,
2714-
ArrayRef<std::pair<TypeVariableType *, OpenedArchetypeType *>>
2715-
openedExistentials,
2716-
ConstraintLocatorBuilder locator) {
2717-
return isRequired(
2718-
cs, resultTy,
2719-
[&](TypeVariableType *typeVar) -> llvm::Optional<Type> {
2720-
auto opened =
2721-
llvm::find_if(openedExistentials, [&typeVar](const auto &entry) {
2722-
return typeVar == entry.first;
2723-
});
2724-
2725-
if (opened == openedExistentials.end())
2726-
return llvm::None;
2727-
2728-
return opened->second->getExistentialType();
2729-
},
2730-
locator);
2731-
}
2732-
2733-
AddExplicitExistentialCoercion *
2734-
AddExplicitExistentialCoercion::create(ConstraintSystem &cs, Type resultTy,
2735-
ConstraintLocator *locator) {
2736-
FixBehavior fixBehavior = FixBehavior::Error;
2737-
return new (cs.getAllocator())
2738-
AddExplicitExistentialCoercion(cs, resultTy, locator, fixBehavior);
2739-
}
2740-
27412488
bool RenameConflictingPatternVariables::diagnose(const Solution &solution,
27422489
bool asNote) const {
27432490
ConflictingPatternVariables failure(solution, ExpectedType,

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13015,19 +13015,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyApplicableFnConstraint(
1301513015
result2, opened.second->getExistentialType(), opened.first,
1301613016
TypePosition::Covariant);
1301713017
}
13018-
13019-
// If result type has any erased existential types it requires explicit
13020-
// `as` coercion.
13021-
if (AddExplicitExistentialCoercion::isRequired(
13022-
*this, func2->getResult(), openedExistentials, locator)) {
13023-
13024-
if (!shouldAttemptFixes())
13025-
return SolutionKind::Error;
13026-
13027-
if (recordFix(AddExplicitExistentialCoercion::create(
13028-
*this, result2, getConstraintLocator(locator))))
13029-
return SolutionKind::Error;
13030-
}
1303113018
}
1303213019

1303313020
// The result types are equivalent.

0 commit comments

Comments
 (0)