Repository: conan-io/conan

Issue:
[bug] `AssertionError: Installer should receive RREV always` with gcc 12 and transitive platform tool
### Environment details

* Operating System+version: Debian 12
* Compiler+version: GCC 12
* Conan version: 2.0.17
* Python version: N/A

### Steps to reproduce

It seems that with GCC 12 (not 11), when a package has a transitive build (tool) dependency, like with `date` on `automake` that is also listed in `[platform_tool_requires]`, conan tries to both download the tool from Conan center and use the platform version.

- Set up Conan to use GCC 12
- Add to profile:
  ```ini
  [platform_tool_requires]
  automake/1.16.5
  ```
- Create `conanfile.txt`:
  ```ini
  [requires]
  date/3.0.1
  ```
- Execute `conan install ./ --build=missing`
- Notice weird output where automake is listed twice:
  ```
  ======== Computing dependency graph ========
  [...]
  Build requirements
  [...]
      automake/1.16.5#058bda3e21c36c9aa8425daf3c1faf50 - Platform
  [...]
  
  ======== Computing necessary packages ========
  [...]
  Requirements
  [...]
      automake/1.16.5#058bda3e21c36c9aa8425daf3c1faf50:9a4eb3c8701508aa9458b1a73d0633783ecc2270#9719e51a6a62041af6a63e00eef35434 - Download (conancenter)
      automake/1.16.5 - Platform
  [...]
  ```
- Crash when installing `automake` package:
  ```
  ERROR: Traceback (most recent call last):
    File "conan/cli/cli.py", line 280, in main
    File "conan/cli/cli.py", line 190, in run
    File "conan/cli/command.py", line 126, in run
    File "conan/cli/commands/install.py", line 73, in install
    File "conan/api/subapi/install.py", line 21, in install_binaries
    File "conans/client/installer.py", line 258, in install
    File "conans/client/installer.py", line 305, in _handle_package
  AssertionError: Installer should receive RREV always
  ```

# Easy Docker repro
```sh
#!/usr/bin/env sh
set -eu

docker run --interactive debian sh <<'EOF_DOCKER'

set -eu
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y wget cmake ninja-build perl g++-12

wget --no-verbose https://github.com/conan-io/conan/releases/latest/download/conan-linux-64.tar.gz
mkdir ./conan/
tar -xf conan-linux-64.tar.gz --directory ./conan/

>./conan_profile echo \
'[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=12
os=Linux

[conf]
tools.build:compiler_executables={"c":"gcc-12", "cpp":"g++-12"}

[platform_tool_requires]
automake/1.16.5'

>./conanfile.txt echo \
'[requires]
date/3.0.1'

./conan/conan install ./ --build=missing --profile:all=./conan_profile

EOF_DOCKER
```

<details>
<summary><h3>Logs</h3></summary>

```
======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=12
os=Linux
[platform_tool_requires]
automake/1.16.5
[conf]
tools.build:compiler_executables={'c': 'gcc-12', 'cpp': 'g++-12'}

Profile build:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=12
os=Linux
[platform_tool_requires]
automake/1.16.5
[conf]
tools.build:compiler_executables={'c': 'gcc-12', 'cpp': 'g++-12'}


======== Computing dependency graph ========
date/3.0.1: Not found in local cache, looking in remotes...
date/3.0.1: Checking remote: conancenter
date/3.0.1: Downloaded recipe revision 032e24ad8bd1fd136dd33c932563d3d1
libcurl/8.6.0: Not found in local cache, looking in remotes...
libcurl/8.6.0: Checking remote: conancenter
libcurl/8.6.0: Downloaded recipe revision ff220b1555b8aebbb78440b25d471217
openssl/3.2.1: Not found in local cache, looking in remotes...
openssl/3.2.1: Checking remote: conancenter
openssl/3.2.1: Downloaded recipe revision 39bd48ed31f1f3fbdcd75a0648aaedcf
zlib/1.3.1: Not found in local cache, looking in remotes...
zlib/1.3.1: Checking remote: conancenter
zlib/1.3.1: Downloaded recipe revision af8f2ef3d8e0fddf1975281d7fe43bf6
libtool/2.4.7: Not found in local cache, looking in remotes...
libtool/2.4.7: Checking remote: conancenter
libtool/2.4.7: Downloaded recipe revision 08316dad5c72c541ed21e039e4cf217b
automake/1.16.5: Not found in local cache, looking in remotes...
automake/1.16.5: Checking remote: conancenter
automake/1.16.5: Downloaded recipe revision 058bda3e21c36c9aa8425daf3c1faf50
autoconf/2.71: Not found in local cache, looking in remotes...
autoconf/2.71: Checking remote: conancenter
autoconf/2.71: Downloaded recipe revision 00a1e46d8ba5baaf7f10d64c1a6a0342
m4/1.4.19: Not found in local cache, looking in remotes...
m4/1.4.19: Checking remote: conancenter
m4/1.4.19: Downloaded recipe revision b38ced39a01e31fef5435bc634461fd2
gnu-config/cci.20210814: Not found in local cache, looking in remotes...
gnu-config/cci.20210814: Checking remote: conancenter
gnu-config/cci.20210814: Downloaded recipe revision dc430d754f465e8c74463019672fb97b
pkgconf/2.1.0: Not found in local cache, looking in remotes...
pkgconf/2.1.0: Checking remote: conancenter
pkgconf/2.1.0: Downloaded recipe revision 27f44583701117b571307cf5b5fe5605
meson/1.2.2: Not found in local cache, looking in remotes...
meson/1.2.2: Checking remote: conancenter
meson/1.2.2: Downloaded recipe revision aace9dcc1db58fa42ecb5292f724092d
ninja/1.11.1: Not found in local cache, looking in remotes...
ninja/1.11.1: Checking remote: conancenter
ninja/1.11.1: Downloaded recipe revision 77587f8c8318662ac8e5a7867eb4be21
Graph root
    conanfile.txt: /conanfile.txt
Requirements
    date/3.0.1#032e24ad8bd1fd136dd33c932563d3d1 - Downloaded (conancenter)
    libcurl/8.6.0#ff220b1555b8aebbb78440b25d471217 - Downloaded (conancenter)
    openssl/3.2.1#39bd48ed31f1f3fbdcd75a0648aaedcf - Downloaded (conancenter)
    zlib/1.3.1#af8f2ef3d8e0fddf1975281d7fe43bf6 - Downloaded (conancenter)
Build requirements
    autoconf/2.71#00a1e46d8ba5baaf7f10d64c1a6a0342 - Downloaded (conancenter)
    automake/1.16.5#058bda3e21c36c9aa8425daf3c1faf50 - Platform
    gnu-config/cci.20210814#dc430d754f465e8c74463019672fb97b - Downloaded (conancenter)
    libtool/2.4.7#08316dad5c72c541ed21e039e4cf217b - Downloaded (conancenter)
    m4/1.4.19#b38ced39a01e31fef5435bc634461fd2 - Downloaded (conancenter)
    meson/1.2.2#aace9dcc1db58fa42ecb5292f724092d - Downloaded (conancenter)
    ninja/1.11.1#77587f8c8318662ac8e5a7867eb4be21 - Downloaded (conancenter)
    pkgconf/2.1.0#27f44583701117b571307cf5b5fe5605 - Downloaded (conancenter)
Resolved version ranges
    libcurl/[>=7.78 <9]: libcurl/8.6.0
    openssl/[>=1.1 <4]: openssl/3.2.1
    zlib/[>=1.2.11 <2]: zlib/1.3.1

======== Computing necessary packages ========
date/3.0.1: Checking 9 compatible configurations
date/3.0.1: Compatible configurations not found in cache, checking servers
date/3.0.1: '7156fd26e94d799841165d64a3b1aacd228ecb46': compiler.cppstd=11
date/3.0.1: 'bdafc85c8e4ee0490e751a9f32f97b16747ee570': compiler.cppstd=gnu11
date/3.0.1: 'cbf02b6433175f39bf56f082e5e7b59c7a703248': compiler.cppstd=14
date/3.0.1: '8fb62d2780743c1dfc2848c0739cae4059861520': compiler.cppstd=gnu14
date/3.0.1: '1b96eaa0e661209ec8f8405123a51e30580f3b2f': compiler.cppstd=17
date/3.0.1: '34949dbc36c10c5b10231dccff777c9c91234874': compiler.cppstd=20
date/3.0.1: 'c2c018fe025cc14f4cb53e6aa8f11c12bfcd6b45': compiler.cppstd=gnu20
date/3.0.1: '23fded3dc2801dc1869298959d54c4fa00d89d63': compiler.cppstd=23
date/3.0.1: 'ea319d297e5e7c3315501cfc58a0d59e3edd8833': compiler.cppstd=gnu23
Requirements
    date/3.0.1#032e24ad8bd1fd136dd33c932563d3d1:4cd7e1ffea6fd4d852638c08c595d4d428266a3f - Build
    libcurl/8.6.0#ff220b1555b8aebbb78440b25d471217:0e54b2f2edc55f1bd4336a8eeb7b971719a2a929 - Build
    openssl/3.2.1#39bd48ed31f1f3fbdcd75a0648aaedcf:aa7941e1289205fbf9a07cfcd48097910375f9ce - Build
    zlib/1.3.1#af8f2ef3d8e0fddf1975281d7fe43bf6:5bc851010eb7b707e5cb2e24cb8ccf0f27989fa9 - Build
Build requirements
    autoconf/2.71#00a1e46d8ba5baaf7f10d64c1a6a0342:da39a3ee5e6b4b0d3255bfef95601890afd80709#7440f8a166fc2063a7fc2b7bed8eacb3 - Download (conancenter)
    automake/1.16.5#058bda3e21c36c9aa8425daf3c1faf50:9a4eb3c8701508aa9458b1a73d0633783ecc2270#9719e51a6a62041af6a63e00eef35434 - Download (conancenter)
    automake/1.16.5 - Platform
    gnu-config/cci.20210814#dc430d754f465e8c74463019672fb97b:da39a3ee5e6b4b0d3255bfef95601890afd80709#22618e30bd9e326eb95e824dc90cc860 - Download (conancenter)
    libtool/2.4.7#08316dad5c72c541ed21e039e4cf217b:5bc851010eb7b707e5cb2e24cb8ccf0f27989fa9 - Build
    m4/1.4.19#b38ced39a01e31fef5435bc634461fd2:3593751651824fb813502c69c971267624ced41a#cd8019a4f9b70880d548f7cc26569604 - Download (conancenter)
    pkgconf/2.1.0#27f44583701117b571307cf5b5fe5605:c0b621fd4b3199fe05075171573398833dba85f4#74a82dec52448dda20253a19d65965c7 - Download (conancenter)
Skipped binaries
    meson/1.2.2, ninja/1.11.1

======== Installing packages ========

-------- Downloading 5 packages --------
gnu-config/cci.20210814: Retrieving package da39a3ee5e6b4b0d3255bfef95601890afd80709 from remote 'conancenter' 
gnu-config/cci.20210814: Package installed da39a3ee5e6b4b0d3255bfef95601890afd80709
gnu-config/cci.20210814: Downloaded package revision 22618e30bd9e326eb95e824dc90cc860
m4/1.4.19: Retrieving package 3593751651824fb813502c69c971267624ced41a from remote 'conancenter' 
m4/1.4.19: Package installed 3593751651824fb813502c69c971267624ced41a
m4/1.4.19: Downloaded package revision cd8019a4f9b70880d548f7cc26569604
pkgconf/2.1.0: Retrieving package c0b621fd4b3199fe05075171573398833dba85f4 from remote 'conancenter' 
pkgconf/2.1.0: Package installed c0b621fd4b3199fe05075171573398833dba85f4
pkgconf/2.1.0: Downloaded package revision 74a82dec52448dda20253a19d65965c7
autoconf/2.71: Retrieving package da39a3ee5e6b4b0d3255bfef95601890afd80709 from remote 'conancenter' 
autoconf/2.71: Package installed da39a3ee5e6b4b0d3255bfef95601890afd80709
autoconf/2.71: Downloaded package revision 7440f8a166fc2063a7fc2b7bed8eacb3
automake/1.16.5: Retrieving package 9a4eb3c8701508aa9458b1a73d0633783ecc2270 from remote 'conancenter' 
automake/1.16.5: Package installed 9a4eb3c8701508aa9458b1a73d0633783ecc2270
automake/1.16.5: Downloaded package revision 9719e51a6a62041af6a63e00eef35434
```
[...]
```
ERROR: Traceback (most recent call last):
  File "conan/cli/cli.py", line 280, in main
  File "conan/cli/cli.py", line 190, in run
  File "conan/cli/command.py", line 126, in run
  File "conan/cli/commands/install.py", line 73, in install
  File "conan/api/subapi/install.py", line 21, in install_binaries
  File "conans/client/installer.py", line 258, in install
  File "conans/client/installer.py", line 305, in _handle_package
AssertionError: Installer should receive RREV always
```
</details>


Discussion:
Thanks very much for the detailed repro case, it really helped a lot.
I have already managed to reproduce, now I am investigating the source and I will try to submit a fix soon.
Submitted PR to fix it https://github.com/conan-io/conan/pull/15665, though the fix approach might change, lets see if we can add it for next 2.1

In the meantime you might make it work it by adding ``[platform_requires]`` to ``automake`` in the "build" profile.



Patch:
diff --git a/conans/client/graph/graph_builder.py b/conans/client/graph/graph_builder.py
index 4c644e395f1..c0b9021eb17 100644
--- a/conans/client/graph/graph_builder.py
+++ b/conans/client/graph/graph_builder.py
@@ -222,8 +222,16 @@ def _resolve_recipe(self, ref, graph_lock):
     @staticmethod
     def _resolved_system(node, require, profile_build, profile_host, resolve_prereleases):
         profile = profile_build if node.context == CONTEXT_BUILD else profile_host
-        dep_type = "platform_tool_requires" if require.build else "platform_requires"
-        system_reqs = getattr(profile, dep_type)
+        if node.context == CONTEXT_BUILD:
+            # If we are in the build context, the platform_tool_requires ALSO applies to the
+            # regular requires. It is not possible in the build context to have tool-requires
+            # and regular requires to the same package from Conan and from Platform
+            system_reqs = profile.platform_tool_requires
+            if not require.build:
+                system_reqs = system_reqs + profile.platform_requires
+        else:
+            system_reqs = profile.platform_tool_requires if require.build \
+                else profile.platform_requires
         if system_reqs:
             version_range = require.version_range
             for d in system_reqs:
diff --git a/conans/client/graph/install_graph.py b/conans/client/graph/install_graph.py
index c044f4fb176..107e20dc033 100644
--- a/conans/client/graph/install_graph.py
+++ b/conans/client/graph/install_graph.py
@@ -4,7 +4,7 @@
 
 from conan.api.output import ConanOutput
 from conans.client.graph.graph import RECIPE_CONSUMER, RECIPE_VIRTUAL, BINARY_SKIP, \
-    BINARY_MISSING, BINARY_INVALID, Overrides, BINARY_BUILD, BINARY_EDITABLE_BUILD
+    BINARY_MISSING, BINARY_INVALID, Overrides, BINARY_BUILD, BINARY_EDITABLE_BUILD, BINARY_PLATFORM
 from conans.errors import ConanInvalidConfiguration, ConanException
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
@@ -370,7 +370,8 @@ def deserialize(data, filename):
 
     def _initialize_deps_graph(self, deps_graph):
         for node in deps_graph.ordered_iterate():
-            if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL) or node.binary == BINARY_SKIP:
+            if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL) \
+                    or node.binary in (BINARY_SKIP, BINARY_PLATFORM):
                 continue
 
             key = node.ref if self._order == "recipe" else node.pref
diff --git a/conans/client/installer.py b/conans/client/installer.py
index 551cf822681..8fc7ea56a21 100644
--- a/conans/client/installer.py
+++ b/conans/client/installer.py
@@ -7,7 +7,7 @@
 from conans.client.conanfile.package import run_package_method
 from conans.client.generators import write_generators
 from conans.client.graph.graph import BINARY_BUILD, BINARY_CACHE, BINARY_DOWNLOAD, BINARY_EDITABLE, \
-    BINARY_PLATFORM, BINARY_UPDATE, BINARY_EDITABLE_BUILD, BINARY_SKIP
+    BINARY_UPDATE, BINARY_EDITABLE_BUILD, BINARY_SKIP
 from conans.client.graph.install_graph import InstallGraph
 from conans.client.source import retrieve_exports_sources, config_source
 from conans.errors import (ConanException, conanfile_exception_formatter, conanfile_remove_attr)
@@ -295,9 +295,6 @@ def _download_pkg(self, package):
         self._remote_manager.get_package(node.pref, node.binary_remote)
 
     def _handle_package(self, package, install_reference, handled_count, total_count):
-        if package.binary == BINARY_PLATFORM:
-            return
-
         if package.binary in (BINARY_EDITABLE, BINARY_EDITABLE_BUILD):
             self._handle_node_editable(package)
             return


Test patch:
diff --git a/conans/test/integration/graph/test_platform_requires.py b/conans/test/integration/graph/test_platform_requires.py
index 486b6d0a5d4..2b4c0fcab66 100644
--- a/conans/test/integration/graph/test_platform_requires.py
+++ b/conans/test/integration/graph/test_platform_requires.py
@@ -58,6 +58,19 @@ def test_platform_requires_no_host(self):
         client.run("create . -pr=profile", assert_error=True)
         assert "ERROR: Package 'dep/1.0' not resolved: No remote defined" in client.out
 
+    def test_platform_requires_build_context(self):
+        """
+        platform_requires must work in the build context too
+        """
+        client = TestClient(light=True)
+        client.save({"tool/conanfile.py": GenConanfile("tool", "1.0").with_requires("dep/1.0"),
+                     "pkg/conanfile.py": GenConanfile("pkg", "1.0").with_tool_requires("tool/1.0"),
+                     "profile": "[settings]\nos=Linux\n[platform_requires]\ndep/1.0"})
+        client.run("create tool -pr:b=profile --build-require")
+        assert "dep/1.0 - Platform" in client.out
+        client.run("create pkg -pr:b=profile")
+        assert "dep/1.0 - Platform" in client.out
+
     def test_graph_info_platform_requires_range(self):
         """
         graph info doesn't crash
@@ -136,6 +149,15 @@ def generate(self):
         assert "ERROR: Package 'dep/1.1' not resolved" in client.out
 
 
+class TestPlatformTestRequires:
+    def test_platform_requires(self):
+        client = TestClient()
+        client.save({"conanfile.py": GenConanfile("pkg", "1.0").with_test_requires("dep/1.0"),
+                     "profile": "[platform_requires]\ndep/1.0"})
+        client.run("create . -pr=profile")
+        assert "dep/1.0 - Platform" in client.out
+
+
 class TestPlatformRequiresLock:
 
     def test_platform_requires_range(self):
diff --git a/conans/test/integration/graph/test_system_tools.py b/conans/test/integration/graph/test_system_tools.py
index f5d101d1554..8b64f9e0fcf 100644
--- a/conans/test/integration/graph/test_system_tools.py
+++ b/conans/test/integration/graph/test_system_tools.py
@@ -136,6 +136,26 @@ def generate(self):
         client.run("install . -pr=profile", assert_error=True)
         assert "ERROR: Package 'tool/1.1' not resolved" in client.out
 
+    def test_require_build_context(self):
+        """ https://github.com/conan-io/conan/issues/15659
+        app -> libcurl --(tool-require)--> libtool -> automake -> autoconf
+                                             \\--(br)-> automake -> autoconf
+        """
+        c = TestClient()
+        c.save({"autoconf/conanfile.py": GenConanfile("autoconf", "0.1"),
+                "automake/conanfile.py": GenConanfile("automake", "0.1").with_requires("autoconf/0.1"),
+                "libtool/conanfile.py": GenConanfile("libtool", "0.1").with_requires("automake/0.1")
+                                                                      .with_tool_requires("automake/0.1"),
+                "libcurl/conanfile.py": GenConanfile("libcurl", "0.1").with_tool_requires("libtool/0.1"),
+                "app/conanfile.py": GenConanfile().with_requires("libcurl/0.1"),
+                "profile_build": "[settings]\nos=Linux\n[platform_tool_requires]\nautomake/0.1"})
+        c.run("create autoconf")
+        c.run("create automake")
+        c.run("export libtool")
+        c.run("export libcurl")
+        c.run("install app -pr:b=profile_build --build=missing")
+        assert "Install finished successfully" in c.out
+
 
 class TestToolRequiresLock: