@@ -321,6 +321,85 @@ static bool buildObjCKeyPathString(KeyPathExpr *E,
321
321
return true ;
322
322
}
323
323
324
+ // / Determine whether the given type refers to a non-final class (or
325
+ // / dynamic self of one).
326
+ static bool isNonFinalClass (Type type) {
327
+ if (auto dynamicSelf = type->getAs <DynamicSelfType>())
328
+ type = dynamicSelf->getSelfType ();
329
+
330
+ if (auto classDecl = type->getClassOrBoundGenericClass ())
331
+ return !classDecl->isFinal ();
332
+
333
+ if (auto archetype = type->getAs <ArchetypeType>())
334
+ if (auto super = archetype->getSuperclass ())
335
+ return isNonFinalClass (super);
336
+
337
+ return false ;
338
+ }
339
+
340
+ // Non-required constructors may not be not inherited. Therefore when
341
+ // constructing a class object, either the metatype must be statically
342
+ // derived (rather than an arbitrary value of metatype type) or the referenced
343
+ // constructor must be required.
344
+ static bool
345
+ diagnoseInvalidDynamicConstructorReferences (ConstraintSystem &cs,
346
+ Expr *base,
347
+ DeclNameLoc memberRefLoc,
348
+ ConstructorDecl *ctorDecl,
349
+ bool SuppressDiagnostics) {
350
+ auto &tc = cs.getTypeChecker ();
351
+ auto baseTy = cs.getType (base)->getRValueType ();
352
+ auto instanceTy = baseTy->getRValueInstanceType ();
353
+
354
+ bool isStaticallyDerived =
355
+ base->isStaticallyDerivedMetatype (
356
+ [&](const Expr *expr) -> Type {
357
+ return cs.getType (expr);
358
+ });
359
+
360
+ // 'super.' is always OK
361
+ if (isa<SuperRefExpr>(base))
362
+ return true ;
363
+
364
+ // 'self.' reference with concrete type is OK
365
+ if (isa<DeclRefExpr>(base) &&
366
+ cast<DeclRefExpr>(base)->getDecl ()->getBaseName () == tc.Context .Id_self &&
367
+ !baseTy->is <ArchetypeType>())
368
+ return true ;
369
+
370
+ // FIXME: The "hasClangNode" check here is a complete hack.
371
+ if (isNonFinalClass (instanceTy) &&
372
+ !isStaticallyDerived &&
373
+ !ctorDecl->hasClangNode () &&
374
+ !(ctorDecl->isRequired () ||
375
+ ctorDecl->getDeclContext ()->getAsProtocolOrProtocolExtensionContext ())) {
376
+ if (SuppressDiagnostics)
377
+ return false ;
378
+
379
+ tc.diagnose (memberRefLoc, diag::dynamic_construct_class, instanceTy)
380
+ .highlight (base->getSourceRange ());
381
+ auto ctor = cast<ConstructorDecl>(ctorDecl);
382
+ tc.diagnose (ctorDecl, diag::note_nonrequired_initializer,
383
+ ctor->isImplicit (), ctor->getFullName ());
384
+ // Constructors cannot be called on a protocol metatype, because there is no
385
+ // metatype to witness it.
386
+ } else if (isa<ConstructorDecl>(ctorDecl) &&
387
+ baseTy->is <MetatypeType>() &&
388
+ instanceTy->isExistentialType ()) {
389
+ if (SuppressDiagnostics)
390
+ return false ;
391
+
392
+ if (isStaticallyDerived) {
393
+ tc.diagnose (memberRefLoc, diag::construct_protocol_by_name, instanceTy)
394
+ .highlight (base->getSourceRange ());
395
+ } else {
396
+ tc.diagnose (memberRefLoc, diag::construct_protocol_value, baseTy)
397
+ .highlight (base->getSourceRange ());
398
+ }
399
+ }
400
+ return true ;
401
+ }
402
+
324
403
namespace {
325
404
326
405
// / \brief Rewrites an expression by applying the solution of a constraint
@@ -825,12 +904,12 @@ namespace {
825
904
if (auto baseMeta = baseTy->getAs <AnyMetatypeType>()) {
826
905
baseIsInstance = false ;
827
906
baseTy = baseMeta->getInstanceType ();
907
+
828
908
// If the member is a constructor, verify that it can be legally
829
909
// referenced from this base.
830
910
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
831
- cs.setExprTypes (base);
832
- if (!tc.diagnoseInvalidDynamicConstructorReferences (base, memberLoc,
833
- baseMeta, ctor, SuppressDiagnostics))
911
+ if (!diagnoseInvalidDynamicConstructorReferences (cs, base, memberLoc,
912
+ ctor, SuppressDiagnostics))
834
913
return nullptr ;
835
914
}
836
915
}
@@ -2461,6 +2540,13 @@ namespace {
2461
2540
ConstructorDecl *ctor,
2462
2541
FunctionRefKind functionRefKind,
2463
2542
Type openedType) {
2543
+
2544
+ // If the member is a constructor, verify that it can be legally
2545
+ // referenced from this base.
2546
+ if (!diagnoseInvalidDynamicConstructorReferences (cs, base, nameLoc,
2547
+ ctor, SuppressDiagnostics))
2548
+ return nullptr ;
2549
+
2464
2550
// If the subexpression is a metatype, build a direct reference to the
2465
2551
// constructor.
2466
2552
if (cs.getType (base)->is <AnyMetatypeType>()) {
@@ -6805,67 +6891,6 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
6805
6891
return literal;
6806
6892
}
6807
6893
6808
- // / Determine whether the given type refers to a non-final class (or
6809
- // / dynamic self of one).
6810
- static bool isNonFinalClass (Type type) {
6811
- if (auto dynamicSelf = type->getAs <DynamicSelfType>())
6812
- type = dynamicSelf->getSelfType ();
6813
-
6814
- if (auto classDecl = type->getClassOrBoundGenericClass ())
6815
- return !classDecl->isFinal ();
6816
-
6817
- if (auto archetype = type->getAs <ArchetypeType>())
6818
- if (auto super = archetype->getSuperclass ())
6819
- return isNonFinalClass (super);
6820
-
6821
- return false ;
6822
- }
6823
-
6824
- // Non-required constructors may not be not inherited. Therefore when
6825
- // constructing a class object, either the metatype must be statically
6826
- // derived (rather than an arbitrary value of metatype type) or the referenced
6827
- // constructor must be required.
6828
- bool
6829
- TypeChecker::diagnoseInvalidDynamicConstructorReferences (Expr *base,
6830
- DeclNameLoc memberRefLoc,
6831
- AnyMetatypeType *metaTy,
6832
- ConstructorDecl *ctorDecl,
6833
- bool SuppressDiagnostics) {
6834
- auto ty = metaTy->getInstanceType ();
6835
-
6836
- // FIXME: The "hasClangNode" check here is a complete hack.
6837
- if (isNonFinalClass (ty) &&
6838
- !base->isStaticallyDerivedMetatype () &&
6839
- !ctorDecl->hasClangNode () &&
6840
- !(ctorDecl->isRequired () ||
6841
- ctorDecl->getDeclContext ()->getAsProtocolOrProtocolExtensionContext ())) {
6842
- if (SuppressDiagnostics)
6843
- return false ;
6844
-
6845
- diagnose (memberRefLoc, diag::dynamic_construct_class, ty)
6846
- .highlight (base->getSourceRange ());
6847
- auto ctor = cast<ConstructorDecl>(ctorDecl);
6848
- diagnose (ctorDecl, diag::note_nonrequired_initializer,
6849
- ctor->isImplicit (), ctor->getFullName ());
6850
- // Constructors cannot be called on a protocol metatype, because there is no
6851
- // metatype to witness it.
6852
- } else if (isa<ConstructorDecl>(ctorDecl) &&
6853
- isa<MetatypeType>(metaTy) &&
6854
- ty->isExistentialType ()) {
6855
- if (SuppressDiagnostics)
6856
- return false ;
6857
-
6858
- if (base->isStaticallyDerivedMetatype ()) {
6859
- diagnose (memberRefLoc, diag::construct_protocol_by_name, ty)
6860
- .highlight (base->getSourceRange ());
6861
- } else {
6862
- diagnose (memberRefLoc, diag::construct_protocol_value, metaTy)
6863
- .highlight (base->getSourceRange ());
6864
- }
6865
- }
6866
- return true ;
6867
- }
6868
-
6869
6894
Expr *ExprRewriter::finishApply (ApplyExpr *apply, Type openedType,
6870
6895
ConstraintLocatorBuilder locator) {
6871
6896
TypeChecker &tc = cs.getTypeChecker ();
0 commit comments