//===--- ResilienceDiagnostics.cpp - Resilience Inlineability Diagnostics -===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements diagnostics for @inlineable.
//
//===----------------------------------------------------------------------===//

#include "TypeChecker.h"
#include "swift/AST/Attr.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/DeclContext.h"
using namespace swift;

enum FragileFunctionKind : unsigned {
  Transparent,
  InlineAlways,
  Inlineable,
  DefaultArgument
};

FragileFunctionKind getFragileFunctionKind(const DeclContext *DC) {
  for (; DC->isLocalContext(); DC = DC->getParent()) {
    if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(DC))
      if (DAI->getResilienceExpansion() == ResilienceExpansion::Minimal)
        return FragileFunctionKind::DefaultArgument;

    if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
      // If the function is a nested function, we will serialize its body if
      // we serialize the parent's body.
      if (AFD->getDeclContext()->isLocalContext())
        continue;

      // Bodies of public transparent and always-inline functions are
      // serialized, so use conservative access patterns.
      if (AFD->isTransparent())
        return FragileFunctionKind::Transparent;

      if (AFD->getAttrs().hasAttribute<InlineableAttr>())
        return FragileFunctionKind::Inlineable;

      if (auto attr = AFD->getAttrs().getAttribute<InlineAttr>())
        if (attr->getKind() == InlineKind::Always)
          return FragileFunctionKind::InlineAlways;

      // If a property or subscript is @_inlineable, the accessors are
      // @_inlineable also.
      if (auto FD = dyn_cast<FuncDecl>(AFD))
        if (auto *ASD = FD->getAccessorStorageDecl())
          if (ASD->getAttrs().getAttribute<InlineableAttr>())
            return FragileFunctionKind::Inlineable;
    }
  }

  llvm_unreachable("Context is not nested inside a fragile function");
}

void TypeChecker::diagnoseInlineableLocalType(const NominalTypeDecl *NTD) {
  auto *DC = NTD->getDeclContext();
  auto expansion = DC->getResilienceExpansion();
  if (expansion == ResilienceExpansion::Minimal) {
    diagnose(NTD, diag::local_type_in_inlineable_function,
             NTD->getFullName(), getFragileFunctionKind(DC));
  }
}

bool TypeChecker::diagnoseInlineableDeclRef(SourceLoc loc,
                                            const ValueDecl *D,
                                            const DeclContext *DC) {
  auto expansion = DC->getResilienceExpansion();

  // Internal declarations referenced from non-inlineable contexts are OK.
  if (expansion == ResilienceExpansion::Maximal)
    return false;

  // Local declarations are OK.
  if (D->getDeclContext()->isLocalContext())
    return false;

  // Type parameters are OK.
  if (isa<AbstractTypeParamDecl>(D))
    return false;

  // Public declarations are OK.
  if (D->getEffectiveAccess(/*forLinkage=*/false) >= Accessibility::Public)
    return false;

  // Enum cases are handled as part of their containing enum.
  if (isa<EnumElementDecl>(D))
    return false;
    
  // Protocol requirements are not versioned because there's no
  // global entry point.
  if (isa<ProtocolDecl>(D->getDeclContext()) &&
      D->isProtocolRequirement())
    return false;

  // FIXME: Figure out what to do with typealiases
  if (isa<TypeAliasDecl>(D))
    return false;

  diagnose(loc, diag::resilience_decl_unavailable,
           D->getDescriptiveKind(), D->getFullName(),
           D->getFormalAccessScope().accessibilityForDiagnostics(),
           getFragileFunctionKind(DC));
  diagnose(D, diag::resilience_decl_declared_here,
           D->getDescriptiveKind(), D->getFullName());
  return true;
}

void TypeChecker::diagnoseResilientConstructor(ConstructorDecl *ctor) {
  auto nominalDecl = ctor->getDeclContext()
    ->getAsNominalTypeOrNominalTypeExtensionContext();

  // These restrictions only apply to concrete types, and not protocol
  // extensions.
  if (isa<ProtocolDecl>(nominalDecl))
    return;

  bool isDelegating =
      (ctor->getDelegatingOrChainedInitKind(&Diags) ==
       ConstructorDecl::BodyInitKind::Delegating);

  if (!isDelegating &&
      !nominalDecl->hasFixedLayout(ctor->getParentModule(),
                                   ctor->getResilienceExpansion())) {
    if (ctor->getResilienceExpansion() == ResilienceExpansion::Minimal) {
      // An @_inlineable designated initializer defined in a resilient type
      // cannot initialize stored properties directly, and must chain to
      // another initializer.
      diagnose(ctor->getLoc(),
               isa<ClassDecl>(nominalDecl)
                 ? diag::class_designated_init_inlineable_resilient
                 : diag::designated_init_inlineable_resilient,
               nominalDecl->getDeclaredInterfaceType(),
               getFragileFunctionKind(ctor));
    } else {
      // A designated initializer defined on an extension of a resilient
      // type from a different resilience domain cannot initialize stored
      // properties directly, and must chain to another initializer.
      diagnose(ctor->getLoc(),
               diag::designated_init_in_extension_resilient,
               nominalDecl->getDeclaredInterfaceType());
    }
  }
}
