]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: resolve: Name resolve trait bounds properly
authorArthur Cohen <arthur.cohen@embecosm.com>
Wed, 25 Dec 2024 11:03:44 +0000 (11:03 +0000)
committerArthur Cohen <arthur.cohen@embecosm.com>
Fri, 21 Mar 2025 11:55:43 +0000 (12:55 +0100)
gcc/rust/ChangeLog:

* resolve/rust-ast-resolve-type.cc (ResolveTypeToCanonicalPath::visit): Resolve additional
trait bounds.
* resolve/rust-late-name-resolver-2.0.cc (Late::visit): Error out properly on unresolved
type-path instead of crashing.

gcc/testsuite/ChangeLog:

* rust/compile/nr2/exclude: Exclude additional-trait-bounds2 for different error message.
* rust/compile/additional-trait-bounds1.rs: New test.
* rust/compile/additional-trait-bounds2.rs: New test.
* rust/compile/additional-trait-bounds2nr2.rs: New test.

gcc/rust/resolve/rust-ast-resolve-type.cc
gcc/rust/resolve/rust-late-name-resolver-2.0.cc
gcc/testsuite/rust/compile/additional-trait-bounds1.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/additional-trait-bounds2.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/nr2/exclude

index ec5e8a762a704ceb7b4e904e8018f0e657b898af..cb5a18d5d477646bc069ef39c684b4338d1dab2b 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "rust-ast-resolve-type.h"
 #include "rust-ast-resolve-expr.h"
+#include "rust-canonical-path.h"
+#include "rust-type.h"
 
 namespace Rust {
 namespace Resolver {
@@ -495,10 +497,59 @@ ResolveTypeToCanonicalPath::visit (AST::TraitObjectTypeOneBound &type)
 }
 
 void
-ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &)
+ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type)
 {
-  // FIXME is this actually allowed? dyn A+B
-  rust_unreachable ();
+  rust_assert (!type.get_type_param_bounds ().empty ());
+
+  auto &first_bound = type.get_type_param_bounds ().front ();
+
+  // Is it allowed or even possible to have a lifetime bound as a first bound?
+  if (first_bound->get_bound_type () == AST::TraitBound::LIFETIME)
+    rust_unreachable ();
+
+  auto &trait = static_cast<AST::TraitBound &> (*first_bound);
+
+  CanonicalPath path = CanonicalPath::create_empty ();
+  bool ok = ResolveTypeToCanonicalPath::go (trait.get_type_path (), path);
+
+  // right?
+  rust_assert (ok);
+
+  auto slice_path = "<dyn " + path.get ();
+
+  for (size_t idx = 1; idx < type.get_type_param_bounds ().size (); idx++)
+    {
+      auto &additional_bound = type.get_type_param_bounds ()[idx];
+
+      std::string str;
+
+      switch (additional_bound->get_bound_type ())
+       {
+         case AST::TypeParamBound::TRAIT: {
+           auto bound_path = CanonicalPath::create_empty ();
+
+           auto &bound_type_path
+             = static_cast<AST::TraitBound &> (*additional_bound)
+                 .get_type_path ();
+           bool ok
+             = ResolveTypeToCanonicalPath::go (bound_type_path, bound_path);
+
+           if (!ok)
+             continue;
+
+           str = bound_path.get ();
+           break;
+         }
+       case AST::TypeParamBound::LIFETIME:
+         rust_unreachable ();
+         break;
+       }
+      slice_path += " + " + str;
+    }
+
+  slice_path += ">";
+
+  result = CanonicalPath::new_seg (type.get_node_id (), slice_path);
 }
 
 void
index ac5f1c575461fbe33374b403d4797f755b3d5334..40f067319b578ee926e2157a55cc0ed4dbba5588 100644 (file)
@@ -282,7 +282,8 @@ Late::visit (AST::TypePath &type)
     ctx.map_usage (Usage (type.get_node_id ()),
                   Definition (resolved->get_node_id ()));
   else
-    rust_unreachable ();
+    rust_error_at (type.get_locus (), "could not resolve type path %qs",
+                  str.c_str ());
 
   DefaultResolver::visit (type);
 }
diff --git a/gcc/testsuite/rust/compile/additional-trait-bounds1.rs b/gcc/testsuite/rust/compile/additional-trait-bounds1.rs
new file mode 100644 (file)
index 0000000..449a72f
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(optin_builtin_traits)]
+
+pub unsafe auto trait Send {}
+#[lang = "sync"]
+pub unsafe auto trait Sync {}
+
+trait A {}
+
+impl dyn A + Send {}
+impl dyn A + Send + Sync {}
diff --git a/gcc/testsuite/rust/compile/additional-trait-bounds2.rs b/gcc/testsuite/rust/compile/additional-trait-bounds2.rs
new file mode 100644 (file)
index 0000000..843228a
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(optin_builtin_traits)]
+
+pub unsafe auto trait Send {}
+#[lang = "sync"]
+pub unsafe auto trait Sync {}
+
+trait A {}
+
+impl dyn A + Send + Sync + NonExist {} // { dg-error "failed to resolve TypePath: NonExist in this scope" }
diff --git a/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs b/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs
new file mode 100644 (file)
index 0000000..6764f6e
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-additional-options "-frust-name-resolution-2.0" }
+
+#![feature(optin_builtin_traits)]
+
+pub unsafe auto trait Send {}
+#[lang = "sync"]
+pub unsafe auto trait Sync {}
+
+trait A {}
+
+impl dyn A + Send + Sync + NonExist {} // { dg-error "could not resolve type path .NonExist." }
index 797e59a5c5808095a929f9f03782811b9770fec6..8bdcc8ac3388157a1c2c4d4cc3f8e3b2fac7bc17 100644 (file)
@@ -208,4 +208,5 @@ issue-2905-2.rs
 issue-2907.rs
 issue-2423.rs
 issue-266.rs
+additional-trait-bounds2.rs
 # please don't delete the trailing newline