Skip to content

Commit d79d0b3

Browse files
Fix type inference issue in LinearCache initialization with LinearVerbosity
This commit resolves a type stability issue in the `init` function where the compiler could not infer a concrete type for the `LinearVerbosity` parameter in `LinearCache`, causing `@inferred` tests to fail. Changes: - Added `Base.@constprop :aggressive` to `__init` function to enable aggressive constant propagation for better type inference - Refactored verbose parameter processing into type-stable helper methods `_process_verbose` that use method dispatch - Made `LinearVerbosity(Standard())` constructor explicit with concrete argument types instead of calling `LinearVerbosity()` - Added `@inline` annotation to preset constructor for better optimization The fix ensures that when `verbose=true` (the default), the compiler can determine the concrete `LinearVerbosity` type at compile time, eliminating the type instability that caused the test failure. Fixes the CI error: ``` return type LinearCache{..., LinearVerbosity{...}, ...} does not match inferred return type LinearCache{..., _A<:LinearVerbosity, ...} ``` All tests pass with this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6a49ebe commit d79d0b3

File tree

2 files changed

+44
-19
lines changed

2 files changed

+44
-19
lines changed

src/common.jl

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,28 @@ default_alias_b(::AbstractSparseFactorization, ::Any, ::Any) = true
232232

233233
DEFAULT_PRECS(A, p) = IdentityOperator(size(A)[1]), IdentityOperator(size(A)[2])
234234

235+
# Helper functions for type-stable verbose conversion
236+
@inline function _process_verbose(verbose::Bool)
237+
# Type-stable processing of boolean verbose parameter
238+
if verbose
239+
verbose_spec = LinearVerbosity(SciMLLogging.Standard())
240+
init_cache_verb = verbose
241+
else
242+
verbose_spec = LinearVerbosity(SciMLLogging.None())
243+
init_cache_verb = verbose
244+
end
245+
return verbose_spec, init_cache_verb
246+
end
247+
248+
@inline function _process_verbose(verbose::SciMLLogging.AbstractVerbosityPreset)
249+
verbose_spec = LinearVerbosity(verbose)
250+
return verbose_spec, verbose_spec
251+
end
252+
253+
@inline function _process_verbose(verbose::LinearVerbosity)
254+
return verbose, verbose
255+
end
256+
235257
"""
236258
__init_u0_from_Ab(A, b)
237259
@@ -261,7 +283,7 @@ function SciMLBase.init(prob::LinearProblem, alg::SciMLLinearSolveAlgorithm, arg
261283
__init(prob, alg, args...; kwargs...)
262284
end
263285

264-
function __init(prob::LinearProblem, alg::SciMLLinearSolveAlgorithm,
286+
Base.@constprop :aggressive function __init(prob::LinearProblem, alg::SciMLLinearSolveAlgorithm,
265287
args...;
266288
alias = LinearAliasSpecifier(),
267289
abstol = default_tol(real(eltype(prob.b))),
@@ -324,22 +346,9 @@ function __init(prob::LinearProblem, alg::SciMLLinearSolveAlgorithm,
324346
copy(A)
325347
end
326348

327-
if verbose isa Bool
328-
# @warn "Using `true` or `false` for `verbose` is being deprecated. Please use a `LinearVerbosity` type to specify verbosity settings.
329-
# For details see the verbosity section of the common solver options documentation page."
330-
init_cache_verb = verbose
331-
if verbose
332-
verbose_spec = LinearVerbosity()
333-
else
334-
verbose_spec = LinearVerbosity(SciMLLogging.None())
335-
end
336-
elseif verbose isa SciMLLogging.AbstractVerbosityPreset
337-
verbose_spec = LinearVerbosity(verbose)
338-
init_cache_verb = verbose_spec
339-
else
340-
verbose_spec = verbose
341-
init_cache_verb = verbose_spec
342-
end
349+
# @warn "Using `true` or `false` for `verbose` is being deprecated. Please use a `LinearVerbosity` type to specify verbosity settings.
350+
# For details see the verbosity section of the common solver options documentation page."
351+
verbose_spec, init_cache_verb = _process_verbose(verbose)
343352

344353
b = if issparsematrix(b) && !(A isa Diagonal)
345354
Array(b) # the solution to a linear solve will always be dense!

src/verbosity.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ end
159159
# Constructor for verbosity presets following the hierarchical levels:
160160
# None < Minimal < Standard < Detailed < All
161161
# Each level includes all messages from levels below it plus additional ones
162-
function LinearVerbosity(verbose::AbstractVerbosityPreset)
162+
@inline function LinearVerbosity(verbose::AbstractVerbosityPreset)
163163
if verbose isa Minimal
164164
# Minimal: Only fatal errors and critical warnings (BLAS errors/invalid args)
165165
LinearVerbosity(
@@ -182,7 +182,23 @@ function LinearVerbosity(verbose::AbstractVerbosityPreset)
182182
)
183183
elseif verbose isa Standard
184184
# Standard: Everything from Minimal + non-fatal warnings
185-
LinearVerbosity()
185+
LinearVerbosity(
186+
Silent(),
187+
Silent(),
188+
Silent(),
189+
Silent(),
190+
CustomLevel(1), # WARN_LEVEL in KrylovKit.jl
191+
Silent(),
192+
InfoLevel(),
193+
Silent(),
194+
ErrorLevel(),
195+
ErrorLevel(),
196+
Silent(),
197+
Silent(),
198+
Silent(),
199+
WarnLevel(),
200+
WarnLevel(),
201+
WarnLevel())
186202
elseif verbose isa Detailed
187203
# Detailed: Everything from Standard + debugging/solver behavior
188204
LinearVerbosity(

0 commit comments

Comments
 (0)