]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Add mechanism use pattern information to improve type info
authorPhilip Herron <herron.philip@googlemail.com>
Sun, 23 Apr 2023 21:41:21 +0000 (22:41 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:34:14 +0000 (18:34 +0100)
When we have an untyped closure we assumed all parameters were inference
variables but we can use the pattern type to try and improve the type info
so if we have a reference pattern it must be a reference to an inference
variables '&_'. This patch adds a new visitor to figure this out for
untyped closure parameters.

Note this test case does fully type resolve into the gimple:

    bool test::main::{{closure}}
        (struct test::main::{{closure}} $closure, struct (& u8) args)
    { ... }

Though the Rustc version does fail type-resolution but we make some
assumptions during comparison expressions here that they resolve to a bool
this will change when we implement the comparison lang items.

Fixes #2142

gcc/rust/ChangeLog:

* hir/tree/rust-hir-pattern.h: add missing get_mutability
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit):
use new ClosureParamInfer on untyped parameters
* typecheck/rust-hir-type-check-pattern.cc (ClosureParamInfer::Resolve): interface
(ClosureParamInfer::ClosureParamInfer): constructor
(ClosureParamInfer::visit): visitors for each pattern
* typecheck/rust-hir-type-check-pattern.h (class ClosureParamInfer): new visitor

gcc/testsuite/ChangeLog:

* rust/compile/issue-2142.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/hir/tree/rust-hir-pattern.h
gcc/rust/typecheck/rust-hir-type-check-expr.cc
gcc/rust/typecheck/rust-hir-type-check-pattern.cc
gcc/rust/typecheck/rust-hir-type-check-pattern.h
gcc/testsuite/rust/compile/issue-2142.rs [new file with mode: 0644]

index f6359f94316fa4e2a4f0c55d5707355667f1f17b..5fa9a1747a8676830587d12e4ebfa6f9d7d25558 100644 (file)
@@ -462,6 +462,8 @@ public:
 
   bool is_mut () const { return mut == Mutability::Mut; }
 
+  Mutability get_mutability () const { return mut; }
+
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRPatternVisitor &vis) override;
 
index f82204872c1d6059d35f97745f90770caac86420..3dafcd219c239d1dd63cf89f89197df8be135564 100644 (file)
@@ -1471,25 +1471,20 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
   std::vector<TyTy::TyVar> parameter_types;
   for (auto &p : expr.get_params ())
     {
+      TyTy::BaseType *param_tyty = nullptr;
       if (p.has_type_given ())
        {
-         TyTy::BaseType *param_tyty
-           = TypeCheckType::Resolve (p.get_type ().get ());
-         TyTy::TyVar param_ty (param_tyty->get_ref ());
-         parameter_types.push_back (param_ty);
-
-         TypeCheckPattern::Resolve (p.get_pattern ().get (),
-                                    param_ty.get_tyty ());
+         param_tyty = TypeCheckType::Resolve (p.get_type ().get ());
        }
       else
        {
-         TyTy::TyVar param_ty
-           = TyTy::TyVar::get_implicit_infer_var (p.get_locus ());
-         parameter_types.push_back (param_ty);
-
-         TypeCheckPattern::Resolve (p.get_pattern ().get (),
-                                    param_ty.get_tyty ());
+         param_tyty = ClosureParamInfer::Resolve (p.get_pattern ().get ());
        }
+
+      TyTy::TyVar param_ty (param_tyty->get_ref ());
+      parameter_types.push_back (param_ty);
+
+      TypeCheckPattern::Resolve (p.get_pattern ().get (), param_ty.get_tyty ());
     }
 
   // we generate an implicit hirid for the closure args
index bde707682387ed0695183a4a217a8f4cb12a21a9..1221bcc6244761596ebed58bac11c55abab31b63 100644 (file)
@@ -447,5 +447,116 @@ TypeCheckPattern::visit (HIR::AltPattern &pattern)
                 "type checking alternate patterns not supported");
 }
 
+TyTy::BaseType *
+ClosureParamInfer::Resolve (HIR::Pattern *pattern)
+{
+  ClosureParamInfer resolver;
+  pattern->accept_vis (resolver);
+
+  if (resolver.infered->get_kind () != TyTy::TypeKind::ERROR)
+    {
+      resolver.context->insert_implicit_type (resolver.infered);
+      resolver.mappings->insert_location (resolver.infered->get_ref (),
+                                         pattern->get_locus ());
+    }
+  return resolver.infered;
+}
+
+ClosureParamInfer::ClosureParamInfer ()
+  : TypeCheckBase (), infered (new TyTy::ErrorType (0))
+{}
+
+void
+ClosureParamInfer::visit (HIR::WildcardPattern &pattern)
+{
+  HirId id = pattern.get_pattern_mappings ().get_hirid ();
+  infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
+                                TyTy::InferType::TypeHint::Default (),
+                                pattern.get_locus ());
+}
+
+void
+ClosureParamInfer::visit (HIR::IdentifierPattern &pattern)
+{
+  HirId id = pattern.get_pattern_mappings ().get_hirid ();
+  infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
+                                TyTy::InferType::TypeHint::Default (),
+                                pattern.get_locus ());
+}
+
+void
+ClosureParamInfer::visit (HIR::ReferencePattern &pattern)
+{
+  TyTy::BaseType *element
+    = ClosureParamInfer::Resolve (pattern.get_referenced_pattern ().get ());
+
+  HirId id = pattern.get_pattern_mappings ().get_hirid ();
+  infered = new TyTy::ReferenceType (id, TyTy::TyVar (element->get_ref ()),
+                                    pattern.get_mutability ());
+}
+
+void
+ClosureParamInfer::visit (HIR::PathInExpression &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::StructPattern &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::TupleStructPattern &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::TuplePattern &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::LiteralPattern &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::RangePattern &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::QualifiedPathInExpression &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::SlicePattern &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
+void
+ClosureParamInfer::visit (HIR::AltPattern &pattern)
+{
+  rust_sorry_at (pattern.get_locus (),
+                "unable to infer this kind of parameter pattern");
+}
+
 } // namespace Resolver
 } // namespace Rust
index 93afe693ffd8c8876275a88efdf4e61c187cb284..4bf371ffa06cba9a0396c7af6d0fe6497663b61d 100644 (file)
@@ -58,6 +58,30 @@ private:
   TyTy::BaseType *infered;
 };
 
+class ClosureParamInfer : private TypeCheckBase, private HIR::HIRPatternVisitor
+{
+public:
+  static TyTy::BaseType *Resolve (HIR::Pattern *pattern);
+
+  void visit (HIR::PathInExpression &pattern) override;
+  void visit (HIR::StructPattern &pattern) override;
+  void visit (HIR::TupleStructPattern &pattern) override;
+  void visit (HIR::WildcardPattern &pattern) override;
+  void visit (HIR::TuplePattern &pattern) override;
+  void visit (HIR::LiteralPattern &pattern) override;
+  void visit (HIR::RangePattern &pattern) override;
+  void visit (HIR::IdentifierPattern &pattern) override;
+  void visit (HIR::QualifiedPathInExpression &pattern) override;
+  void visit (HIR::ReferencePattern &pattern) override;
+  void visit (HIR::SlicePattern &pattern) override;
+  void visit (HIR::AltPattern &pattern) override;
+
+private:
+  ClosureParamInfer ();
+
+  TyTy::BaseType *infered;
+};
+
 } // namespace Resolver
 } // namespace Rust
 
diff --git a/gcc/testsuite/rust/compile/issue-2142.rs b/gcc/testsuite/rust/compile/issue-2142.rs
new file mode 100644 (file)
index 0000000..7a8bb2a
--- /dev/null
@@ -0,0 +1,14 @@
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+    #[lang = "fn_once_output"]
+    type Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+fn main() {
+    let lambda = |&c| c != b'9';
+
+    let a = b'1';
+    lambda(&a);
+}