Merge topic 'gtest-alias'

741233a02b GoogleTest: Allow alias target in test discovery

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !11876
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 053dc41..ac1a49a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1383,7 +1383,7 @@
     variables:
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang21.1-cl-fastbuild:
+t:windows-clang22.1-cl-fastbuild:
     extends:
         - .windows_clang_fastbuild
         - .cmake_test_windows_external
@@ -1393,10 +1393,10 @@
     needs:
         - t:windows-vs2026-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang21.1_cl_fastbuild
+        CMAKE_CI_BUILD_NAME: windows_clang22.1_cl_fastbuild
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang21.1-cl-ninja:
+t:windows-clang22.1-cl-ninja:
     extends:
         - .windows_clang_ninja
         - .cmake_test_windows_external
@@ -1406,10 +1406,10 @@
     needs:
         - t:windows-vs2026-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang21.1_cl_ninja
+        CMAKE_CI_BUILD_NAME: windows_clang22.1_cl_ninja
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang21.1-cl-nmake:
+t:windows-clang22.1-cl-nmake:
     extends:
         - .windows_clang_nmake
         - .cmake_test_windows_external
@@ -1419,10 +1419,10 @@
     needs:
         - t:windows-vs2026-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang21.1_cl_nmake
+        CMAKE_CI_BUILD_NAME: windows_clang22.1_cl_nmake
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang21.1-gnu-ninja:
+t:windows-clang22.1-gnu-ninja:
     extends:
         - .windows_clang_ninja
         - .cmake_test_windows_external
@@ -1432,10 +1432,10 @@
     needs:
         - t:windows-vs2026-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang21.1_gnu_ninja
+        CMAKE_CI_BUILD_NAME: windows_clang22.1_gnu_ninja
         CMAKE_CI_JOB_NIGHTLY: "true"
 
-t:windows-clang21.1-gnu-nmake:
+t:windows-clang22.1-gnu-nmake:
     extends:
         - .windows_clang_nmake
         - .cmake_test_windows_external
@@ -1445,7 +1445,7 @@
     needs:
         - t:windows-vs2026-x64-ninja
     variables:
-        CMAKE_CI_BUILD_NAME: windows_clang21.1_gnu_nmake
+        CMAKE_CI_BUILD_NAME: windows_clang22.1_gnu_nmake
         CMAKE_CI_JOB_NIGHTLY: "true"
 
 t:windows-intel2021.9-ninja:
diff --git a/.gitlab/ci/clang.ps1 b/.gitlab/ci/clang.ps1
index 327fe3b..20830cc 100644
--- a/.gitlab/ci/clang.ps1
+++ b/.gitlab/ci/clang.ps1
@@ -1,10 +1,10 @@
 $erroractionpreference = "stop"
 
-if ("$env:CMAKE_CI_BUILD_NAME".Contains("clang21.1")) {
-    # LLVM/Clang 21.1.8
-    # https://github.com/llvm/llvm-project/releases/tag/llvmorg-21.1.8
-    $filename = "llvm-21.1.8-win-x86_64-1"
-    $sha256sum = "3DB0063A6E434C694799CDD70052F27F08A758F1FF4B4C04D9910AD4198F6064"
+if ("$env:CMAKE_CI_BUILD_NAME".Contains("clang22.1")) {
+    # LLVM/Clang 22.1.2
+    # https://github.com/llvm/llvm-project/releases/tag/llvmorg-22.1.2
+    $filename = "llvm-22.1.2-win-x86_64-1"
+    $sha256sum = "31022498417A1225FABF31EE66AF11971BA2E4BA97FFE7A10F9A206CAD8A85E7"
 } else {
     throw ('unknown CMAKE_CI_BUILD_NAME: ' + "$env:CMAKE_CI_BUILD_NAME")
 }
diff --git a/.gitlab/ci/configure_windows_clang_ninja.cmake b/.gitlab/ci/configure_windows_clang_ninja.cmake
index 214c754..e8a0171 100644
--- a/.gitlab/ci/configure_windows_clang_ninja.cmake
+++ b/.gitlab/ci/configure_windows_clang_ninja.cmake
@@ -1,4 +1,2 @@
-if("$ENV{CMAKE_CI_BUILD_NAME}" MATCHES "(^|_)gnu(_|$)")
-  set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database" CACHE STRING "")
-endif()
+set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database" CACHE STRING "")
 include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_clang_common.cmake")
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst
index a17bdcd..30d53ff 100644
--- a/Help/dev/experimental.rst
+++ b/Help/dev/experimental.rst
@@ -127,7 +127,7 @@
 In order to activate support for Rust, set
 
 * variable ``CMAKE_EXPERIMENTAL_RUST`` to
-* value ``6b6e613b-f6cb-402d-8aea-59034fa8c65b``.
+* value ``efaed83b-d73a-48af-999a-bd0a6172c313``.
 
 This UUID may change in future versions of CMake.  Be sure to use the value
 documented here by the source tree of the version of CMake with which you are
diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst
index 9dc14d2..3964386 100644
--- a/Help/manual/cmake-cxxmodules.7.rst
+++ b/Help/manual/cmake-cxxmodules.7.rst
@@ -69,7 +69,13 @@
 modules includes:
 
 * MSVC toolset 14.34 and newer (provided with Visual Studio 17.4 and newer)
+
 * LLVM/Clang 16.0 and newer
+
+  .. versionadded:: 4.4
+
+    ``clang-cl`` version 19.1 and newer
+
 * GCC 14 and newer
 
 ``import std`` Support
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index a530637..682d592 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -405,6 +405,7 @@
    /prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG
    /prop_tgt/RUNTIME_OUTPUT_NAME
    /prop_tgt/RUNTIME_OUTPUT_NAME_CONFIG
+   /prop_tgt/Rust_EDITION
    /prop_tgt/SKIP_BUILD_RPATH
    /prop_tgt/SKIP_LINTING
    /prop_tgt/SOURCE_DIR
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index d7987ba..fe285e4 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -579,6 +579,7 @@
    /variable/CMAKE_POSITION_INDEPENDENT_CODE
    /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY
    /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY_CONFIG
+   /variable/CMAKE_Rust_EDITION
    /variable/CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS
    /variable/CMAKE_SHARED_LINKER_FLAGS
    /variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG
diff --git a/Help/prop_tgt/Rust_EDITION.rst b/Help/prop_tgt/Rust_EDITION.rst
new file mode 100644
index 0000000..454b1b1
--- /dev/null
+++ b/Help/prop_tgt/Rust_EDITION.rst
@@ -0,0 +1,25 @@
+Rust_EDITION
+------------
+
+.. versionadded:: 4.4
+
+.. note::
+   Experimental. Gated by ``CMAKE_EXPERIMENTAL_RUST``.
+
+The Rust edition required to build this target. It is initialized from the
+:variable:`CMAKE_Rust_EDITION` variable if defined. Setting this property
+results in adding a flag such as ``--edition=2018`` to the compile line.
+
+Supported values are:
+
+``2015``
+  Rust 2015, the default edition, started with Rust 1.0.
+
+``2018``
+  Rust 2018, available since Rust 1.31.
+
+``2021``
+  Rust 2021, available since Rust 1.56.
+
+``2024``
+  Rust 2024, available since Rust 1.85.
diff --git a/Help/release/dev/clang-cl-cxxmodules.rst b/Help/release/dev/clang-cl-cxxmodules.rst
new file mode 100644
index 0000000..7a3a23f
--- /dev/null
+++ b/Help/release/dev/clang-cl-cxxmodules.rst
@@ -0,0 +1,5 @@
+clang-cl-cxxmodules
+-------------------
+
+* C++ 20 named modules are now supported with ``clang-cl``.
+  See :manual:`cmake-cxxmodules(7)`.
diff --git a/Help/variable/CMAKE_Rust_EDITION.rst b/Help/variable/CMAKE_Rust_EDITION.rst
new file mode 100644
index 0000000..273aea6
--- /dev/null
+++ b/Help/variable/CMAKE_Rust_EDITION.rst
@@ -0,0 +1,10 @@
+CMAKE_Rust_EDITION
+------------------
+
+.. versionadded:: 4.4
+
+.. note::
+   Experimental. Gated by ``CMAKE_EXPERIMENTAL_RUST``.
+
+Default value for :prop_tgt:`Rust_EDITION` target property if set when a target
+is created.
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake
index 205c5f7..7b3bd45 100644
--- a/Modules/Compiler/Clang-CXX.cmake
+++ b/Modules/Compiler/Clang-CXX.cmake
@@ -20,43 +20,48 @@
   set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
 endif()
 
-if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
-  if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
-    if (CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR)
-      set(_clang_scan_deps_resource_dir
-        " -resource-dir \"${CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR}\"")
-    else()
-      set(_clang_scan_deps_resource_dir "")
-    endif ()
-    if (CMAKE_HOST_WIN32)
-      # `rename` doesn't overwrite and doesn't retry in case of "target file is
-      # busy".
-      set(_clang_scan_deps_mv "\"${CMAKE_COMMAND}\" -E rename")
-    else ()
-      set(_clang_scan_deps_mv "mv")
-    endif ()
-    string(CONCAT CMAKE_CXX_SCANDEP_SOURCE
-      "\"${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}\""
-      " -format=p1689"
-      " --"
-      " <CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS>"
-      " -x c++ <SOURCE> -c -o <OBJECT>"
-      "${_clang_scan_deps_resource_dir}"
-      " -MT <DYNDEP_FILE>"
-      " -MD -MF <DEP_FILE>"
-      # Write to a temporary file. If the scan fails, we do not want to update
-      # the actual output file as `ninja` (at least) assumes that failed
-      # commands either delete or leave output files alone. See Issue#25419.
-      " > <DYNDEP_FILE>.tmp"
-      # We cannot use `copy_if_different` as the rule does not have a feature
-      # analogous to `ninja`'s `restat = 1`. It would also leave behind the
-      # `.tmp` file.
-      " && ${_clang_scan_deps_mv} <DYNDEP_FILE>.tmp <DYNDEP_FILE>")
-    unset(_clang_scan_deps_resource_dir)
-    unset(_clang_scan_deps_mv)
-    set(CMAKE_CXX_MODULE_MAP_FORMAT "clang")
-    set(CMAKE_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")
-    set(CMAKE_CXX_COMPILE_BMI
-      "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> --precompile <SOURCE>")
+if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") OR
+   (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.1 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
+  if (CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR)
+    set(_clang_scan_deps_resource_dir
+      " -resource-dir \"${CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR}\"")
+  else()
+    set(_clang_scan_deps_resource_dir "")
+  endif ()
+  if (CMAKE_HOST_WIN32)
+    # `rename` doesn't overwrite and doesn't retry in case of "target file is
+    # busy".
+    set(_clang_scan_deps_mv "\"${CMAKE_COMMAND}\" -E rename")
+  else ()
+    set(_clang_scan_deps_mv "mv")
+  endif ()
+  if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
+    set(_clang "-clang:")
+  else()
+    set(_clang "")
   endif()
+  string(CONCAT CMAKE_CXX_SCANDEP_SOURCE
+    "\"${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}\""
+    " -format=p1689"
+    " --"
+    " <CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS>"
+    " -x c++ <SOURCE> -c ${_clang}-o ${_clang}<OBJECT>"
+    "${_clang_scan_deps_resource_dir}"
+    " ${_clang}-MT ${_clang}<DYNDEP_FILE>"
+    " ${_clang}-MD ${_clang}-MF ${_clang}<DEP_FILE>"
+    # Write to a temporary file. If the scan fails, we do not want to update
+    # the actual output file as `ninja` (at least) assumes that failed
+    # commands either delete or leave output files alone. See Issue#25419.
+    " > <DYNDEP_FILE>.tmp"
+    # We cannot use `copy_if_different` as the rule does not have a feature
+    # analogous to `ninja`'s `restat = 1`. It would also leave behind the
+    # `.tmp` file.
+    " && ${_clang_scan_deps_mv} <DYNDEP_FILE>.tmp <DYNDEP_FILE>")
+  unset(_clang_scan_deps_resource_dir)
+  unset(_clang_scan_deps_mv)
+  set(CMAKE_CXX_MODULE_MAP_FORMAT "clang")
+  set(CMAKE_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")
+  set(CMAKE_CXX_COMPILE_BMI
+    "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> ${_clang}-o ${_clang}<OBJECT> --precompile <SOURCE>")
+  unset(_clang)
 endif()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 2c047d2..763b486 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 4)
 set(CMake_VERSION_MINOR 3)
-set(CMake_VERSION_PATCH 20260328)
+set(CMake_VERSION_PATCH 20260331)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx
index 03a08eb..7d40c0b 100644
--- a/Source/cmExperimental.cxx
+++ b/Source/cmExperimental.cxx
@@ -64,7 +64,7 @@
     cmExperimental::TryCompileCondition::Never },
   // Rust support
   { "Rust",
-    "6b6e613b-f6cb-402d-8aea-59034fa8c65b",
+    "efaed83b-d73a-48af-999a-bd0a6172c313",
     "CMAKE_EXPERIMENTAL_RUST",
     "CMake's support for the Rust programming language is experimental. "
     "It is meant only for experimentation and feedback to CMake developers.",
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 421feca..2feea2b 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -2802,6 +2802,14 @@
   }
 }
 
+void cmGeneratorTarget::AddRustTargetFlags(std::string& flags) const
+{
+  cmValue const edition = this->GetProperty("Rust_EDITION");
+  if (edition && !edition->empty()) {
+    flags += " --edition=" + *edition;
+  }
+}
+
 void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const
 {
   std::string const& compiler =
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 388fa32..c0fceea 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -626,6 +626,8 @@
 
   void AddISPCTargetFlags(std::string& flags) const;
 
+  void AddRustTargetFlags(std::string& flags) const;
+
   std::string GetFeatureSpecificLinkRuleVariable(
     std::string const& var, std::string const& lang,
     std::string const& config) const;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 258ce56..d7a591c 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2140,6 +2140,8 @@
     }
   } else if (lang == "HIP") {
     target->AddHIPArchitectureFlags(compileOrLink, config, flags);
+  } else if (lang == "Rust") {
+    target->AddRustTargetFlags(flags);
   }
 
   // Add VFS Overlay for Clang compilers
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 3172093..2b3217e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -381,6 +381,7 @@
   { "Swift_MODULE_DIRECTORY"_s, IC::CanCompileSources },
   { "Swift_COMPILATION_MODE"_s, IC::CanCompileSources },
   // ---- Rust
+  { "Rust_EDITION"_s, IC::CanCompileSources },
   { "Rust_MAIN_CRATE_ROOT"_s, IC::CanCompileSources },
   // ---- moc
   { "AUTOMOC"_s, IC::CanCompileSources },
diff --git a/Tests/RunCMake/Rust/Editions-build-stdout.txt b/Tests/RunCMake/Rust/Editions-build-stdout.txt
new file mode 100644
index 0000000..21786cd
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions-build-stdout.txt
@@ -0,0 +1,5 @@
+\[1/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[2/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[3/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[4/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
+\[5/5\] Linking Rust executable (Debug[\\/])?Editions
diff --git a/Tests/RunCMake/Rust/Editions-stderr.txt b/Tests/RunCMake/Rust/Editions-stderr.txt
new file mode 100644
index 0000000..c048dd6
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Warning \(dev\) at Editions\.cmake:[0-9]+ \(enable_language\):
+  CMake's support for the Rust programming language is experimental\.  It is
+  meant only for experimentation and feedback to CMake developers\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/Rust/Editions-stdout.txt b/Tests/RunCMake/Rust/Editions-stdout.txt
new file mode 100644
index 0000000..e54269b
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions-stdout.txt
@@ -0,0 +1,4 @@
+Not searching for unused variables given on the command line.
+-- Configuring done \([.0-9]+s\)
+-- Generating done \([.0-9]+s\)
+-- Build files have been written to: .*[\\/]Editions-build
diff --git a/Tests/RunCMake/Rust/Editions.cmake b/Tests/RunCMake/Rust/Editions.cmake
new file mode 100644
index 0000000..0520e06
--- /dev/null
+++ b/Tests/RunCMake/Rust/Editions.cmake
@@ -0,0 +1,32 @@
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
+enable_language(Rust)
+
+# No Edition set, rustc defaults to 2015.
+add_library(Edition.2015 OBJECT edition_2015.rs)
+set_target_properties(Edition.2015 PROPERTIES Rust_EDITION 2015)
+
+# Explicitly set edition on target, without default value from variable.
+add_library(Edition.2018 OBJECT edition_2018.rs)
+set_target_properties(Edition.2018 PROPERTIES Rust_EDITION 2018)
+
+# Implicitly set edition on target from variable
+set(CMAKE_Rust_EDITION 2021)
+add_library(Edition.2021 OBJECT edition_2021.rs)
+
+# Explicitly override the edition.
+add_library(Edition.2024 OBJECT edition_2024.rs)
+set_target_properties(Edition.2024 PROPERTIES Rust_EDITION 2024)
+
+# Rust guarantees that we can link multiple crates with different editions
+# together. We specify explicitly the edition to make sure CMake properly pass
+# the edition in the linking step too.
+unset(CMAKE_Rust_EDITION)
+add_executable(Editions editions.rs)
+set_target_properties(Editions PROPERTIES Rust_EDITION 2018)
+target_link_libraries(
+    Editions PRIVATE
+    Edition.2015
+    Edition.2018
+    Edition.2021
+    Edition.2024
+)
diff --git a/Tests/RunCMake/Rust/Enable.cmake b/Tests/RunCMake/Rust/Enable.cmake
index 14b641f..ec06ab6 100644
--- a/Tests/RunCMake/Rust/Enable.cmake
+++ b/Tests/RunCMake/Rust/Enable.cmake
@@ -1,3 +1,3 @@
-set(CMAKE_EXPERIMENTAL_RUST "6b6e613b-f6cb-402d-8aea-59034fa8c65b")
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
 enable_language(Rust)
 message(STATUS "CMAKE_Rust_COMPILER='${CMAKE_Rust_COMPILER}'")
diff --git a/Tests/RunCMake/Rust/RunCMakeTest.cmake b/Tests/RunCMake/Rust/RunCMakeTest.cmake
index 5178b4f..c3d0207 100644
--- a/Tests/RunCMake/Rust/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Rust/RunCMakeTest.cmake
@@ -2,3 +2,10 @@
 
 run_cmake(Enable)
 run_cmake(EnableExperimental)
+
+block()
+    set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Editions-build)
+    run_cmake(Editions)
+    set(RunCMake_TEST_NO_CLEAN 1)
+    run_cmake_command(Editions-build ${CMAKE_COMMAND} --build . --config Debug)
+endblock()
diff --git a/Tests/RunCMake/Rust/edition_2015.rs b/Tests/RunCMake/Rust/edition_2015.rs
new file mode 100644
index 0000000..3c85b92
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2015.rs
@@ -0,0 +1,2 @@
+// dyn is as an identifier is only allowed in Rust 2015
+pub fn dyn() {}
diff --git a/Tests/RunCMake/Rust/edition_2018.rs b/Tests/RunCMake/Rust/edition_2018.rs
new file mode 100644
index 0000000..2e68a3a
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2018.rs
@@ -0,0 +1,18 @@
+#![allow(rust_2021_compatibility)]
+
+pub trait Foo {}
+
+struct FooA {}
+impl Foo for FooA {}
+
+struct FooB {}
+impl Foo for FooB {}
+
+// dyn keyword is available in 2018+
+pub fn make_foo(value: i32) -> Box<dyn Foo> {
+    match value {
+        // Unsupported in 2021+, should be 0..=42
+        0...42 => Box::new(FooA{}),
+        _ => Box::new(FooB{}),
+    }
+}
diff --git a/Tests/RunCMake/Rust/edition_2021.rs b/Tests/RunCMake/Rust/edition_2021.rs
new file mode 100644
index 0000000..ad113c7
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2021.rs
@@ -0,0 +1,5 @@
+// gen is becoming a keyword in 2024
+pub fn gen() -> i32 {
+    // This does not compile before Rust 2021
+    [1, 2, 3].into_iter().reduce(|acc, n| acc + n).unwrap_or(0)
+}
diff --git a/Tests/RunCMake/Rust/edition_2024.rs b/Tests/RunCMake/Rust/edition_2024.rs
new file mode 100644
index 0000000..4ba8093
--- /dev/null
+++ b/Tests/RunCMake/Rust/edition_2024.rs
@@ -0,0 +1,8 @@
+pub fn add_options(a: Option<i32>, b: Option<i32>) -> Option<i32> {
+    // let chains only allowed in Rust 2024
+    if let Some(a) = a && let Some(b) = b {
+        Some(a + b)
+    } else {
+        None
+    }
+}
diff --git a/Tests/RunCMake/Rust/editions.rs b/Tests/RunCMake/Rust/editions.rs
new file mode 100644
index 0000000..01aaa74
--- /dev/null
+++ b/Tests/RunCMake/Rust/editions.rs
@@ -0,0 +1,12 @@
+
+use edition_2015;
+use edition_2018;
+use edition_2021;
+use edition_2024;
+
+fn main() {
+    edition_2015::r#dyn();
+    let _ = edition_2018::make_foo(1337);
+    let _ = edition_2021::r#gen();
+    let _ = edition_2024::add_options(None, None);
+}
diff --git a/Tests/RustMix/CMakeLists.txt b/Tests/RustMix/CMakeLists.txt
index e3e821b..bf2f2c8 100644
--- a/Tests/RustMix/CMakeLists.txt
+++ b/Tests/RustMix/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 4.2)
 
-set(CMAKE_EXPERIMENTAL_RUST "6b6e613b-f6cb-402d-8aea-59034fa8c65b")
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
 
 project(RustMix LANGUAGES C CXX Rust)
 
diff --git a/Tests/RustOnly/CMakeLists.txt b/Tests/RustOnly/CMakeLists.txt
index 33e9742..29b4a5b 100644
--- a/Tests/RustOnly/CMakeLists.txt
+++ b/Tests/RustOnly/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 4.2)
 
-set(CMAKE_EXPERIMENTAL_RUST "6b6e613b-f6cb-402d-8aea-59034fa8c65b")
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
 
 project(RustOnly LANGUAGES Rust)
 
diff --git a/Tests/RustOnly/main.rs b/Tests/RustOnly/main.rs
index d177874..af91fc3 100644
--- a/Tests/RustOnly/main.rs
+++ b/Tests/RustOnly/main.rs
@@ -17,5 +17,6 @@
     unsafe { liba_greet() };
     unsafe { libb_greet() };
     libc_greet();
+    libd_greet();
     unsafe { libe_greet() };
 }
diff --git a/Tests/RustPie/CMakeLists.txt b/Tests/RustPie/CMakeLists.txt
index b32b852..0c3b657 100644
--- a/Tests/RustPie/CMakeLists.txt
+++ b/Tests/RustPie/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 4.2)
 
-set(CMAKE_EXPERIMENTAL_RUST "6b6e613b-f6cb-402d-8aea-59034fa8c65b")
+set(CMAKE_EXPERIMENTAL_RUST "efaed83b-d73a-48af-999a-bd0a6172c313")
 
 function(setup PREFIX)
     add_library(${PREFIX}_static STATIC ../static.rs)