I taught LinkedExprAnalyzer about ForceValueExpr if (auto FVE = dyn_cast<ForceValueExpr>(expr)) { LTI.collectedTypes.insert(CS.getType(FVE)->lookThroughAllAnyOptionalTypes().getPointer()); return { false, expr }; }
This seems to get it - didn’t check whether this regresses things, but this seems to be the right fix at a high level. ~Robert Widmann > On Dec 31, 2016, at 11:22 AM, Mark Lacey via swift-dev <swift-dev@swift.org> > wrote: > >> >> On Dec 30, 2016, at 2:07 PM, Jacob Bandes-Storch via swift-dev >> <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote: >> >> This is a pretty great bug: https://bugs.swift.org/browse/SR-3483 >> <https://bugs.swift.org/browse/SR-3483> >> >> let x: Double? = 1 >> >> // error: ambiguous reference to member '+' >> let sum = x! + x! + x! >> >> // error: value of optional type 'Double?' not unwrapped; did you mean >> to use '!' or '?'? >> let sum: Double = x! + x! + x! >> >> I've been poking around and I think the problem might be in >> LinkedExprAnalyzer. > > Yeah I think you’re onto something there. Just looking at the output of the > constraint solver and where bindings are happening in matchTypes(), it looks > like the constraint optimizer is trying to force the result type of both adds > to ‘Double?’ rather than ‘Double’, so we only ever try to solve for that type. > > I haven’t looked at the constraint optimizer code in a while, so I don’t have > a lot of insight into the best fix, but it’s clearly the problematic piece > here. > > Mark > > >> This class collects type info about elements in a chain of binary operators >> to speed up constraint solving. It does so in this case by grabbing the >> DeclRefExpr's type: >> https://github.com/apple/swift/tree/474096b9cbd6ff7ac998d7cea41d629512e25570#L230-L239 >> >> <https://github.com/apple/swift/tree/474096b9cbd6ff7ac998d7cea41d629512e25570#L230-L239> >> >> However, since this is an ASTWalker, (I think) it automatically traverses >> into the ForceValueExpr without remembering that the type it finds inside >> (from the DeclRefExpr) should have one level of optionality removed when >> added to the constraint system. >> >> This theory sort of makes sense to me, but it doesn't explain why the >> simpler "let sum = x! + x!" typechecks correctly, because that goes through >> the same code path. >> >> Am I correct that the LinkedExprAnalyzer probably needs to make sure it >> doesn't keep the Optional when adding the type of a ForceValueExpr? Why >> wouldn't this also cause problems for a single binop application? >> >> Would it be more appropriate for LinkedExprAnalyzer to be an ASTVisitor >> (ExprVisitor) so that instead of just saying "yes, continue traversing >> downwards" (by returning {true, expr}), its ForceValueExpr case could >> recursively call visit() and then getAnyOptionalObjectType on the result? >> >> >> Semi-eptly, >> Jacob >> _______________________________________________ >> swift-dev mailing list >> swift-dev@swift.org <mailto:swift-dev@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-dev > > _______________________________________________ > swift-dev mailing list > swift-dev@swift.org <mailto:swift-dev@swift.org> > https://lists.swift.org/mailman/listinfo/swift-dev > <https://lists.swift.org/mailman/listinfo/swift-dev>
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev