GenericEnvironment *
TypeChecker::markInvalidGenericSignature(DeclContext *DC) {
  GenericParamList *genericParams = DC->getGenericParamsOfContext();
  GenericSignature *genericSig = DC->getGenericSignatureOfContext();

  // Build new archetypes without any generic requirements.
  DeclContext *parentDC = DC->getParent();
  auto builder = createArchetypeBuilder(parentDC->getParentModule());

  auto parentSig = parentDC->getGenericSignatureOfContext();
  auto parentEnv = parentDC->getGenericEnvironmentOfContext();

  assert(parentSig != nullptr || DC->isInnermostContextGeneric());

  if (parentSig != nullptr)
    builder.addGenericSignature(parentSig, parentEnv);

  if (DC->isInnermostContextGeneric()) {
    // Visit each of the generic parameters.
    for (auto param : *genericParams)
      builder.addGenericParameter(param);
  }

  // Wire up the archetypes.
  auto genericEnv = builder.getGenericEnvironment(
      genericSig->getGenericParams());

  return genericEnv;
}
Exemple #2
0
void
TypeChecker::validateGenericSubscriptSignature(SubscriptDecl *subscript) {
  auto *dc = subscript->getDeclContext();

  GenericSignature *sig;
  if (auto *gp = subscript->getGenericParams()) {
    gp->setOuterParameters(dc->getGenericParamsOfContext());
    prepareGenericParamList(gp, subscript);

    // Create the generic signature builder.
    GenericSignatureBuilder builder(Context);

    // Type check the function declaration, treating all generic type
    // parameters as dependent, unresolved.
    checkGenericSubscriptSignature(*this, &builder, subscript,
                                   TypeResolution::forStructural(subscript));

    // The generic subscript signature is complete and well-formed. Determine
    // the type of the generic subscript.
    sig =
      std::move(builder).computeGenericSignature(subscript->getLoc());

    // The generic signature builder now has all of the requirements, although
    // there might still be errors that have not yet been diagnosed. Revert the
    // generic function signature and type-check it again, completely.
    revertGenericSubscriptSignature(subscript);
    revertGenericParamList(*this, gp);

    // Debugging of generic signature generation.
    if (Context.LangOpts.DebugGenericSignatures) {
      subscript->dumpRef(llvm::errs());
      llvm::errs() << "\n";
      llvm::errs() << "Generic signature: ";
      sig->print(llvm::errs());
      llvm::errs() << "\n";
      llvm::errs() << "Canonical generic signature: ";
      sig->getCanonicalSignature()->print(llvm::errs());
      llvm::errs() << "\n";
    }

    subscript->setGenericEnvironment(sig->createGenericEnvironment());
  } else {
    // Inherit the signature of our environment.
    sig = dc->getGenericSignatureOfContext();
    subscript->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
  }

  checkGenericSubscriptSignature(*this, nullptr, subscript,
                                 TypeResolution::forInterface(subscript, sig));

  subscript->computeType();
}
Exemple #3
0
static void initDocGenericParams(const Decl *D, DocEntityInfo &Info) {
  auto *DC = dyn_cast<DeclContext>(D);
  if (DC == nullptr || !DC->isInnermostContextGeneric())
    return;

  GenericSignature *GenericSig = DC->getGenericSignatureOfContext();

  if (!GenericSig)
    return;

  // FIXME: Not right for extensions of nested generic types
  for (auto *GP : GenericSig->getInnermostGenericParams()) {
    if (GP->getDecl()->isImplicit())
      continue;
    DocGenericParam Param;
    Param.Name = GP->getName().str();
    Info.GenericParams.push_back(Param);
  }

  ProtocolDecl *proto = nullptr;
  if (auto *typeDC = DC->getInnermostTypeContext())
    proto = typeDC->getAsProtocolOrProtocolExtensionContext();

  for (auto &Req : GenericSig->getRequirements()) {
    if (Req.getKind() == RequirementKind::WitnessMarker)
      continue;

    // Skip protocol Self requirement.
    if (proto &&
        Req.getKind() == RequirementKind::Conformance &&
        Req.getFirstType()->isEqual(proto->getSelfInterfaceType()) &&
        Req.getSecondType()->getAnyNominal() == proto)
      continue;

    std::string ReqStr;
    PrintOptions Opts;
    llvm::raw_string_ostream OS(ReqStr);
    Req.print(OS, Opts);
    OS.flush();
    Info.GenericRequirements.push_back(std::move(ReqStr));
  }
}
Exemple #4
0
GenericEnvironment *TypeChecker::checkGenericEnvironment(
                      GenericParamList *genericParams,
                      DeclContext *dc,
                      GenericSignature *parentSig,
                      bool allowConcreteGenericParams,
                      ExtensionDecl *ext,
                      llvm::function_ref<void(GenericSignatureBuilder &)>
                        inferRequirements,
                      bool mustInferRequirements) {
  assert(genericParams && "Missing generic parameters?");
  bool recursivelyVisitGenericParams =
    genericParams->getOuterParameters() && !parentSig;

  GenericSignature *sig;
  if (!ext || mustInferRequirements || ext->getTrailingWhereClause() ||
      getExtendedTypeGenericDepth(ext) != genericParams->getDepth()) {
    // Collect the generic parameters.
    SmallVector<GenericTypeParamType *, 4> allGenericParams;
    if (recursivelyVisitGenericParams) {
      visitOuterToInner(genericParams,
                        [&](GenericParamList *gpList) {
        addGenericParamTypes(gpList, allGenericParams);
      });
    } else {
      if (parentSig) {
        allGenericParams.append(parentSig->getGenericParams().begin(),
                                parentSig->getGenericParams().end());
      }

      addGenericParamTypes(genericParams, allGenericParams);
    }

    // Create the generic signature builder.
    GenericSignatureBuilder builder(Context);

    // Type check the generic parameters, treating all generic type
    // parameters as dependent, unresolved.
    if (recursivelyVisitGenericParams) {
      visitOuterToInner(genericParams,
                        [&](GenericParamList *gpList) {
      auto genericParamsDC = gpList->begin()[0]->getDeclContext();
      TypeResolution structuralResolution =
        TypeResolution::forStructural(genericParamsDC);
        checkGenericParamList(*this, &builder, gpList, nullptr,
                              structuralResolution);
      });
    } else {
      auto genericParamsDC = genericParams->begin()[0]->getDeclContext();
      TypeResolution structuralResolution =
        TypeResolution::forStructural(genericParamsDC);
      checkGenericParamList(*this, &builder, genericParams, parentSig,
                            structuralResolution);
    }

    /// Perform any necessary requirement inference.
    inferRequirements(builder);

    // Record the generic type parameter types and the requirements.
    sig = std::move(builder).computeGenericSignature(
                                         genericParams->getSourceRange().Start,
                                         allowConcreteGenericParams);

    // The generic signature builder now has all of the requirements, although
    // there might still be errors that have not yet been diagnosed. Revert the
    // signature and type-check it again, completely.
    if (recursivelyVisitGenericParams) {
      visitOuterToInner(genericParams,
                        [&](GenericParamList *gpList) {
        revertGenericParamList(*this, gpList);
      });
    } else {
      revertGenericParamList(*this, genericParams);
    }

    // Debugging of the generic signature builder and generic signature
    // generation.
    if (Context.LangOpts.DebugGenericSignatures) {
      dc->printContext(llvm::errs());
      llvm::errs() << "\n";
      llvm::errs() << "Generic signature: ";
      sig->print(llvm::errs());
      llvm::errs() << "\n";
      llvm::errs() << "Canonical generic signature: ";
      sig->getCanonicalSignature()->print(llvm::errs());
      llvm::errs() << "\n";
    }
  } else {
    // Re-use the signature of the type being extended.
    sig = ext->getSelfNominalTypeDecl()->getGenericSignatureOfContext();
  }

  if (recursivelyVisitGenericParams) {
    visitOuterToInner(genericParams,
                      [&](GenericParamList *gpList) {
      auto paramsDC = gpList->getParams().front()->getDeclContext();
      TypeResolution interfaceResolution =
        TypeResolution::forInterface(paramsDC, sig);
      checkGenericParamList(*this, nullptr, gpList, nullptr,
                            interfaceResolution);
    });
  } else {
    auto paramsDC = genericParams->getParams().front()->getDeclContext();
    TypeResolution interfaceResolution =
      TypeResolution::forInterface(paramsDC, sig);
    checkGenericParamList(*this, nullptr, genericParams, parentSig,
                          interfaceResolution);
  }

  // Form the generic environment.
  return sig->createGenericEnvironment();
}
GenericSignature *
TypeChecker::validateGenericSubscriptSignature(SubscriptDecl *subscript) {
  bool invalid = false;

  GenericSignature *sig;
  if (auto *gp = subscript->getGenericParams()) {
    prepareGenericParamList(gp, subscript);

    // Create the generic signature builder.
    GenericSignatureBuilder builder(Context);

    // Type check the function declaration, treating all generic type
    // parameters as dependent, unresolved.
    DependentGenericTypeResolver dependentResolver;
    if (checkGenericSubscriptSignature(*this, &builder, subscript,
                                       dependentResolver))
      invalid = true;

    // The generic subscript signature is complete and well-formed. Determine
    // the type of the generic subscript.
    sig =
      std::move(builder).computeGenericSignature(subscript->getLoc());

    // The generic signature builder now has all of the requirements, although
    // there might still be errors that have not yet been diagnosed. Revert the
    // generic function signature and type-check it again, completely.
    revertGenericSubscriptSignature(subscript);
    revertGenericParamList(gp);

    // Debugging of generic signature generation.
    if (Context.LangOpts.DebugGenericSignatures) {
      subscript->dumpRef(llvm::errs());
      llvm::errs() << "\n";
      llvm::errs() << "Generic signature: ";
      sig->print(llvm::errs());
      llvm::errs() << "\n";
      llvm::errs() << "Canonical generic signature: ";
      sig->getCanonicalSignature()->print(llvm::errs());
      llvm::errs() << "\n";
    }
  } else {
    // Inherit the signature of our environment.
    sig = subscript->getDeclContext()->getGenericSignatureOfContext();
  }

  CompleteGenericTypeResolver completeResolver(*this, sig);
  if (checkGenericSubscriptSignature(*this, nullptr, subscript, completeResolver))
    invalid = true;

  if (!invalid)
    invalid = checkProtocolSelfRequirements(sig, subscript, *this);

  if (invalid) {
    subscript->setInterfaceType(ErrorType::get(Context));
    subscript->setInvalid();
    // null doesn't mean error here: callers still expect the signature.
    return sig;
  }

  configureInterfaceType(subscript, sig);
  return sig;
}