about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-03-20 01:59:38 +0000
committerMichael Goulet <michael@errs.io>2025-03-20 02:17:14 +0000
commit220851cc75558d06df98c7650b50d59ef2b5e348 (patch)
treef8fc2057fa27b06825427ff319e8e5515cf93faa
parent2947be7af8732d1c298a15030325cc50c8910061 (diff)
downloadrust-220851cc75558d06df98c7650b50d59ef2b5e348.tar.gz
rust-220851cc75558d06df98c7650b50d59ef2b5e348.zip
Do not rely on type_var_origin in OrphanCheckErr::NonLocalInputType
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs63
-rw-r--r--compiler/rustc_next_trait_solver/src/coherence.rs5
-rw-r--r--compiler/rustc_type_ir/src/macros.rs13
-rw-r--r--tests/crashes/132826.rs10
-rw-r--r--tests/ui/coherence/orphan-check-error-reporting-ty-var.rs17
-rw-r--r--tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr16
6 files changed, 60 insertions, 64 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 0b7fc44460e..74ba4ffe25e 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -3,11 +3,10 @@
 
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::ErrorGuaranteed;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
 use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
 use rustc_middle::ty::{
-    self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -356,13 +355,20 @@ fn orphan_check<'tcx>(
             })
         }
         OrphanCheckErr::NonLocalInputType(tys) => {
-            let generics = tcx.generics_of(impl_def_id);
-            let tys = tys
-                .into_iter()
-                .map(|(ty, is_target_ty)| {
-                    (ty.fold_with(&mut TyVarReplacer { infcx: &infcx, generics }), is_target_ty)
-                })
-                .collect();
+            let tys = infcx.probe(|_| {
+                // Map the unconstrained args back to their params,
+                // ignoring any type unification errors.
+                for (arg, id_arg) in
+                    std::iter::zip(args, ty::GenericArgs::identity_for_item(tcx, impl_def_id))
+                {
+                    let _ = infcx.at(&cause, ty::ParamEnv::empty()).eq(
+                        DefineOpaqueTypes::No,
+                        arg,
+                        id_arg,
+                    );
+                }
+                infcx.resolve_vars_if_possible(tys)
+            });
             OrphanCheckErr::NonLocalInputType(tys)
         }
     })
@@ -536,40 +542,3 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> {
         }
     }
 }
-
-struct TyVarReplacer<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'tcx>,
-    generics: &'tcx ty::Generics,
-}
-
-impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
-            return ty;
-        }
-        let ty::Infer(ty::TyVar(vid)) = *ty.kind() else {
-            return ty.super_fold_with(self);
-        };
-        let origin = self.infcx.type_var_origin(vid);
-        if let Some(def_id) = origin.param_def_id {
-            // The generics of an `impl` don't have a parent, we can index directly.
-            let index = self.generics.param_def_id_to_index[&def_id];
-            let name = self.generics.own_params[index as usize].name;
-
-            Ty::new_param(self.infcx.tcx, index, name)
-        } else {
-            ty
-        }
-    }
-
-    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if !ct.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
-            return ct;
-        }
-        ct.super_fold_with(self)
-    }
-}
diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs
index 53290203600..f8215a228f5 100644
--- a/compiler/rustc_next_trait_solver/src/coherence.rs
+++ b/compiler/rustc_next_trait_solver/src/coherence.rs
@@ -4,7 +4,8 @@ use std::ops::ControlFlow;
 use derive_where::derive_where;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::{
-    self as ty, InferCtxtLike, Interner, TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self as ty, InferCtxtLike, Interner, TrivialTypeTraversalImpls, TypeVisitable,
+    TypeVisitableExt, TypeVisitor,
 };
 use tracing::instrument;
 
@@ -95,6 +96,8 @@ pub fn trait_ref_is_local_or_fundamental<I: Interner>(tcx: I, trait_ref: ty::Tra
     trait_ref.def_id.is_local() || tcx.trait_is_fundamental(trait_ref.def_id)
 }
 
+TrivialTypeTraversalImpls! { IsFirstInputType, }
+
 #[derive(Debug, Copy, Clone)]
 pub enum IsFirstInputType {
     No,
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index fab1a11304d..c8c293121ca 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -1,10 +1,11 @@
 /// Used for types that are `Copy` and which **do not care arena
 /// allocated data** (i.e., don't need to be folded).
+#[macro_export]
 macro_rules! TrivialTypeTraversalImpls {
     ($($ty:ty,)+) => {
         $(
-            impl<I: $crate::Interner> $crate::fold::TypeFoldable<I> for $ty {
-                fn try_fold_with<F: $crate::fold::FallibleTypeFolder<I>>(
+            impl<I: $crate::Interner> $crate::TypeFoldable<I> for $ty {
+                fn try_fold_with<F: $crate::FallibleTypeFolder<I>>(
                     self,
                     _: &mut F,
                 ) -> ::std::result::Result<Self, F::Error> {
@@ -12,7 +13,7 @@ macro_rules! TrivialTypeTraversalImpls {
                 }
 
                 #[inline]
-                fn fold_with<F: $crate::fold::TypeFolder<I>>(
+                fn fold_with<F: $crate::TypeFolder<I>>(
                     self,
                     _: &mut F,
                 ) -> Self {
@@ -20,14 +21,14 @@ macro_rules! TrivialTypeTraversalImpls {
                 }
             }
 
-            impl<I: $crate::Interner> $crate::visit::TypeVisitable<I> for $ty {
+            impl<I: $crate::Interner> $crate::TypeVisitable<I> for $ty {
                 #[inline]
-                fn visit_with<F: $crate::visit::TypeVisitor<I>>(
+                fn visit_with<F: $crate::TypeVisitor<I>>(
                     &self,
                     _: &mut F)
                     -> F::Result
                 {
-                    <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
+                    <F::Result as $crate::VisitorResult>::output()
                 }
             }
         )+
diff --git a/tests/crashes/132826.rs b/tests/crashes/132826.rs
deleted file mode 100644
index 9889cecdac5..00000000000
--- a/tests/crashes/132826.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ known-bug: #132826
-pub trait MyTrait {
-    type Item;
-}
-
-impl<K> MyTrait for Vec<K> {
-    type Item = Vec<K>;
-}
-
-impl<K> From<Vec<K>> for <Vec<K> as MyTrait>::Item {}
diff --git a/tests/ui/coherence/orphan-check-error-reporting-ty-var.rs b/tests/ui/coherence/orphan-check-error-reporting-ty-var.rs
new file mode 100644
index 00000000000..99a83453354
--- /dev/null
+++ b/tests/ui/coherence/orphan-check-error-reporting-ty-var.rs
@@ -0,0 +1,17 @@
+// Regression test for #132826.
+
+// Make sure we don't try to resolve the variable `K1` in the generics of the impl
+// (which only has `K2`).
+
+pub trait MyTrait {
+    type Item;
+}
+
+impl<K1> MyTrait for Vec<K1> {
+    type Item = Vec<K1>;
+}
+
+impl<K2> From<Vec<K2>> for <Vec<K2> as MyTrait>::Item {}
+//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
+
+fn main() {}
diff --git a/tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr b/tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr
new file mode 100644
index 00000000000..f229f8b2e38
--- /dev/null
+++ b/tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr
@@ -0,0 +1,16 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/orphan-check-error-reporting-ty-var.rs:14:1
+   |
+LL | impl<K2> From<Vec<K2>> for <Vec<K2> as MyTrait>::Item {}
+   | ^^^^^^^^^-------------^^^^^--------------------------
+   |          |                 |
+   |          |                 `Vec` is not defined in the current crate
+   |          `Vec` is not defined in the current crate
+   |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0117`.