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