mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SE-0157: Enable recursive protocol constraints by default.
We don't know if they work in general, but specific cases of recursive protocol constraints are working, and enabling them doesn't break anything.
This commit is contained in:
@@ -1668,8 +1668,6 @@ ERROR(requires_generic_param_made_equal_to_concrete,none,
|
|||||||
(Type))
|
(Type))
|
||||||
ERROR(recursive_type_reference,none,
|
ERROR(recursive_type_reference,none,
|
||||||
"%0 %1 references itself", (DescriptiveDeclKind, Identifier))
|
"%0 %1 references itself", (DescriptiveDeclKind, Identifier))
|
||||||
ERROR(recursive_requirement_reference,none,
|
|
||||||
"type may not reference itself as a requirement",())
|
|
||||||
ERROR(recursive_same_type_constraint,none,
|
ERROR(recursive_same_type_constraint,none,
|
||||||
"same-type constraint %0 == %1 is recursive", (Type, Type))
|
"same-type constraint %0 == %1 is recursive", (Type, Type))
|
||||||
ERROR(recursive_superclass_constraint,none,
|
ERROR(recursive_superclass_constraint,none,
|
||||||
|
|||||||
@@ -426,10 +426,6 @@ private:
|
|||||||
template<typename F>
|
template<typename F>
|
||||||
void visitPotentialArchetypes(F f);
|
void visitPotentialArchetypes(F f);
|
||||||
|
|
||||||
void markPotentialArchetypeRecursive(PotentialArchetype *pa,
|
|
||||||
ProtocolDecl *proto,
|
|
||||||
const RequirementSource *source);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Construct a new generic signature builder.
|
/// Construct a new generic signature builder.
|
||||||
///
|
///
|
||||||
@@ -1358,23 +1354,20 @@ class GenericSignatureBuilder::PotentialArchetype {
|
|||||||
/// that share a name.
|
/// that share a name.
|
||||||
llvm::MapVector<Identifier, StoredNestedType> NestedTypes;
|
llvm::MapVector<Identifier, StoredNestedType> NestedTypes;
|
||||||
|
|
||||||
/// \brief Recursively conforms to itself.
|
|
||||||
unsigned IsRecursive : 1;
|
|
||||||
|
|
||||||
/// \brief Construct a new potential archetype for an unresolved
|
/// \brief Construct a new potential archetype for an unresolved
|
||||||
/// associated type.
|
/// associated type.
|
||||||
PotentialArchetype(PotentialArchetype *parent, Identifier name);
|
PotentialArchetype(PotentialArchetype *parent, Identifier name);
|
||||||
|
|
||||||
/// \brief Construct a new potential archetype for an associated type.
|
/// \brief Construct a new potential archetype for an associated type.
|
||||||
PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
|
PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
|
||||||
: parentOrBuilder(parent), identifier(assocType), IsRecursive(false)
|
: parentOrBuilder(parent), identifier(assocType)
|
||||||
{
|
{
|
||||||
assert(parent != nullptr && "Not an associated type?");
|
assert(parent != nullptr && "Not an associated type?");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Construct a new potential archetype for a concrete declaration.
|
/// \brief Construct a new potential archetype for a concrete declaration.
|
||||||
PotentialArchetype(PotentialArchetype *parent, TypeDecl *concreteDecl)
|
PotentialArchetype(PotentialArchetype *parent, TypeDecl *concreteDecl)
|
||||||
: parentOrBuilder(parent), identifier(concreteDecl), IsRecursive(false)
|
: parentOrBuilder(parent), identifier(concreteDecl)
|
||||||
{
|
{
|
||||||
assert(parent != nullptr && "Not an associated type?");
|
assert(parent != nullptr && "Not an associated type?");
|
||||||
}
|
}
|
||||||
@@ -1382,8 +1375,7 @@ class GenericSignatureBuilder::PotentialArchetype {
|
|||||||
/// \brief Construct a new potential archetype for a generic parameter.
|
/// \brief Construct a new potential archetype for a generic parameter.
|
||||||
PotentialArchetype(GenericSignatureBuilder *builder,
|
PotentialArchetype(GenericSignatureBuilder *builder,
|
||||||
GenericParamKey genericParam)
|
GenericParamKey genericParam)
|
||||||
: parentOrBuilder(builder), identifier(genericParam),
|
: parentOrBuilder(builder), identifier(genericParam)
|
||||||
IsRecursive(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1626,9 +1618,6 @@ public:
|
|||||||
return Type();
|
return Type();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIsRecursive() { IsRecursive = true; }
|
|
||||||
bool isRecursive() const { return IsRecursive; }
|
|
||||||
|
|
||||||
LLVM_ATTRIBUTE_DEPRECATED(
|
LLVM_ATTRIBUTE_DEPRECATED(
|
||||||
void dump() const,
|
void dump() const,
|
||||||
"only for use within the debugger");
|
"only for use within the debugger");
|
||||||
|
|||||||
@@ -210,9 +210,6 @@ namespace swift {
|
|||||||
/// Should we use \c ASTScope-based resolution for unqualified name lookup?
|
/// Should we use \c ASTScope-based resolution for unqualified name lookup?
|
||||||
bool EnableASTScopeLookup = false;
|
bool EnableASTScopeLookup = false;
|
||||||
|
|
||||||
/// Enable SE-0157: Recursive Protocol Constraints.
|
|
||||||
bool EnableRecursiveConstraints = false;
|
|
||||||
|
|
||||||
/// Whether to use the import as member inference system
|
/// Whether to use the import as member inference system
|
||||||
///
|
///
|
||||||
/// When importing a global, try to infer whether we can import it as a
|
/// When importing a global, try to infer whether we can import it as a
|
||||||
|
|||||||
@@ -109,9 +109,6 @@ def disable_target_os_checking :
|
|||||||
def enable_astscope_lookup : Flag<["-"], "enable-astscope-lookup">,
|
def enable_astscope_lookup : Flag<["-"], "enable-astscope-lookup">,
|
||||||
HelpText<"Enable ASTScope-based unqualified name lookup">;
|
HelpText<"Enable ASTScope-based unqualified name lookup">;
|
||||||
|
|
||||||
def enable_recursive_constraints : Flag<["-"], "enable-recursive-constraints">,
|
|
||||||
HelpText<"Enable SE-0157: Recursive Protocol Constraints">;
|
|
||||||
|
|
||||||
def print_clang_stats : Flag<["-"], "print-clang-stats">,
|
def print_clang_stats : Flag<["-"], "print-clang-stats">,
|
||||||
HelpText<"Print Clang importer statistics">;
|
HelpText<"Print Clang importer statistics">;
|
||||||
|
|
||||||
|
|||||||
@@ -1945,9 +1945,7 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
|
|||||||
// If we were asked for a complete, well-formed archetype, make sure we
|
// If we were asked for a complete, well-formed archetype, make sure we
|
||||||
// process delayed requirements if anything changed.
|
// process delayed requirements if anything changed.
|
||||||
SWIFT_DEFER {
|
SWIFT_DEFER {
|
||||||
ASTContext &ctx = assocType ? assocType->getASTContext()
|
if (kind == ArchetypeResolutionKind::CompleteWellFormed)
|
||||||
: concreteDecl->getASTContext();
|
|
||||||
if (ctx.LangOpts.EnableRecursiveConstraints)
|
|
||||||
getBuilder()->processDelayedRequirements();
|
getBuilder()->processDelayedRequirements();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3474,28 +3472,6 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementDirect(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local function to mark the given associated type as recursive,
|
|
||||||
// diagnosing it if this is the first such occurrence.
|
|
||||||
void GenericSignatureBuilder::markPotentialArchetypeRecursive(
|
|
||||||
PotentialArchetype *pa, ProtocolDecl *proto, const RequirementSource *source) {
|
|
||||||
if (pa->isRecursive())
|
|
||||||
return;
|
|
||||||
pa->setIsRecursive();
|
|
||||||
|
|
||||||
pa->addConformance(proto, source, *this);
|
|
||||||
if (!pa->getParent())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto assocType = pa->getResolvedAssociatedType();
|
|
||||||
if (!assocType || assocType->isInvalid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Diags.diagnose(assocType->getLoc(), diag::recursive_requirement_reference);
|
|
||||||
|
|
||||||
// Silence downstream errors referencing this associated type.
|
|
||||||
assocType->setInvalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstraintResult GenericSignatureBuilder::addInheritedRequirements(
|
ConstraintResult GenericSignatureBuilder::addInheritedRequirements(
|
||||||
TypeDecl *decl,
|
TypeDecl *decl,
|
||||||
UnresolvedType type,
|
UnresolvedType type,
|
||||||
@@ -3546,26 +3522,6 @@ ConstraintResult GenericSignatureBuilder::addInheritedRequirements(
|
|||||||
getFloatingSource(typeRepr, /*forInferred=*/true));
|
getFloatingSource(typeRepr, /*forInferred=*/true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decl->getASTContext().LangOpts.EnableRecursiveConstraints) {
|
|
||||||
// Check for direct recursion.
|
|
||||||
if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
|
|
||||||
auto proto = assocType->getProtocol();
|
|
||||||
if (auto inheritedProto = inheritedType->getAs<ProtocolType>()) {
|
|
||||||
if (inheritedProto->getDecl() == proto ||
|
|
||||||
inheritedProto->getDecl()->inheritsFrom(proto)) {
|
|
||||||
auto source = getFloatingSource(typeRepr, /*forInferred=*/false);
|
|
||||||
if (auto resolved = resolve(type, source)) {
|
|
||||||
if (auto pa = resolved->getPotentialArchetype()) {
|
|
||||||
markPotentialArchetypeRecursive(pa, proto,
|
|
||||||
source.getSource(pa));
|
|
||||||
return ConstraintResult::Conflicting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return addTypeRequirement(type, inheritedType,
|
return addTypeRequirement(type, inheritedType,
|
||||||
getFloatingSource(typeRepr,
|
getFloatingSource(typeRepr,
|
||||||
/*forInferred=*/false),
|
/*forInferred=*/false),
|
||||||
|
|||||||
@@ -1014,8 +1014,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Opts.EnableASTScopeLookup |= Args.hasArg(OPT_enable_astscope_lookup);
|
Opts.EnableASTScopeLookup |= Args.hasArg(OPT_enable_astscope_lookup);
|
||||||
Opts.EnableRecursiveConstraints |=
|
|
||||||
Args.hasArg(OPT_enable_recursive_constraints);
|
|
||||||
Opts.DebugConstraintSolver |= Args.hasArg(OPT_debug_constraints);
|
Opts.DebugConstraintSolver |= Args.hasArg(OPT_debug_constraints);
|
||||||
Opts.EnableConstraintPropagation |= Args.hasArg(OPT_propagate_constraints);
|
Opts.EnableConstraintPropagation |= Args.hasArg(OPT_propagate_constraints);
|
||||||
Opts.IterativeTypeChecker |= Args.hasArg(OPT_iterative_type_checker);
|
Opts.IterativeTypeChecker |= Args.hasArg(OPT_iterative_type_checker);
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ extension Dictionary {
|
|||||||
|
|
||||||
// rdar://problem/19245317
|
// rdar://problem/19245317
|
||||||
protocol P {
|
protocol P {
|
||||||
associatedtype T: P // expected-error{{type may not reference itself as a requirement}}
|
associatedtype T: P
|
||||||
}
|
}
|
||||||
|
|
||||||
struct S<A: P> {
|
struct S<A: P> {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// -----
|
// -----
|
||||||
|
|
||||||
protocol Foo {
|
protocol Foo {
|
||||||
associatedtype Bar : Foo // expected-error{{type may not reference itself as a requirement}}
|
associatedtype Bar : Foo
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Oroborous : Foo {
|
struct Oroborous : Foo {
|
||||||
@@ -13,7 +13,7 @@ struct Oroborous : Foo {
|
|||||||
// -----
|
// -----
|
||||||
|
|
||||||
protocol P {
|
protocol P {
|
||||||
associatedtype A : P // expected-error{{type may not reference itself as a requirement}}
|
associatedtype A : P
|
||||||
}
|
}
|
||||||
|
|
||||||
struct X<T: P> {
|
struct X<T: P> {
|
||||||
@@ -26,7 +26,7 @@ func f<T : P>(_ z: T) {
|
|||||||
// -----
|
// -----
|
||||||
|
|
||||||
protocol PP2 {
|
protocol PP2 {
|
||||||
associatedtype A : P2 = Self // expected-error{{type may not reference itself as a requirement}}
|
associatedtype A : P2 = Self
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol P2 : PP2 {
|
protocol P2 : PP2 {
|
||||||
@@ -41,13 +41,13 @@ struct Y2 : P2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func f<T : P2>(_ z: T) {
|
func f<T : P2>(_ z: T) {
|
||||||
_ = X2<T.A>() // expected-error{{type 'T.A' does not conform to protocol 'P2'}}
|
_ = X2<T.A>()
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
protocol P3 {
|
protocol P3 {
|
||||||
associatedtype A: P4 = Self // expected-error{{type may not reference itself as a requirement}}
|
associatedtype A: P4 = Self
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol P4 : P3 {}
|
protocol P4 : P3 {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// RUN: %target-typecheck-verify-swift -enable-recursive-constraints
|
// RUN: %target-typecheck-verify-swift
|
||||||
|
|
||||||
protocol P {
|
protocol P {
|
||||||
associatedtype Assoc : P
|
associatedtype Assoc : P
|
||||||
|
|||||||
Reference in New Issue
Block a user