Skip to main content

Explains and proposes fixes for compile-time errors for many programming languages.

Project description

CWhy

by Emery Berger, Nicolas van Kempen, and Bryce Adelstein Lelbach.

PyPI downloads downloads/month

("See why")

Explains and suggests fixes for compiler error messages for a wide range of programming languages, including C, C++, C#, Go, Java, LaTeX, PHP, Python, Ruby, Rust, Swift, and TypeScript.

Installation

Note

CWhy needs to be connected to an OpenAI account. Your account will need to have a positive balance for this to work (check your balance). Get a key here.

CWhy currently defaults to GPT-4, and falls back to GPT-3.5-turbo if a request error occurs. For the newest and best model (GPT-4) to work, you need to have purchased at least $1 in credits (if your API account was created before August 13, 2023) or $0.50 (if you have a newer API account).

Once you have an API key, set it as an environment variable called OPENAI_API_KEY.

# On Linux/MacOs.
export OPENAI_API_KEY=<your-api-key>

# On Windows.
$env:OPENAI_API_KEY=<your-api-key>
python3 -m pip install cwhy

Usage

Linux/MacOS

The wrapper mode is now default and mandatory, with a slightly modified interface. CWhy can either be used standalone by passing the full command after the triple dashes ---, or as part of a build tool by creating a short executable script wrapping the compiler command.

# Invoking the compiler directly.
% cwhy --- g++ mycode.cpp

# Using CWhy with Java and an increased timeout.
% cwhy --timeout 180 --- javac MyCode.java

# Invoking with GNU Make, using GPT-3.5.
% CXX=`cwhy --llm=gpt-3.5-turbo --wrapper --- c++` make

# Invoking with CMake, using GPT-4 and clang++.
% cmake -DCMAKE_CXX_COMPILER=`cwhy --llm=gpt-4 --wrapper --- clang++` ...

When running a configuration tool such as CMake or Autoconf, this may greatly increase configuration time, as these tools will occasionally invoke the compiler to check for features, which will fail and invoke CWhy unnecessarily if not available on the machine. To circumvent this, CWHY_DISABLE can be set in the environment to disable CWhy at configuration time.

% CWHY_DISABLE='ON' cmake -DCMAKE_CXX_COMPILER=`cwhy --wrapper --- c++` ...

Windows

Windows support has been tested using Powershell. On the command line, using Ninja is required as MSBuild / .vcxproj will override any option set.

% $env:CWHY_DISABLE='ON'
% cmake -G Ninja -DCMAKE_CXX_COMPILER="$(python -m cwhy --wrapper --- cl)"  ...
% $env:CWHY_DISABLE=''

Options

These options can be displayed with cwhy --help.

  • --llm: pick a specific OpenAI LLM. CWhy has been tested with gpt-3.5-turbo and gpt-4.
  • --timeout: pick a different timeout than the default for API calls.
  • --show-prompt (debug): print prompts before calling the API.

Examples

C++

This highlighted example is missing-hash.cpp, which is one of the first cases we experimented with.

Expand to see the original (pretty obscure) error message:
% clang++ --std=c++20 -c missing-hash.cpp
missing-hash.cpp:13:45: error: call to implicitly-deleted default constructor of 'std::unordered_set<std::pair<int, int>>'
    std::unordered_set<std::pair<int, int>> visited;
                                            ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unordered_set.h:135:7: note: explicitly defaulted function was implicitly deleted here
      unordered_set() = default;
      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unordered_set.h:100:18: note: default constructor of 'unordered_set<std::pair<int, int>>' is implicitly deleted because field '_M_h' has a deleted default constructor
      _Hashtable _M_h;
                 ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:451:7: note: explicitly defaulted function was implicitly deleted here
      _Hashtable() = default;
      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:174:7: note: default constructor of '_Hashtable<std::pair<int, int>, std::pair<int, int>, std::allocator<std::pair<int, int>>, std::__detail::_Identity, std::equal_to<std::pair<int, int>>, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, true, true>>' is implicitly deleted because base class '__detail::_Hashtable_base<pair<int, int>, pair<int, int>, _Identity, equal_to<pair<int, int>>, hash<pair<int, int>>, _Mod_range_hashing, _Default_ranged_hash, _Hashtable_traits<true, true, true>>' has a deleted default constructor
    : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1791:5: note: explicitly defaulted function was implicitly deleted here
    _Hashtable_base() = default;
    ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1726:5: note: default constructor of '_Hashtable_base<std::pair<int, int>, std::pair<int, int>, std::__detail::_Identity, std::equal_to<std::pair<int, int>>, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, true, true>>' is implicitly deleted because base class '_Hash_code_base<pair<int, int>, pair<int, int>, _Identity, hash<pair<int, int>>, _Mod_range_hashing, _Default_ranged_hash, _Hashtable_traits<true, true, true>::__hash_cached::value>' has a deleted default constructor
  : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
    ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1368:7: note: explicitly defaulted function was implicitly deleted here
      _Hash_code_base() = default;
      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1344:7: note: default constructor of '_Hash_code_base<std::pair<int, int>, std::pair<int, int>, std::__detail::_Identity, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>' is implicitly deleted because base class '_Hashtable_ebo_helper<1, hash<pair<int, int>>>' has a deleted default constructor
      private _Hashtable_ebo_helper<1, _H1>,
      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1112:7: note: explicitly defaulted function was implicitly deleted here
      _Hashtable_ebo_helper() = default;
      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1110:7: note: default constructor of '_Hashtable_ebo_helper<1, std::hash<std::pair<int, int>>, true>' is implicitly deleted because base class 'std::hash<std::pair<int, int>>' has a deleted default constructor
    : private _Tp
      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/functional_hash.h:101:19: note: default constructor of 'hash<std::pair<int, int>>' is implicitly deleted because base class '__hash_enum<pair<int, int>>' has no default constructor
    struct hash : __hash_enum<_Tp>
                  ^
In file included from missing-hash.cpp:1:
In file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:61:
In file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/unordered_map:46:
In file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:35:
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1377:2: error: static assertion failed due to requirement 'std::__is_invocable<const std::hash<std::pair<int, int>> &, const std::pair<int, int> &>{}': hash function must be invocable with an argument of key type
        static_assert(__is_invocable<const _H1&, const _Key&>{},
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:1675:29: note: in instantiation of member function 'std::__detail::_Hash_code_base<std::pair<int, int>, std::pair<int, int>, std::__detail::_Identity, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>::_M_hash_code' requested here
        __hash_code __code = this->_M_hash_code(__k);
                                   ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:788:11: note: in instantiation of function template specialization 'std::_Hashtable<std::pair<int, int>, std::pair<int, int>, std::allocator<std::pair<int, int>>, std::__detail::_Identity, std::equal_to<std::pair<int, int>>, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, true, true>>::_M_emplace<const std::pair<int, int> &>' requested here
        { return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
                 ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unordered_set.h:377:16: note: in instantiation of function template specialization 'std::_Hashtable<std::pair<int, int>, std::pair<int, int>, std::allocator<std::pair<int, int>>, std::__detail::_Identity, std::equal_to<std::pair<int, int>>, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, true, true>>::emplace<const std::pair<int, int> &>' requested here
        { return _M_h.emplace(std::forward<_Args>(__args)...); }
                      ^
missing-hash.cpp:20:44: note: in instantiation of function template specialization 'std::unordered_set<std::pair<int, int>>::emplace<const std::pair<int, int> &>' requested here
        const auto [_, inserted] = visited.emplace(n->position);
                                           ^
In file included from missing-hash.cpp:1:
In file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:61:
In file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/unordered_map:46:
In file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:35:
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1379:9: error: type 'const std::hash<std::pair<int, int>>' does not provide a call operator
        return _M_h1()(__k);
               ^~~~~~~
3 errors generated.

And here's the English-language explanation from cwhy:

% cwhy --- clang++ --std=c++20 -c missing-hash.cpp
The problem is that you are attempting to use `std::unordered_set`
with `std::pair<int, int>` as the key type. However, the standard
library does not provide a hash function specialization for
`std::pair` out of the box, so the default constructor of the
unordered set is deleted.

To resolve this, you'll need to provide a custom hash function for
`std::pair<int, int>`. Here's an example of how you can define one:

```cpp
struct PairHash {
    template <typename T1, typename T2>
    std::size_t operator()(const std::pair<T1, T2>& pair) const {
        std::hash<T1> hash1;
        std::hash<T2> hash2;
        return hash1(pair.first) ^ (hash2(pair.second) << 1);
    }
};
```

Then, when instantiating the `std::unordered_set`, you can specify the
custom hash function:

```cpp
std::unordered_set<std::pair<int, int>, PairHash> visited;
```

With this change, the code should now compile and work as expected.

Rust

% cwhy --- cargo build
There are three issues:  1. There are two unused variables `x` in the
code.  2. The variable `x` is used after it has already been moved in
the call to `f(x)`, which takes ownership of `x`. 3. The function
`f(x)` takes ownership of `x`, which may not be necessary and could be
changed to borrow the value instead.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cwhy-0.4.2.tar.gz (58.8 kB view details)

Uploaded Source

Built Distribution

cwhy-0.4.2-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

File details

Details for the file cwhy-0.4.2.tar.gz.

File metadata

  • Download URL: cwhy-0.4.2.tar.gz
  • Upload date:
  • Size: 58.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for cwhy-0.4.2.tar.gz
Algorithm Hash digest
SHA256 fbed505ee81121421c116829c7b22a043985995495349e18cb91061295660417
MD5 3c197878c6fa7ab3a80a7f16849c5177
BLAKE2b-256 50b5988864c94bc7eeec6f9c520eb4a119a735ad41d85bd5ba8b1b20ae9da1f2

See more details on using hashes here.

File details

Details for the file cwhy-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: cwhy-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 17.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.7

File hashes

Hashes for cwhy-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5c6945dc09c0161cec2e4bf053fd71151a6762107419e85dec39469f7a26fc96
MD5 494842fff84468e34c7ed863154432de
BLAKE2b-256 d014b071687ba64569b88beaca46e4252e2287871b9b166d4770f59936fa31e0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page