https://gcc.gnu.org/g:97a7ae203920812de36f3131bd096b499718c6fb

commit r16-2799-g97a7ae203920812de36f3131bd096b499718c6fb
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Mon May 5 21:07:20 2025 +0100

    gccrs: Emit error diagnostic for bad impl type usage
    
    Rust only allows impl traits to be used in the return position of
    functions.
    
    Fixes Rust-GCC#1485
    
    gcc/rust/ChangeLog:
    
            * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): allow 
impl type
            * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): likewise
            * hir/rust-ast-lower-type.cc (ASTLoweringType::ASTLoweringType): 
new flag for impl trait
            (ASTLoweringType::translate): pass flag
            (ASTLoweringType::visit): track impl trait tag
            (ASTLoweringType::emit_impl_trait_error): new diagnostic
            * hir/rust-ast-lower-type.h: add new field
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/impl_trait_diag.rs: New test.
            * rust/compile/issue-1485.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/hir/rust-ast-lower-implitem.cc       |  3 +-
 gcc/rust/hir/rust-ast-lower-item.cc           |  3 +-
 gcc/rust/hir/rust-ast-lower-type.cc           | 57 ++++++++++++++++++++-------
 gcc/rust/hir/rust-ast-lower-type.h            | 13 +++---
 gcc/testsuite/rust/compile/impl_trait_diag.rs | 17 ++++++++
 gcc/testsuite/rust/compile/issue-1485.rs      | 16 ++++++++
 6 files changed, 85 insertions(+), 24 deletions(-)

diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc 
b/gcc/rust/hir/rust-ast-lower-implitem.cc
index d815a71564ec..fc9fe1ace4a9 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.cc
+++ b/gcc/rust/hir/rust-ast-lower-implitem.cc
@@ -138,7 +138,8 @@ ASTLowerImplItem::visit (AST::Function &function)
 
   std::unique_ptr<HIR::Type> return_type
     = function.has_return_type () ? std::unique_ptr<HIR::Type> (
-       ASTLoweringType::translate (function.get_return_type ()))
+       ASTLoweringType::translate (function.get_return_type (), false,
+                                   true /* impl trait is allowed here*/))
                                  : nullptr;
 
   Defaultness defaultness
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc 
b/gcc/rust/hir/rust-ast-lower-item.cc
index f4396b58e595..1810d16d515d 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -411,7 +411,8 @@ ASTLoweringItem::visit (AST::Function &function)
 
   std::unique_ptr<HIR::Type> return_type
     = function.has_return_type () ? std::unique_ptr<HIR::Type> (
-       ASTLoweringType::translate (function.get_return_type ()))
+       ASTLoweringType::translate (function.get_return_type (), false,
+                                   true /* impl trait is allowed here*/))
                                  : nullptr;
 
   std::vector<HIR::FunctionParam> function_params;
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc 
b/gcc/rust/hir/rust-ast-lower-type.cc
index a678f189ac28..5aedb9196dc5 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -209,10 +209,17 @@ ASTLowerQualifiedPathInType::visit 
(AST::QualifiedPathInType &path)
                                             path.get_locus ());
 }
 
+ASTLoweringType::ASTLoweringType (bool default_to_static_lifetime,
+                                 bool impl_trait_allowed)
+  : ASTLoweringBase (), default_to_static_lifetime 
(default_to_static_lifetime),
+    impl_trait_allowed (impl_trait_allowed), translated (nullptr)
+{}
+
 HIR::Type *
-ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime)
+ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime,
+                           bool impl_trait_allowed)
 {
-  ASTLoweringType resolver (default_to_static_lifetime);
+  ASTLoweringType resolver (default_to_static_lifetime, impl_trait_allowed);
   type.accept_vis (resolver);
 
   rust_assert (resolver.translated != nullptr);
@@ -260,7 +267,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
 
       HIR::Type *param_type
        = ASTLoweringType::translate (param.get_type (),
-                                     default_to_static_lifetime);
+                                     default_to_static_lifetime,
+                                     impl_trait_allowed);
 
       HIR::MaybeNamedParam p (param.get_name (), kind,
                              std::unique_ptr<HIR::Type> (param_type),
@@ -272,7 +280,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
   if (fntype.has_return_type ())
     {
       return_type = ASTLoweringType::translate (fntype.get_return_type (),
-                                               default_to_static_lifetime);
+                                               default_to_static_lifetime,
+                                               impl_trait_allowed);
     }
 
   auto crate_num = mappings.get_current_crate ();
@@ -292,8 +301,8 @@ ASTLoweringType::visit (AST::TupleType &tuple)
   std::vector<std::unique_ptr<HIR::Type>> elems;
   for (auto &e : tuple.get_elems ())
     {
-      HIR::Type *t
-       = ASTLoweringType::translate (*e, default_to_static_lifetime);
+      HIR::Type *t = ASTLoweringType::translate (*e, 
default_to_static_lifetime,
+                                                impl_trait_allowed);
       elems.push_back (std::unique_ptr<HIR::Type> (t));
     }
 
@@ -323,7 +332,8 @@ ASTLoweringType::visit (AST::ArrayType &type)
 {
   HIR::Type *translated_type
     = ASTLoweringType::translate (type.get_elem_type (),
-                                 default_to_static_lifetime);
+                                 default_to_static_lifetime,
+                                 impl_trait_allowed);
   HIR::Expr *array_size = ASTLoweringExpr::translate (type.get_size_expr ());
 
   auto crate_num = mappings.get_current_crate ();
@@ -343,9 +353,9 @@ ASTLoweringType::visit (AST::ReferenceType &type)
   HIR::Lifetime lifetime
     = lower_lifetime (type.get_lifetime (), default_to_static_lifetime);
 
-  HIR::Type *base_type
-    = ASTLoweringType::translate (type.get_base_type (),
-                                 default_to_static_lifetime);
+  HIR::Type *base_type = ASTLoweringType::translate (type.get_base_type (),
+                                                    default_to_static_lifetime,
+                                                    impl_trait_allowed);
 
   auto crate_num = mappings.get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -364,7 +374,8 @@ ASTLoweringType::visit (AST::RawPointerType &type)
 {
   HIR::Type *base_type
     = ASTLoweringType::translate (type.get_type_pointed_to (),
-                                 default_to_static_lifetime);
+                                 default_to_static_lifetime,
+                                 impl_trait_allowed);
 
   auto crate_num = mappings.get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -384,9 +395,9 @@ ASTLoweringType::visit (AST::RawPointerType &type)
 void
 ASTLoweringType::visit (AST::SliceType &type)
 {
-  HIR::Type *base_type
-    = ASTLoweringType::translate (type.get_elem_type (),
-                                 default_to_static_lifetime);
+  HIR::Type *base_type = ASTLoweringType::translate (type.get_elem_type (),
+                                                    default_to_static_lifetime,
+                                                    impl_trait_allowed);
 
   auto crate_num = mappings.get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -463,7 +474,8 @@ void
 ASTLoweringType::visit (AST::ParenthesisedType &type)
 {
   auto *inner = ASTLoweringType::translate (*type.get_type_in_parens (),
-                                           default_to_static_lifetime);
+                                           default_to_static_lifetime,
+                                           impl_trait_allowed);
 
   auto crate_num = mappings.get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -480,6 +492,9 @@ ASTLoweringType::visit (AST::ParenthesisedType &type)
 void
 ASTLoweringType::visit (AST::ImplTraitType &type)
 {
+  if (!impl_trait_allowed)
+    emit_impl_trait_error (type.get_locus ());
+
   std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
   for (auto &bound : type.get_type_param_bounds ())
     {
@@ -499,6 +514,9 @@ ASTLoweringType::visit (AST::ImplTraitType &type)
 void
 ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type)
 {
+  if (!impl_trait_allowed)
+    emit_impl_trait_error (type.get_locus ());
+
   std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
 
   auto b = ASTLoweringTypeBounds::translate (type.get_trait_bound ());
@@ -513,6 +531,15 @@ ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type)
     = new HIR::ImplTraitType (mapping, std::move (bounds), type.get_locus ());
 }
 
+void
+ASTLoweringType::emit_impl_trait_error (location_t locus)
+{
+  rich_location r (line_table, locus);
+  rust_error_at (r, ErrorCode::E0562,
+                "%<impl Trait%> not allowed outside of function and inherent "
+                "method return types");
+}
+
 HIR::GenericParam *
 ASTLowerGenericParam::translate (AST::GenericParam &param)
 {
diff --git a/gcc/rust/hir/rust-ast-lower-type.h 
b/gcc/rust/hir/rust-ast-lower-type.h
index 4efaeee13149..50f543a357cf 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -66,7 +66,8 @@ class ASTLoweringType : public ASTLoweringBase
 
 public:
   static HIR::Type *translate (AST::Type &type,
-                              bool default_to_static_lifetime = false);
+                              bool default_to_static_lifetime = false,
+                              bool impl_trait_allowed = false);
 
   void visit (AST::BareFunctionType &fntype) override;
   void visit (AST::TupleType &tuple) override;
@@ -81,19 +82,17 @@ public:
   void visit (AST::TraitObjectTypeOneBound &type) override;
   void visit (AST::TraitObjectType &type) override;
   void visit (AST::ParenthesisedType &type) override;
-
   void visit (AST::ImplTraitType &type) override;
   void visit (AST::ImplTraitTypeOneBound &type) override;
 
+  void emit_impl_trait_error (location_t locus);
+
 private:
-  ASTLoweringType (bool default_to_static_lifetime)
-    : ASTLoweringBase (),
-      default_to_static_lifetime (default_to_static_lifetime),
-      translated (nullptr)
-  {}
+  ASTLoweringType (bool default_to_static_lifetime, bool impl_trait_allowed);
 
   /** Used when compiling const and static items. */
   bool default_to_static_lifetime;
+  bool impl_trait_allowed;
 
   HIR::Type *translated;
 };
diff --git a/gcc/testsuite/rust/compile/impl_trait_diag.rs 
b/gcc/testsuite/rust/compile/impl_trait_diag.rs
new file mode 100644
index 000000000000..54a0cd220a39
--- /dev/null
+++ b/gcc/testsuite/rust/compile/impl_trait_diag.rs
@@ -0,0 +1,17 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+trait Foo {
+    fn method(&self);
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {
+    let x: impl Foo = Bar; // { dg-error ".impl Trait. not allowed outside of 
function and inherent method return types .E0562." }
+
+    struct Wrapper {
+        field: impl Foo, // { dg-error ".impl Trait. not allowed outside of 
function and inherent method return types .E0562." }
+    }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1485.rs 
b/gcc/testsuite/rust/compile/issue-1485.rs
new file mode 100644
index 000000000000..a0cd5a0f1f92
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1485.rs
@@ -0,0 +1,16 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+    #[lang = "fn_once_output"]
+    type Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+struct BinOpInvalid {
+    lhs: i32,
+    rhs: i32,
+    f: impl FnOnce(i32) -> i32, // { dg-error ".impl Trait. not allowed 
outside of function and inherent method return types .E0562." }
+}

Reply via email to