From 220851cc75558d06df98c7650b50d59ef2b5e348 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Mar 2025 01:59:38 +0000 Subject: [PATCH] Do not rely on type_var_origin in OrphanCheckErr::NonLocalInputType --- .../src/coherence/orphan.rs | 63 +++++-------------- .../rustc_next_trait_solver/src/coherence.rs | 5 +- compiler/rustc_type_ir/src/macros.rs | 13 ++-- tests/crashes/132826.rs | 10 --- .../orphan-check-error-reporting-ty-var.rs | 17 +++++ ...orphan-check-error-reporting-ty-var.stderr | 16 +++++ 6 files changed, 60 insertions(+), 64 deletions(-) delete mode 100644 tests/crashes/132826.rs create mode 100644 tests/ui/coherence/orphan-check-error-reporting-ty-var.rs create mode 100644 tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 0b7fc44460ead..74ba4ffe25ea1 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> for UncoveredTyParamCollector<'_, 'tcx> { } } } - -struct TyVarReplacer<'cx, 'tcx> { - infcx: &'cx InferCtxt<'tcx>, - generics: &'tcx ty::Generics, -} - -impl<'cx, 'tcx> TypeFolder> 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 5329020360053..f8215a228f5b6 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(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 fab1a11304d57..c8c293121ca0a 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 $crate::fold::TypeFoldable for $ty { - fn try_fold_with>( + impl $crate::TypeFoldable for $ty { + fn try_fold_with>( self, _: &mut F, ) -> ::std::result::Result { @@ -12,7 +13,7 @@ macro_rules! TrivialTypeTraversalImpls { } #[inline] - fn fold_with>( + fn fold_with>( self, _: &mut F, ) -> Self { @@ -20,14 +21,14 @@ macro_rules! TrivialTypeTraversalImpls { } } - impl $crate::visit::TypeVisitable for $ty { + impl $crate::TypeVisitable for $ty { #[inline] - fn visit_with>( + fn visit_with>( &self, _: &mut F) -> F::Result { - ::output() + ::output() } } )+ diff --git a/tests/crashes/132826.rs b/tests/crashes/132826.rs deleted file mode 100644 index 9889cecdac541..0000000000000 --- a/tests/crashes/132826.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #132826 -pub trait MyTrait { - type Item; -} - -impl MyTrait for Vec { - type Item = Vec; -} - -impl From> for 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 0000000000000..99a8345335448 --- /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 MyTrait for Vec { + type Item = Vec; +} + +impl From> for 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 0000000000000..f229f8b2e385e --- /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 From> for 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`.