• Stars
    star
    266
  • Rank 148,335 (Top 4 %)
  • Language
    C++
  • License
    Apache License 2.0
  • Created about 1 year ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

"See why!" Explains and suggests fixes for compile-time errors for C, C++, C#, Go, Java, LaTeX, PHP, Python, Ruby, Rust, and TypeScript

cwhy

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

PyPI Latest ReleaseDownloads Downloads Python versions

("See why")

Explains and suggest fixes for C/C++/Rust compiler error messages.

Installation

python3 -m pip install cwhy

NOTE: To use cwhy, you must first set up an OpenAI API key. If you already have an API key, you can set it as an environment variable called OPENAI_API_KEY. If you do not have one yet, you can get a key here: https://platform.openai.com/account/api-keys

export OPENAI_API_KEY=<your-api-key>

Usage

Just pipe your compiler's output to cwhy. cwhy will by default provide an explanation. If you'd like a suggested fix, add fix.

e.g.,

% clang++ -g mycode.cpp |& cwhy     # explanation only
% clang++ -g mycode.cpp |& cwhy fix # to see a suggested fix

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:

% clang++ --std=c++20 -c missing-hash.cpp |& cwhy
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

% rustc test/testme.rs |& cwhy
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.

More Repositories

1

scalene

Scalene: a high-performance, high-precision CPU, GPU, and memory profiler for Python with AI-powered optimization proposals
Python
10,992
star
2

coz

Coz: Causal Profiling
C
3,753
star
3

browsix

Browsix is a Unix-like operating system for the browser.
JavaScript
3,117
star
4

doppio

Breaks the browser language barrier (includes a plugin-free JVM).
TypeScript
2,150
star
5

Mesh

A memory allocator that automatically reduces the memory footprint of C/C++ applications.
C++
1,618
star
6

ChatDBG

ChatDBG - AI-assisted debugging. Uses AI to answer 'why'
C++
669
star
7

BLeak

BLeak: Automatically Debugging Memory Leaks in Web Applications
TypeScript
409
star
8

slipcover

Near Zero-Overhead Python Code Coverage
Python
399
star
9

sqlwrite

SQLwrite: AI in your DBMS! Automatically converts natural language queries to SQL.
C
106
star
10

NextDoor

Graph Sampling using GPU
Cuda
47
star
11

DataDebug

Excel 2010/2013 add-in that automatically finds errors in spreadsheets
C#
46
star
12

systemgo

Init system in Go, intended to run on Browsix and other Unix-like OS. Part of GSoC 2016 project.
Go
31
star
13

sheriff

Sheriff consists of two tools: Sheriff-Detect, a false-sharing detector, and Sheriff-Protect, a false-sharing eliminator that you can link with your code to eliminate false sharing.
C++
29
star
14

DoubleTake

Evidence-based dynamic analysis: a fast checker for memory errors.
C
21
star
15

commentator

Automatically comments Python code, adding docstrings and type annotations, with optional translation to other languages.
Python
19
star
16

Predator

Predator: Predictive False Sharing Detection
C
19
star
17

memory-landscape

The space of memory management research and systems produced by the PLASMA lab (https://plasma-umass.org).
16
star
18

snakefish

parallel Python
Python
13
star
19

parcel

An Excel formula parser
C#
12
star
20

entroprise

measure entropy of memory allocators
C++
12
star
21

Rehearsal

Rehearsal: A Configuration Verification Tool for Puppet
Scala
12
star
22

Hound

Hound memory leak detector
C++
11
star
23

smash-project

Smash compressing allocator project
C++
10
star
24

browsix-spec

JavaScript
9
star
25

Archipelago

Archipelago memory allocator
C
8
star
26

simplesocket

A simple socket wrapper for C++.
C++
8
star
27

pythoness

Pythoness: use natural language to define Python functions.
Python
7
star
28

compsci631

Support code for Programming Languages (COMPSCI631)
OCaml
7
star
29

Tortoise

Tortoise: Interactive System Configuration Repair
Scala
6
star
30

scalene-gui

Scalene web GUI
JavaScript
5
star
31

transparentFS

TransparentFS code, paper, and slides
C
5
star
32

homebrew-scalene

Homebrew tap for Scalene (emeryberger/scalene)
Ruby
4
star
33

GSoC

Description of our Google Summer of Code projects for 2015
4
star
34

HeapToss

HeapToss is an LLVM compiler pass that moves stack variables that may escape their declaring function's context into the heap.
3
star
35

GSoC-2013

Google Summer of Code 2013
2
star
36

jsvm

JavaScript
2
star
37

plasma-umass.github.io

home page
HTML
2
star
38

spl

Rust
2
star
39

llm-utils

Utilities for our LLM projects (CWhy, ChatDBG, ...).
Python
2
star
40

coverup

Automatic AI-powered test suite generator
Python
2
star
41

doppio_jcl

Scripts that produce a version of the Java Class Library and Java Home in a way that is compatible with DoppioJVM.
TypeScript
2
star
42

nextdoor-eurosys21

HTML
1
star
43

mesh-testsuite

C
1
star
44

proto

probabilistic race tolerance
C
1
star
45

ChatSheet

Python
1
star
46

custom-public

Jupyter Notebook
1
star
47

wasm-gc-template

C++
1
star
48

typissed

Generates MTurk typo jobs
C#
1
star
49

scalene-benchmarks

Benchmarks comparing Scalene with other commonly-used profilers
Python
1
star
50

emcc_control

C
1
star
51

transparentMM

Transparent memory management
1
star