RequirementMachine: Add two more completion termination checks for concrete type requirements

The concrete nesting limit, which defaults to 30, catches
things like A == G<A>. However, with something like
A == (A, A), you end up with an exponential problem size
before you hit the limit.

Add two new limits.

The first is the total size of the concrete type, counting
all leaves, which defaults to 4000. It can be set with the
-requirement-machine-max-concrete-size= frontend flag.

The second avoids an assertion in addTypeDifference() which
can be hit if a certain counter overflows before any other
limit is breached. This also defaults to 4000 and can be set
with the -requirement-machine-max-type-differences= frontend flag.
This commit is contained in:
Slava Pestov
2025-06-17 15:51:45 -04:00
parent d22a24744f
commit 7f8175b3da
17 changed files with 191 additions and 34 deletions

View File

@@ -1769,6 +1769,28 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}
if (const Arg *A = Args.getLastArg(OPT_requirement_machine_max_concrete_size)) {
unsigned limit;
if (StringRef(A->getValue()).getAsInteger(10, limit)) {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
A->getAsString(Args), A->getValue());
HadError = true;
} else {
Opts.RequirementMachineMaxConcreteSize = limit;
}
}
if (const Arg *A = Args.getLastArg(OPT_requirement_machine_max_type_differences)) {
unsigned limit;
if (StringRef(A->getValue()).getAsInteger(10, limit)) {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
A->getAsString(Args), A->getValue());
HadError = true;
} else {
Opts.RequirementMachineMaxTypeDifferences = limit;
}
}
if (const Arg *A = Args.getLastArg(OPT_requirement_machine_max_split_concrete_equiv_class_attempts)) {
unsigned limit;
if (StringRef(A->getValue()).getAsInteger(10, limit)) {