]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Emit error diagnostic for bad impl type usage
authorPhilip Herron <herron.philip@googlemail.com>
Mon, 5 May 2025 20:07:20 +0000 (21:07 +0100)
committerPhilip Herron <philip.herron@embecosm.com>
Wed, 7 May 2025 12:04:19 +0000 (12:04 +0000)
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.philip@googlemail.com>
gcc/rust/hir/rust-ast-lower-implitem.cc
gcc/rust/hir/rust-ast-lower-item.cc
gcc/rust/hir/rust-ast-lower-type.cc
gcc/rust/hir/rust-ast-lower-type.h
gcc/testsuite/rust/compile/impl_trait_diag.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/issue-1485.rs [new file with mode: 0644]

index 66488ac7892d4e95e9a6a2564929813d76231bcf..c06e88f2b695bfdff723e6c4e391446febac4afa 100644 (file)
@@ -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
index 47b4b71974a4424fd22d51c2f29f28a0890f7145..9bb968f028f8eb9b668d8048a3ced69a1fee5d0d 100644 (file)
@@ -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;
index baffbf8b5e39622433778c8e1ce71d229272f2a0..d871583253c734a06eabab32f2c6e2df04803479 100644 (file)
@@ -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)
 {
index 35862981e48eda78b5cea4607c712223b09d5fe4..72a361f93394e7a4e60fd10a9e2d90f0acdbdbda 100644 (file)
@@ -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 (file)
index 0000000..54a0cd2
--- /dev/null
@@ -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 (file)
index 0000000..a0cd5a0
--- /dev/null
@@ -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." }
+}