From 14f2acd0ac5d20a58f3333276d1ea77510379ac0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 8 Sep 2022 17:02:09 +0200 Subject: [PATCH 1/2] `resolve_instance`: remove `BoundVarsCollector` --- compiler/rustc_ty_utils/src/instance.rs | 111 +----------------------- 1 file changed, 3 insertions(+), 108 deletions(-) diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 661e413fc5b81..392aa6a88186e 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -4,112 +4,12 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{ - self, Binder, Instance, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, Instance, TyCtxt, TypeVisitable, }; use rustc_span::{sym, DUMMY_SP}; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; -use rustc_data_structures::sso::SsoHashSet; -use std::collections::btree_map::Entry; -use std::collections::BTreeMap; -use std::ops::ControlFlow; - -// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used -// outside of `resolve_associated_item`. It's just to address #64494, -// #83765, and #85848 which are creating bound types/regions that lose -// their `Binder` *unintentionally*. -// It's ideal to remove `BoundVarsCollector` and just use -// `ty::Binder::*` methods but we use this stopgap until we figure out -// the "real" fix. -struct BoundVarsCollector<'tcx> { - binder_index: ty::DebruijnIndex, - vars: BTreeMap, - // We may encounter the same variable at different levels of binding, so - // this can't just be `Ty` - visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, -} - -impl<'tcx> BoundVarsCollector<'tcx> { - fn new() -> Self { - BoundVarsCollector { - binder_index: ty::INNERMOST, - vars: BTreeMap::new(), - visited: SsoHashSet::default(), - } - } - - fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List { - let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or(0); - for i in 0..max { - if let None = self.vars.get(&i) { - panic!("Unknown variable: {:?}", i); - } - } - - tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v)) - } -} - -impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - type BreakTy = (); - - fn visit_binder>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { - self.binder_index.shift_in(1); - let result = t.super_visit_with(self); - self.binder_index.shift_out(1); - result - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - if t.outer_exclusive_binder() < self.binder_index - || !self.visited.insert((self.binder_index, t)) - { - return ControlFlow::CONTINUE; - } - match *t.kind() { - ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { - match self.vars.entry(bound_ty.var.as_u32()) { - Entry::Vacant(entry) => { - entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind)); - } - Entry::Occupied(entry) => match entry.get() { - ty::BoundVariableKind::Ty(_) => {} - _ => bug!("Conflicting bound vars"), - }, - } - } - - _ => (), - }; - - t.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - match *r { - ty::ReLateBound(index, br) if index == self.binder_index => { - match self.vars.entry(br.var.as_u32()) { - Entry::Vacant(entry) => { - entry.insert(ty::BoundVariableKind::Region(br.kind)); - } - Entry::Occupied(entry) => match entry.get() { - ty::BoundVariableKind::Region(_) => {} - _ => bug!("Conflicting bound vars"), - }, - } - } - - _ => (), - }; - - r.super_visit_with(self) - } -} - fn resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>, @@ -201,19 +101,14 @@ fn resolve_associated_item<'tcx>( let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - // See FIXME on `BoundVarsCollector`. - let mut bound_vars_collector = BoundVarsCollector::new(); - trait_ref.visit_with(&mut bound_vars_collector); - let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx)); - let vtbl = match tcx.codegen_fulfill_obligation((param_env, trait_binder)) { + let vtbl = match tcx.codegen_fulfill_obligation((param_env, ty::Binder::dummy(trait_ref))) { Ok(vtbl) => vtbl, Err(CodegenObligationError::Ambiguity) => { let reported = tcx.sess.delay_span_bug( tcx.def_span(trait_item_id), &format!( - "encountered ambiguity selecting `{:?}` during codegen, presuming due to \ + "encountered ambiguity selecting `{trait_ref:?}` during codegen, presuming due to \ overflow or prior type error", - trait_binder ), ); return Err(reported); From c63020a7c3e624f610f1f402a44a0db92bd21a88 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 9 Sep 2022 13:36:27 +0200 Subject: [PATCH 2/2] rename `codegen_fulfill_obligation` --- compiler/rustc_middle/src/query/mod.rs | 7 ++----- compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_monomorphize/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/traits/codegen.rs | 2 +- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- compiler/rustc_ty_utils/src/instance.rs | 6 ++---- src/test/ui/const-generics/issues/issue-83765.stderr | 4 ++-- 7 files changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index adf479c423604..f72e7389fc606 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1202,14 +1202,11 @@ rustc_queries! { } } - query codegen_fulfill_obligation( + query codegen_select_candidate( key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) ) -> Result<&'tcx ImplSource<'tcx, ()>, traits::CodegenObligationError> { cache_on_disk_if { true } - desc { |tcx| - "checking if `{}` fulfills its obligations", - tcx.def_path_str(key.1.def_id()) - } + desc { |tcx| "computing candidate for `{}`", key.1 } } /// Return all `impl` blocks in the current crate. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a56fac7c4dd2c..755d9f8f69667 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -1024,7 +1024,7 @@ pub enum MethodViolationCode { UndispatchableReceiver(Option), } -/// These are the error cases for `codegen_fulfill_obligation`. +/// These are the error cases for `codegen_select_candidate`. #[derive(Copy, Clone, Debug, Hash, HashStable, Encodable, Decodable)] pub enum CodegenObligationError { /// Ambiguity can happen when monomorphizing during trans diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index d64de44705bb2..3afff7bcabf7d 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -35,7 +35,7 @@ fn custom_coerce_unsize_info<'tcx>( substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]), }); - match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) { + match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) { Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData { impl_def_id, .. diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 26f8e7d34c6ea..08adbcbd410c6 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{self, TyCtxt}; /// obligations *could be* resolved if we wanted to. /// /// This also expects that `trait_ref` is fully normalized. -pub fn codegen_fulfill_obligation<'tcx>( +pub fn codegen_select_candidate<'tcx>( tcx: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 14e078096783e..40596078f0414 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -971,7 +971,7 @@ pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, - codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, + codegen_select_candidate: codegen::codegen_select_candidate, own_existential_vtable_entries, vtable_entries, vtable_trait_upcasting_coercion_new_vptr_slot, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 392aa6a88186e..b55302de2a733 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -3,9 +3,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{ - self, Instance, TyCtxt, TypeVisitable, -}; +use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable}; use rustc_span::{sym, DUMMY_SP}; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; @@ -101,7 +99,7 @@ fn resolve_associated_item<'tcx>( let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = match tcx.codegen_fulfill_obligation((param_env, ty::Binder::dummy(trait_ref))) { + let vtbl = match tcx.codegen_select_candidate((param_env, ty::Binder::dummy(trait_ref))) { Ok(vtbl) => vtbl, Err(CodegenObligationError::Ambiguity) => { let reported = tcx.sess.delay_span_bug( diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr index 28ddddf1be62b..d5f914f46f873 100644 --- a/src/test/ui/const-generics/issues/issue-83765.stderr +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -4,13 +4,13 @@ error[E0391]: cycle detected when resolving instance ` as TensorDimension>`... --> $DIR/issue-83765.rs:4:1 | LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires resolving instance ` as TensorDimension>::DIM`, completing the cycle -note: cycle used when checking if `TensorDimension` fulfills its obligations +note: cycle used when computing candidate for ` as TensorDimension>` --> $DIR/issue-83765.rs:4:1 | LL | trait TensorDimension {