@@ -3635,6 +3635,10 @@ static bool repairOutOfOrderArgumentsInBinaryFunction(
3635
3635
return false ;
3636
3636
}
3637
3637
3638
+ // / Switch between restrictions mechanism and original PR using
3639
+ // / ConversionRestrictionKind::PointerToPointer in repairFailures().
3640
+ static bool useRestrictions = true ;
3641
+
3638
3642
// / Attempt to repair typing failures and record fixes if needed.
3639
3643
// / \return true if at least some of the failures has been repaired
3640
3644
// / successfully, which allows type matcher to continue.
@@ -4972,21 +4976,56 @@ bool ConstraintSystem::repairFailures(
4972
4976
}
4973
4977
4974
4978
// Accept mutable pointers in the place of immutables.
4975
- if (toImmutablePossible (lhs, rhs))
4979
+ if (implicitConversionAvailable (lhs, rhs))
4976
4980
conversionsOrFixes.push_back (
4977
4981
ConversionRestrictionKind::PointerToPointer);
4978
4982
4979
4983
return !conversionsOrFixes.empty ();
4980
4984
}
4981
4985
4982
- bool ConstraintSystem::toImmutablePossible (Type lhs, Type rhs) {
4983
- #if 1
4984
- if (auto nominal = lhs->getAnyNominal ())
4985
- if (auto func = nominal->implicitConversionTo (rhs))
4986
- return true ;
4987
- #else
4988
- if (rhs->isUnsafeRawPointer() && (lhs->isUnsafeMutableRawPointer() ||
4989
- lhs->isUnsafeMutablePointer() || lhs->isUnsafePointer())) {
4986
+ bool ConstraintSystem::implicitConversionAvailable (Type fromType, Type toType) {
4987
+ #if 01 // Determine implicit conversions from init(implicit:) constructors
4988
+ fprintf (stderr, " \n\n FROM %p " , fromType.getPointer ());
4989
+ fromType->dump ();
4990
+ fprintf (stderr, " TO %p " , toType.getPointer ());
4991
+ toType->dump ();
4992
+ if (NominalTypeDecl *toNominal = toType->getAnyNominal ()) {
4993
+ auto typeKey = ^TypeBase *(Type t) {
4994
+ return t->getAnyNominal ()->getInterfaceType ()
4995
+ ->getCanonicalType ().getPointer ();
4996
+ };
4997
+ TypeBase *toBase = typeKey (toType);
4998
+ auto &ctx = getASTContext ();
4999
+ if (!toNominal->setConversionsComputed ()) {
5000
+ auto implicitArgId = ctx.Id_implicit ;
5001
+ for (ExtensionDecl *extension : toNominal->getExtensions ()) {
5002
+ Type extType = extension->getDeclaredInterfaceType ()->getCanonicalType ();
5003
+ fprintf (stderr, " \n EXT %p " , extType.getPointer ());
5004
+ extType->dump ();
5005
+ for (Decl *member : extension->getMembers ())
5006
+ if (ConstructorDecl *initDecl = dyn_cast<ConstructorDecl>(member)) {
5007
+ ParameterList *args = initDecl->getParameters ();
5008
+ if (args->size () == 1 &&
5009
+ args->get (0 )->getBaseName ().getIdentifier () == implicitArgId) {
5010
+ Type argType = args->get (0 )->getType ()->getCanonicalType ();
5011
+ fprintf (stderr, " ARG %p " , argType.getPointer ());
5012
+ argType->dump ();
5013
+ (*ctx.implicitConversionsTo (typeKey (extType), /* create*/ true ))
5014
+ [typeKey (argType)].push_back (initDecl);
5015
+ }
5016
+ }
5017
+ }
5018
+ }
5019
+ if (auto *exists = ctx.implicitConversionsTo (toBase, /* create*/ false )) {
5020
+ for (ConstructorDecl *initFunc : (*exists)[typeKey (fromType)])
5021
+ // More detailed check of conversion here...
5022
+ if (initFunc != nullptr )
5023
+ return true ;
5024
+ }
5025
+ }
5026
+ #else // Original hard coded rules.
5027
+ if (toType->isUnsafeRawPointer() && (fromType->isUnsafeMutableRawPointer() ||
5028
+ fromType->isUnsafeMutablePointer() || fromType->isUnsafePointer())) {
4990
5029
return true; // Unsafe[Mutable][Raw]Pointer -> UnsafeRawPointer
4991
5030
}
4992
5031
@@ -4995,39 +5034,16 @@ bool ConstraintSystem::toImmutablePossible(Type lhs, Type rhs) {
4995
5034
->getGenericArgs()[0]->getCanonicalType();
4996
5035
};
4997
5036
4998
- if (lhs ->isUnsafeMutablePointer() && rhs ->isUnsafePointer() &&
4999
- firstGenericArgument(lhs ) == firstGenericArgument(rhs )) {
5000
- rhs ->dump();
5001
- lhs ->dump();
5037
+ if (fromType ->isUnsafeMutablePointer() && toType ->isUnsafePointer() &&
5038
+ firstGenericArgument(fromType ) == firstGenericArgument(toType )) {
5039
+ toType ->dump();
5040
+ fromType ->dump();
5002
5041
return true; // UnsafeMutablePointer<Pointee> -> UnsafePointer<Pointee>
5003
5042
}
5004
5043
#endif
5005
5044
return false ;
5006
5045
}
5007
5046
5008
- ConstructorDecl *NominalTypeDecl::implicitConversionTo (Type type) {
5009
- if (NominalTypeDecl *toNominal = type->getAnyNominal ()) {
5010
- auto &ctx = getASTContext ();
5011
- if (!toNominal->implicitConversionsComputed ) {
5012
- auto implicitArgId = ctx.Id_implicit ;
5013
- for (ExtensionDecl *extension : toNominal->getExtensions ())
5014
- for (Decl *member : extension->getMembers ())
5015
- if (ConstructorDecl *initDecl = dyn_cast<ConstructorDecl>(member)) {
5016
- ParameterList *args = initDecl->getParameters ();
5017
- if (args->size () == 1 &&
5018
- args->get (0 )->getBaseName ().getIdentifier () == implicitArgId)
5019
- if (auto fromNominal = args->get (0 )->getType ()->getAnyNominal ())
5020
- (*ctx.implicitConversionsFor (fromNominal, /* create*/ true ))
5021
- [toNominal] = initDecl;
5022
- }
5023
- toNominal->implicitConversionsComputed = true ;
5024
- }
5025
- if (auto *exists = ctx.implicitConversionsFor (this , /* create*/ false ))
5026
- return (*exists)[toNominal];
5027
- }
5028
- return nullptr ;
5029
- }
5030
-
5031
5047
ConstraintSystem::TypeMatchResult
5032
5048
ConstraintSystem::matchTypes (Type type1, Type type2, ConstraintKind kind,
5033
5049
TypeMatchOptions flags,
@@ -5374,7 +5390,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
5374
5390
if (kind >= ConstraintKind::Subtype &&
5375
5391
nominal1->getDecl () != nominal2->getDecl () &&
5376
5392
((nominal1->isCGFloatType () || nominal2->isCGFloatType ()) &&
5377
- (nominal1->isDouble () || nominal2->isDouble ()))) {
5393
+ (nominal1->isDouble () || nominal2->isDouble ())) ||
5394
+ useRestrictions && implicitConversionAvailable (type1, type2)) {
5378
5395
ConstraintLocatorBuilder location{locator};
5379
5396
// Look through all value-to-optional promotions to allow
5380
5397
// conversions like Double -> CGFloat?? and vice versa.
@@ -5442,14 +5459,17 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
5442
5459
rawElt.getAs <LocatorPathElt::ImplicitConversion>()) {
5443
5460
auto convKind = elt->getConversionKind ();
5444
5461
return convKind == ConversionRestrictionKind::DoubleToCGFloat ||
5445
- convKind == ConversionRestrictionKind::CGFloatToDouble;
5462
+ convKind == ConversionRestrictionKind::CGFloatToDouble ||
5463
+ convKind == ConversionRestrictionKind::ImplicitConversion;
5446
5464
}
5447
5465
return false ;
5448
5466
})) {
5449
5467
conversionsOrFixes.push_back (
5450
5468
desugar1->isCGFloatType ()
5451
- ? ConversionRestrictionKind::CGFloatToDouble
5452
- : ConversionRestrictionKind::DoubleToCGFloat);
5469
+ ? ConversionRestrictionKind::CGFloatToDouble :
5470
+ desugar2->isCGFloatType ()
5471
+ ? ConversionRestrictionKind::DoubleToCGFloat :
5472
+ ConversionRestrictionKind::ImplicitConversion);
5453
5473
}
5454
5474
}
5455
5475
@@ -11177,7 +11197,8 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
11177
11197
}
11178
11198
11179
11199
case ConversionRestrictionKind::DoubleToCGFloat:
11180
- case ConversionRestrictionKind::CGFloatToDouble: {
11200
+ case ConversionRestrictionKind::CGFloatToDouble:
11201
+ case ConversionRestrictionKind::ImplicitConversion: {
11181
11202
// Prefer CGFloat -> Double over other way araund.
11182
11203
auto impact =
11183
11204
restriction == ConversionRestrictionKind::CGFloatToDouble ? 1 : 10 ;
@@ -11224,16 +11245,17 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
11224
11245
memberTy, DC, FunctionRefKind::DoubleApply,
11225
11246
/* outerAlternatives=*/ {}, memberLoc);
11226
11247
11248
+ Identifier label;
11249
+ if (restriction == ConversionRestrictionKind::ImplicitConversion)
11250
+ label = getASTContext ().Id_implicit ;
11227
11251
addConstraint (ConstraintKind::ApplicableFunction,
11228
- FunctionType::get ({FunctionType::Param (type1)}, type2),
11252
+ FunctionType::get ({FunctionType::Param (type1, label )}, type2),
11229
11253
memberTy, applicationLoc);
11230
11254
11231
11255
ImplicitValueConversions.push_back (
11232
11256
{getConstraintLocator (locator), restriction});
11233
11257
return SolutionKind::Solved;
11234
11258
}
11235
- case ConversionRestrictionKind::ImplicitConversion:
11236
- return SolutionKind::Solved;
11237
11259
}
11238
11260
11239
11261
llvm_unreachable (" bad conversion restriction" );
0 commit comments