microsoft / GSL

Guidelines Support Library
Other
6.23k stars 739 forks source link

`not_null<std::unique_ptr<>>` not working in v4.1.0 with g++-10 #1162

Open asartori86 opened 1 month ago

asartori86 commented 1 month ago

With the 4.1.0 release, the following snippet does not compile with g++-10

// filename: minimal.cc

#include "gsl/gsl"
#include <iostream>
#include <memory>

int main() {
  gsl::not_null<std::unique_ptr<int>> ptr = std::make_unique<int>(42);
  std::cout << *ptr << std::endl;
}
$ g++ minimal.cc -I GSL-4.1.0/include -std=c++20
In file included from GSL-4.1.0/include/gsl/gsl:24,
                 from minimal.cc:1:
GSL-4.1.0/include/gsl/pointers: In instantiation of ‘constexpr gsl::details::value_or_reference_return_t<T> gsl::not_null<T>::get() const [with T = std::unique_ptr<int>; gsl::details::value_or_reference_return_t<T> = const std::unique_ptr<int>&]’:
GSL-4.1.0/include/gsl/pointers:127:58:   required from ‘constexpr decltype(auto) gsl::not_null<T>::operator*() const [with T = std::unique_ptr<int>]’
minimal.cc:7:17:   required from here
GSL-4.1.0/include/gsl/pointers:120:18: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
  120 |         noexcept(noexcept(details::value_or_reference_return_t<T>{std::declval<T&>()}))
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/10/memory:83,
                 from GSL-4.1.0/include/gsl/span:28,
                 from GSL-4.1.0/include/gsl/algorithm:21,
                 from GSL-4.1.0/include/gsl/gsl:21,
                 from minimal.cc:1:
/usr/include/c++/10/bits/unique_ptr.h:468:7: note: declared here
  468 |       unique_ptr(const unique_ptr&) = delete;
      |       ^~~~~~~~~~
$ g++ --version
g++ (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
carsonRadtke commented 1 month ago

Thank you for reporting this issue; we will look into it.

It looks like the same issue is preventing a PR pipeline from succeeding. https://github.com/microsoft/GSL/actions/runs/11384471183

mhthies commented 14 hours ago

The same error also happens with g++-14, but it can give us a little more diagnostic output:

$ g++ minimal.cc -fdiagnostics-all-candidates -I GSL-4.1.0/include -std=c++20 
In file included from /usr/include/gsl/gsl:24,
                 from minimal.cc:3:
/usr/include/gsl/pointers: In instantiation of ‘constexpr gsl::details::value_or_reference_return_t<T> gsl::not_null<T>::get() const [with T = std::unique_ptr<int>; gsl::details::value_or_reference_return_t<T> = const std::unique_ptr<int>&]’:
/usr/include/gsl/pointers:127:58:   required from ‘constexpr decltype(auto) gsl::not_null<T>::operator*() const [with T = std::unique_ptr<int>]’
  127 |     constexpr decltype(auto) operator*() const { return *get(); }
      |                                                          ^~~
minimal.cc:9:17:   required from here
    9 |   std::cout << *ptr << std::endl;
      |                 ^~~
/usr/include/gsl/pointers:120:18: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
  120 |         noexcept(noexcept(details::value_or_reference_return_t<T>{std::declval<T&>()}))
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/14.2.1/memory:78,
                 from /usr/include/gsl/span:28,
                 from /usr/include/gsl/algorithm:21,
                 from /usr/include/gsl/gsl:21:
/usr/include/c++/14.2.1/bits/unique_ptr.h:516:7: note: declared here
  516 |       unique_ptr(const unique_ptr&) = delete;
      |       ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:516:7: note: candidate: ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’ (deleted)
/usr/include/c++/14.2.1/bits/unique_ptr.h:374:9: note: candidate: ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Up, _Ep>&&) [with _Up = int; _Ep = std::default_delete<int>; <template-parameter-2-3> = void; _Tp = int; _Dp = std::default_delete<int>]’ (near match)
  374 |         unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
      |         ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:374:9: note:   conversion of argument 1 would be ill-formed:
/usr/include/c++/14.2.1/bits/unique_ptr.h:374:9: error: cannot bind rvalue reference of type ‘std::unique_ptr<int>&&’ to lvalue of type ‘std::unique_ptr<int>’
/usr/include/c++/14.2.1/bits/unique_ptr.h:360:7: note: candidate: ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int; _Dp = std::default_delete<int>]’ (near match)
  360 |       unique_ptr(unique_ptr&&) = default;
      |       ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:360:7: note:   conversion of argument 1 would be ill-formed:
/usr/include/c++/14.2.1/bits/unique_ptr.h:360:7: error: cannot bind rvalue reference of type ‘std::unique_ptr<int>&&’ to lvalue of type ‘std::unique_ptr<int>’
/usr/include/c++/14.2.1/bits/unique_ptr.h:384:9: note: candidate: ‘template<class _Up, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&) [with <template-parameter-2-2> = _Up; _Tp = int; _Dp = std::default_delete<int>]’
  384 |         unique_ptr(auto_ptr<_Up>&& __u) noexcept;
      |         ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:384:9: note:   template argument deduction/substitution failed:
/usr/include/gsl/pointers:120:18: note:   ‘std::unique_ptr<int>’ is not derived from ‘std::auto_ptr<_Up>’
  120 |         noexcept(noexcept(details::value_or_reference_return_t<T>{std::declval<T&>()}))
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:353:19: note: candidate: ‘template<class _Del, class> constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with <template-parameter-2-2> = _Del; _Tp = int; _Dp = std::default_delete<int>]’
  353 |         constexpr unique_ptr(nullptr_t) noexcept
      |                   ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:353:19: note:   template argument deduction/substitution failed:
/usr/include/gsl/pointers:120:18: note:   cannot convert ‘std::declval<unique_ptr<int>&>()’ (type ‘std::unique_ptr<int>’) to type ‘std::nullptr_t’
  120 |         noexcept(noexcept(details::value_or_reference_return_t<T>{std::declval<T&>()}))
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:347:9: note: candidate: ‘template<class _Del, class _DelUnref> std::unique_ptr<_Tp, _Dp>::unique_ptr(pointer, std::__enable_if_t<((bool)std::is_lvalue_reference<_Del>::value), _DelUnref&&>) [with _DelUnref = _Del; _Tp = int; _Dp = std::default_delete<int>]’ (deleted)
  347 |         unique_ptr(pointer,
      |         ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:347:9: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/14.2.1/bits/unique_ptr.h:338:9: note: candidate: ‘template<class _Del, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(pointer, std::__enable_if_t<((bool)(! std::is_lvalue_reference<_Del>::value)), _Del&&>) [with <template-parameter-2-2> = _Del; _Tp = int; _Dp = std::default_delete<int>]’
  338 |         unique_ptr(pointer __p,
      |         ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:338:9: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/14.2.1/bits/unique_ptr.h:325:9: note: candidate: ‘template<class _Del, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(pointer, const deleter_type&) [with <template-parameter-2-2> = _Del; _Tp = int; _Dp = std::default_delete<int>]’
  325 |         unique_ptr(pointer __p, const deleter_type& __d) noexcept
      |         ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:325:9: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/14.2.1/bits/unique_ptr.h:311:9: note: candidate: ‘template<class _Del, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(pointer) [with <template-parameter-2-2> = _Del; _Tp = int; _Dp = std::default_delete<int>]’
  311 |         unique_ptr(pointer __p) noexcept
      |         ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:311:9: note:   template argument deduction/substitution failed:
/usr/include/gsl/pointers:120:18: note:   cannot convert ‘std::declval<unique_ptr<int>&>()’ (type ‘std::unique_ptr<int>’) to type ‘std::unique_ptr<int>::pointer’ {aka ‘int*’}
  120 |         noexcept(noexcept(details::value_or_reference_return_t<T>{std::declval<T&>()}))
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:298:19: note: candidate: ‘template<class _Del, class> constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with <template-parameter-2-2> = _Del; _Tp = int; _Dp = std::default_delete<int>]’
  298 |         constexpr unique_ptr() noexcept
      |                   ^~~~~~~~~~
/usr/include/c++/14.2.1/bits/unique_ptr.h:298:19: note:   candidate expects 0 arguments, 1 provided
$ g++ --version                                                                                                                                                                                                                          g++ (GCC) 14.2.1 20240910
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
mhthies commented 14 hours ago

I'd assume that it is related to the changes in commit 991fa6682e819590c695f00c6b880548e55fa914