Fix: Resolve IntelliSense/linter false positive for type_is_unformattable_for#4634
Fix: Resolve IntelliSense/linter false positive for type_is_unformattable_for#4634subashc2023 wants to merge 1 commit intofmtlib:masterfrom subashc2023:fix/type_is_unformattable_for-linter-error
Conversation
…able_for - Make type_is_unformattable_for a complete struct definition - Replace variable declaration with static_assert for compile-time errors - Fixes false positive IDE errors while maintaining original behavior Fixes issue where IDEs like VS Code show red error indicators in file tree for projects using fmt, even though compilation succeeds.
There was a problem hiding this comment.
Pull request overview
This PR fixes IntelliSense and linter false positives caused by an intentionally undefined struct type_is_unformattable_for that was used to trigger compile-time errors. The solution defines the struct as empty and replaces the variable declaration with a static_assert to maintain the compile-time error behavior while satisfying linters.
Key Changes:
- Define
type_is_unformattable_foras an empty struct instead of leaving it undefined - Replace the unused variable declaration with a
static_assertthat provides clearer error messages
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // This type is intentionally undefined, only used for errors. | ||
| template <typename T, typename Char> struct type_is_unformattable_for; | ||
| template <typename T, typename Char> struct type_is_unformattable_for { | ||
| // Intentionally incomplete - causes compile error when instantiated | ||
| }; |
There was a problem hiding this comment.
The comment and struct implementation are contradictory. The comment on line 2150 says "This type is intentionally undefined" but the struct is now fully defined with an empty body. The comment on line 2152 says "Intentionally incomplete" but an empty struct is actually a complete type in C++.
Consider updating the comments to accurately reflect the new implementation. For example:
- Line 2150: "This type is intentionally defined but unused, only for avoiding linter errors."
- Line 2152: Remove this comment or change to explain that the struct exists only to satisfy linters while compile-time errors are generated via static_assert at usage sites.
| static_assert(sizeof(T) != sizeof(T), | ||
| "Type is not formattable. Provide a formatter<T> specialization."); |
There was a problem hiding this comment.
The static_assert condition sizeof(T) != sizeof(T) is technically always false, which is the intended behavior. However, this is a known pattern that may be deprecated in C++23 and beyond. Consider using std::false_type::value or a more explicit dependent false pattern like sizeof(T) && false to make the intent clearer and ensure future compatibility.
Additionally, consider whether the condition should be dependent on the template parameter to avoid potential issues with immediate evaluation. A safer alternative would be:
template<typename> struct always_false : std::false_type {};
static_assert(always_false<T>::value, "Type is not formattable. Provide a formatter<T> specialization.");|
This change is incorrect and contradicts the comment right next to the changed type. |
Fix: Resolve IntelliSense/linter false positive for
type_is_unformattable_forProblem
The
type_is_unformattable_forstruct is intentionally left undefined to trigger compile-time errors when attempting to format types without formatters. However, this causes false positive errors in IDEs like VS Code that use IntelliSense or clangd, which flag the undefined struct as an error.Impact
Example
In VS Code, when opening a project using fmt (or spdlog which bundles fmt), the file tree shows a red dot on the submodule/folder containing
base.h, indicating errors even though the code compiles successfully.Solution
Make
type_is_unformattable_fora complete (but empty) struct definition instead of leaving it undefined. Replace the variable declaration with a type alias and add astatic_assertto maintain the compile-time error behavior.Changes
Before:
After:
The
static_assert(sizeof(T) != sizeof(T), ...)always evaluates to false, ensuring a compile-time error while the struct definition satisfies the linter.Benefits
static_assertand type alias still trigger appropriate errors when unformattable types are usedstatic_assertprovides a clear, actionable error messageTesting
Files Changed
include/fmt/base.h(lines ~2150 and ~2314)Related
This issue affects any project using fmt (or libraries that bundle fmt like spdlog) when viewed in VS Code or other IDEs with IntelliSense/clangd support.