blob: 598fbb69b847bea5202db92df12f855b4c06ae10 [file] [log] [blame]
//===--- ITCType.cpp - Iterative Type Checker for Types -------------------===//
//
// 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 the portions of the IterativeTypeChecker
// class that involve types.
//
//===----------------------------------------------------------------------===//
#include "GenericTypeResolver.h"
#include "TypeChecker.h"
#include "swift/Sema/IterativeTypeChecker.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
using namespace swift;
//===----------------------------------------------------------------------===//
// Type resolution.
//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isResolveTypeReprSatisfied(
std::tuple<TypeRepr *, DeclContext *, unsigned> payload) {
auto typeRepr = std::get<0>(payload);
auto options = static_cast<TypeResolutionOptions>(std::get<2>(payload));
// FIXME: Introduce a bit indicating when everything in the TypeRepr
// has been name-bound, which indicates that we can always compute a
// structural type.
struct FindUnboundTypeRepr : public ASTWalker {
TypeResolutionOptions Options;
// Whether we've found an unbound type.
bool HasUnbound = false;
FindUnboundTypeRepr(TypeResolutionOptions options) : Options(options) { }
bool walkToTypeReprPre(TypeRepr *T) override {
// If we already found an unbound type, we're done.
if (HasUnbound) return false;
if (auto ident = dyn_cast<ComponentIdentTypeRepr>(T)) {
if (!ident->isBound()) {
HasUnbound = true;
return false;
}
// If we're only looking to resolve the structure of the type,
// don't walk into generic arguments. They don't affect the
// structure.
if (Options.contains(TypeResolutionFlags::ResolveStructure) &&
isa<GenericIdentTypeRepr>(ident))
return false;
}
// Keep walking.
return true;
}
} findUnboundTypeRepr(options);
typeRepr->walk(findUnboundTypeRepr);
return findUnboundTypeRepr.HasUnbound;
}
void IterativeTypeChecker::processResolveTypeRepr(
std::tuple<TypeRepr *, DeclContext *, unsigned> payload,
UnsatisfiedDependency unsatisfiedDependency) {
auto typeRepr = std::get<0>(payload);
auto dc = std::get<1>(payload);
auto options = static_cast<TypeResolutionOptions>(std::get<2>(payload));
// FIXME: TypeChecker::resolveType() is mostly non-ad-hoc-recursive
// when given an UnsatisfiedDependency.
TC.resolveType(typeRepr, dc, options, nullptr, &unsatisfiedDependency);
}
bool IterativeTypeChecker::breakCycleForResolveTypeRepr(
std::tuple<TypeRepr *, DeclContext *, unsigned> payload) {
std::get<0>(payload)->setInvalid();
return true;
}