Example #1
0
static void finalizeType(TypeChecker &TC, NominalTypeDecl *nominal) {
  Optional<bool> lazyVarsAlreadyHaveImplementation;

  for (auto *D : nominal->getMembers()) {
    auto VD = dyn_cast<ValueDecl>(D);
    if (!VD)
      continue;

    if (!shouldValidateMemberDuringFinalization(nominal, VD))
      continue;

    TC.validateDecl(VD);

    // The only thing left to do is synthesize storage for lazy variables.
    // We only have to do that if it's a type from another file, though.
    // In NDEBUG builds, bail out as soon as we can.
#ifdef NDEBUG
    if (lazyVarsAlreadyHaveImplementation.hasValue() &&
        lazyVarsAlreadyHaveImplementation.getValue())
      continue;
#endif
    auto *prop = dyn_cast<VarDecl>(D);
    if (!prop)
      continue;

    if (prop->getAttrs().hasAttribute<LazyAttr>() && !prop->isStatic()
                                                  && prop->getGetter()) {
      bool hasImplementation = prop->getGetter()->hasBody();

      if (lazyVarsAlreadyHaveImplementation.hasValue()) {
        assert(lazyVarsAlreadyHaveImplementation.getValue() ==
                 hasImplementation &&
               "only some lazy vars already have implementations");
      } else {
        lazyVarsAlreadyHaveImplementation = hasImplementation;
      }

      if (!hasImplementation)
        TC.completeLazyVarImplementation(prop);
    }
  }

  // FIXME: We need to add implicit initializers and dtors when a decl is
  // touched, because it affects vtable layout.  If you're not defining the
  // class, you shouldn't have to know what the vtable layout is.
  if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
    TC.addImplicitConstructors(CD);
    TC.addImplicitDestructor(CD);
  }

  // validateDeclForNameLookup will not trigger an immediate full
  // validation of protocols, but clients will assume that things
  // like the requirement signature have been set.
  if (auto PD = dyn_cast<ProtocolDecl>(nominal)) {
    if (!PD->isRequirementSignatureComputed()) {
      TC.validateDecl(PD);
    }
  }
}