From: Arthur Cohen <arthur.co...@embecosm.com>

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     | 57 ++++++++++++++++++-
 .../resolve/rust-late-name-resolver-2.0.cc    |  3 +-
 .../rust/compile/additional-trait-bounds1.rs  | 10 ++++
 .../rust/compile/additional-trait-bounds2.rs  |  9 +++
 .../compile/additional-trait-bounds2nr2.rs    | 11 ++++
 gcc/testsuite/rust/compile/nr2/exclude        |  1 +
 6 files changed, 87 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/additional-trait-bounds1.rs
 create mode 100644 gcc/testsuite/rust/compile/additional-trait-bounds2.rs
 create mode 100644 gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs

diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc 
b/gcc/rust/resolve/rust-ast-resolve-type.cc
index ec5e8a762a7..cb5a18d5d47 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -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
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index ac5f1c57546..40f067319b5 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -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
index 00000000000..449a72fe461
--- /dev/null
+++ b/gcc/testsuite/rust/compile/additional-trait-bounds1.rs
@@ -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
index 00000000000..843228ae9a6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/additional-trait-bounds2.rs
@@ -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
index 00000000000..6764f6e8012
--- /dev/null
+++ b/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs
@@ -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." }
diff --git a/gcc/testsuite/rust/compile/nr2/exclude 
b/gcc/testsuite/rust/compile/nr2/exclude
index 797e59a5c58..8bdcc8ac338 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -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
-- 
2.45.2

Reply via email to