@@ -321,6 +321,75 @@ 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
+ // FIXME: The "hasClangNode" check here is a complete hack.
361
+ if (isNonFinalClass (instanceTy) &&
362
+ !isStaticallyDerived &&
363
+ !ctorDecl->hasClangNode () &&
364
+ !(ctorDecl->isRequired () ||
365
+ ctorDecl->getDeclContext ()->getAsProtocolOrProtocolExtensionContext ())) {
366
+ if (SuppressDiagnostics)
367
+ return false ;
368
+
369
+ tc.diagnose (memberRefLoc, diag::dynamic_construct_class, instanceTy)
370
+ .highlight (base->getSourceRange ());
371
+ auto ctor = cast<ConstructorDecl>(ctorDecl);
372
+ tc.diagnose (ctorDecl, diag::note_nonrequired_initializer,
373
+ ctor->isImplicit (), ctor->getFullName ());
374
+ // Constructors cannot be called on a protocol metatype, because there is no
375
+ // metatype to witness it.
376
+ } else if (isa<ConstructorDecl>(ctorDecl) &&
377
+ baseTy->is <MetatypeType>() &&
378
+ instanceTy->isExistentialType ()) {
379
+ if (SuppressDiagnostics)
380
+ return false ;
381
+
382
+ if (isStaticallyDerived) {
383
+ tc.diagnose (memberRefLoc, diag::construct_protocol_by_name, instanceTy)
384
+ .highlight (base->getSourceRange ());
385
+ } else {
386
+ tc.diagnose (memberRefLoc, diag::construct_protocol_value, baseTy)
387
+ .highlight (base->getSourceRange ());
388
+ }
389
+ }
390
+ return true ;
391
+ }
392
+
324
393
namespace {
325
394
326
395
// / \brief Rewrites an expression by applying the solution of a constraint
@@ -825,12 +894,12 @@ namespace {
825
894
if (auto baseMeta = baseTy->getAs <AnyMetatypeType>()) {
826
895
baseIsInstance = false ;
827
896
baseTy = baseMeta->getInstanceType ();
897
+
828
898
// If the member is a constructor, verify that it can be legally
829
899
// referenced from this base.
830
900
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
831
- cs.setExprTypes (base);
832
- if (!tc.diagnoseInvalidDynamicConstructorReferences (base, memberLoc,
833
- baseMeta, ctor, SuppressDiagnostics))
901
+ if (!diagnoseInvalidDynamicConstructorReferences (cs, base, memberLoc,
902
+ ctor, SuppressDiagnostics))
834
903
return nullptr ;
835
904
}
836
905
}
@@ -6805,67 +6874,6 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
6805
6874
return literal;
6806
6875
}
6807
6876
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
6877
Expr *ExprRewriter::finishApply (ApplyExpr *apply, Type openedType,
6870
6878
ConstraintLocatorBuilder locator) {
6871
6879
TypeChecker &tc = cs.getTypeChecker ();
0 commit comments