Bug 120318 - Module deduced return type error.
Summary: Module deduced return type error.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 15.1.0
: P3 normal
Target Milestone: 16.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: c++-modules
  Show dependency tree / graph
 
Reported: 2025-05-17 03:58 UTC by kongmingd234
Modified: 2026-01-23 23:03 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work: 16.0
Known to fail: 15.1.1
Last reconfirmed: 2025-05-20 00:00:00


Attachments
This code does not compile. (162 bytes, text/plain)
2025-05-17 03:58 UTC, kongmingd234
Details

Note You need to log in before you can comment on or make changes to this bug.
Description kongmingd234 2025-05-17 03:58:25 UTC
Created attachment 61452 [details]
This code does not compile.

The code given in the file does not compile, however, using include instead will cause this code to compile perfectly fine.

Weirder is that having the code inside a lambda function instead of a normal function causes the error to go away.

This could be an issue with libstdc++, but seems unlikely to me. In the off chance that it was I apologize for tagging it as c++.
Comment 1 Nathaniel Shead 2025-05-17 16:21:12 UTC
This compiles fine on trunk, but errors on 15.  I'm not sure what fixed the bug; r16-652-g9694bb129c0dbf seemed likely but reverting it locally didn't cause trunk to error.
Comment 2 Patrick Palka 2025-05-20 21:26:06 UTC
Fixed on trunk by r16-504-g3c7c2a6b86da64 "c++: visibility of instantiated template friends", perhaps the fix is suitable for backporting?
Comment 3 Patrick Palka 2025-05-21 20:59:07 UTC
Probably not very useful but here's a mechanically reduced testcase (fixed by r16-504):

$ cat std.ii
module;                                                                                                                                                                                             16:56 [38/1494]
namespace std {                                                                                          
template <typename> auto declval() -> decltype(0);
template <typename> void forward() {}                                                                    
template <typename, typename>                       
concept convertible_to = requires { declval; };     
template <typename _Tp>                             
concept move_constructible = convertible_to<_Tp, _Tp>;               
namespace ranges {                                  
inline namespace _Cpo {}                            
} // namespace ranges                               
namespace __detail {                                                                                     
template <typename _Iter> using __iter_concept = _Iter;
}                                                   
template <typename _Iter>                           
concept input_iterator = requires { typename __detail::__iter_concept<_Iter>; };
namespace ranges {                                  
namespace _Cpo {                                    
int end;                                            
}                                                   
template <typename>                                 
concept range = requires { end; };                  
template <typename _Tp>                             
concept input_range = input_iterator<_Tp>;          
template <typename _Tp>                             
concept viewable_range = range<_Tp>;                
} // namespace ranges                               
struct vector {};                                   
namespace ranges {                                  
template <typename _Adaptor, typename>              
concept __adaptor_invocable = requires { declval<_Adaptor>; };
template <typename...> struct _Partial;
template <typename _Tp>                             
concept __is_range_adaptor_closure = requires(_Tp __t) { __t; };
template <typename _Self, typename _Range>       
  requires __is_range_adaptor_closure<_Self> &&     
           __adaptor_invocable<_Self, _Range>       
constexpr auto operator|(_Range &&, _Self &&) {}
template <typename> struct _RangeAdaptorClosure {
  template <typename _Self, typename _Range>
    requires __is_range_adaptor_closure<_Self> &&
             __adaptor_invocable<_Self, _Range>
  friend constexpr auto operator|(_Range &&, _Self &&);
};                                                  
struct _RangeAdaptor {                              
  template <typename... _Args> auto operator()(_Args...) {
    return _Partial<int, _Args...>{0, forward<_Args>...};
  }                                                 
};                                                  
template <typename _Adaptor, typename _Arg>
struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure<_Arg> {
  template <typename _Tp> _Partial(int, _Tp) {}
};                                                  
namespace views {                                   
_RangeAdaptorClosure<int> all;
template <viewable_range> using all_t = decltype(all);
} // namespace views                                
template <input_range, move_constructible> class transform_view;
template <typename _Range, typename _Fp>
transform_view() -> transform_view<views::all_t<_Range>, _Fp>;
namespace views {                                   
namespace __detail {                                
template <typename, typename>
concept __can_transform_view = requires { transform_view(declval); };
} // namespace __detail                             
struct _Transform : _RangeAdaptor {
  template <viewable_range _Range, typename _Fp>
    requires __detail::__can_transform_view<_Range, _Fp>
  auto operator0();                                 
} inline transform;                                 
} // namespace views                                
} // namespace ranges                               
} // namespace std                                  
export module std;                                  
export namespace std {                              
namespace ranges {                                  
namespace views {                                   
using views::transform;                             
}                                                   
} // namespace ranges                               
using std::vector;                                  
} // namespace std                                  

$ cat 120318.C
import std;                                         
using std::vector;                                  
using std::ranges::views::transform;
int main(int argl,char**argv)
{                                                   
    vector v;                                       
    v | transform([](int x){return x * x % 24;});
    return 0;                                       
}
Comment 4 kongmingd234 2026-01-23 18:05:04 UTC
If this is fixed, can I mark as resolved?
Comment 5 Nathaniel Shead 2026-01-23 23:03:29 UTC
Yeah, I'll mark as fixed for now.  Perhaps suitable for backporting to 15 but we had a lot of other fixes to 16 regarding temploid friends as well that probably aren't suitable to backporting.