From fc0cbe834098fc7c69cc4273bd1d16ed028b01ad Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 20 Mar 2023 15:48:32 +0000 Subject: [PATCH] Don't split up TreatProjections and TreatParams anymore --- .../src/coherence/inherent_impls.rs | 16 ++------ compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- .../rustc_hir_typeck/src/method/suggest.rs | 20 +++------- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 +- compiler/rustc_middle/src/ty/fast_reject.rs | 37 +++++++++++-------- compiler/rustc_middle/src/ty/trait_def.rs | 26 ++++++------- .../traits/specialize/specialization_graph.rs | 28 +++++--------- 7 files changed, 53 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index d4dfe455b29..3d37e0ce0c6 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -11,7 +11,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams, TreatProjections}; +use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -97,12 +97,7 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type( - self.tcx, - self_ty, - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected self type: {:?}", self_ty); @@ -162,12 +157,7 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type( - self.tcx, - ty, - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) { 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 0eff5c956ef..dab709e17f0 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -16,7 +16,6 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; -use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; @@ -701,7 +700,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, TreatProjections::AsCandidateKey) else { + let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index b219be4ae19..55f684599e7 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -25,7 +25,6 @@ use rustc_infer::infer::{ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::DeepRejectCtxt; -use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths}; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt}; @@ -1524,7 +1523,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, TreatProjections::AsCandidateKey) + simplify_type(tcx, ty, TreatParams::AsCandidateKey) .and_then(|simp| { tcx.incoherent_impls(simp) .iter() @@ -2653,12 +2652,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Even though negative bounds are not implemented, we could maybe handle // 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, - TreatProjections::ForLookup, - ) { + } else if let Some(simp_rcvr_ty) = + simplify_type(self.tcx, rcvr_ty, TreatParams::ForLookup) + { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); for candidate in candidates { @@ -2671,12 +2667,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .any(|imp_did| { let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity(); - let imp_simp = simplify_type( - self.tcx, - imp.self_ty(), - TreatParams::ForLookup, - TreatProjections::ForLookup, - ); + let imp_simp = + simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0b438d1ffad..2652a4280d3 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::interpret; use rustc_middle::query::LocalCrate; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; -use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_middle::util::common::to_readable_str; @@ -1881,7 +1881,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, ); fx_hash_map diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index ee505742be9..669d50a7fda 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -56,7 +56,15 @@ pub enum TreatParams { AsCandidateKey, /// 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, + /// Treat parameters as placeholders in the given environment. This is the + /// correct mode for *lookup*, as during candidate selection. + /// + /// N.B. during deep rejection, this acts identically to `ForLookup`. + NextSolverLookup, } /// During fast-rejection, we have the choice of treating projection types @@ -64,13 +72,6 @@ pub enum TreatParams { /// to be normalized/rigid. #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum TreatProjections { - /// In candidates, we may be able to normalize the projection - /// after instantiating the candidate and equating it with a goal. - /// - /// We must assume that the `impl Trait for ::This` - /// can apply to all self types so we don't return a simplified type - /// for `::This`. - AsCandidateKey, /// In the old solver we don't try to normalize projections /// when looking up impls and only access them by using the /// current self type. This means that if the self type is @@ -107,7 +108,6 @@ pub fn simplify_type<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, treat_params: TreatParams, - treat_projections: TreatProjections, ) -> Option { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -136,13 +136,20 @@ pub fn simplify_type<'tcx>( ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Placeholder(..) => Some(PlaceholderSimplifiedType), ty::Param(_) => match treat_params { - TreatParams::ForLookup => Some(PlaceholderSimplifiedType), + TreatParams::ForLookup | TreatParams::NextSolverLookup => { + Some(PlaceholderSimplifiedType) + } TreatParams::AsCandidateKey => None, }, - ty::Alias(..) => match treat_projections { - TreatProjections::ForLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType), - TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType), - TreatProjections::AsCandidateKey | TreatProjections::ForLookup => 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. + // + // We will have to be careful with lazy normalization here. + // FIXME(lazy_normalization): This is probably not right... + TreatParams::ForLookup if !ty.has_non_region_infer() => Some(PlaceholderSimplifiedType), + TreatParams::NextSolverLookup => Some(PlaceholderSimplifiedType), + TreatParams::ForLookup | TreatParams::AsCandidateKey => None, }, ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, @@ -310,7 +317,7 @@ impl DeepRejectCtxt { // 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::ForLookup | TreatParams::NextSolverLookup => false, TreatParams::AsCandidateKey => true, }, @@ -348,7 +355,7 @@ impl DeepRejectCtxt { let k = impl_ct.kind(); match obligation_ct.kind() { ty::ConstKind::Param(_) => match self.treat_obligation_params { - TreatParams::ForLookup => false, + TreatParams::ForLookup | TreatParams::NextSolverLookup => false, TreatParams::AsCandidateKey => true, }, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index bf2b121f704..6747da7abd3 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -153,12 +153,7 @@ 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, - TreatProjections::AsCandidateKey, - ) { + if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { return impls.iter().copied(); } @@ -191,13 +186,17 @@ impl<'tcx> TyCtxt<'tcx> { } } + // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using + // `TreatParams::AsCandidateKey` while actually adding them. + let treat_params = match treat_projections { + TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup, + TreatProjections::ForLookup => TreatParams::ForLookup, + }; // This way, when searching for some impl for `T: Trait`, we do not look at any impls // 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. - if let Some(simp) = - fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup, treat_projections) - { + if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { if let result @ Some(_) = f(impl_def_id) { @@ -258,12 +257,9 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait continue; } - if let Some(simplified_self_ty) = fast_reject::simplify_type( - tcx, - impl_self_ty, - TreatParams::AsCandidateKey, - TreatProjections::AsCandidateKey, - ) { + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey) + { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { impls.blanket_impls.push(impl_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 cd665d9471d..11eb968a415 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -3,7 +3,7 @@ use super::OverlapError; use crate::traits; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; -use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; pub use rustc_middle::traits::specialization_graph::*; @@ -49,12 +49,9 @@ impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. 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, - TreatProjections::AsCandidateKey, - ) { + if let Some(st) = + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey) + { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { @@ -69,12 +66,9 @@ impl<'tcx> ChildrenExt<'tcx> for Children { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { 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, - TreatProjections::AsCandidateKey, - ) { + if let Some(st) = + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey) + { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { @@ -310,12 +304,8 @@ impl<'tcx> GraphExt<'tcx> for 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, - TreatProjections::AsCandidateKey, - ); + let simplified = + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey); // Descend the specialization tree, where `parent` is the current parent node. loop {