Let us have
let array: [Int]? = [0]
I need to build array?.makeIterator()
out of array
for later use. Normally it would be array.makeIterator()
, but I need optional chaining because I expect an optional sequence. How to build it if array
were not optional is described in TypeChecker::callWitness with a couple of fixits.
This is the basic workflow I have based on what's in callWitness
.
auto BOE = new (Context) BindOptionalExpr(base, base->getEndLoc(), 0);
auto UDE = new (Context) UnresolvedDotExpr(
BOE, SourceLoc(), witness.getDecl()->getFullName(),
DeclNameLoc(BOE->getEndLoc()), /*Implicit=*/true);
unresolvedDot->setFunctionRefKind(FunctionRefKind::SingleApply);
auto dotLocator = cs.getConstraintLocator(unresolvedDot);
Type openedFullType, openedType;
std::tie(openedFullType, openedType)
= cs.getTypeOfMemberReference(base->getType(), witness.getDecl(), dc,
/*isDynamicResult=*/false,
FunctionRefKind::DoubleApply,
dotLocator);
auto getType = [&](const Expr *E) -> Type {
return cs.getType(E);
};
auto call = CallExpr::create(Context, UDE, base->getStartLoc(), arguments,
argLabels, {}, base->getEndLoc(),
/*trailingClosure=*/nullptr,
/*implicit=*/true, getType);
auto OEE = new (Context) OptionalEvaluationExpr(call);
cs.cacheSubExprTypes(OEE);
auto openedFuncType = openedType->castTo<FunctionType>();
cs.addConstraint(
ConstraintKind::ArgumentTupleConversion, cs.getType(call->getArg()),
FunctionType::composeInput(cs.getASTContext(),
openedFuncType->getParams(), false),
cs.getConstraintLocator(call, ConstraintLocator::ApplyArgument));
// solve the CS.
The constraint system before solving it:
Type Variables:
$T0 as [Int]?
Active Constraints:
$T0 conforms to Collection
$T0.Iterator equal IndexingIterator<$T0>
The main problem is this $T0 conforms to Collection
constraint that is added by getTypeOfMemberReference
and makes everything break.
If I pass base->getType()->getOptionalObjectType()
to getTypeOfMemberReference
instead, it's a bit better since T0
becomes [Int]
, but still crashes on an unhandled coercion further on.
P.S. Judging from this comment, this approach is more of a hack, and a bad one – I would be glad to learn the proper way of doing whatever the comment refers to.