Repository: apple/swift
File: lib/AST/Decl.cpp (C++)

Code before:
  Bits.VarDecl.IsPropertyWrapperBackingProperty = false;
  Bits.VarDecl.IsTopLevelGlobal = false;
  Bits.VarDecl.NoAttachedPropertyWrappers = false;
  Bits.VarDecl.NoPropertyWrapperAuxiliaryVariables = false;
}

VarDecl *VarDecl::createImported(bool isStatic, Introducer introducer,
                                 SourceLoc nameLoc, Identifier name,
                                 DeclContext *dc, Type interfaceType,
                                 ClangNode clangNode) {
  auto &ctx = dc->getASTContext();

  auto *V = new (ctx) VarDecl(isStatic, introducer, nameLoc, name, dc);

  V->setAccess(swift::AccessLevel::Public);
  V->setInterfaceType(interfaceType);

  V->addAttribute(new (ctx) TransparentAttr(/*Implicit*/ true));
  V->addAttribute(new (ctx) InlineAttr(InlineKind::AlwaysUnderscored));
  V->addAttribute(new (ctx) PreconcurrencyAttr(/*IsImplicit=*/true));

  V->setSynthesized();
  V->setClangNode(clangNode);

  return V;
}

Type VarDecl::getTypeInContext() const {
  return getDeclContext()->mapTypeIntoEnvironment(getInterfaceType());
}

/// Translate an "is mutable" bit into a StorageMutability value.
static StorageMutability storageIsMutable(bool isMutable) {
  return isMutable ? StorageMutability::Mutable
                   : StorageMutability::Immutable;
}

/// Returns whether the var is settable in the specified context: this
/// is either because it is a stored var, because it has a custom setter, or
/// is a let member in an initializer.
StorageMutability
VarDecl::mutability(const DeclContext *UseDC,
                    std::optional<const DeclRefExpr *> base) const {
  // Parameters are settable or not depending on their ownership convention.
  if (auto *PD = dyn_cast<ParamDecl>(this))
    return storageIsMutable(!PD->isImmutableInFunctionBody());

  // If this is a 'var' decl, then we're settable if we have storage or a
  // setter.
  if (!isLet()) {
    if (hasInitAccessor()) {

Review comment (suggestion):
I think that making this a (static) freestanding function in `ImportMacro.cpp` is better. This doesn't give you a generic constructor for a `VarDecl` (e.g. you cannot control the attributes nor the access level).

Code after:
  Bits.VarDecl.IsPropertyWrapperBackingProperty = false;
  Bits.VarDecl.IsTopLevelGlobal = false;
  Bits.VarDecl.NoAttachedPropertyWrappers = false;
  Bits.VarDecl.NoPropertyWrapperAuxiliaryVariables = false;
}

Type VarDecl::getTypeInContext() const {
  return getDeclContext()->mapTypeIntoEnvironment(getInterfaceType());
}

/// Translate an "is mutable" bit into a StorageMutability value.
static StorageMutability storageIsMutable(bool isMutable) {
  return isMutable ? StorageMutability::Mutable
                   : StorageMutability::Immutable;
}

/// Returns whether the var is settable in the specified context: this
/// is either because it is a stored var, because it has a custom setter, or
/// is a let member in an initializer.
StorageMutability
VarDecl::mutability(const DeclContext *UseDC,
                    std::optional<const DeclRefExpr *> base) const {
  // Parameters are settable or not depending on their ownership convention.
  if (auto *PD = dyn_cast<ParamDecl>(this))
    return storageIsMutable(!PD->isImmutableInFunctionBody());

  // If this is a 'var' decl, then we're settable if we have storage or a
  // setter.
  if (!isLet()) {
    if (hasInitAccessor()) {
      if (auto *ctor = dyn_cast_or_null<ConstructorDecl>(UseDC)) {
        // If we're referencing 'self.', it's mutable.
        if (!base ||
            (*base && ctor->getImplicitSelfDecl() == (*base)->getDecl()))
          return StorageMutability::Mutable;

        return storageIsMutable(supportsMutation());
      }
    }

    return storageIsMutable(supportsMutation());
  }

  // Static 'let's are always immutable.
  if (isStatic()) {
    return StorageMutability::Immutable;
  }

  //
  // All the remaining logic handles the special cases where you can
  // assign a 'let'.