@@ -367,11 +367,15 @@ namespace {
367367 // /
368368 // / \param variadicArgs The source indices that are mapped to the variadic
369369 // / parameter of the resulting tuple, as provided by \c computeTupleShuffle.
370+ // /
371+ // / \param typeFromPattern Optionally, the caller can specifiy the pattern
372+ // / from where the toType is derived, so that we can deliver better fixit.
370373 Expr *coerceTupleToTuple (Expr *expr, TupleType *fromTuple,
371374 TupleType *toTuple,
372375 ConstraintLocatorBuilder locator,
373376 SmallVectorImpl<int > &sources,
374- SmallVectorImpl<unsigned > &variadicArgs);
377+ SmallVectorImpl<unsigned > &variadicArgs,
378+ Optional<Pattern*> typeFromPattern = None);
375379
376380 // / \brief Coerce the given scalar value to the given tuple type.
377381 // /
@@ -407,7 +411,8 @@ namespace {
407411 // / \brief Coerce an expression of (possibly unchecked) optional
408412 // / type to have a different (possibly unchecked) optional type.
409413 Expr *coerceOptionalToOptional (Expr *expr, Type toType,
410- ConstraintLocatorBuilder locator);
414+ ConstraintLocatorBuilder locator,
415+ Optional<Pattern*> typeFromPattern = None);
411416
412417 // / \brief Coerce an expression of implicitly unwrapped optional type to its
413418 // / underlying value type, in the correct way for an implicit
@@ -1083,10 +1088,13 @@ namespace {
10831088 // / \param expr The expression to coerce.
10841089 // / \param toType The type to coerce the expression to.
10851090 // / \param locator Locator used to describe where in this expression we are.
1091+ // / \param typeFromPattern Optionally, the caller can specifiy the pattern
1092+ // / from where the toType is derived, so that we can deliver better fixit.
10861093 // /
10871094 // / \returns the coerced expression, which will have type \c ToType.
10881095 Expr *coerceToType (Expr *expr, Type toType,
1089- ConstraintLocatorBuilder locator);
1096+ ConstraintLocatorBuilder locator,
1097+ Optional<Pattern*> typeFromPattern = None);
10901098
10911099 // / \brief Coerce the given expression (which is the argument to a call) to
10921100 // / the given parameter type.
@@ -3673,6 +3681,56 @@ findDefaultArgsOwner(ConstraintSystem &cs, const Solution &solution,
36733681 return nullptr ;
36743682}
36753683
3684+ static bool
3685+ shouldApplyAddingLabelFixit (TuplePattern *tuplePattern, TupleType *fromTuple,
3686+ TupleType *toTuple,
3687+ std::vector<std::pair<SourceLoc, std::string>> &locInsertPairs) {
3688+ std::vector<TuplePattern*> patternParts;
3689+ std::vector<TupleType*> fromParts;
3690+ std::vector<TupleType*> toParts;
3691+ patternParts.push_back (tuplePattern);
3692+ fromParts.push_back (fromTuple);
3693+ toParts.push_back (toTuple);
3694+ while (!patternParts.empty ()) {
3695+ TuplePattern *curPattern = patternParts.back ();
3696+ TupleType *curFrom = fromParts.back ();
3697+ TupleType *curTo = toParts.back ();
3698+ patternParts.pop_back ();
3699+ fromParts.pop_back ();
3700+ toParts.pop_back ();
3701+ unsigned n = curPattern->getElements ().size ();
3702+ if (curFrom->getElements ().size () != n ||
3703+ curTo->getElements ().size () != n)
3704+ return false ;
3705+ for (unsigned i = 0 ; i < n; i ++) {
3706+ Pattern* subPat = curPattern->getElement (i).getPattern ();
3707+ const TupleTypeElt &subFrom = curFrom->getElement (i);
3708+ const TupleTypeElt &subTo = curTo->getElement (i);
3709+ if ((subFrom.getType ()->getKind () == TypeKind::Tuple) ^
3710+ (subTo.getType ()->getKind () == TypeKind::Tuple))
3711+ return false ;
3712+ auto addLabelFunc = [&]() {
3713+ if (subFrom.getName ().empty () && !subTo.getName ().empty ()) {
3714+ llvm::SmallString<8 > Name;
3715+ Name.append (subTo.getName ().str ());
3716+ Name.append (" : " );
3717+ locInsertPairs.push_back ({subPat->getStartLoc (), Name.str ()});
3718+ }
3719+ };
3720+ if (auto subFromTuple = subFrom.getType ()->getAs <TupleType>()) {
3721+ fromParts.push_back (subFromTuple);
3722+ toParts.push_back (subTo.getType ()->getAs <TupleType>());
3723+ patternParts.push_back (static_cast <TuplePattern*>(subPat));
3724+ addLabelFunc ();
3725+ } else if (subFrom.getType ()->isEqual (subTo.getType ())) {
3726+ addLabelFunc ();
3727+ } else
3728+ return false ;
3729+ }
3730+ }
3731+ return true ;
3732+ }
3733+
36763734// / Produce the caller-side default argument for this default argument, or
36773735// / null if the default argument will be provided by the callee.
36783736static std::pair<Expr *, DefaultArgumentKind>
@@ -3792,7 +3850,8 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
37923850 TupleType *toTuple,
37933851 ConstraintLocatorBuilder locator,
37943852 SmallVectorImpl<int > &sources,
3795- SmallVectorImpl<unsigned > &variadicArgs){
3853+ SmallVectorImpl<unsigned > &variadicArgs,
3854+ Optional<Pattern*> typeFromPattern){
37963855 auto &tc = cs.getTypeChecker ();
37973856
37983857 // Capture the tuple expression, if there is one.
@@ -3883,9 +3942,19 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
38833942 // We need to convert the source element to the destination type.
38843943 if (!fromTupleExpr) {
38853944 // FIXME: Lame! We can't express this in the AST.
3886- tc.diagnose (expr->getLoc (),
3887- diag::tuple_conversion_not_expressible,
3888- fromTuple, toTuple);
3945+ InFlightDiagnostic diag = tc.diagnose (expr->getLoc (),
3946+ diag::tuple_conversion_not_expressible,
3947+ fromTuple, toTuple);
3948+ if (typeFromPattern) {
3949+ std::vector<std::pair<SourceLoc, std::string>> locInsertPairs;
3950+ TuplePattern *tupleP = dyn_cast<TuplePattern>(typeFromPattern.getValue ());
3951+ if (tupleP && shouldApplyAddingLabelFixit (tupleP, toTuple, fromTuple,
3952+ locInsertPairs)) {
3953+ for (auto &Pair : locInsertPairs) {
3954+ diag.fixItInsert (Pair.first , Pair.second );
3955+ }
3956+ }
3957+ }
38893958 return nullptr ;
38903959 }
38913960
@@ -4238,7 +4307,8 @@ static Type getOptionalBaseType(const Type &type) {
42384307}
42394308
42404309Expr *ExprRewriter::coerceOptionalToOptional (Expr *expr, Type toType,
4241- ConstraintLocatorBuilder locator) {
4310+ ConstraintLocatorBuilder locator,
4311+ Optional<Pattern*> typeFromPattern) {
42424312 auto &tc = cs.getTypeChecker ();
42434313 Type fromType = expr->getType ();
42444314
@@ -4287,7 +4357,7 @@ Expr *ExprRewriter::coerceOptionalToOptional(Expr *expr, Type toType,
42874357 expr = new (tc.Context ) BindOptionalExpr (expr, expr->getSourceRange ().End ,
42884358 /* depth*/ 0 , fromValueType);
42894359 expr->setImplicit (true );
4290- expr = coerceToType (expr, toValueType, locator);
4360+ expr = coerceToType (expr, toValueType, locator, typeFromPattern );
42914361 if (!expr) return nullptr ;
42924362
42934363 expr = new (tc.Context ) InjectIntoOptionalExpr (expr, toType);
@@ -4743,7 +4813,8 @@ maybeDiagnoseUnsupportedFunctionConversion(TypeChecker &tc, Expr *expr,
47434813}
47444814
47454815Expr *ExprRewriter::coerceToType (Expr *expr, Type toType,
4746- ConstraintLocatorBuilder locator) {
4816+ ConstraintLocatorBuilder locator,
4817+ Optional<Pattern*> typeFromPattern) {
47474818 auto &tc = cs.getTypeChecker ();
47484819
47494820 // The type we're converting from.
@@ -4769,7 +4840,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
47694840 assert (!failed && " Couldn't convert tuple to tuple?" );
47704841 (void )failed;
47714842 return coerceTupleToTuple (expr, fromTuple, toTuple, locator, sources,
4772- variadicArgs);
4843+ variadicArgs, typeFromPattern );
47734844 }
47744845
47754846 case ConversionRestrictionKind::ScalarToTuple: {
@@ -4876,7 +4947,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
48764947 case ConversionRestrictionKind::OptionalToImplicitlyUnwrappedOptional:
48774948 case ConversionRestrictionKind::ImplicitlyUnwrappedOptionalToOptional:
48784949 case ConversionRestrictionKind::OptionalToOptional:
4879- return coerceOptionalToOptional (expr, toType, locator);
4950+ return coerceOptionalToOptional (expr, toType, locator, typeFromPattern );
48804951
48814952 case ConversionRestrictionKind::ForceUnchecked: {
48824953 auto valueTy = fromType->getImplicitlyUnwrappedOptionalObjectType ();
@@ -5175,7 +5246,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
51755246
51765247 if (toType->getAnyOptionalObjectType () &&
51775248 expr->getType ()->getAnyOptionalObjectType ()) {
5178- return coerceOptionalToOptional (expr, toType, locator);
5249+ return coerceOptionalToOptional (expr, toType, locator, typeFromPattern );
51795250 }
51805251
51815252 // Coercion to Optional<T>.
@@ -6193,12 +6264,13 @@ Expr *ConstraintSystem::applySolutionShallow(const Solution &solution,
61936264
61946265Expr *Solution::coerceToType (Expr *expr, Type toType,
61956266 ConstraintLocator *locator,
6196- bool ignoreTopLevelInjection) const {
6267+ bool ignoreTopLevelInjection,
6268+ Optional<Pattern*> typeFromPattern) const {
61976269 auto &cs = getConstraintSystem ();
61986270 ExprRewriter rewriter (cs, *this ,
61996271 /* suppressDiagnostics=*/ false ,
62006272 /* skipClosures=*/ false );
6201- Expr *result = rewriter.coerceToType (expr, toType, locator);
6273+ Expr *result = rewriter.coerceToType (expr, toType, locator, typeFromPattern );
62026274 if (!result)
62036275 return nullptr ;
62046276
0 commit comments