ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) {
  // Conformance can't be synthesized in an extension.
  if (checkAndDiagnoseDisallowedContext(requirement))
    return nullptr;

  // Check that we can actually derive CaseIterable for this type.
  if (!canDeriveConformance(Nominal))
    return nullptr;

  Type returnTy;
  Identifier propertyId;

  if (requirement->getBaseName() == TC.Context.Id_allCases) {
      returnTy = computeAllCasesType(Nominal);
      propertyId = TC.Context.Id_allCases;
  } else if (requirement->getBaseName() == TC.Context.Id_first) {
      returnTy = Nominal->getDeclaredInterfaceType();
      propertyId = TC.Context.Id_first;
  } else {
      TC.diagnose(requirement->getLoc(), diag::broken_case_iterable_requirement);
      return nullptr;
  }

  VarDecl *propDecl;
  PatternBindingDecl *pbDecl;
  std::tie(propDecl, pbDecl) =
      declareDerivedProperty(propertyId, returnTy, returnTy,
                             /*isStatic=*/true, /*isFinal=*/true);

  if (requirement->getBaseName() == TC.Context.Id_allCases) {
    getterDecl->setBodySynthesizer(&deriveCaseIterable_enum_getter);
  } else {
    getterDecl->setBodySynthesizer(&deriveCaseIterable_first);
  }

  addMembersToConformanceContext({getterDecl, propDecl, pbDecl});

  return propDecl;
}