]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix bad type inference
authorPhilip Herron <herron.philip@googlemail.com>
Thu, 23 Mar 2023 21:18:18 +0000 (21:18 +0000)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:21:14 +0000 (18:21 +0100)
gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-resolve.cc: don't inject extra inference variables

gcc/testsuite/ChangeLog:

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

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/typecheck/rust-hir-trait-resolve.cc
gcc/testsuite/rust/compile/issue-1893.rs [new file with mode: 0644]

index 767e56c5929a19bdebf6d4ff260a6baba39fe46c..48ffd088542e307d498f941e1807e2efe96ff3c6 100644 (file)
@@ -472,7 +472,7 @@ AssociatedImplTrait::setup_associated_types (
   TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), {},
                                                      locus, param_subst_cb);
   TyTy::BaseType *impl_self_infer
-    = (associated_self->needs_generic_substitutions ())
+    = (!associated_self->is_concrete ())
        ? SubstMapperInternal::Resolve (associated_self, infer_arguments)
        : associated_self;
 
@@ -495,19 +495,6 @@ AssociatedImplTrait::setup_associated_types (
       impl_trait_predicate_args.push_back (r);
     }
 
-  // we need to unify the receiver with the impl-block Self so that we compute
-  // the type correctly as our receiver may be generic and we are inferring its
-  // generic arguments and this Self might be the concrete version or vice
-  // versa.
-  auto result = unify_site_and (get_impl_block ()->get_mappings ().get_hirid (),
-                               TyTy::TyWithLocation (receiver),
-                               TyTy::TyWithLocation (impl_self_infer),
-                               impl_predicate.get_locus (),
-                               true /*emit-errors*/, true /*commit-if-ok*/,
-                               true /*infer*/, true /*cleanup-on-fail*/);
-  rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
-  TyTy::BaseType *self_result = result;
-
   // unify the bounds arguments
   std::vector<TyTy::BaseType *> hrtb_bound_arguments;
   for (const auto &arg : bound.get_substs ())
@@ -520,22 +507,34 @@ AssociatedImplTrait::setup_associated_types (
       hrtb_bound_arguments.push_back (r);
     }
 
-  if (impl_trait_predicate_args.size () != hrtb_bound_arguments.size ())
-    return self_result;
-
+  rust_assert (impl_trait_predicate_args.size ()
+              == hrtb_bound_arguments.size ());
   for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
     {
       TyTy::BaseType *a = impl_trait_predicate_args.at (i);
       TyTy::BaseType *b = hrtb_bound_arguments.at (i);
 
-      result
+      TyTy::BaseType *result
        = unify_site_and (a->get_ref (), TyTy::TyWithLocation (a),
                          TyTy::TyWithLocation (b), impl_predicate.get_locus (),
                          true /*emit-errors*/, true /*commit-if-ok*/,
-                         true /*infer*/, true /*cleanup-on-fail*/);
+                         false /*infer*/, true /*cleanup-on-fail*/);
       rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
     }
 
+  // we need to unify the receiver with the impl-block Self so that we compute
+  // the type correctly as our receiver may be generic and we are inferring its
+  // generic arguments and this Self might be the concrete version or vice
+  // versa.
+  auto result = unify_site_and (get_impl_block ()->get_mappings ().get_hirid (),
+                               TyTy::TyWithLocation (receiver),
+                               TyTy::TyWithLocation (impl_self_infer),
+                               impl_predicate.get_locus (),
+                               true /*emit-errors*/, true /*commit-if-ok*/,
+                               false /*infer*/, true /*cleanup-on-fail*/);
+  rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+  TyTy::BaseType *self_result = result;
+
   // create the argument list
   std::vector<TyTy::SubstitutionArg> associated_arguments;
   for (auto &p : substitutions)
diff --git a/gcc/testsuite/rust/compile/issue-1893.rs b/gcc/testsuite/rust/compile/issue-1893.rs
new file mode 100644 (file)
index 0000000..ff8bef7
--- /dev/null
@@ -0,0 +1,42 @@
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+pub enum Result<T, E> {
+    Ok(T),
+    Err(E),
+}
+
+pub trait TryFrom<T> {
+    /// The type returned in the event of a conversion error.
+    type Error;
+
+    /// Performs the conversion.
+    fn try_from(value: T) -> Result<Self, Self::Error>;
+}
+
+pub trait From<T> {
+    fn from(_: T) -> Self;
+}
+
+impl<T> From<T> for T {
+    fn from(t: T) -> T {
+        t
+    }
+}
+
+impl<T, U> TryFrom<U> for T
+where
+    T: From<U>,
+{
+    type Error = !;
+
+    fn try_from(value: U) -> Result<Self, Self::Error> {
+        Result::Ok(T::from(value))
+    }
+}
+
+pub fn test(n: usize) {
+    let _a = <usize>::try_from(n);
+}