From: Arthur Cohen <[email protected]>
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