From 6738c1ec14f004400d4acd9ec4dfab863badb267 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Sun, 4 Aug 2024 19:52:15 +0300 Subject: [PATCH 1/5] Make `DeepRejectCtxt` symmetric with respect to `TreatParams` --- .../src/coherence/inherent_impls.rs | 5 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 14 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 12 +- .../src/solve/normalizes_to/mod.rs | 10 +- .../src/solve/trait_goals.rs | 2 +- .../error_reporting/infer/note_and_explain.rs | 24 +- .../src/traits/coherence.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 6 +- .../traits/specialize/specialization_graph.rs | 6 +- compiler/rustc_type_ir/src/fast_reject.rs | 340 +++++++++--------- src/librustdoc/html/render/write_shared.rs | 6 +- 14 files changed, 235 insertions(+), 202 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 89acb778d6c29..3ca43955e3102 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -90,7 +90,8 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) { + if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) + { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected self type: {:?}", self_ty); @@ -129,7 +130,7 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) { + if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::InstantiateWithInfer) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected primitive type: {:?}", ty); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 28f537c87c4ee..a566759091209 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -714,7 +714,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { - let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else { + let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3b71e2f19b168..52a3bcb84dbfe 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2234,8 +2234,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let target_ty = self .autoderef(sugg_span, rcvr_ty) .find(|(rcvr_ty, _)| { - DeepRejectCtxt::new(self.tcx, TreatParams::ForLookup) - .types_may_unify(*rcvr_ty, impl_ty) + DeepRejectCtxt::new( + self.tcx, + TreatParams::AsRigid, + TreatParams::InstantiateWithInfer, + ) + .types_may_unify(*rcvr_ty, impl_ty) }) .map_or(impl_ty, |(ty, _)| ty) .peel_refs(); @@ -2497,7 +2501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .any(|info| self.associated_value(info.def_id, item_name).is_some()); let found_assoc = |ty: Ty<'tcx>| { - simplify_type(tcx, ty, TreatParams::AsCandidateKey) + simplify_type(tcx, ty, TreatParams::InstantiateWithInfer) .and_then(|simp| { tcx.incoherent_impls(simp) .into_iter() @@ -3927,7 +3931,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // cases where a positive bound implies a negative impl. (candidates, Vec::new()) } else if let Some(simp_rcvr_ty) = - simplify_type(self.tcx, rcvr_ty, TreatParams::ForLookup) + simplify_type(self.tcx, rcvr_ty, TreatParams::AsRigid) { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); @@ -3945,7 +3949,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .any(|header| { let imp = header.trait_ref.instantiate_identity(); let imp_simp = - simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup); + simplify_type(self.tcx, imp.self_ty(), TreatParams::AsRigid); imp_simp.is_some_and(|s| s == simp_rcvr_ty) }) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0d83f8c6c5c93..f8128e988e257 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2017,7 +2017,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), - TreatParams::AsCandidateKey, + TreatParams::InstantiateWithInfer, ); trait_impls .entry(trait_ref.def_id) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 83799e40868fc..5c4fa09a51d62 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -437,7 +437,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { let simp = ty::fast_reject::simplify_type( tcx, self_ty, - ty::fast_reject::TreatParams::ForLookup, + ty::fast_reject::TreatParams::AsRigid, ) .unwrap(); consider_impls_for_simplified_type(simp); diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index dfb137f738f1e..82690f70e5f18 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -168,9 +168,9 @@ impl<'tcx> TyCtxt<'tcx> { // whose outer level is not a parameter or projection. Especially for things like // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. - // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using - // `TreatParams::AsCandidateKey` while actually adding them. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup) { + // Note that we're using `TreatParams::AsRigid` to query `non_blanket_impls` while using + // `TreatParams::InstantiateWithInfer` while actually adding them. + if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsRigid) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { f(impl_def_id); @@ -190,7 +190,9 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, ) -> impl Iterator + 'tcx { let impls = self.trait_impls_of(trait_def_id); - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) { + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, TreatParams::InstantiateWithInfer) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { return impls.iter().copied(); } @@ -239,7 +241,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey) + fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::InstantiateWithInfer) { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 5738173c7a804..861f032e268dc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -144,10 +144,12 @@ where let goal_trait_ref = goal.predicate.alias.trait_ref(cx); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); - if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup).args_may_unify( - goal.predicate.alias.trait_ref(cx).args, - impl_trait_ref.skip_binder().args, - ) { + if !DeepRejectCtxt::new(ecx.cx(), TreatParams::AsRigid, TreatParams::InstantiateWithInfer) + .args_may_unify( + goal.predicate.alias.trait_ref(cx).args, + impl_trait_ref.skip_binder().args, + ) + { return Err(NoSolution); } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 1314b7eb6ffc6..67442e264b69b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -47,7 +47,7 @@ where let cx = ecx.cx(); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); - if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup) + if !DeepRejectCtxt::new(ecx.cx(), TreatParams::AsRigid, TreatParams::InstantiateWithInfer) .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 05c79170902de..b0d23efebfcca 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -316,8 +316,12 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) - .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + if DeepRejectCtxt::new( + tcx, + TreatParams::AsRigid, + TreatParams::InstantiateWithInfer, + ) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) { has_matching_impl = true; } @@ -337,8 +341,12 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.expected, |did| { - if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) - .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) + if DeepRejectCtxt::new( + tcx, + TreatParams::AsRigid, + TreatParams::InstantiateWithInfer, + ) + .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) { has_matching_impl = true; } @@ -357,8 +365,12 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) - .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + if DeepRejectCtxt::new( + tcx, + TreatParams::AsRigid, + TreatParams::InstantiateWithInfer, + ) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) { has_matching_impl = true; } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 2d843d8f17406..61a1b26132f53 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -94,7 +94,11 @@ pub fn overlapping_impls( // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. - let drcx = DeepRejectCtxt::new(tcx, TreatParams::AsCandidateKey); + let drcx = DeepRejectCtxt::new( + tcx, + TreatParams::InstantiateWithInfer, + TreatParams::InstantiateWithInfer, + ); let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cb8deeaedb66f..84090c7606b92 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -580,7 +580,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - let drcx = DeepRejectCtxt::new(self.tcx(), TreatParams::ForLookup); + let drcx = DeepRejectCtxt::new( + self.tcx(), + TreatParams::AsRigid, + TreatParams::InstantiateWithInfer, + ); let obligation_args = obligation.predicate.skip_binder().trait_ref.args; self.tcx().for_each_relevant_impl( obligation.predicate.def_id(), diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 732f1b0a3d7cc..c0a712cbf9fd8 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -40,7 +40,7 @@ impl<'tcx> Children { fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); if let Some(st) = - fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey) + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) @@ -57,7 +57,7 @@ impl<'tcx> Children { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let vec: &mut Vec; if let Some(st) = - fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey) + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); @@ -278,7 +278,7 @@ impl<'tcx> Graph { let mut parent = trait_def_id; let mut last_lint = None; let simplified = - fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey); + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer); // Descend the specialization tree, where `parent` is the current parent node. loop { diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index fab4a0991175d..b08a971bf21b2 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -74,13 +74,13 @@ impl> ToStableHashKey for SimplifiedType pub enum TreatParams { /// Treat parameters as infer vars. This is the correct mode for caching /// an impl's type for lookup. - AsCandidateKey, + InstantiateWithInfer, /// Treat parameters as placeholders in the given environment. This is the /// correct mode for *lookup*, as during candidate selection. /// /// This also treats projections with inference variables as infer vars /// since they could be further normalized. - ForLookup, + AsRigid, } /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. @@ -140,18 +140,16 @@ pub fn simplify_type( } ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Param(_) => match treat_params { - TreatParams::ForLookup => Some(SimplifiedType::Placeholder), - TreatParams::AsCandidateKey => None, + TreatParams::AsRigid => Some(SimplifiedType::Placeholder), + TreatParams::InstantiateWithInfer => None, }, ty::Alias(..) => match treat_params { // When treating `ty::Param` as a placeholder, projections also // don't unify with anything else as long as they are fully normalized. // FIXME(-Znext-solver): Can remove this `if` and always simplify to `Placeholder` // when the new solver is enabled by default. - TreatParams::ForLookup if !ty.has_non_region_infer() => { - Some(SimplifiedType::Placeholder) - } - TreatParams::ForLookup | TreatParams::AsCandidateKey => None, + TreatParams::AsRigid if !ty.has_non_region_infer() => Some(SimplifiedType::Placeholder), + TreatParams::AsRigid | TreatParams::InstantiateWithInfer => None, }, ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), ty::Error(_) => Some(SimplifiedType::Error), @@ -173,27 +171,26 @@ impl SimplifiedType { } } -/// Given generic arguments from an obligation and an impl, -/// could these two be unified after replacing parameters in the -/// the impl with inference variables. +/// Given generic arguments, could they be unified after +/// replacing parameters with inference variables or placeholders. +/// This behavior is toggled using the `TreatParams` fields. /// -/// For obligations, parameters won't be replaced by inference -/// variables and only unify with themselves. We treat them -/// the same way we treat placeholders. +/// We use this to quickly reject impl/wc candidates without needing +/// to instantiate generic arguments/having to enter a probe. /// /// We also use this function during coherence. For coherence the /// impls only have to overlap for some value, so we treat parameters -/// on both sides like inference variables. This behavior is toggled -/// using the `treat_obligation_params` field. +/// on both sides like inference variables. #[derive(Debug, Clone, Copy)] pub struct DeepRejectCtxt { - treat_obligation_params: TreatParams, + treat_lhs_params: TreatParams, + treat_rhs_params: TreatParams, _interner: PhantomData, } impl DeepRejectCtxt { - pub fn new(_interner: I, treat_obligation_params: TreatParams) -> Self { - DeepRejectCtxt { treat_obligation_params, _interner: PhantomData } + pub fn new(_interner: I, treat_lhs_params: TreatParams, treat_rhs_params: TreatParams) -> Self { + DeepRejectCtxt { treat_lhs_params, treat_rhs_params, _interner: PhantomData } } pub fn args_may_unify( @@ -216,181 +213,184 @@ impl DeepRejectCtxt { }) } - pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool { - match impl_ty.kind() { - // Start by checking whether the type in the impl may unify with - // pretty much everything. Just return `true` in that case. - ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true, - // These types only unify with inference variables or their own - // variant. - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(..) - | ty::Str - | ty::Array(..) - | ty::Slice(..) - | ty::RawPtr(..) - | ty::Dynamic(..) - | ty::Pat(..) - | ty::Ref(..) - | ty::Never - | ty::Tuple(..) - | ty::FnPtr(..) - | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()), - ty::FnDef(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Placeholder(..) - | ty::Bound(..) - | ty::Infer(_) => panic!("unexpected impl_ty: {impl_ty:?}"), - } + pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { + match (lhs.kind(), rhs.kind()) { + (ty::Error(_), _) | (_, ty::Error(_)) => true, - let k = impl_ty.kind(); - match obligation_ty.kind() { - // Purely rigid types, use structural equivalence. - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::Never - | ty::Foreign(_) => obligation_ty == impl_ty, - ty::Ref(_, obl_ty, obl_mutbl) => match k { - ty::Ref(_, impl_ty, impl_mutbl) => { - obl_mutbl == impl_mutbl && self.types_may_unify(obl_ty, impl_ty) - } - _ => false, - }, - ty::Adt(obl_def, obl_args) => match k { - ty::Adt(impl_def, impl_args) => { - obl_def == impl_def && self.args_may_unify(obl_args, impl_args) + // As we're walking the whole type, it may encounter projections + // inside of binders and what not, so we're just going to assume that + // projections can unify with other stuff. + // + // Looking forward to lazy normalization this is the safer strategy anyways. + (ty::Alias(..), _) | (_, ty::Alias(..)) => true, + + // Bound type variables may unify with rigid types e.g. when using + // non-lifetime binders. + (ty::Bound(..), _) | (_, ty::Bound(..)) => true, + + (ty::Infer(var), _) => self.var_and_ty_may_unify(var, rhs), + (_, ty::Infer(var)) => self.var_and_ty_may_unify(var, lhs), + + (ty::Param(lhs), ty::Param(rhs)) => { + match (self.treat_lhs_params, self.treat_rhs_params) { + (TreatParams::AsRigid, TreatParams::AsRigid) => lhs == rhs, + (TreatParams::InstantiateWithInfer, _) + | (_, TreatParams::InstantiateWithInfer) => true, } - _ => false, - }, - ty::Pat(obl_ty, _) => { - // FIXME(pattern_types): take pattern into account - matches!(k, ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty)) } - ty::Slice(obl_ty) => { - matches!(k, ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty)) + (ty::Param(_), _) => self.treat_lhs_params == TreatParams::InstantiateWithInfer, + (_, ty::Param(_)) => self.treat_rhs_params == TreatParams::InstantiateWithInfer, + + // Placeholder types don't unify with anything on their own. + (ty::Placeholder(lhs), ty::Placeholder(rhs)) => lhs == rhs, + + // Purely rigid types, use structural equivalence. + (ty::Bool, ty::Bool) + | (ty::Char, ty::Char) + | (ty::Int(_), ty::Int(_)) + | (ty::Uint(_), ty::Uint(_)) + | (ty::Float(_), ty::Float(_)) + | (ty::Str, ty::Str) + | (ty::Never, ty::Never) + | (ty::Foreign(_), ty::Foreign(_)) => lhs == rhs, + + (ty::Ref(_, lhs_ty, lhs_mutbl), ty::Ref(_, rhs_ty, rhs_mutbl)) => { + lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) } - ty::Array(obl_ty, obl_len) => match k { - ty::Array(impl_ty, impl_len) => { - self.types_may_unify(obl_ty, impl_ty) - && self.consts_may_unify(obl_len, impl_len) - } - _ => false, - }, - ty::Tuple(obl) => match k { - ty::Tuple(imp) => { - obl.len() == imp.len() - && iter::zip(obl.iter(), imp.iter()) - .all(|(obl, imp)| self.types_may_unify(obl, imp)) - } - _ => false, - }, - ty::RawPtr(obl_ty, obl_mutbl) => match k { - ty::RawPtr(imp_ty, imp_mutbl) => { - obl_mutbl == imp_mutbl && self.types_may_unify(obl_ty, imp_ty) - } - _ => false, - }, - ty::Dynamic(obl_preds, ..) => { - // Ideally we would walk the existential predicates here or at least - // compare their length. But considering that the relevant `Relate` impl - // actually sorts and deduplicates these, that doesn't work. - matches!(k, ty::Dynamic(impl_preds, ..) if - obl_preds.principal_def_id() == impl_preds.principal_def_id() - ) + + (ty::Adt(lhs_def, lhs_args), ty::Adt(rhs_def, rhs_args)) => { + lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args) } - ty::FnPtr(obl_sig_tys, obl_hdr) => match k { - ty::FnPtr(impl_sig_tys, impl_hdr) => { - let obl_sig_tys = obl_sig_tys.skip_binder().inputs_and_output; - let impl_sig_tys = impl_sig_tys.skip_binder().inputs_and_output; - - obl_hdr == impl_hdr - && obl_sig_tys.len() == impl_sig_tys.len() - && iter::zip(obl_sig_tys.iter(), impl_sig_tys.iter()) - .all(|(obl, imp)| self.types_may_unify(obl, imp)) - } - _ => false, - }, - // Impls cannot contain these types as these cannot be named directly. - ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) => false, + (ty::Pat(lhs_ty, _), ty::Pat(rhs_ty, _)) => { + // FIXME(pattern_types): take pattern into account + self.types_may_unify(lhs_ty, rhs_ty) + } - // Placeholder types don't unify with anything on their own - ty::Placeholder(..) | ty::Bound(..) => false, + (ty::Slice(lhs_ty), ty::Slice(rhs_ty)) => self.types_may_unify(lhs_ty, rhs_ty), - // Depending on the value of `treat_obligation_params`, we either - // treat generic parameters like placeholders or like inference variables. - ty::Param(_) => match self.treat_obligation_params { - TreatParams::ForLookup => false, - TreatParams::AsCandidateKey => true, - }, + (ty::Array(lhs_ty, lhs_len), ty::Array(rhs_ty, rhs_len)) => { + self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) + } - ty::Infer(ty::IntVar(_)) => impl_ty.is_integral(), + (ty::Tuple(lhs), ty::Tuple(rhs)) => { + lhs.len() == rhs.len() + && iter::zip(lhs.iter(), rhs.iter()) + .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) + } - ty::Infer(ty::FloatVar(_)) => impl_ty.is_floating_point(), + (ty::RawPtr(lhs_ty, lhs_mutbl), ty::RawPtr(rhs_ty, rhs_mutbl)) => { + lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) + } - ty::Infer(_) => true, + (ty::Dynamic(lhs_preds, ..), ty::Dynamic(rhs_preds, ..)) => { + // Ideally we would walk the existential predicates here or at least + // compare their length. But considering that the relevant `Relate` impl + // actually sorts and deduplicates these, that doesn't work. + lhs_preds.principal_def_id() == rhs_preds.principal_def_id() + } - // As we're walking the whole type, it may encounter projections - // inside of binders and what not, so we're just going to assume that - // projections can unify with other stuff. - // - // Looking forward to lazy normalization this is the safer strategy anyways. - ty::Alias(..) => true, + (ty::FnPtr(lhs_sig_tys, lhs_hdr), ty::FnPtr(rhs_sig_tys, rhs_hdr)) => { + let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output; - ty::Error(_) => true, + let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output; - ty::CoroutineWitness(..) => { - panic!("unexpected obligation type: {:?}", obligation_ty) + lhs_hdr == rhs_hdr + && lhs_sig_tys.len() == rhs_sig_tys.len() + && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter()) + .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) } + + (ty::FnDef(lhs_def_id, lhs_args), ty::FnDef(rhs_def_id, rhs_args)) + | (ty::Closure(lhs_def_id, lhs_args), ty::Closure(rhs_def_id, rhs_args)) + | ( + ty::CoroutineClosure(lhs_def_id, lhs_args), + ty::CoroutineClosure(rhs_def_id, rhs_args), + ) + | (ty::Coroutine(lhs_def_id, lhs_args), ty::Coroutine(rhs_def_id, rhs_args)) + | ( + ty::CoroutineWitness(lhs_def_id, lhs_args), + ty::CoroutineWitness(rhs_def_id, rhs_args), + ) => lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args), + + (ty::Placeholder(_), _) + | (_, ty::Placeholder(_)) + | (ty::Bool, _) + | (_, ty::Bool) + | (ty::Char, _) + | (_, ty::Char) + | (ty::Int(_), _) + | (_, ty::Int(_)) + | (ty::Uint(_), _) + | (_, ty::Uint(_)) + | (ty::Float(_), _) + | (_, ty::Float(_)) + | (ty::Str, _) + | (_, ty::Str) + | (ty::Never, _) + | (_, ty::Never) + | (ty::Foreign(_), _) + | (_, ty::Foreign(_)) + | (ty::Ref(..), _) + | (_, ty::Ref(..)) + | (ty::Adt(..), _) + | (_, ty::Adt(..)) + | (ty::Pat(..), _) + | (_, ty::Pat(..)) + | (ty::Slice(_), _) + | (_, ty::Slice(_)) + | (ty::Array(..), _) + | (_, ty::Array(..)) + | (ty::Tuple(_), _) + | (_, ty::Tuple(_)) + | (ty::RawPtr(..), _) + | (_, ty::RawPtr(..)) + | (ty::Dynamic(..), _) + | (_, ty::Dynamic(..)) + | (ty::FnPtr(..), _) + | (_, ty::FnPtr(..)) + | (ty::FnDef(..), _) + | (_, ty::FnDef(..)) + | (ty::Closure(..), _) + | (_, ty::Closure(..)) + | (ty::CoroutineClosure(..), _) + | (_, ty::CoroutineClosure(..)) + | (ty::Coroutine(..), _) + | (_, ty::Coroutine(..)) => false, } } - pub fn consts_may_unify(self, obligation_ct: I::Const, impl_ct: I::Const) -> bool { - let impl_val = match impl_ct.kind() { - ty::ConstKind::Expr(_) - | ty::ConstKind::Param(_) - | ty::ConstKind::Unevaluated(_) - | ty::ConstKind::Error(_) => { - return true; - } - ty::ConstKind::Value(_, impl_val) => impl_val, - ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { - panic!("unexpected impl arg: {:?}", impl_ct) + pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool { + // As we don't necessarily eagerly evaluate constants, values + // may unify with everything except placeholder consts. + match (lhs.kind(), rhs.kind()) { + (ty::ConstKind::Value(_, lhs_val), ty::ConstKind::Value(_, rhs_val)) => { + lhs_val == rhs_val } - }; - - match obligation_ct.kind() { - ty::ConstKind::Param(_) => match self.treat_obligation_params { - TreatParams::ForLookup => false, - TreatParams::AsCandidateKey => true, - }, - // Placeholder consts don't unify with anything on their own - ty::ConstKind::Placeholder(_) => false, + (ty::ConstKind::Value(..), ty::ConstKind::Placeholder(_)) + | (ty::ConstKind::Placeholder(_), ty::ConstKind::Value(..)) => false, - // As we don't necessarily eagerly evaluate constants, - // they might unify with any value. - ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { - true + (ty::ConstKind::Param(_), ty::ConstKind::Value(..)) => { + self.treat_lhs_params == TreatParams::InstantiateWithInfer } - ty::ConstKind::Value(_, obl_val) => obl_val == impl_val, + (ty::ConstKind::Value(..), ty::ConstKind::Param(_)) => { + self.treat_rhs_params == TreatParams::InstantiateWithInfer + } + + _ => true, + } + } - ty::ConstKind::Infer(_) => true, + fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool { + if !ty.is_known_rigid() { + return true; + } - ty::ConstKind::Bound(..) => { - panic!("unexpected obl const: {:?}", obligation_ct) - } + match var { + ty::IntVar(_) => ty.is_integral(), + ty::FloatVar(_) => ty.is_floating_point(), + _ => true, } } } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 8fd56eae37ffc..589b7ef96ae70 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -507,7 +507,11 @@ else if (window.initSearch) window.initSearch(searchIndex); // Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress. let Some(impl_did) = impl_item_id.as_def_id() else { continue }; let for_ty = self.cx.tcx().type_of(impl_did).skip_binder(); - let reject_cx = DeepRejectCtxt::new(self.cx.tcx(), TreatParams::AsCandidateKey); + let reject_cx = DeepRejectCtxt::new( + self.cx.tcx(), + TreatParams::InstantiateWithInfer, + TreatParams::InstantiateWithInfer, + ); if !reject_cx.types_may_unify(aliased_ty, for_ty) { continue; } From 35ca8f8c4f866603087015590e5d6bfa82f7595c Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Wed, 14 Aug 2024 16:26:03 +0300 Subject: [PATCH 2/5] apply micro optimizations to `DeepRejectCtxt` --- .../rustc_hir_typeck/src/method/suggest.rs | 10 +- compiler/rustc_middle/src/ty/fast_reject.rs | 6 +- .../src/solve/normalizes_to/mod.rs | 12 +- .../src/solve/trait_goals.rs | 6 +- .../error_reporting/infer/note_and_explain.rs | 26 +--- .../src/traits/coherence.rs | 8 +- .../src/traits/select/candidate_assembly.rs | 8 +- compiler/rustc_type_ir/src/fast_reject.rs | 130 +++++++++--------- src/librustdoc/html/render/write_shared.rs | 9 +- 9 files changed, 97 insertions(+), 118 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 52a3bcb84dbfe..4cf077cac9f9e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -21,7 +21,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath}; use rustc_infer::infer::{self, RegionVariableOrigin}; use rustc_middle::bug; -use rustc_middle::ty::fast_reject::{simplify_type, DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{new_reject_ctxt, simplify_type, DeepRejectCtxt, TreatParams}; use rustc_middle::ty::print::{ with_crate_prefix, with_forced_trimmed_paths, PrintTraitRefExt as _, }; @@ -2234,12 +2234,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let target_ty = self .autoderef(sugg_span, rcvr_ty) .find(|(rcvr_ty, _)| { - DeepRejectCtxt::new( - self.tcx, - TreatParams::AsRigid, - TreatParams::InstantiateWithInfer, - ) - .types_may_unify(*rcvr_ty, impl_ty) + new_reject_ctxt!(self.tcx, AsRigid, InstantiateWithInfer) + .types_may_unify(*rcvr_ty, impl_ty) }) .map_or(impl_ty, |(ty, _)| ty) .peel_refs(); diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 91344c4e39c8b..0715362aaccd3 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,8 +1,8 @@ use rustc_hir::def_id::DefId; pub use rustc_type_ir::fast_reject::*; +pub use rustc_type_ir::new_reject_ctxt; -use super::TyCtxt; - -pub type DeepRejectCtxt<'tcx> = rustc_type_ir::fast_reject::DeepRejectCtxt>; +pub type DeepRejectCtxt = + rustc_type_ir::fast_reject::DeepRejectCtxt; pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType; diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 861f032e268dc..3fef721b1190b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -6,7 +6,7 @@ mod weak_types; use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _}; +use rustc_type_ir::{self as ty, new_reject_ctxt, Interner, NormalizesTo, Upcast as _}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -144,12 +144,10 @@ where let goal_trait_ref = goal.predicate.alias.trait_ref(cx); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); - if !DeepRejectCtxt::new(ecx.cx(), TreatParams::AsRigid, TreatParams::InstantiateWithInfer) - .args_may_unify( - goal.predicate.alias.trait_ref(cx).args, - impl_trait_ref.skip_binder().args, - ) - { + if !new_reject_ctxt!(ecx.cx(), AsRigid, InstantiateWithInfer).args_may_unify( + goal.predicate.alias.trait_ref(cx).args, + impl_trait_ref.skip_binder().args, + ) { return Err(NoSolution); } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 67442e264b69b..3dc6a965a1f89 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -6,7 +6,9 @@ use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::visit::TypeVisitableExt as _; -use rustc_type_ir::{self as ty, elaborate, Interner, TraitPredicate, Upcast as _}; +use rustc_type_ir::{ + self as ty, elaborate, new_reject_ctxt, Interner, TraitPredicate, Upcast as _, +}; use tracing::{instrument, trace}; use crate::delegate::SolverDelegate; @@ -47,7 +49,7 @@ where let cx = ecx.cx(); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); - if !DeepRejectCtxt::new(ecx.cx(), TreatParams::AsRigid, TreatParams::InstantiateWithInfer) + if !new_reject_ctxt!(ecx.cx(), AsRigid, InstantiateWithInfer) .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index b0d23efebfcca..87839d3ba93aa 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; use rustc_middle::ty::print::{FmtPrinter, Printer}; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; use rustc_span::def_id::DefId; @@ -316,12 +316,8 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - if DeepRejectCtxt::new( - tcx, - TreatParams::AsRigid, - TreatParams::InstantiateWithInfer, - ) - .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + if new_reject_ctxt!(tcx, AsRigid, InstantiateWithInfer) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) { has_matching_impl = true; } @@ -341,12 +337,8 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.expected, |did| { - if DeepRejectCtxt::new( - tcx, - TreatParams::AsRigid, - TreatParams::InstantiateWithInfer, - ) - .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) + if new_reject_ctxt!(tcx, AsRigid, InstantiateWithInfer) + .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) { has_matching_impl = true; } @@ -365,12 +357,8 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - if DeepRejectCtxt::new( - tcx, - TreatParams::AsRigid, - TreatParams::InstantiateWithInfer, - ) - .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + if new_reject_ctxt!(tcx, AsRigid, InstantiateWithInfer) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) { has_matching_impl = true; } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 61a1b26132f53..3891c53b86bde 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -15,7 +15,7 @@ use rustc_middle::bug; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; pub use rustc_next_trait_solver::coherence::*; @@ -94,11 +94,7 @@ pub fn overlapping_impls( // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. - let drcx = DeepRejectCtxt::new( - tcx, - TreatParams::InstantiateWithInfer, - TreatParams::InstantiateWithInfer, - ); + let drcx = new_reject_ctxt!(tcx, InstantiateWithInfer, InstantiateWithInfer); let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 84090c7606b92..ec0c094d66a79 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -13,7 +13,7 @@ use hir::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_hir as hir; use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; @@ -580,11 +580,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - let drcx = DeepRejectCtxt::new( - self.tcx(), - TreatParams::AsRigid, - TreatParams::InstantiateWithInfer, - ); + let drcx = new_reject_ctxt!(self.tcx(), AsRigid, InstantiateWithInfer); let obligation_args = obligation.predicate.skip_binder().trait_ref.args; self.tcx().for_each_relevant_impl( obligation.predicate.def_id(), diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index b08a971bf21b2..388f1366e5eb6 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -173,7 +173,7 @@ impl SimplifiedType { /// Given generic arguments, could they be unified after /// replacing parameters with inference variables or placeholders. -/// This behavior is toggled using the `TreatParams` fields. +/// This behavior is toggled using the const generics. /// /// We use this to quickly reject impl/wc candidates without needing /// to instantiate generic arguments/having to enter a probe. @@ -182,15 +182,31 @@ impl SimplifiedType { /// impls only have to overlap for some value, so we treat parameters /// on both sides like inference variables. #[derive(Debug, Clone, Copy)] -pub struct DeepRejectCtxt { - treat_lhs_params: TreatParams, - treat_rhs_params: TreatParams, +pub struct DeepRejectCtxt { _interner: PhantomData, } -impl DeepRejectCtxt { - pub fn new(_interner: I, treat_lhs_params: TreatParams, treat_rhs_params: TreatParams) -> Self { - DeepRejectCtxt { treat_lhs_params, treat_rhs_params, _interner: PhantomData } +impl TreatParams { + pub const fn into_bool(&self) -> bool { + match *self { + TreatParams::InstantiateWithInfer => true, + TreatParams::AsRigid => false, + } + } +} + +#[macro_export] +macro_rules! new_reject_ctxt { + ($interner:expr, $lhs:ident, $rhs:ident) => { + DeepRejectCtxt::<_, {TreatParams::$lhs.into_bool()}, {TreatParams::$rhs.into_bool()}>::new($interner) + } +} + +impl + DeepRejectCtxt +{ + pub fn new(_interner: I) -> Self { + DeepRejectCtxt { _interner: PhantomData } } pub fn args_may_unify( @@ -215,45 +231,6 @@ impl DeepRejectCtxt { pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { match (lhs.kind(), rhs.kind()) { - (ty::Error(_), _) | (_, ty::Error(_)) => true, - - // As we're walking the whole type, it may encounter projections - // inside of binders and what not, so we're just going to assume that - // projections can unify with other stuff. - // - // Looking forward to lazy normalization this is the safer strategy anyways. - (ty::Alias(..), _) | (_, ty::Alias(..)) => true, - - // Bound type variables may unify with rigid types e.g. when using - // non-lifetime binders. - (ty::Bound(..), _) | (_, ty::Bound(..)) => true, - - (ty::Infer(var), _) => self.var_and_ty_may_unify(var, rhs), - (_, ty::Infer(var)) => self.var_and_ty_may_unify(var, lhs), - - (ty::Param(lhs), ty::Param(rhs)) => { - match (self.treat_lhs_params, self.treat_rhs_params) { - (TreatParams::AsRigid, TreatParams::AsRigid) => lhs == rhs, - (TreatParams::InstantiateWithInfer, _) - | (_, TreatParams::InstantiateWithInfer) => true, - } - } - (ty::Param(_), _) => self.treat_lhs_params == TreatParams::InstantiateWithInfer, - (_, ty::Param(_)) => self.treat_rhs_params == TreatParams::InstantiateWithInfer, - - // Placeholder types don't unify with anything on their own. - (ty::Placeholder(lhs), ty::Placeholder(rhs)) => lhs == rhs, - - // Purely rigid types, use structural equivalence. - (ty::Bool, ty::Bool) - | (ty::Char, ty::Char) - | (ty::Int(_), ty::Int(_)) - | (ty::Uint(_), ty::Uint(_)) - | (ty::Float(_), ty::Float(_)) - | (ty::Str, ty::Str) - | (ty::Never, ty::Never) - | (ty::Foreign(_), ty::Foreign(_)) => lhs == rhs, - (ty::Ref(_, lhs_ty, lhs_mutbl), ty::Ref(_, rhs_ty, rhs_mutbl)) => { lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) } @@ -262,16 +239,27 @@ impl DeepRejectCtxt { lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args) } - (ty::Pat(lhs_ty, _), ty::Pat(rhs_ty, _)) => { - // FIXME(pattern_types): take pattern into account - self.types_may_unify(lhs_ty, rhs_ty) - } + (ty::Infer(var), _) => self.var_and_ty_may_unify(var, rhs), + (_, ty::Infer(var)) => self.var_and_ty_may_unify(var, lhs), - (ty::Slice(lhs_ty), ty::Slice(rhs_ty)) => self.types_may_unify(lhs_ty, rhs_ty), + (ty::Int(_), ty::Int(_)) | (ty::Uint(_), ty::Uint(_)) => lhs == rhs, - (ty::Array(lhs_ty, lhs_len), ty::Array(rhs_ty, rhs_len)) => { - self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) - } + (ty::Param(lhs), ty::Param(rhs)) => match (TREAT_LHS_PARAMS, TREAT_RHS_PARAMS) { + (false, false) => lhs == rhs, + (true, _) | (_, true) => true, + }, + + // As we're walking the whole type, it may encounter projections + // inside of binders and what not, so we're just going to assume that + // projections can unify with other stuff. + // + // Looking forward to lazy normalization this is the safer strategy anyways. + (ty::Alias(..), _) | (_, ty::Alias(..)) => true, + + (ty::Bound(..), _) | (_, ty::Bound(..)) => true, + + (ty::Param(_), _) => TREAT_LHS_PARAMS, + (_, ty::Param(_)) => TREAT_RHS_PARAMS, (ty::Tuple(lhs), ty::Tuple(rhs)) => { lhs.len() == rhs.len() @@ -279,10 +267,23 @@ impl DeepRejectCtxt { .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) } + (ty::Array(lhs_ty, lhs_len), ty::Array(rhs_ty, rhs_len)) => { + self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) + } + (ty::RawPtr(lhs_ty, lhs_mutbl), ty::RawPtr(rhs_ty, rhs_mutbl)) => { lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) } + (ty::Slice(lhs_ty), ty::Slice(rhs_ty)) => self.types_may_unify(lhs_ty, rhs_ty), + + (ty::Float(_), ty::Float(_)) + | (ty::Str, ty::Str) + | (ty::Bool, ty::Bool) + | (ty::Char, ty::Char) + | (ty::Never, ty::Never) + | (ty::Foreign(_), ty::Foreign(_)) => lhs == rhs, + (ty::Dynamic(lhs_preds, ..), ty::Dynamic(rhs_preds, ..)) => { // Ideally we would walk the existential predicates here or at least // compare their length. But considering that the relevant `Relate` impl @@ -290,9 +291,11 @@ impl DeepRejectCtxt { lhs_preds.principal_def_id() == rhs_preds.principal_def_id() } + // Placeholder types don't unify with anything on their own. + (ty::Placeholder(lhs), ty::Placeholder(rhs)) => lhs == rhs, + (ty::FnPtr(lhs_sig_tys, lhs_hdr), ty::FnPtr(rhs_sig_tys, rhs_hdr)) => { let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output; - let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output; lhs_hdr == rhs_hdr @@ -313,7 +316,14 @@ impl DeepRejectCtxt { ty::CoroutineWitness(rhs_def_id, rhs_args), ) => lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args), - (ty::Placeholder(_), _) + (ty::Pat(lhs_ty, _), ty::Pat(rhs_ty, _)) => { + // FIXME(pattern_types): take pattern into account + self.types_may_unify(lhs_ty, rhs_ty) + } + + (ty::Error(..), _) + | (_, ty::Error(..)) + | (ty::Placeholder(_), _) | (_, ty::Placeholder(_)) | (ty::Bool, _) | (_, ty::Bool) @@ -371,12 +381,8 @@ impl DeepRejectCtxt { (ty::ConstKind::Value(..), ty::ConstKind::Placeholder(_)) | (ty::ConstKind::Placeholder(_), ty::ConstKind::Value(..)) => false, - (ty::ConstKind::Param(_), ty::ConstKind::Value(..)) => { - self.treat_lhs_params == TreatParams::InstantiateWithInfer - } - (ty::ConstKind::Value(..), ty::ConstKind::Param(_)) => { - self.treat_rhs_params == TreatParams::InstantiateWithInfer - } + (ty::ConstKind::Param(_), ty::ConstKind::Value(..)) => TREAT_LHS_PARAMS, + (ty::ConstKind::Value(..), ty::ConstKind::Param(_)) => TREAT_RHS_PARAMS, _ => true, } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 589b7ef96ae70..71631e70b087c 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -9,7 +9,7 @@ use indexmap::IndexMap; use itertools::Itertools; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; use rustc_span::def_id::DefId; use rustc_span::Symbol; use serde::ser::SerializeSeq; @@ -507,11 +507,8 @@ else if (window.initSearch) window.initSearch(searchIndex); // Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress. let Some(impl_did) = impl_item_id.as_def_id() else { continue }; let for_ty = self.cx.tcx().type_of(impl_did).skip_binder(); - let reject_cx = DeepRejectCtxt::new( - self.cx.tcx(), - TreatParams::InstantiateWithInfer, - TreatParams::InstantiateWithInfer, - ); + let reject_cx = + new_reject_ctxt!(self.cx.tcx(), InstantiateWithInfer, InstantiateWithInfer); if !reject_cx.types_may_unify(aliased_ty, for_ty) { continue; } From 6061b8c5324a22ae3fb7dbb6113f8740f14e9239 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 19 Aug 2024 16:06:04 +0300 Subject: [PATCH 3/5] `DeepRejectCtxt`: match over lhs only --- compiler/rustc_type_ir/src/fast_reject.rs | 276 +++++++++++++--------- 1 file changed, 159 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 388f1366e5eb6..10c006a1049f1 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -230,143 +230,189 @@ impl } pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { - match (lhs.kind(), rhs.kind()) { - (ty::Ref(_, lhs_ty, lhs_mutbl), ty::Ref(_, rhs_ty, rhs_mutbl)) => { - lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) - } + if let ty::Infer(var) = rhs.kind() { + return self.var_and_ty_may_unify(var, lhs); + } - (ty::Adt(lhs_def, lhs_args), ty::Adt(rhs_def, rhs_args)) => { - lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args) - } + if !Self::type_is_rigid::(rhs) { + return true; + } - (ty::Infer(var), _) => self.var_and_ty_may_unify(var, rhs), - (_, ty::Infer(var)) => self.var_and_ty_may_unify(var, lhs), + match lhs.kind() { + ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() { + ty::Ref(_, rhs_ty, rhs_mutbl) => { + lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) + } + _ => false, + }, + + ty::Adt(lhs_def, lhs_args) => match rhs.kind() { + ty::Adt(rhs_def, rhs_args) => { + lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - (ty::Int(_), ty::Int(_)) | (ty::Uint(_), ty::Uint(_)) => lhs == rhs, + ty::Param(lhs) => match rhs.kind() { + ty::Param(rhs) => match (TREAT_LHS_PARAMS, TREAT_RHS_PARAMS) { + (false, false) => lhs == rhs, + (true, _) | (_, true) => true, + }, + _ => TREAT_LHS_PARAMS, + }, - (ty::Param(lhs), ty::Param(rhs)) => match (TREAT_LHS_PARAMS, TREAT_RHS_PARAMS) { - (false, false) => lhs == rhs, - (true, _) | (_, true) => true, + ty::Placeholder(lhs) => match rhs.kind() { + ty::Placeholder(rhs) => lhs == rhs, + _ => false, }, + ty::Infer(var) => self.var_and_ty_may_unify(var, rhs), + // As we're walking the whole type, it may encounter projections // inside of binders and what not, so we're just going to assume that // projections can unify with other stuff. // // Looking forward to lazy normalization this is the safer strategy anyways. - (ty::Alias(..), _) | (_, ty::Alias(..)) => true, + ty::Alias(..) => true, + + ty::Uint(_) + | ty::Int(_) + | ty::Float(_) + | ty::Str + | ty::Bool + | ty::Char + | ty::Never + | ty::Foreign(_) => lhs == rhs, + + ty::Tuple(lhs) => match rhs.kind() { + ty::Tuple(rhs) => { + lhs.len() == rhs.len() + && iter::zip(lhs.iter(), rhs.iter()) + .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) + } + _ => false, + }, - (ty::Bound(..), _) | (_, ty::Bound(..)) => true, + ty::Array(lhs_ty, lhs_len) => match rhs.kind() { + ty::Array(rhs_ty, rhs_len) => { + self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) + } + _ => false, + }, - (ty::Param(_), _) => TREAT_LHS_PARAMS, - (_, ty::Param(_)) => TREAT_RHS_PARAMS, + ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() { + ty::RawPtr(rhs_ty, rhs_mutbl) => { + lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) + } + _ => false, + }, - (ty::Tuple(lhs), ty::Tuple(rhs)) => { - lhs.len() == rhs.len() - && iter::zip(lhs.iter(), rhs.iter()) - .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) - } + ty::Slice(lhs_ty) => match rhs.kind() { + ty::Slice(rhs_ty) => self.types_may_unify(lhs_ty, rhs_ty), + _ => false, + }, - (ty::Array(lhs_ty, lhs_len), ty::Array(rhs_ty, rhs_len)) => { - self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) - } + ty::Dynamic(lhs_preds, ..) => match rhs.kind() { + ty::Dynamic(rhs_preds, ..) => { + // Ideally we would walk the existential predicates here or at least + // compare their length. But considering that the relevant `Relate` impl + // actually sorts and deduplicates these, that doesn't work. + lhs_preds.principal_def_id() == rhs_preds.principal_def_id() + } + _ => false, + }, - (ty::RawPtr(lhs_ty, lhs_mutbl), ty::RawPtr(rhs_ty, rhs_mutbl)) => { - lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) - } + ty::FnPtr(lhs_sig_tys, lhs_hdr) => match rhs.kind() { + ty::FnPtr(rhs_sig_tys, rhs_hdr) => { + let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output; + let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output; - (ty::Slice(lhs_ty), ty::Slice(rhs_ty)) => self.types_may_unify(lhs_ty, rhs_ty), + lhs_hdr == rhs_hdr + && lhs_sig_tys.len() == rhs_sig_tys.len() + && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter()) + .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) + } + _ => false, + }, - (ty::Float(_), ty::Float(_)) - | (ty::Str, ty::Str) - | (ty::Bool, ty::Bool) - | (ty::Char, ty::Char) - | (ty::Never, ty::Never) - | (ty::Foreign(_), ty::Foreign(_)) => lhs == rhs, + ty::Bound(..) => true, - (ty::Dynamic(lhs_preds, ..), ty::Dynamic(rhs_preds, ..)) => { - // Ideally we would walk the existential predicates here or at least - // compare their length. But considering that the relevant `Relate` impl - // actually sorts and deduplicates these, that doesn't work. - lhs_preds.principal_def_id() == rhs_preds.principal_def_id() - } + ty::FnDef(lhs_def_id, lhs_args) => match rhs.kind() { + ty::FnDef(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - // Placeholder types don't unify with anything on their own. - (ty::Placeholder(lhs), ty::Placeholder(rhs)) => lhs == rhs, + ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() { + ty::Closure(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - (ty::FnPtr(lhs_sig_tys, lhs_hdr), ty::FnPtr(rhs_sig_tys, rhs_hdr)) => { - let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output; - let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output; + ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() { + ty::CoroutineClosure(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - lhs_hdr == rhs_hdr - && lhs_sig_tys.len() == rhs_sig_tys.len() - && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter()) - .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) - } + ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() { + ty::Coroutine(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - (ty::FnDef(lhs_def_id, lhs_args), ty::FnDef(rhs_def_id, rhs_args)) - | (ty::Closure(lhs_def_id, lhs_args), ty::Closure(rhs_def_id, rhs_args)) - | ( - ty::CoroutineClosure(lhs_def_id, lhs_args), - ty::CoroutineClosure(rhs_def_id, rhs_args), - ) - | (ty::Coroutine(lhs_def_id, lhs_args), ty::Coroutine(rhs_def_id, rhs_args)) - | ( - ty::CoroutineWitness(lhs_def_id, lhs_args), - ty::CoroutineWitness(rhs_def_id, rhs_args), - ) => lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args), - - (ty::Pat(lhs_ty, _), ty::Pat(rhs_ty, _)) => { - // FIXME(pattern_types): take pattern into account - self.types_may_unify(lhs_ty, rhs_ty) - } + ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() { + ty::CoroutineWitness(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, + + ty::Pat(lhs_ty, _) => match rhs.kind() { + ty::Pat(rhs_ty, _) => { + // FIXME(pattern_types): take pattern into account + self.types_may_unify(lhs_ty, rhs_ty) + } + _ => false, + }, - (ty::Error(..), _) - | (_, ty::Error(..)) - | (ty::Placeholder(_), _) - | (_, ty::Placeholder(_)) - | (ty::Bool, _) - | (_, ty::Bool) - | (ty::Char, _) - | (_, ty::Char) - | (ty::Int(_), _) - | (_, ty::Int(_)) - | (ty::Uint(_), _) - | (_, ty::Uint(_)) - | (ty::Float(_), _) - | (_, ty::Float(_)) - | (ty::Str, _) - | (_, ty::Str) - | (ty::Never, _) - | (_, ty::Never) - | (ty::Foreign(_), _) - | (_, ty::Foreign(_)) - | (ty::Ref(..), _) - | (_, ty::Ref(..)) - | (ty::Adt(..), _) - | (_, ty::Adt(..)) - | (ty::Pat(..), _) - | (_, ty::Pat(..)) - | (ty::Slice(_), _) - | (_, ty::Slice(_)) - | (ty::Array(..), _) - | (_, ty::Array(..)) - | (ty::Tuple(_), _) - | (_, ty::Tuple(_)) - | (ty::RawPtr(..), _) - | (_, ty::RawPtr(..)) - | (ty::Dynamic(..), _) - | (_, ty::Dynamic(..)) - | (ty::FnPtr(..), _) - | (_, ty::FnPtr(..)) - | (ty::FnDef(..), _) - | (_, ty::FnDef(..)) - | (ty::Closure(..), _) - | (_, ty::Closure(..)) - | (ty::CoroutineClosure(..), _) - | (_, ty::CoroutineClosure(..)) - | (ty::Coroutine(..), _) - | (_, ty::Coroutine(..)) => false, + ty::Error(..) => true, + } + } + + fn type_is_rigid(ty: I::Ty) -> bool { + match ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(..) + | ty::Dynamic(_, _, _) + | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::Placeholder(_) => true, + + ty::Param(_) => !TREAT_PARAM, + + ty::Error(_) | ty::Infer(_) | ty::Alias(_, _) | ty::Bound(_, _) => false, } } @@ -389,10 +435,6 @@ impl } fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool { - if !ty.is_known_rigid() { - return true; - } - match var { ty::IntVar(_) => ty.is_integral(), ty::FloatVar(_) => ty.is_floating_point(), From e328a26a838828dd32a9be0864dd89c4af6b0669 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 19 Aug 2024 17:26:41 +0300 Subject: [PATCH 4/5] fix `fast_reject` paths --- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_middle/src/ty/fast_reject.rs | 6 ++++-- .../src/solve/normalizes_to/mod.rs | 1 - compiler/rustc_next_trait_solver/src/solve/trait_goals.rs | 1 - .../src/error_reporting/infer/note_and_explain.rs | 2 +- compiler/rustc_trait_selection/src/traits/coherence.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 2 +- compiler/rustc_type_ir/src/fast_reject.rs | 8 ++++++-- src/librustdoc/html/render/write_shared.rs | 2 +- 9 files changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4cf077cac9f9e..22277765a1db7 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -21,7 +21,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath}; use rustc_infer::infer::{self, RegionVariableOrigin}; use rustc_middle::bug; -use rustc_middle::ty::fast_reject::{new_reject_ctxt, simplify_type, DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::{new_reject_ctxt, simplify_type, TreatParams}; use rustc_middle::ty::print::{ with_crate_prefix, with_forced_trimmed_paths, PrintTraitRefExt as _, }; diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 0715362aaccd3..a7ccd02a17664 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -2,7 +2,9 @@ use rustc_hir::def_id::DefId; pub use rustc_type_ir::fast_reject::*; pub use rustc_type_ir::new_reject_ctxt; -pub type DeepRejectCtxt = - rustc_type_ir::fast_reject::DeepRejectCtxt; +use super::TyCtxt; + +pub type DeepRejectCtxt<'tcx, const TREAT_LHS_PARAMS: bool, const TREAT_RHS_PARAMS: bool> = + rustc_type_ir::fast_reject::DeepRejectCtxt, TREAT_LHS_PARAMS, TREAT_RHS_PARAMS>; pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType; diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 3fef721b1190b..18e6eb97262e4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -3,7 +3,6 @@ mod inherent; mod opaque_types; mod weak_types; -use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::{self as ty, new_reject_ctxt, Interner, NormalizesTo, Upcast as _}; diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 3dc6a965a1f89..b33b97e76f180 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -2,7 +2,6 @@ use rustc_ast_ir::Movability; use rustc_type_ir::data_structures::IndexSet; -use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::visit::TypeVisitableExt as _; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 87839d3ba93aa..1615f1ee6cc96 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::new_reject_ctxt; use rustc_middle::ty::print::{FmtPrinter, Printer}; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; use rustc_span::def_id::DefId; diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 3891c53b86bde..44bb1bf3a805e 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -15,7 +15,7 @@ use rustc_middle::bug; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; -use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::new_reject_ctxt; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; pub use rustc_next_trait_solver::coherence::*; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index ec0c094d66a79..adb7749a3fd0f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -13,7 +13,7 @@ use hir::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_hir as hir; use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError}; -use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::new_reject_ctxt; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 10c006a1049f1..f892dcd9f2dbf 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -198,8 +198,12 @@ impl TreatParams { #[macro_export] macro_rules! new_reject_ctxt { ($interner:expr, $lhs:ident, $rhs:ident) => { - DeepRejectCtxt::<_, {TreatParams::$lhs.into_bool()}, {TreatParams::$rhs.into_bool()}>::new($interner) - } + $crate::fast_reject::DeepRejectCtxt::< + _, + { $crate::fast_reject::TreatParams::$lhs.into_bool() }, + { $crate::fast_reject::TreatParams::$rhs.into_bool() }, + >::new($interner) + }; } impl diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 71631e70b087c..c475431f690ca 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -9,7 +9,7 @@ use indexmap::IndexMap; use itertools::Itertools; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::new_reject_ctxt; use rustc_span::def_id::DefId; use rustc_span::Symbol; use serde::ser::SerializeSeq; From 639ae912700ec5a6107d6cc49667f87c561ff466 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 19 Aug 2024 18:50:05 +0300 Subject: [PATCH 5/5] fix var_and_ty_may_unify --- compiler/rustc_type_ir/src/fast_reject.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index f892dcd9f2dbf..d3263dfa9b46e 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -439,6 +439,10 @@ impl } fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool { + if !ty.is_known_rigid() { + return true; + } + match var { ty::IntVar(_) => ty.is_integral(), ty::FloatVar(_) => ty.is_floating_point(),