From 017be57e9b51a576b2bf0e642f5fb8a28b39dc95 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 25 Jun 2025 18:55:45 -0400 Subject: [PATCH] Sema: Fix -warn-long-expression-type-checking when expression timer is turned off My change 983b75e1cf645be5133812094daaba2caca6ce36 broke -warn-long-expression-type-checking because now the ExpressionTimer is not instantiated by default and that entire code path is skipped. Change it so that if -warn-long-expression-type-checking is passed in, we still start the timer, we just don't ever consider it to have 'expired'. Fixes rdar://problem/152998878. --- include/swift/Sema/ConstraintSystem.h | 5 +++++ lib/Sema/ConstraintSystem.cpp | 15 ++++++++++++--- test/Constraints/warn_long_compile.swift | 5 ++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index d43ceabc98e..c45a3e1298f 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -249,6 +249,8 @@ private: bool PrintWarning; public: + const static unsigned NoLimit = (unsigned) -1; + ExpressionTimer(AnchorType Anchor, ConstraintSystem &CS, unsigned thresholdInSecs); @@ -274,6 +276,9 @@ public: /// Return the remaining process time in seconds until the /// threshold specified during construction is reached. unsigned getRemainingProcessTimeInSeconds() const { + if (ThresholdInSecs == NoLimit) + return NoLimit; + auto elapsed = unsigned(getElapsedProcessTimeInFractionalSeconds()); return elapsed >= ThresholdInSecs ? 0 : ThresholdInSecs - elapsed; } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index a25c415733d..ae5669929be 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -141,9 +141,18 @@ ConstraintSystem::~ConstraintSystem() { void ConstraintSystem::startExpressionTimer(ExpressionTimer::AnchorType anchor) { ASSERT(!Timer); - unsigned timeout = getASTContext().TypeCheckerOpts.ExpressionTimeoutThreshold; - if (timeout == 0) - return; + const auto &opts = getASTContext().TypeCheckerOpts; + unsigned timeout = opts.ExpressionTimeoutThreshold; + + // If either the timeout is set, or we're asked to emit warnings, + // start the timer. Otherwise, don't start the timer, it's needless + // overhead. + if (timeout == 0) { + if (opts.WarnLongExpressionTypeChecking == 0) + return; + + timeout = ExpressionTimer::NoLimit; + } Timer.emplace(anchor, *this, timeout); } diff --git a/test/Constraints/warn_long_compile.swift b/test/Constraints/warn_long_compile.swift index 3ae762edc85..037004fc28e 100644 --- a/test/Constraints/warn_long_compile.swift +++ b/test/Constraints/warn_long_compile.swift @@ -1,5 +1,4 @@ -// RUN: %target-typecheck-verify-swift -warn-long-expression-type-checking=1 -warn-long-function-bodies=1 -// REQUIRES: rdar44305428 +// RUN: %target-typecheck-verify-swift -warn-long-expression-type-checking=1 -solver-disable-shrink -warn-long-function-bodies=1 @_silgen_name("generic_foo") func foo(_ x: T) -> T @@ -8,6 +7,6 @@ func foo(_ x: Int) -> Int func test(m: Double) -> Int { // expected-warning@-1 {{global function 'test(m:)' took}} - return Int(foo(Float(m) / 20) * 20 - 2) + 10 + return ~(~(~(~(~(~(~(~(~(~(~(~(0)))))))))))) // expected-warning@-1 {{expression took}} }