plasma-umass / cwhy

"See why!" Explains and suggests fixes for compile-time errors for C, C++, C#, Go, Java, LaTeX, PHP, Python, Ruby, Rust, and TypeScript
Apache License 2.0
272 stars 6 forks source link

Prompt upgrades #16

Closed nicovank closed 1 year ago

nicovank commented 1 year ago

Various prompt changes, which hopefully help GPT produce better error messages / diffs.

  1. Put line numbers next to each line instead of giving the range of lines.
  2. Concatenate source lines if adjacent instead of producing two different code blocks. This can still be improved if there is less than X lines between two blocks in the same file.
  3. Use max-error-tokens and max-code-tokens instead of max-context. I set the default to 2048 - 128 = 1920 for each to leave a bit of space for other parts of the prompt.
A sample prompt before this change (note that overriding the default max context is necessary). ```` % g++ -x c++ `./tests/anonymizer.py tests/c++/missing-hash.cpp` |& cwhy --max-context=10 --show-prompt This is my code: File `/tmp/tmpdi_yyfvl` line 6 to 15: ``` struct Node { const std::pair position; std::vector neighbors; }; void bfs(Node* start, std::function f) { std::unordered_set> visited; std::queue queue; queue.push(start); ``` File `/usr/include/c++/11/bits/unordered_set.h` line 128 to 137: ``` using node_type = typename _Hashtable::node_type; using insert_return_type = typename _Hashtable::insert_return_type; #endif // construct/destroy/copy /// Default constructor. unordered_set() = default; /** ``` File `/usr/include/c++/11/bits/hashtable.h` line 521 to 530: ``` _Hashtable(_InputIterator __first, _InputIterator __last, size_type __bkt_count_hint, const _Hash&, const _Equal&, const allocator_type&, false_type __uks); public: // Constructor, destructor, assignment, swap _Hashtable() = default; _Hashtable(const _Hashtable&); ``` File `/usr/include/c++/11/bits/hashtable_policy.h` line 1597 to 1606: ``` static bool _S_node_equals(const _Hash_node_code_cache& __lhn, const _Hash_node_code_cache& __rhn) { return __lhn._M_hash_code == __rhn._M_hash_code; } protected: _Hashtable_base() = default; _Hashtable_base(const _Hash& __hash, const _Equal& __eq) ``` File `/usr/include/c++/11/bits/hashtable_policy.h` line 1203 to 1212: ``` { return _M_hash(); } protected: typedef std::size_t __hash_code; // We need the default constructor for the local iterators and _Hashtable // default constructor. _Hash_code_base() = default; _Hash_code_base(const _Hash& __hash) : __ebo_hash(__hash) { } ``` File `/usr/include/c++/11/bits/hashtable_policy.h` line 1120 to 1129: ``` struct _Hashtable_ebo_helper; /// Specialization using EBO. template struct _Hashtable_ebo_helper<_Nm, _Tp, true> : private _Tp { _Hashtable_ebo_helper() noexcept(noexcept(_Tp())) : _Tp() { } template ``` File `/usr/include/c++/11/bits/functional_hash.h` line 95 to 104: ``` return hash<__type>{}(static_cast<__type>(__val)); } }; /// Primary class template hash, usable for enum types only. // Use with non-enum types still SFINAES. template struct hash : __hash_enum<_Tp> { }; ``` File `/usr/include/c++/11/bits/functional_hash.h` line 76 to 85: ``` // Helper struct for SFINAE-poisoning non-enum types. template::value> struct __hash_enum { private: // Private rather than deleted to be non-trivially-copyable. __hash_enum(__hash_enum&&); ~__hash_enum(); }; ``` File `/usr/include/c++/11/bits/functional_hash.h` line 77 to 86: ``` // Helper struct for SFINAE-poisoning non-enum types. template::value> struct __hash_enum { private: // Private rather than deleted to be non-trivially-copyable. __hash_enum(__hash_enum&&); ~__hash_enum(); }; ``` File `/usr/include/c++/11/bits/hashtable_policy.h` line 1117 to 1126: ``` */ template struct _Hashtable_ebo_helper; /// Specialization using EBO. template struct _Hashtable_ebo_helper<_Nm, _Tp, true> : private _Tp { ``` This is my error: ``` /tmp/tmpdi_yyfvl: In function ‘void bfs(Node*, std::function)’: /tmp/tmpdi_yyfvl:13:45: error: use of deleted function ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set() [with _Value = std::pair; _Hash = std::hash >; _Pred = std::equal_to >; _Alloc = std::allocator >]’ 13 | std::unordered_set> visited; | ^~~~~~~ In file included from /usr/include/c++/11/unordered_set:47, from /tmp/tmpdi_yyfvl:3: /usr/include/c++/11/bits/unordered_set.h:135:7: note: ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set() [with _Value = std::pair; _Hash = std::hash >; _Pred = std::equal_to >; _Alloc = std::allocator >]’ is implicitly deleted because the default definition would be ill-formed: 135 | unordered_set() = default; | ^~~~~~~~~~~~~ /usr/include/c++/11/bits/unordered_set.h:135:7: error: use of deleted function ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable() [with _Key = std::pair; _Value = std::pair; _Alloc = std::allocator >; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to >; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits]’ In file included from /usr/include/c++/11/unordered_map:46, from /usr/include/c++/11/functional:61, from /tmp/tmpdi_yyfvl:1: /usr/include/c++/11/bits/hashtable.h:528:7: note: ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable() [with _Key = std::pair; _Value = std::pair; _Alloc = std::allocator >; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to >; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits]’ is implicitly deleted because the default definition would be ill-formed: 528 | _Hashtable() = default; | ^~~~~~~~~~ /usr/include/c++/11/bits/hashtable.h:528:7: error: use of deleted function ‘std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _Traits>::_Hashtable_base() [with _Key = std::pair; _Value = std::pair; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to >; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _Traits = std::__detail::_Hashtable_traits]’ In file included from /usr/include/c++/11/bits/hashtable.h:35, from /usr/include/c++/11/unordered_map:46, from /usr/include/c++/11/functional:61, from /tmp/tmpdi_yyfvl:1: /usr/include/c++/11/bits/hashtable_policy.h:1604:7: note: ‘std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _Traits>::_Hashtable_base() [with _Key = std::pair; _Value = std::pair; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to >; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _Traits = std::__detail::_Hashtable_traits]’ is implicitly deleted because the default definition would be ill-formed: 1604 | _Hashtable_base() = default; | ^~~~~~~~~~~~~~~ /usr/include/c++/11/bits/hashtable_policy.h:1604:7: error: use of deleted function ‘std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash, _Unused, __cache_hash_code>::_Hash_code_base() [with _Key = std::pair; _Value = std::pair; _ExtractKey = std::__detail::_Identity; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; bool __cache_hash_code = true]’ /usr/include/c++/11/bits/hashtable_policy.h: In instantiation of ‘std::__detail::_Hashtable_ebo_helper<_Nm, _Tp, true>::_Hashtable_ebo_helper() [with int _Nm = 1; _Tp = std::hash >]’: /usr/include/c++/11/bits/hashtable_policy.h:1210:7: required from here /usr/include/c++/11/bits/hashtable_policy.h:1127:49: error: use of deleted function ‘std::hash >::hash()’ 1127 | _Hashtable_ebo_helper() noexcept(noexcept(_Tp())) : _Tp() { } | ^~~~~ In file included from /usr/include/c++/11/functional:56, from /tmp/tmpdi_yyfvl:1: /usr/include/c++/11/bits/functional_hash.h:102:12: note: ‘std::hash >::hash()’ is implicitly deleted because the default definition would be ill-formed: 102 | struct hash : __hash_enum<_Tp> | ^~~~ /usr/include/c++/11/bits/functional_hash.h:102:12: error: no matching function for call to ‘std::__hash_enum, false>::__hash_enum()’ /usr/include/c++/11/bits/functional_hash.h:83:7: note: candidate: ‘std::__hash_enum<_Tp, >::__hash_enum(std::__hash_enum<_Tp, >&&) [with _Tp = std::pair; bool = false]’ 83 | __hash_enum(__hash_enum&&); | ^~~~~~~~~~~ /usr/include/c++/11/bits/functional_hash.h:83:7: note: candidate expects 1 argument, 0 provided /usr/include/c++/11/bits/functional_hash.h:102:12: error: ‘std::__hash_enum<_Tp, >::~__hash_enum() [with _Tp = std::pair; bool = false]’ is private within this context 102 | struct hash : __hash_enum<_Tp> | ^~~~ /usr/include/c++/11/bits/functional_hash.h:84:7: note: declared private here 84 | ~__hash_enum(); | ^ In file included from /usr/include/c++/11/bits/hashtable.h:35, from /usr/include/c++/11/unordered_map:46, from /usr/include/c++/11/functional:61, from /tmp/tmpdi_yyfvl:1: /usr/include/c++/11/bits/hashtable_policy.h:1210:7: note: ‘std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash, _Unused, __cache_hash_code>::_Hash_code_base() [with _Key = std::pair; _Value = std::pair; _ExtractKey = std::__detail::_Identity; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; bool __cache_hash_code = true]’ is implicitly deleted because the default definition would be ill-formed: 1210 | _Hash_code_base() = default; | ^~~~~~~~~~~~~~~ /usr/include/c++/11/bits/hashtable_policy.h:1210:7: error: use of deleted function ‘std::__detail::_Hashtable_ebo_helper<1, std::hash >, true>::~_Hashtable_ebo_helper()’ /usr/include/c++/11/bits/hashtable_policy.h:1124:12: note: ‘std::__detail::_Hashtable_ebo_helper<1, std::hash >, true>::~_Hashtable_ebo_helper()’ is implicitly deleted because the default definition would be ill-formed: 1124 | struct _Hashtable_ebo_helper<_Nm, _Tp, true> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/c++/11/bits/hashtable_policy.h:1124:12: error: use of deleted function ‘std::hash >::~hash()’ ``` What's the problem? ````
The same sample prompt now. ```` % g++ -x c++ `./tests/anonymizer.py tests/c++/missing-hash.cpp` |& cwhy --show-prompt This is my code: File `/tmp/tmpiegd__jl`: ``` 7 struct Node { 8 const std::pair position; 9 std::vector neighbors; 10 }; 11 12 void bfs(Node* start, std::function f) { 13 std::unordered_set> visited; 14 std::queue queue; 15 queue.push(start); 16 17 while (!queue.empty()) { 18 auto* n = queue.front(); 19 queue.pop(); 20 const auto [_, inserted] = visited.emplace(n->position); 21 if (inserted) { 22 f(n); 23 for (auto* neighbor : n->neighbors) { ``` File `/usr/include/c++/11/bits/unordered_set.h`: ``` 128 using node_type = typename _Hashtable::node_type; 129 using insert_return_type = typename _Hashtable::insert_return_type; 130 #endif 131 132 // construct/destroy/copy 133 134 /// Default constructor. 135 unordered_set() = default; 136 137 /** 138 * @brief Default constructor creates no elements. ``` File `/usr/include/c++/11/bits/unordered_set.h`: ``` 91 * alias __uset_hashtable. 92 */ 93 template, 95 typename _Pred = equal_to<_Value>, 96 typename _Alloc = allocator<_Value>> 97 class unordered_set 98 { 99 typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; 100 _Hashtable _M_h; ``` File `/usr/include/c++/11/bits/unordered_set.h`: ``` 372 * 373 * Insertion requires amortized constant time. 374 */ 375 template 376 std::pair 377 emplace(_Args&&... __args) 378 { return _M_h.emplace(std::forward<_Args>(__args)...); } 379 380 /** 381 * @brief Attempts to insert an element into the %unordered_set. ``` File `/usr/include/c++/11/bits/hashtable.h`: ``` 521 _Hashtable(_InputIterator __first, _InputIterator __last, 522 size_type __bkt_count_hint, 523 const _Hash&, const _Equal&, const allocator_type&, 524 false_type __uks); 525 526 public: 527 // Constructor, destructor, assignment, swap 528 _Hashtable() = default; 529 530 _Hashtable(const _Hashtable&); ``` File `/usr/include/c++/11/bits/hashtable.h`: ``` 1528 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, 1529 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>:: 1530 ~_Hashtable() noexcept 1531 { 1532 clear(); 1533 _M_deallocate_buckets(); 1534 } 1535 1536 template pair 1964 { 1965 // First build the node to get access to the hash code 1966 _Scoped_node __node { this, std::forward<_Args>(__args)... }; 1967 const key_type& __k = _ExtractKey{}(__node._M_node->_M_v()); 1968 __hash_code __code = this->_M_hash_code(__k); 1969 size_type __bkt = _M_bucket_index(__code); 1970 if (__node_ptr __p = _M_find_node(__bkt, __k, __code)) 1971 // There is already an equivalent node, no insertion ``` File `/usr/include/c++/11/bits/hashtable.h`: ``` 910 public: 911 // Emplace 912 template 913 __ireturn_type 914 emplace(_Args&&... __args) 915 { return _M_emplace(__unique_keys{}, std::forward<_Args>(__args)...); } 916 917 template 918 iterator ``` File `/usr/include/c++/11/bits/hashtable_policy.h`: ``` 1598 static bool 1599 _S_node_equals(const _Hash_node_code_cache& __lhn, 1600 const _Hash_node_code_cache& __rhn) 1601 { return __lhn._M_hash_code == __rhn._M_hash_code; } 1602 1603 protected: 1604 _Hashtable_base() = default; 1605 1606 _Hashtable_base(const _Hash& __hash, const _Equal& __eq) 1607 : __hash_code_base(__hash), _EqualEBO(__eq) ``` File `/usr/include/c++/11/bits/hashtable_policy.h`: ``` 1205 protected: 1206 typedef std::size_t __hash_code; 1207 1208 // We need the default constructor for the local iterators and _Hashtable 1209 // default constructor. 1210 _Hash_code_base() = default; 1211 1212 _Hash_code_base(const _Hash& __hash) : __ebo_hash(__hash) { } ``` File `/usr/include/c++/11/bits/hashtable_policy.h`: ``` 1122 /// Specialization using EBO. 1123 template 1124 struct _Hashtable_ebo_helper<_Nm, _Tp, true> 1125 : private _Tp 1126 { 1127 _Hashtable_ebo_helper() noexcept(noexcept(_Tp())) : _Tp() { } 1128 1129 template 1130 _Hashtable_ebo_helper(_OtherTp&& __tp) ``` File `/usr/include/c++/11/bits/hashtable_policy.h`: ``` 1118 template ``` File `/usr/include/c++/11/bits/hashtable_policy.h`: ``` 1182 * to implement local_iterator and const_local_iterator. As with 1183 * any iterator type we prefer to make it as small as possible. 1184 */ 1185 template 1188 struct _Hash_code_base 1189 : private _Hashtable_ebo_helper<1, _Hash> 1190 { 1191 private: ``` File `/usr/include/c++/11/bits/hashtable_policy.h`: ``` 1555 * - __detail::_Hash_code_base 1556 * - __detail::_Hashtable_ebo_helper 1557 */ 1558 template 1561 struct _Hashtable_base 1562 : public _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash, 1563 _Unused, _Traits::__hash_cached::value>, 1564 private _Hashtable_ebo_helper<0, _Equal> ``` File `/usr/include/c++/11/bits/hashtable_policy.h`: ``` 1215 _M_hash_code(const _Key& __k) const 1216 { 1217 static_assert(__is_invocable{}, 1218 "hash function must be invocable with an argument of key type"); 1219 return _M_hash()(__k); 1220 } 1221 1222 template ``` This is my error: ``` /tmp/tmpiegd__jl: In function ‘void bfs(Node*, std::function)’: /tmp/tmpiegd__jl:13:45: error: use of deleted function ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set() [with _Value = std::pair; _Hash = std::hash >; _Pred = std::equal_to >; _Alloc = std::allocator >]’ 13 | std::unordered_set> visited; | ^~~~~~~ In file included from /usr/include/c++/11/unordered_set:47, from /tmp/tmpiegd__jl:3: /usr/include/c++/11/bits/unordered_set.h:135:7: note: ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set() [with _Value = std::pair; _Hash = std::hash >; _Pred = std::equal_to >; _Alloc = std::allocator >]’ is implicitly deleted because the default definition would be ill-formed: 135 | unordered_set() = default; | ^~~~~~~~~~~~~ /usr/include/c++/11/bits/unordered_set.h:135:7: error: use of deleted function ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable() [with _Key = std::pair; _Value = std::pair; _Alloc = std::allocator >; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to >; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits]’ In file included from /usr/include/c++/11/unordered_map:46, [...] /usr/include/c++/11/bits/hashtable.h:915:21: required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__ireturn_type std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::emplace(_Args&& ...) [with _Args = {const std::pair&}; _Key = std::pair; _Value = std::pair; _Alloc = std::allocator >; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to >; _Hash = std::hash >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__ireturn_type = std::_Hashtable, std::pair, std::allocator >, std::__detail::_Identity, std::equal_to >, std::hash >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::__ireturn_type]’ /usr/include/c++/11/bits/unordered_set.h:378:23: required from ‘std::pair, std::__is_nothrow_invocable > >::value, true, true> >::iterator, bool> std::unordered_set<_Value, _Hash, _Pred, _Alloc>::emplace(_Args&& ...) [with _Args = {const std::pair&}; _Value = std::pair; _Hash = std::hash >; _Pred = std::equal_to >; _Alloc = std::allocator >; typename std::_Hashtable<_Value, _Value, _Alloc, std::__detail::_Identity, _Pred, _Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits, std::__is_nothrow_invocable > >::value, true, true> >::iterator = std::__detail::_Insert_base, std::pair, std::allocator >, std::__detail::_Identity, std::equal_to >, std::hash >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::iterator]’ /tmp/tmpiegd__jl:20:51: required from here /usr/include/c++/11/bits/hashtable_policy.h:1217:23: error: static assertion failed: hash function must be invocable with an argument of key type 1217 | static_assert(__is_invocable{}, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/c++/11/bits/hashtable_policy.h:1217:23: note: ‘std::__is_invocable >&, const std::pair&>{}’ evaluates to false /usr/include/c++/11/bits/hashtable_policy.h:1219:25: error: no match for call to ‘(const std::hash >) (const std::pair&)’ 1219 | return _M_hash()(__k); | ~~~~~~~~~^~~~~ ``` What's the problem? ````
nicovank commented 1 year ago

One more thing: I wonder if it would make sense to offer an option to exclude files not in the current path or set of paths. I tried it with a LaTeX build error and I think all the includes throw it off (with just the source, GPT-4 figured out the error).

Maybe something like header-filter in clang, specifying with a regex which paths to include/exclude?

emeryberger commented 1 year ago

Maybe - Scalene by default uses only local files, and has options to profile-all and profile-exclude (the latter uses substrings). AFAICT the default for clang-tidy is to include all by default, and then only include the ones listed in header-filter. This seems like a lot of complexity. It might just be the case that includes are only a problem for LaTeX, and we could solve this with a latex / pdflatex wrapper.