Files
swift-mirror/lib/Sema/DerivedConformances.h
Doug Gregor 126e404fe5 Reimplement inference of type witnesses with a separate non-recursive pass.
Inference of type witnesses for associated types was previously
implemented as part of value witness matching in the constraint
solver. This led to a number of serious problems, including:
  - Recursion problems with the solver hunting for a type witness,
  which triggers more attemts to match value witnesses...
  - Arbitrarily crummy attempts to break the recursion causing
  type-check failures in fun places.
  - Ordering dependencies abound: different results depending on which
  value witnesses were satisfied first, failures because of the order
  in which we attempted to infer type witnesses, etc.

This new implementation of type witness inference uses a separate pass
that occurs whenever we're looking for any type witness, and solves
all of the type witnesses within a given conformance
simultaneously. We still look at potential value witnesses to infer
type witnesses, but we match them structurally, without invoking the
constraint solver.

There are a few caveats to this implementation:
  * We're not currently able to infer type witnesses from value
  witnesses that are global operators, so some tricks involving global
  operators (*cough* ~> *cough*) might require some manually-specified
  type witnesses. Note that the standard library doesn't include any
  such cases.

  * Yes, it's another kind of solver. At simple one, fortunately.

On the other hand, this implementation should be a big step forward:
  * It's far more predictable, order-invariant, and non-recursive.
  * The diagnostics for failures to infer type witnesses have
  improved.

Fixes rdar://problem/20598513.

Swift SVN r27616
2015-04-23 00:20:05 +00:00

118 lines
4.4 KiB
C++

//===--- DerivedConformances.h - Derived protocol conformance ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines entry points to synthesize compiler-derived conformances
// to certain known protocols.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SEMA_DERIVEDCONFORMANCES_H
#define SWIFT_SEMA_DERIVEDCONFORMANCES_H
#include <utility>
namespace swift {
class Decl;
class FuncDecl;
class NominalTypeDecl;
class Type;
class TypeChecker;
class ValueDecl;
namespace DerivedConformance {
/// Derive a RawRepresentable requirement for an enum, if it has a valid
/// raw type and raw values for all of its cases.
///
/// \returns the derived member, which will also be added to the type.
ValueDecl *deriveRawRepresentable(TypeChecker &tc,
NominalTypeDecl *type,
ValueDecl *requirement);
/// Derive a RawRepresentable type witness for an enum, if it has a valid
/// raw type and raw values for all of its cases.
///
/// \returns the derived member, which will also be added to the type.
Type deriveRawRepresentable(TypeChecker &tc,
NominalTypeDecl *type,
AssociatedTypeDecl *assocType);
/// Derive an Equatable requirement for a type.
///
/// Currently this is only implemented for enums without associated values.
/// Obvious generalizations would be to enums with all-Hashable payloads and to
/// structs with all-Hashable stored properties.
///
/// \returns the derived member, which will also be added to the type.
ValueDecl *deriveEquatable(TypeChecker &tc,
NominalTypeDecl *type,
ValueDecl *requirement);
/// Derive a Hashable requirement for a type.
///
/// Currently this is only implemented for enums without associated values.
/// Obvious generalizations would be to enums with all-Hashable payloads and to
/// structs with all-Hashable stored properties.
///
/// \returns the derived member, which will also be added to the type.
ValueDecl *deriveHashable(TypeChecker &tc,
NominalTypeDecl *type,
ValueDecl *requirement);
/// Derive an ErrorType requirement for an enum type.
///
/// A unique string representation of the enum type will be used as the domain
/// for members of the enum, and each case will have its own integer code.
///
/// \returns the derived member, which will also be added to the type.
ValueDecl *deriveErrorType(TypeChecker &tc,
NominalTypeDecl *type,
ValueDecl *requirement);
/// Insert an operator declaration associated with a nominal type. The
/// declaration is added at global scope.
void _insertOperatorDecl(NominalTypeDecl *scope, Decl *member);
/// Insert a declaration as a member of a nominal type. The declaration is
/// added at file scope as close as possible to the
template<typename SomeDecl>
inline SomeDecl *insertOperatorDecl(NominalTypeDecl *scope, SomeDecl *member) {
::swift::DerivedConformance::_insertOperatorDecl(scope, member);
return member;
}
/// Declare a getter for a derived property.
FuncDecl *declareDerivedPropertyGetter(TypeChecker &tc,
NominalTypeDecl *typeDecl,
Type contextType,
Type propertyInterfaceType,
Type propertyContextType);
/// Declare a read-only property with an existing getter.
std::pair<VarDecl *, PatternBindingDecl *>
declareDerivedReadOnlyProperty(TypeChecker &tc,
NominalTypeDecl *typeDecl,
Identifier name,
Type propertyInterfaceType,
Type propertyContextType,
FuncDecl *getterDecl);
/// Build a reference to the 'self' decl of a derived function.
DeclRefExpr *createSelfDeclRef(AbstractFunctionDecl *fn);
}
}
#endif