From 532149eb88e6d1d69d883727a216c22839cdf6cc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Jun 2024 17:59:08 -0400 Subject: [PATCH] Uplift the new trait solver --- Cargo.lock | 9 + compiler/rustc_middle/src/ty/adt.rs | 10 +- compiler/rustc_middle/src/ty/consts.rs | 6 +- compiler/rustc_middle/src/ty/context.rs | 363 ++++++++++-- compiler/rustc_middle/src/ty/generic_args.rs | 14 + compiler/rustc_middle/src/ty/generics.rs | 4 + compiler/rustc_middle/src/ty/mod.rs | 10 + compiler/rustc_middle/src/ty/predicate.rs | 42 +- compiler/rustc_middle/src/ty/sty.rs | 16 + compiler/rustc_middle/src/ty/util.rs | 36 -- compiler/rustc_next_trait_solver/Cargo.toml | 18 +- compiler/rustc_next_trait_solver/src/infcx.rs | 116 +++- compiler/rustc_next_trait_solver/src/lib.rs | 6 + compiler/rustc_next_trait_solver/src/solve.rs | 1 - .../src/solve/alias_relate.rs | 19 +- .../src/solve/assembly/mod.rs | 514 +++++++---------- .../src/solve/assembly/structural_traits.rs | 12 +- .../src/solve/eval_ctxt/canonical.rs | 238 +++----- .../src/solve/eval_ctxt/mod.rs | 363 ++++++------ .../src/solve/eval_ctxt/probe.rs | 15 +- .../src/solve/inspect/build.rs | 40 +- .../src/solve/inspect/mod.rs | 4 + .../src/solve/mod.rs | 128 ++--- .../src/solve/normalizes_to/anon_const.rs | 18 +- .../src/solve/normalizes_to/inherent.rs | 26 +- .../src/solve/normalizes_to/mod.rs | 541 ++++++++---------- .../src/solve/normalizes_to/opaque_types.rs | 68 ++- .../src/solve/normalizes_to/weak_types.rs | 23 +- .../src/solve/project_goals.rs | 18 +- .../src/solve/search_graph.rs | 19 +- .../src/solve/trait_goals.rs | 421 +++++++------- .../src/solve/inspect/mod.rs | 7 - compiler/rustc_type_ir/src/inherent.rs | 182 +++++- compiler/rustc_type_ir/src/interner.rs | 124 +++- compiler/rustc_type_ir/src/lang_items.rs | 32 +- compiler/rustc_type_ir/src/predicate.rs | 8 +- 36 files changed, 2014 insertions(+), 1457 deletions(-) delete mode 100644 compiler/rustc_next_trait_solver/src/solve.rs rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/alias_relate.rs (90%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/assembly/mod.rs (59%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/assembly/structural_traits.rs (98%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/eval_ctxt/canonical.rs (63%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/eval_ctxt/mod.rs (78%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/eval_ctxt/probe.rs (95%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/inspect/build.rs (96%) create mode 100644 compiler/rustc_next_trait_solver/src/solve/inspect/mod.rs rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/mod.rs (75%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/normalizes_to/anon_const.rs (66%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/normalizes_to/inherent.rs (75%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/normalizes_to/mod.rs (63%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/normalizes_to/opaque_types.rs (64%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/normalizes_to/weak_types.rs (67%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/project_goals.rs (63%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/search_graph.rs (98%) rename compiler/{rustc_trait_selection => rustc_next_trait_solver}/src/solve/trait_goals.rs (77%) delete mode 100644 compiler/rustc_trait_selection/src/solve/inspect/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 2e10b4c49ab..14ee031ad04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4520,7 +4520,16 @@ dependencies = [ name = "rustc_next_trait_solver" version = "0.0.0" dependencies = [ + "bitflags 2.5.0", + "derivative", + "rustc_ast_ir", + "rustc_data_structures", + "rustc_index", + "rustc_macros", + "rustc_serialize", "rustc_type_ir", + "rustc_type_ir_macros", + "tracing", ] [[package]] diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 684b3233cfd..8e221cdc603 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -205,6 +205,14 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { self.did() } + fn is_struct(self) -> bool { + self.is_struct() + } + + fn struct_tail_ty(self, interner: TyCtxt<'tcx>) -> Option>> { + Some(interner.type_of(self.non_enum_variant().tail_opt()?.did)) + } + fn is_phantom_data(self) -> bool { self.is_phantom_data() } @@ -212,7 +220,7 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { fn all_field_tys( self, tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<'tcx, impl Iterator>> { + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { ty::EarlyBinder::bind( self.all_fields().map(move |field| tcx.type_of(field.did).skip_binder()), ) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 12f0c38b054..32d01d07c17 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -16,8 +16,8 @@ mod valtree; pub use int::*; pub use kind::*; -use rustc_span::Span; use rustc_span::DUMMY_SP; +use rustc_span::{ErrorGuaranteed, Span}; pub use valtree::*; pub type ConstKind<'tcx> = ir::ConstKind>; @@ -176,6 +176,10 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self { Const::new_expr(interner, expr) } + + fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { + Const::new_error(interner, guar) + } } impl<'tcx> Const<'tcx> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 828cd761c19..2663dca7460 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -90,46 +90,65 @@ use std::ops::{Bound, Deref}; impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; type LocalDefId = LocalDefId; - type AdtDef = ty::AdtDef<'tcx>; - type GenericArgs = ty::GenericArgsRef<'tcx>; + type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; type GenericArg = ty::GenericArg<'tcx>; type Term = ty::Term<'tcx>; - type BoundVarKinds = &'tcx List; - type BoundVarKind = ty::BoundVariableKind; - type CanonicalVars = CanonicalVarInfos<'tcx>; + type BoundVarKind = ty::BoundVariableKind; type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; + + fn mk_predefined_opaques_in_body( + self, + data: PredefinedOpaquesData, + ) -> Self::PredefinedOpaques { + self.mk_predefined_opaques_in_body(data) + } type DefiningOpaqueTypes = &'tcx ty::List; - type ExternalConstraints = ExternalConstraints<'tcx>; type CanonicalGoalEvaluationStepRef = &'tcx solve::inspect::CanonicalGoalEvaluationStep>; + type CanonicalVars = CanonicalVarInfos<'tcx>; + fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars { + self.mk_canonical_var_infos(infos) + } + type ExternalConstraints = ExternalConstraints<'tcx>; + fn mk_external_constraints( + self, + data: ExternalConstraintsData, + ) -> ExternalConstraints<'tcx> { + self.mk_external_constraints(data) + } + type DepNodeIndex = DepNodeIndex; + fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) { + self.dep_graph.with_anon_task(self, crate::dep_graph::dep_kinds::TraitSelect, task) + } type Ty = Ty<'tcx>; type Tys = &'tcx List>; + type FnInputTys = &'tcx [Ty<'tcx>]; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; - type PlaceholderTy = ty::PlaceholderType; + type PlaceholderTy = ty::PlaceholderType; type ErrorGuaranteed = ErrorGuaranteed; type BoundExistentialPredicates = &'tcx List>; - type AllocId = crate::mir::interpret::AllocId; + type AllocId = crate::mir::interpret::AllocId; type Pat = Pattern<'tcx>; type Safety = hir::Safety; type Abi = abi::Abi; - type Const = ty::Const<'tcx>; type PlaceholderConst = ty::PlaceholderConst; + type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; type ValueConst = ty::ValTree<'tcx>; type ExprConst = ty::Expr<'tcx>; - type Region = Region<'tcx>; + type EarlyParamRegion = ty::EarlyParamRegion; type LateParamRegion = ty::LateParamRegion; type BoundRegion = ty::BoundRegion; @@ -137,15 +156,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ParamEnv = ty::ParamEnv<'tcx>; type Predicate = Predicate<'tcx>; + type Clause = Clause<'tcx>; type Clauses = ty::Clauses<'tcx>; - type DepNodeIndex = DepNodeIndex; - fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) { - self.dep_graph.with_anon_task(self, crate::dep_graph::dep_kinds::TraitSelect, task) - } - type EvaluationCache = &'tcx solve::EvaluationCache<'tcx>; + fn evaluation_cache(self, mode: SolverMode) -> &'tcx solve::EvaluationCache<'tcx> { match mode { SolverMode::Normal => &self.new_solver_evaluation_cache, @@ -157,17 +173,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.expand_abstract_consts(t) } - fn mk_external_constraints( - self, - data: ExternalConstraintsData, - ) -> ExternalConstraints<'tcx> { - self.mk_external_constraints(data) - } - - fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars { - self.mk_canonical_var_infos(infos) - } - type GenericsOf = &'tcx ty::Generics; fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { @@ -184,6 +189,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.type_of(def_id) } + type AdtDef = ty::AdtDef<'tcx>; + fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { + self.adt_def(adt_def_id) + } + fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { match self.def_kind(alias.def_id) { DefKind::AssocTy => { @@ -221,8 +231,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn trait_ref_and_own_args_for_alias( self, def_id: DefId, - args: Self::GenericArgs, - ) -> (rustc_type_ir::TraitRef, Self::GenericArgsSlice) { + args: ty::GenericArgsRef<'tcx>, + ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); let trait_def_id = self.parent(def_id); assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); @@ -233,18 +243,22 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) } - fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs { + fn mk_args(self, args: &[Self::GenericArg]) -> ty::GenericArgsRef<'tcx> { self.mk_args(args) } fn mk_args_from_iter(self, args: I) -> T::Output where I: Iterator, - T: CollectAndApply, + T: CollectAndApply>, { self.mk_args_from_iter(args) } + fn check_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> bool { + self.check_args_compatible(def_id, args) + } + fn check_and_mk_args( self, def_id: DefId, @@ -263,7 +277,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn mk_type_list_from_iter(self, args: I) -> T::Output where I: Iterator, - T: CollectAndApply, + T: CollectAndApply, &'tcx List>>, { self.mk_type_list_from_iter(args) } @@ -312,6 +326,24 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.item_bounds(def_id).map_bound(IntoIterator::into_iter) } + fn predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + ty::EarlyBinder::bind( + self.predicates_of(def_id).instantiate_identity(self).predicates.into_iter(), + ) + } + + fn own_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + ty::EarlyBinder::bind( + self.predicates_of(def_id).instantiate_own_identity().map(|(clause, _)| clause), + ) + } + fn super_predicates_of( self, def_id: DefId, @@ -326,15 +358,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } fn require_lang_item(self, lang_item: TraitSolverLangItem) -> DefId { - self.require_lang_item( - match lang_item { - TraitSolverLangItem::Future => hir::LangItem::Future, - TraitSolverLangItem::FutureOutput => hir::LangItem::FutureOutput, - TraitSolverLangItem::AsyncFnKindHelper => hir::LangItem::AsyncFnKindHelper, - TraitSolverLangItem::AsyncFnKindUpvars => hir::LangItem::AsyncFnKindUpvars, - }, - None, - ) + self.require_lang_item(trait_lang_item_to_lang_item(lang_item), None) + } + + fn is_lang_item(self, def_id: DefId, lang_item: TraitSolverLangItem) -> bool { + self.is_lang_item(def_id, trait_lang_item_to_lang_item(lang_item)) } fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { @@ -343,6 +371,257 @@ impl<'tcx> Interner for TyCtxt<'tcx> { .filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type)) .map(|assoc_item| assoc_item.def_id) } + + fn args_may_unify_deep( + self, + obligation_args: ty::GenericArgsRef<'tcx>, + impl_args: ty::GenericArgsRef<'tcx>, + ) -> bool { + ty::fast_reject::DeepRejectCtxt { + treat_obligation_params: ty::fast_reject::TreatParams::ForLookup, + } + .args_may_unify(obligation_args, impl_args) + } + + // This implementation is a bit different from `TyCtxt::for_each_relevant_impl`, + // since we want to skip over blanket impls for non-rigid aliases, and also we + // only want to consider types that *actually* unify with float/int vars. + fn for_each_relevant_impl( + self, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + mut f: impl FnMut(DefId), + ) { + let tcx = self; + let trait_impls = tcx.trait_impls_of(trait_def_id); + let mut consider_impls_for_simplified_type = |simp| { + if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { + for &impl_def_id in impls_for_type { + f(impl_def_id); + } + } + }; + + match self_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::Never + | ty::Tuple(_) => { + let simp = ty::fast_reject::simplify_type( + tcx, + self_ty, + ty::fast_reject::TreatParams::ForLookup, + ) + .unwrap(); + consider_impls_for_simplified_type(simp); + } + + // HACK: For integer and float variables we have to manually look at all impls + // which have some integer or float as a self type. + ty::Infer(ty::IntVar(_)) => { + use ty::IntTy::*; + use ty::UintTy::*; + // This causes a compiler error if any new integer kinds are added. + let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy; + let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy; + let possible_integers = [ + // signed integers + ty::SimplifiedType::Int(I8), + ty::SimplifiedType::Int(I16), + ty::SimplifiedType::Int(I32), + ty::SimplifiedType::Int(I64), + ty::SimplifiedType::Int(I128), + ty::SimplifiedType::Int(Isize), + // unsigned integers + ty::SimplifiedType::Uint(U8), + ty::SimplifiedType::Uint(U16), + ty::SimplifiedType::Uint(U32), + ty::SimplifiedType::Uint(U64), + ty::SimplifiedType::Uint(U128), + ty::SimplifiedType::Uint(Usize), + ]; + for simp in possible_integers { + consider_impls_for_simplified_type(simp); + } + } + + ty::Infer(ty::FloatVar(_)) => { + // This causes a compiler error if any new float kinds are added. + let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128); + let possible_floats = [ + ty::SimplifiedType::Float(ty::FloatTy::F16), + ty::SimplifiedType::Float(ty::FloatTy::F32), + ty::SimplifiedType::Float(ty::FloatTy::F64), + ty::SimplifiedType::Float(ty::FloatTy::F128), + ]; + + for simp in possible_floats { + consider_impls_for_simplified_type(simp); + } + } + + // The only traits applying to aliases and placeholders are blanket impls. + // + // Impls which apply to an alias after normalization are handled by + // `assemble_candidates_after_normalizing_self_ty`. + ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (), + + // FIXME: These should ideally not exist as a self type. It would be nice for + // the builtin auto trait impls of coroutines to instead directly recurse + // into the witness. + ty::CoroutineWitness(..) => (), + + // These variants should not exist as a self type. + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Param(_) + | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"), + } + + let trait_impls = tcx.trait_impls_of(trait_def_id); + for &impl_def_id in trait_impls.blanket_impls() { + f(impl_def_id); + } + } + + fn has_item_definition(self, def_id: DefId) -> bool { + self.defaultness(def_id).has_value() + } + + fn impl_is_default(self, impl_def_id: DefId) -> bool { + self.defaultness(impl_def_id).is_default() + } + + fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { + self.impl_trait_ref(impl_def_id).unwrap() + } + + fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity { + self.impl_polarity(impl_def_id) + } + + fn trait_is_auto(self, trait_def_id: DefId) -> bool { + self.trait_is_auto(trait_def_id) + } + + fn trait_is_alias(self, trait_def_id: DefId) -> bool { + self.trait_is_alias(trait_def_id) + } + + fn trait_is_object_safe(self, trait_def_id: DefId) -> bool { + self.is_object_safe(trait_def_id) + } + + fn trait_may_be_implemented_via_object(self, trait_def_id: DefId) -> bool { + self.trait_def(trait_def_id).implement_via_object + } + + fn fn_trait_kind_from_def_id(self, trait_def_id: DefId) -> Option { + self.fn_trait_kind_from_def_id(trait_def_id) + } + + fn async_fn_trait_kind_from_def_id(self, trait_def_id: DefId) -> Option { + self.async_fn_trait_kind_from_def_id(trait_def_id) + } + + fn supertrait_def_ids(self, trait_def_id: DefId) -> impl IntoIterator { + self.supertrait_def_ids(trait_def_id) + } + + fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { + self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) + } + + fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { + self.is_general_coroutine(coroutine_def_id) + } + + fn coroutine_is_async(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_async(coroutine_def_id) + } + + fn coroutine_is_gen(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_gen(coroutine_def_id) + } + + fn coroutine_is_async_gen(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_async_gen(coroutine_def_id) + } + + fn layout_is_pointer_like(self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { + self.layout_of(self.erase_regions(param_env.and(ty))) + .is_ok_and(|layout| layout.layout.is_pointer_like(&self.data_layout)) + } + + type UnsizingParams = &'tcx rustc_index::bit_set::BitSet; + fn unsizing_params_for_adt(self, adt_def_id: DefId) -> Self::UnsizingParams { + self.unsizing_params_for_adt(adt_def_id) + } + + fn find_const_ty_from_env( + self, + param_env: ty::ParamEnv<'tcx>, + placeholder: Self::PlaceholderConst, + ) -> Ty<'tcx> { + placeholder.find_const_ty_from_env(param_env) + } +} + +fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem { + match lang_item { + TraitSolverLangItem::AsyncDestruct => LangItem::AsyncDestruct, + TraitSolverLangItem::AsyncFnKindHelper => LangItem::AsyncFnKindHelper, + TraitSolverLangItem::AsyncFnKindUpvars => LangItem::AsyncFnKindUpvars, + TraitSolverLangItem::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput, + TraitSolverLangItem::AsyncIterator => LangItem::AsyncIterator, + TraitSolverLangItem::CallOnceFuture => LangItem::CallOnceFuture, + TraitSolverLangItem::CallRefFuture => LangItem::CallRefFuture, + TraitSolverLangItem::Clone => LangItem::Clone, + TraitSolverLangItem::Copy => LangItem::Copy, + TraitSolverLangItem::Coroutine => LangItem::Coroutine, + TraitSolverLangItem::CoroutineReturn => LangItem::CoroutineReturn, + TraitSolverLangItem::CoroutineYield => LangItem::CoroutineYield, + TraitSolverLangItem::Destruct => LangItem::Destruct, + TraitSolverLangItem::DiscriminantKind => LangItem::DiscriminantKind, + TraitSolverLangItem::DynMetadata => LangItem::DynMetadata, + TraitSolverLangItem::FnPtrTrait => LangItem::FnPtrTrait, + TraitSolverLangItem::FusedIterator => LangItem::FusedIterator, + TraitSolverLangItem::Future => LangItem::Future, + TraitSolverLangItem::FutureOutput => LangItem::FutureOutput, + TraitSolverLangItem::Iterator => LangItem::Iterator, + TraitSolverLangItem::Metadata => LangItem::Metadata, + TraitSolverLangItem::Option => LangItem::Option, + TraitSolverLangItem::PointeeTrait => LangItem::PointeeTrait, + TraitSolverLangItem::PointerLike => LangItem::PointerLike, + TraitSolverLangItem::Poll => LangItem::Poll, + TraitSolverLangItem::Sized => LangItem::Sized, + TraitSolverLangItem::TransmuteTrait => LangItem::TransmuteTrait, + TraitSolverLangItem::Tuple => LangItem::Tuple, + TraitSolverLangItem::Unpin => LangItem::Unpin, + TraitSolverLangItem::Unsize => LangItem::Unsize, + } +} + +impl<'tcx> rustc_type_ir::inherent::DefId> for DefId { + fn as_local(self) -> Option { + self.as_local() + } } impl<'tcx> rustc_type_ir::inherent::Abi> for abi::Abi { @@ -377,6 +656,10 @@ impl<'tcx> rustc_type_ir::inherent::Features> for &'tcx rustc_featu fn coroutine_clone(self) -> bool { self.coroutine_clone } + + fn associated_const_equality(self) -> bool { + self.associated_const_equality + } } type InternedSet<'tcx, T> = ShardedHashMap, ()>; diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 54c88e48614..4155b120e51 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -44,10 +44,23 @@ pub struct GenericArg<'tcx> { impl<'tcx> rustc_type_ir::inherent::GenericArg> for GenericArg<'tcx> {} impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArgsRef<'tcx> { + fn rebase_onto( + self, + tcx: TyCtxt<'tcx>, + source_ancestor: DefId, + target_args: GenericArgsRef<'tcx>, + ) -> GenericArgsRef<'tcx> { + self.rebase_onto(tcx, source_ancestor, target_args) + } + fn type_at(self, i: usize) -> Ty<'tcx> { self.type_at(i) } + fn region_at(self, i: usize) -> ty::Region<'tcx> { + self.region_at(i) + } + fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericArgsRef<'tcx> { GenericArgs::identity_for_item(tcx, def_id) } @@ -281,6 +294,7 @@ impl<'tcx> GenericArg<'tcx> { pub fn is_non_region_infer(self) -> bool { match self.unpack() { GenericArgKind::Lifetime(_) => false, + // FIXME: This shouldn't return numerical/float. GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(), GenericArgKind::Const(ct) => ct.is_ct_infer(), } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 185dbe44735..6467689a8aa 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -392,6 +392,10 @@ impl<'tcx> GenericPredicates<'tcx> { EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args) } + pub fn instantiate_own_identity(&self) -> impl Iterator, Span)> { + EarlyBinder::bind(self.predicates).instantiate_identity_iter_copied() + } + #[instrument(level = "debug", skip(self, tcx))] fn instantiate_into( &self, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d07541bad93..9c2bfc12a18 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -990,6 +990,16 @@ pub struct ParamEnv<'tcx> { packed: CopyTaggedPtr, ParamTag, true>, } +impl<'tcx> rustc_type_ir::inherent::ParamEnv> for ParamEnv<'tcx> { + fn reveal(self) -> Reveal { + self.reveal() + } + + fn caller_bounds(self) -> impl IntoIterator> { + self.caller_bounds() + } +} + #[derive(Copy, Clone)] struct ParamTag { reveal: traits::Reveal, diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index ae36f2624ca..e9b37503bb3 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -175,6 +175,14 @@ pub struct Clause<'tcx>( impl<'tcx> rustc_type_ir::inherent::Clause> for Clause<'tcx> {} +impl<'tcx> rustc_type_ir::inherent::IntoKind for Clause<'tcx> { + type Kind = ty::Binder<'tcx, ClauseKind<'tcx>>; + + fn kind(self) -> Self::Kind { + self.kind() + } +} + impl<'tcx> Clause<'tcx> { pub fn as_predicate(self) -> Predicate<'tcx> { Predicate(self.0) @@ -251,6 +259,28 @@ impl<'tcx> ExistentialPredicate<'tcx> { pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>; +impl<'tcx> rustc_type_ir::inherent::BoundExistentialPredicates> + for &'tcx ty::List> +{ + fn principal_def_id(self) -> Option { + self.principal_def_id() + } + + fn principal(self) -> Option> { + self.principal() + } + + fn auto_traits(self) -> impl IntoIterator { + self.auto_traits() + } + + fn projection_bounds( + self, + ) -> impl IntoIterator>> { + self.projection_bounds() + } +} + impl<'tcx> ty::List> { /// Returns the "principal `DefId`" of this set of existential predicates. /// @@ -481,12 +511,6 @@ impl<'tcx> UpcastFrom, TraitRef<'tcx>> for Predicate<'tcx> { } } -impl<'tcx> UpcastFrom, TraitRef<'tcx>> for TraitPredicate<'tcx> { - fn upcast_from(from: TraitRef<'tcx>, _tcx: TyCtxt<'tcx>) -> Self { - TraitPredicate { trait_ref: from, polarity: PredicatePolarity::Positive } - } -} - impl<'tcx> UpcastFrom, TraitRef<'tcx>> for Clause<'tcx> { fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self { let p: Predicate<'tcx> = from.upcast(tcx); @@ -543,6 +567,12 @@ impl<'tcx> UpcastFrom, PolyTraitPredicate<'tcx>> for Clause<'tcx> { } } +impl<'tcx> UpcastFrom, RegionOutlivesPredicate<'tcx>> for Predicate<'tcx> { + fn upcast_from(from: RegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(from))).upcast(tcx) + } +} + impl<'tcx> UpcastFrom, PolyRegionOutlivesPredicate<'tcx>> for Predicate<'tcx> { fn upcast_from(from: PolyRegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self { from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8308e537e5e..9c8a3484aa5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -930,6 +930,22 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self { Ty::new_pat(interner, ty, pat) } + + fn new_unit(interner: TyCtxt<'tcx>) -> Self { + interner.types.unit + } + + fn new_usize(interner: TyCtxt<'tcx>) -> Self { + interner.types.usize + } + + fn discriminant_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> { + self.discriminant_ty(interner) + } + + fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> { + self.async_destructor_ty(interner) + } } /// Type utilities diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 52a0e72e17e..b079ed521d3 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -565,42 +565,6 @@ impl<'tcx> TyCtxt<'tcx> { Ok(()) } - /// Checks whether each generic argument is simply a unique generic placeholder. - /// - /// This is used in the new solver, which canonicalizes params to placeholders - /// for better caching. - pub fn uses_unique_placeholders_ignoring_regions( - self, - args: GenericArgsRef<'tcx>, - ) -> Result<(), NotUniqueParam<'tcx>> { - let mut seen = GrowableBitSet::default(); - for arg in args { - match arg.unpack() { - // Ignore regions, since we can't resolve those in a canonicalized - // query in the trait solver. - GenericArgKind::Lifetime(_) => {} - GenericArgKind::Type(t) => match t.kind() { - ty::Placeholder(p) => { - if !seen.insert(p.bound.var) { - return Err(NotUniqueParam::DuplicateParam(t.into())); - } - } - _ => return Err(NotUniqueParam::NotParam(t.into())), - }, - GenericArgKind::Const(c) => match c.kind() { - ty::ConstKind::Placeholder(p) => { - if !seen.insert(p.bound) { - return Err(NotUniqueParam::DuplicateParam(c.into())); - } - } - _ => return Err(NotUniqueParam::NotParam(c.into())), - }, - } - } - - Ok(()) - } - /// Returns `true` if `def_id` refers to a closure, coroutine, or coroutine-closure /// (i.e. an async closure). These are all represented by `hir::Closure`, and all /// have the same `DefKind`. diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index 50dbc991f8f..3a5f438b432 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -5,9 +5,25 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +bitflags = "2.4.1" +derivative = "2.2.0" +rustc_ast_ir = { path = "../rustc_ast_ir" } +rustc_data_structures = { path = "../rustc_data_structures", optional = true } +rustc_index = { path = "../rustc_index", default-features = false } +rustc_macros = { path = "../rustc_macros", optional = true } +rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_type_ir = { path = "../rustc_type_ir", default-features = false } +rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } +tracing = "0.1" # tidy-alphabetical-end [features] default = ["nightly"] -nightly = ["rustc_type_ir/nightly"] +nightly = [ + "rustc_ast_ir/nightly", + "rustc_data_structures", + "rustc_index/nightly", + "rustc_macros", + "rustc_serialize", + "rustc_type_ir/nightly", +] diff --git a/compiler/rustc_next_trait_solver/src/infcx.rs b/compiler/rustc_next_trait_solver/src/infcx.rs index cb46d8f8f73..e1d5c37fada 100644 --- a/compiler/rustc_next_trait_solver/src/infcx.rs +++ b/compiler/rustc_next_trait_solver/src/infcx.rs @@ -1,13 +1,27 @@ +use std::fmt::Debug; + use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::relate::Relate; -use rustc_type_ir::solve::{Goal, NoSolution}; +use rustc_type_ir::solve::{Goal, NoSolution, SolverMode}; use rustc_type_ir::{self as ty, Interner}; pub trait SolverDelegate: Sized { type Interner: Interner; - fn interner(&self) -> Self::Interner; + fn solver_mode(&self) -> SolverMode; + + fn build_with_canonical( + interner: Self::Interner, + solver_mode: SolverMode, + canonical: &ty::Canonical, + ) -> (Self, V, ty::CanonicalVarValues) + where + V: TypeFoldable; + + fn universe(&self) -> ty::UniverseIndex; + fn create_next_universe(&self) -> ty::UniverseIndex; + fn universe_of_ty(&self, ty: ty::TyVid) -> Option; fn universe_of_lt(&self, lt: ty::RegionVid) -> Option; fn universe_of_ct(&self, ct: ty::ConstVid) -> Option; @@ -74,4 +88,102 @@ pub trait SolverDelegate: Sized { T: TypeFoldable; fn probe(&self, probe: impl FnOnce() -> T) -> T; + + // FIXME: Uplift the leak check into this crate. + fn leak_check(&self, max_input_universe: ty::UniverseIndex) -> Result<(), NoSolution>; + + // FIXME: This is only here because elaboration lives in `rustc_infer`! + fn elaborate_supertraits( + interner: Self::Interner, + trait_ref: ty::Binder>, + ) -> impl Iterator>>; + + fn try_const_eval_resolve( + &self, + param_env: ::ParamEnv, + unevaluated: ty::UnevaluatedConst, + ) -> Option<::Const>; + + fn sub_regions( + &self, + sub: ::Region, + sup: ::Region, + ); + + fn register_ty_outlives( + &self, + ty: ::Ty, + r: ::Region, + ); + + // FIXME: This only is here because `wf::obligations` is in `rustc_trait_selection`! + fn well_formed_goals( + &self, + param_env: ::ParamEnv, + arg: ::GenericArg, + ) -> Option::Predicate>>>; + + fn clone_opaque_types_for_query_response( + &self, + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + + fn make_deduplicated_outlives_constraints( + &self, + ) -> Vec::GenericArg>>; + + fn instantiate_canonical( + &self, + canonical: ty::Canonical, + values: ty::CanonicalVarValues, + ) -> V + where + V: TypeFoldable; + + fn instantiate_canonical_var_with_infer( + &self, + cv_info: ty::CanonicalVarInfo, + universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, + ) -> ::GenericArg; + + // FIXME: Can we implement this in terms of `add` and `inject`? + fn insert_hidden_type( + &self, + opaque_type_key: ty::OpaqueTypeKey, + param_env: ::ParamEnv, + hidden_ty: ::Ty, + goals: &mut Vec::Predicate>>, + ) -> Result<(), NoSolution>; + + fn add_item_bounds_for_hidden_type( + &self, + def_id: ::DefId, + args: ::GenericArgs, + param_env: ::ParamEnv, + hidden_ty: ::Ty, + goals: &mut Vec::Predicate>>, + ); + + fn inject_new_hidden_type_unchecked( + &self, + key: ty::OpaqueTypeKey, + hidden_ty: ::Ty, + ); + + fn reset_opaque_types(&self); + + fn trait_ref_is_knowable( + &self, + trait_ref: ty::TraitRef, + lazily_normalize_ty: impl FnMut( + ::Ty, + ) -> Result<::Ty, E>, + ) -> Result; + + fn fetch_eligible_assoc_item( + &self, + param_env: ::ParamEnv, + goal_trait_ref: ty::TraitRef, + trait_assoc_def_id: ::DefId, + impl_def_id: ::DefId, + ) -> Result::DefId>, NoSolution>; } diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index ea3e18872fa..a6002bfd7ca 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -4,6 +4,12 @@ //! but were uplifted in the process of making the new trait solver generic. //! So if you got to this crate from the old solver, it's totally normal. +#![feature(let_chains)] + +// TODO: remove this, use explicit imports. +#[macro_use] +extern crate tracing; + pub mod canonicalizer; pub mod infcx; pub mod resolve; diff --git a/compiler/rustc_next_trait_solver/src/solve.rs b/compiler/rustc_next_trait_solver/src/solve.rs deleted file mode 100644 index eba96facabc..00000000000 --- a/compiler/rustc_next_trait_solver/src/solve.rs +++ /dev/null @@ -1 +0,0 @@ -pub use rustc_type_ir::solve::*; diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs similarity index 90% rename from compiler/rustc_trait_selection/src/solve/alias_relate.rs rename to compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index 722e86f5b84..3228146c689 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -15,17 +15,22 @@ //! (3.) Otherwise, if we end with two rigid (non-projection) or infer types, //! relate them structurally. -use super::infcx::SolverDelegate; -use super::EvalCtxt; -use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; -use rustc_middle::ty; +use rustc_type_ir::inherent::*; +use rustc_type_ir::{self as ty, Interner}; -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +use crate::infcx::SolverDelegate; +use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult}; + +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ #[instrument(level = "trace", skip(self), ret)] pub(super) fn compute_alias_relate_goal( &mut self, - goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>, - ) -> QueryResult<'tcx> { + goal: Goal, + ) -> QueryResult { let tcx = self.interner(); let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some()); diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs similarity index 59% rename from compiler/rustc_trait_selection/src/solve/assembly/mod.rs rename to compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 45d21285ff1..2664b3916e1 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -1,33 +1,25 @@ //! Code shared by trait and projection goals for candidate assembly. -use crate::solve::infcx::SolverDelegate; -use derivative::Derivative; -use rustc_hir::def_id::DefId; -use rustc_hir::LangItem; -use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::util::supertraits; -use rustc_middle::bug; -use rustc_middle::traits::solve::inspect::ProbeKind; -use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause, QueryResult}; -use rustc_middle::traits::BuiltinImplSource; -use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; -use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{fast_reject, TypeFoldable}; -use rustc_middle::ty::{TypeVisitableExt, Upcast}; -use rustc_span::{ErrorGuaranteed, DUMMY_SP}; -use rustc_type_ir::solve::{CandidateSource, CanonicalResponse}; -use rustc_type_ir::Interner; - -use crate::solve::GoalSource; -use crate::solve::{EvalCtxt, SolverMode}; - pub(super) mod structural_traits; +use rustc_type_ir::fold::TypeFoldable; +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, Interner, Upcast as _}; + +use crate::infcx::SolverDelegate; +use crate::solve::inspect::ProbeKind; +use crate::solve::{ + BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, + MaybeCause, NoSolution, QueryResult, SolverMode, +}; + /// A candidate is a possible way to prove a goal. /// /// It consists of both the `source`, which describes how that goal would be proven, /// and the `result` when using the given `source`. -#[derive(Derivative)] +#[derive(derivative::Derivative)] #[derivative(Debug(bound = ""), Clone(bound = ""))] pub(super) struct Candidate { pub(super) source: CandidateSource, @@ -35,39 +27,42 @@ pub(super) struct Candidate { } /// Methods used to assemble candidates for either trait or projection goals. -pub(super) trait GoalKind<'tcx>: - TypeFoldable> + Copy + Eq + std::fmt::Display +pub(super) trait GoalKind::Interner>: + TypeFoldable + Copy + Eq + std::fmt::Display +where + Infcx: SolverDelegate, + I: Interner, { - fn self_ty(self) -> Ty<'tcx>; + fn self_ty(self) -> I::Ty; - fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx>; + fn trait_ref(self, tcx: I) -> ty::TraitRef; - fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self; + fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self; - fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId; + fn trait_def_id(self, tcx: I) -> I::DefId; /// Try equating an assumption predicate against a goal's predicate. If it /// holds, then execute the `then` callback, which should do any additional /// work, then produce a response (typically by executing /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]). fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - source: CandidateSource>, - goal: Goal<'tcx, Self>, - assumption: ty::Clause<'tcx>, - then: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> QueryResult<'tcx>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + source: CandidateSource, + goal: Goal, + assumption: I::Clause, + then: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult, + ) -> Result, NoSolution>; /// Consider a clause, which consists of a "assumption" and some "requirements", /// to satisfy a goal. If the requirements hold, then attempt to satisfy our /// goal by equating it with the assumption. fn probe_and_consider_implied_clause( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - parent_source: CandidateSource>, - goal: Goal<'tcx, Self>, - assumption: ty::Clause<'tcx>, - requirements: impl IntoIterator>)>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + parent_source: CandidateSource, + goal: Goal, + assumption: I::Clause, + requirements: impl IntoIterator)>, + ) -> Result, NoSolution> { Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| { for (nested_source, goal) in requirements { ecx.add_goal(nested_source, goal); @@ -80,15 +75,15 @@ pub(super) trait GoalKind<'tcx>: /// additionally checking all of the supertraits and object bounds to hold, /// since they're not implied by the well-formedness of the object type. fn probe_and_consider_object_bound_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - source: CandidateSource>, - goal: Goal<'tcx, Self>, - assumption: ty::Clause<'tcx>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + source: CandidateSource, + goal: Goal, + assumption: I::Clause, + ) -> Result, NoSolution> { Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { let tcx = ecx.interner(); - let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else { - bug!("expected object type in `probe_and_consider_object_bound_candidate`"); + let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else { + panic!("expected object type in `probe_and_consider_object_bound_candidate`"); }; ecx.add_goals( GoalSource::ImplWhereBound, @@ -104,10 +99,10 @@ pub(super) trait GoalKind<'tcx>: } fn consider_impl_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - impl_def_id: DefId, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + impl_def_id: I::DefId, + ) -> Result, NoSolution>; /// If the predicate contained an error, we want to avoid emitting unnecessary trait /// errors but still want to emit errors for other trait goals. We have some special @@ -116,85 +111,85 @@ pub(super) trait GoalKind<'tcx>: /// Trait goals always hold while projection goals never do. This is a bit arbitrary /// but prevents incorrect normalization while hiding any trait errors. fn consider_error_guaranteed_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - guar: ErrorGuaranteed, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + guar: I::ErrorGuaranteed, + ) -> Result, NoSolution>; /// A type implements an `auto trait` if its components do as well. /// /// These components are given by built-in rules from /// [`structural_traits::instantiate_constituent_tys_for_auto_trait`]. fn consider_auto_trait_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A trait alias holds if the RHS traits and `where` clauses hold. fn consider_trait_alias_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A type is `Sized` if its tail component is `Sized`. /// /// These components are given by built-in rules from /// [`structural_traits::instantiate_constituent_tys_for_sized_trait`]. fn consider_builtin_sized_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. /// /// These components are given by built-in rules from /// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`]. fn consider_builtin_copy_clone_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A type is `PointerLike` if we can compute its layout, and that layout /// matches the layout of `usize`. fn consider_builtin_pointer_like_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A type is a `FnPtr` if it is of `FnPtr` type. fn consider_builtin_fn_ptr_trait_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn` /// family of traits where `A` is given by the signature of the type. fn consider_builtin_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, kind: ty::ClosureKind, - ) -> Result>, NoSolution>; + ) -> Result, NoSolution>; /// An async closure is known to implement the `AsyncFn` family of traits /// where `A` is given by the signature of the type. fn consider_builtin_async_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, kind: ty::ClosureKind, - ) -> Result>, NoSolution>; + ) -> Result, NoSolution>; /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which /// is used internally to delay computation for async closures until after /// upvar analysis is performed in HIR typeck. fn consider_builtin_async_fn_kind_helper_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// `Tuple` is implemented if the `Self` type is a tuple. fn consider_builtin_tuple_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// `Pointee` is always implemented. /// @@ -202,65 +197,65 @@ pub(super) trait GoalKind<'tcx>: /// the built-in types. For structs, the metadata type is given by the struct /// tail. fn consider_builtin_pointee_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A coroutine (that comes from an `async` desugaring) is known to implement /// `Future`, where `O` is given by the coroutine's return type /// that was computed during type-checking. fn consider_builtin_future_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A coroutine (that comes from a `gen` desugaring) is known to implement /// `Iterator`, where `O` is given by the generator's yield type /// that was computed during type-checking. fn consider_builtin_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A coroutine (that comes from a `gen` desugaring) is known to implement /// `FusedIterator` fn consider_builtin_fused_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; fn consider_builtin_async_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to /// implement `Coroutine`, given the resume, yield, /// and return types of the coroutine computed during type-checking. fn consider_builtin_coroutine_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; fn consider_builtin_discriminant_kind_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; fn consider_builtin_async_destruct_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; fn consider_builtin_destruct_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; fn consider_builtin_transmute_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution>; /// Consider (possibly several) candidates to upcast or unsize a type to another /// type, excluding the coercion of a sized type into a `dyn Trait`. @@ -270,16 +265,20 @@ pub(super) trait GoalKind<'tcx>: /// otherwise recompute this for codegen. This is a bit of a mess but the /// easiest way to maintain the existing behavior for now. fn consider_structural_builtin_unsize_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Vec>>; + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Vec>; } -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { - pub(super) fn assemble_and_evaluate_candidates>( +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ + pub(super) fn assemble_and_evaluate_candidates>( &mut self, - goal: Goal<'tcx, G>, - ) -> Vec>> { + goal: Goal, + ) -> Vec> { let Ok(normalized_self_ty) = self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty()) else { @@ -291,7 +290,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { return self.forced_ambiguity(MaybeCause::Ambiguity).into_iter().collect(); } - let goal: Goal<'tcx, G> = goal.with( + let goal: Goal = goal.with( self.interner(), goal.predicate.with_self_ty(self.interner(), normalized_self_ty), ); @@ -301,7 +300,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { let mut candidates = vec![]; - self.assemble_non_blanket_impl_candidates(goal, &mut candidates); + self.assemble_impl_candidates(goal, &mut candidates); self.assemble_builtin_impl_candidates(goal, &mut candidates); @@ -309,8 +308,6 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { self.assemble_object_bound_candidates(goal, &mut candidates); - self.assemble_blanket_impl_candidates(goal, &mut candidates); - self.assemble_param_env_candidates(goal, &mut candidates); match self.solver_mode() { @@ -326,7 +323,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { pub(super) fn forced_ambiguity( &mut self, cause: MaybeCause, - ) -> Result>, NoSolution> { + ) -> Result, NoSolution> { // This may fail if `try_evaluate_added_goals` overflows because it // fails to reach a fixpoint but ends up getting an error after // running for some additional step. @@ -339,149 +336,36 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { } #[instrument(level = "trace", skip_all)] - fn assemble_non_blanket_impl_candidates>( + fn assemble_impl_candidates>( &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + goal: Goal, + candidates: &mut Vec>, ) { let tcx = self.interner(); - let self_ty = goal.predicate.self_ty(); - let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx)); - let mut consider_impls_for_simplified_type = |simp| { - if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { - for &impl_def_id in impls_for_type { - // For every `default impl`, there's always a non-default `impl` - // that will *also* apply. There's no reason to register a candidate - // for this impl, since it is *not* proof that the trait goal holds. - if tcx.defaultness(impl_def_id).is_default() { - return; - } - - match G::consider_impl_candidate(self, goal, impl_def_id) { - Ok(candidate) => candidates.push(candidate), - Err(NoSolution) => (), - } + tcx.for_each_relevant_impl( + goal.predicate.trait_def_id(tcx), + goal.predicate.self_ty(), + |impl_def_id| { + // For every `default impl`, there's always a non-default `impl` + // that will *also* apply. There's no reason to register a candidate + // for this impl, since it is *not* proof that the trait goal holds. + if tcx.impl_is_default(impl_def_id) { + return; } - } - }; - match self_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::Never - | ty::Tuple(_) => { - let simp = - fast_reject::simplify_type(tcx, self_ty, TreatParams::ForLookup).unwrap(); - consider_impls_for_simplified_type(simp); - } - - // HACK: For integer and float variables we have to manually look at all impls - // which have some integer or float as a self type. - ty::Infer(ty::IntVar(_)) => { - use ty::IntTy::*; - use ty::UintTy::*; - // This causes a compiler error if any new integer kinds are added. - let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy; - let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy; - let possible_integers = [ - // signed integers - SimplifiedType::Int(I8), - SimplifiedType::Int(I16), - SimplifiedType::Int(I32), - SimplifiedType::Int(I64), - SimplifiedType::Int(I128), - SimplifiedType::Int(Isize), - // unsigned integers - SimplifiedType::Uint(U8), - SimplifiedType::Uint(U16), - SimplifiedType::Uint(U32), - SimplifiedType::Uint(U64), - SimplifiedType::Uint(U128), - SimplifiedType::Uint(Usize), - ]; - for simp in possible_integers { - consider_impls_for_simplified_type(simp); + match G::consider_impl_candidate(self, goal, impl_def_id) { + Ok(candidate) => candidates.push(candidate), + Err(NoSolution) => (), } - } - - ty::Infer(ty::FloatVar(_)) => { - // This causes a compiler error if any new float kinds are added. - let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128); - let possible_floats = [ - SimplifiedType::Float(ty::FloatTy::F16), - SimplifiedType::Float(ty::FloatTy::F32), - SimplifiedType::Float(ty::FloatTy::F64), - SimplifiedType::Float(ty::FloatTy::F128), - ]; - - for simp in possible_floats { - consider_impls_for_simplified_type(simp); - } - } - - // The only traits applying to aliases and placeholders are blanket impls. - // - // Impls which apply to an alias after normalization are handled by - // `assemble_candidates_after_normalizing_self_ty`. - ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (), - - // FIXME: These should ideally not exist as a self type. It would be nice for - // the builtin auto trait impls of coroutines to instead directly recurse - // into the witness. - ty::CoroutineWitness(..) => (), - - // These variants should not exist as a self type. - ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) - | ty::Param(_) - | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"), - } + }, + ); } #[instrument(level = "trace", skip_all)] - fn assemble_blanket_impl_candidates>( + fn assemble_builtin_impl_candidates>( &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, - ) { - let tcx = self.interner(); - let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx)); - for &impl_def_id in trait_impls.blanket_impls() { - // For every `default impl`, there's always a non-default `impl` - // that will *also* apply. There's no reason to register a candidate - // for this impl, since it is *not* proof that the trait goal holds. - if tcx.defaultness(impl_def_id).is_default() { - return; - } - - match G::consider_impl_candidate(self, goal, impl_def_id) { - Ok(candidate) => candidates.push(candidate), - Err(NoSolution) => (), - } - } - } - - #[instrument(level = "trace", skip_all)] - fn assemble_builtin_impl_candidates>( - &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + goal: Goal, + candidates: &mut Vec>, ) { let tcx = self.interner(); let trait_def_id = goal.predicate.trait_def_id(tcx); @@ -499,43 +383,43 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { G::consider_auto_trait_candidate(self, goal) } else if tcx.trait_is_alias(trait_def_id) { G::consider_trait_alias_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::Sized) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Sized) { G::consider_builtin_sized_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::Copy) - || tcx.is_lang_item(trait_def_id, LangItem::Clone) + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Copy) + || tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Clone) { G::consider_builtin_copy_clone_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::PointerLike) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::PointerLike) { G::consider_builtin_pointer_like_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::FnPtrTrait) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::FnPtrTrait) { G::consider_builtin_fn_ptr_trait_candidate(self, goal) } else if let Some(kind) = self.interner().fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_fn_trait_candidates(self, goal, kind) } else if let Some(kind) = self.interner().async_fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_async_fn_trait_candidates(self, goal, kind) - } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncFnKindHelper) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncFnKindHelper) { G::consider_builtin_async_fn_kind_helper_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::Tuple) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Tuple) { G::consider_builtin_tuple_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::PointeeTrait) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::PointeeTrait) { G::consider_builtin_pointee_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::Future) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Future) { G::consider_builtin_future_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::Iterator) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Iterator) { G::consider_builtin_iterator_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::FusedIterator) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::FusedIterator) { G::consider_builtin_fused_iterator_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncIterator) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncIterator) { G::consider_builtin_async_iterator_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Coroutine) { G::consider_builtin_coroutine_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::DiscriminantKind) { G::consider_builtin_discriminant_kind_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncDestruct) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncDestruct) { G::consider_builtin_async_destruct_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::Destruct) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Destruct) { G::consider_builtin_destruct_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, LangItem::TransmuteTrait) { + } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) { G::consider_builtin_transmute_candidate(self, goal) } else { Err(NoSolution) @@ -545,18 +429,18 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // There may be multiple unsize candidates for a trait with several supertraits: // `trait Foo: Bar + Bar` and `dyn Foo: Unsize>` - if tcx.is_lang_item(trait_def_id, LangItem::Unsize) { + if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) { candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal)); } } #[instrument(level = "trace", skip_all)] - fn assemble_param_env_candidates>( + fn assemble_param_env_candidates>( &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + goal: Goal, + candidates: &mut Vec>, ) { - for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { + for (i, assumption) in goal.param_env.caller_bounds().into_iter().enumerate() { candidates.extend(G::probe_and_consider_implied_clause( self, CandidateSource::ParamEnv(i), @@ -568,10 +452,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { } #[instrument(level = "trace", skip_all)] - fn assemble_alias_bound_candidates>( + fn assemble_alias_bound_candidates>( &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + goal: Goal, + candidates: &mut Vec>, ) { let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| { ecx.assemble_alias_bound_candidates_recur(goal.predicate.self_ty(), goal, candidates); @@ -587,13 +471,13 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// If so, continue searching by recursively calling after normalization. // FIXME: This may recurse infinitely, but I can't seem to trigger it without // hitting another overflow error something. Add a depth parameter needed later. - fn assemble_alias_bound_candidates_recur>( + fn assemble_alias_bound_candidates_recur>( &mut self, - self_ty: Ty<'tcx>, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + self_ty: I::Ty, + goal: Goal, + candidates: &mut Vec>, ) { - let (kind, alias_ty) = match *self_ty.kind() { + let (kind, alias_ty) = match self_ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -621,7 +505,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Error(_) => return, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => { - bug!("unexpected self type for `{goal:?}`") + panic!("unexpected self type for `{goal:?}`") } ty::Infer(ty::TyVar(_)) => { @@ -638,16 +522,15 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), ty::Alias(ty::Inherent | ty::Weak, _) => { - self.interner().sess.dcx().span_delayed_bug( - DUMMY_SP, - format!("could not normalize {self_ty}, it is not WF"), - ); + self.interner().delay_bug(format!("could not normalize {self_ty:?}, it is not WF")); return; } }; - for assumption in - self.interner().item_bounds(alias_ty.def_id).instantiate(self.interner(), alias_ty.args) + for assumption in self + .interner() + .item_bounds(alias_ty.def_id) + .iter_instantiated(self.interner(), &alias_ty.args) { candidates.extend(G::probe_and_consider_implied_clause( self, @@ -672,18 +555,18 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { } #[instrument(level = "trace", skip_all)] - fn assemble_object_bound_candidates>( + fn assemble_object_bound_candidates>( &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + goal: Goal, + candidates: &mut Vec>, ) { let tcx = self.interner(); - if !tcx.trait_def(goal.predicate.trait_def_id(tcx)).implement_via_object { + if !tcx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(tcx)) { return; } let self_ty = goal.predicate.self_ty(); - let bounds = match *self_ty.kind() { + let bounds = match self_ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -711,12 +594,12 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Error(_) => return, ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) - | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"), + | ty::Bound(..) => panic!("unexpected self type for `{goal:?}`"), ty::Dynamic(bounds, ..) => bounds, }; // Do not consider built-in object impls for non-object-safe types. - if bounds.principal_def_id().is_some_and(|def_id| !tcx.is_object_safe(def_id)) { + if bounds.principal_def_id().is_some_and(|def_id| !tcx.trait_is_object_safe(def_id)) { return; } @@ -745,7 +628,9 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // a projection goal. if let Some(principal) = bounds.principal() { let principal_trait_ref = principal.with_self_ty(tcx, self_ty); - for (idx, assumption) in supertraits(self.interner(), principal_trait_ref).enumerate() { + for (idx, assumption) in + Infcx::elaborate_supertraits(tcx, principal_trait_ref).enumerate() + { candidates.extend(G::probe_and_consider_object_bound_candidate( self, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)), @@ -763,10 +648,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// To do so we add an ambiguous candidate in case such an unknown impl could /// apply to the current goal. #[instrument(level = "trace", skip_all)] - fn assemble_coherence_unknowable_candidates>( + fn assemble_coherence_unknowable_candidates>( &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + goal: Goal, + candidates: &mut Vec>, ) { let tcx = self.interner(); @@ -792,13 +677,13 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // to improve this however. However, this should make it fairly straightforward to refine // the filtering going forward, so it seems alright-ish for now. #[instrument(level = "debug", skip(self, goal))] - fn discard_impls_shadowed_by_env>( + fn discard_impls_shadowed_by_env>( &mut self, - goal: Goal<'tcx, G>, - candidates: &mut Vec>>, + goal: Goal, + candidates: &mut Vec>, ) { let tcx = self.interner(); - let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = + let trait_goal: Goal> = goal.with(tcx, goal.predicate.trait_ref(tcx)); let mut trait_candidates_from_env = vec![]; @@ -823,7 +708,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { false } CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => true, - CandidateSource::CoherenceUnknowable => bug!("uh oh"), + CandidateSource::CoherenceUnknowable => panic!("uh oh"), }); } // If it is still ambiguous we instead just force the whole goal @@ -841,10 +726,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// to somehow try to merge the candidates into one. If that fails, we return /// ambiguity. #[instrument(level = "debug", skip(self), ret)] - pub(super) fn merge_candidates( - &mut self, - candidates: Vec>>, - ) -> QueryResult<'tcx> { + pub(super) fn merge_candidates(&mut self, candidates: Vec>) -> QueryResult { // First try merging all candidates. This is complete and fully sound. let responses = candidates.iter().map(|c| c.result).collect::>(); if let Some(result) = self.try_merge_responses(&responses) { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs similarity index 98% rename from compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs rename to compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 496be3af573..eb37add61cc 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -3,20 +3,16 @@ use rustc_ast_ir::{Movability, Mutability}; use rustc_data_structures::fx::FxHashMap; -use rustc_next_trait_solver::infcx::SolverDelegate; -use rustc_next_trait_solver::solve::{Goal, NoSolution}; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::{self as ty, Interner, Upcast}; +use rustc_type_ir::{self as ty, Interner, Upcast as _}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::solve::EvalCtxt; +use crate::infcx::SolverDelegate; +use crate::solve::{EvalCtxt, Goal, NoSolution}; // Calculates the constituent types of a type for `auto trait` purposes. -// -// For types with an "existential" binder, i.e. coroutine witnesses, we also -// instantiate the binder with placeholders eagerly. #[instrument(level = "trace", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait( ecx: &EvalCtxt<'_, Infcx>, @@ -745,7 +741,7 @@ impl, I: Interner> TypeFolder ) .expect("expected to be able to unify goal projection with dyn's projection"), ); - proj.term.expect_type() + proj.term.expect_ty() } else { ty.super_fold_with(self) } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs similarity index 63% rename from compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs rename to compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 3ba17a0dcf9..e4b54fff0b3 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -8,60 +8,52 @@ //! section of the [rustc-dev-guide][c]. //! //! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html -use super::{CanonicalInput, Certainty, EvalCtxt, Goal}; -use crate::solve::eval_ctxt::NestedGoals; -use crate::solve::infcx::SolverDelegate; -use crate::solve::{ - inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response, -}; -use rustc_data_structures::fx::FxHashSet; -use rustc_index::IndexVec; -use rustc_infer::infer::canonical::query_response::make_query_region_constraints; -use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; -use rustc_infer::infer::RegionVariableOrigin; -use rustc_infer::infer::{InferCtxt, InferOk}; -use rustc_infer::traits::solve::NestedNormalizationGoals; -use rustc_middle::bug; -use rustc_middle::infer::canonical::Canonical; -use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::solve::{ - ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput, -}; -use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable}; -use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer}; -use rustc_next_trait_solver::infcx::SolverDelegate as IrSolverDelegate; -use rustc_next_trait_solver::resolve::EagerResolver; -use rustc_span::{Span, DUMMY_SP}; -use rustc_type_ir::CanonicalVarValues; -use rustc_type_ir::Interner; -use std::assert_matches::assert_matches; + use std::iter; -use std::ops::Deref; -trait ResponseT<'tcx> { - fn var_values(&self) -> CanonicalVarValues>; +use rustc_index::IndexVec; +use rustc_type_ir::fold::TypeFoldable; +use rustc_type_ir::inherent::*; +use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, Interner}; + +use crate::canonicalizer::{CanonicalizeMode, Canonicalizer}; +use crate::infcx::SolverDelegate; +use crate::resolve::EagerResolver; +use crate::solve::eval_ctxt::NestedGoals; +use crate::solve::inspect; +use crate::solve::{ + response_no_constraints_raw, CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, + ExternalConstraintsData, Goal, MaybeCause, NestedNormalizationGoals, NoSolution, + PredefinedOpaquesData, QueryInput, QueryResult, Response, +}; + +trait ResponseT { + fn var_values(&self) -> CanonicalVarValues; } -impl<'tcx> ResponseT<'tcx> for Response> { - fn var_values(&self) -> CanonicalVarValues> { +impl ResponseT for Response { + fn var_values(&self) -> CanonicalVarValues { self.var_values } } -impl<'tcx, T> ResponseT<'tcx> for inspect::State, T> { - fn var_values(&self) -> CanonicalVarValues> { +impl ResponseT for inspect::State { + fn var_values(&self) -> CanonicalVarValues { self.var_values } } -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ /// Canonicalizes the goal remembering the original values /// for each bound variable. - pub(super) fn canonicalize_goal>>( + pub(super) fn canonicalize_goal>( &self, - goal: Goal<'tcx, T>, - ) -> (Vec>, CanonicalInput<'tcx, T>) { + goal: Goal, + ) -> (Vec, CanonicalInput) { let opaque_types = self.infcx.clone_opaque_types_for_query_response(); let (goal, opaque_types) = (goal, opaque_types).fold_with(&mut EagerResolver::new(self.infcx)); @@ -91,7 +83,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response( &mut self, certainty: Certainty, - ) -> QueryResult<'tcx> { + ) -> QueryResult { self.inspect.make_canonical_response(certainty); let goals_certainty = self.try_evaluate_added_goals()?; @@ -104,8 +96,8 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // We only check for leaks from universes which were entered inside // of the query. - self.infcx.leak_check(self.max_input_universe, None).map_err(|e| { - trace!(?e, "failed the leak check"); + self.infcx.leak_check(self.max_input_universe).map_err(|NoSolution| { + trace!("failed the leak check"); NoSolution })?; @@ -121,7 +113,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { if cfg!(debug_assertions) { assert!(normalizes_to_goals.is_empty()); if goals.is_empty() { - assert_matches!(goals_certainty, Certainty::Yes); + assert!(matches!(goals_certainty, Certainty::Yes)); } } (certainty, NestedNormalizationGoals(goals)) @@ -160,7 +152,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { pub(in crate::solve) fn make_ambiguous_response_no_constraints( &self, maybe_cause: MaybeCause, - ) -> CanonicalResponse<'tcx> { + ) -> CanonicalResponse { response_no_constraints_raw( self.interner(), self.max_input_universe, @@ -180,8 +172,8 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { fn compute_external_query_constraints( &self, certainty: Certainty, - normalization_nested_goals: NestedNormalizationGoals>, - ) -> ExternalConstraintsData> { + normalization_nested_goals: NestedNormalizationGoals, + ) -> ExternalConstraintsData { // We only return region constraints once the certainty is `Yes`. This // is necessary as we may drop nested goals on ambiguity, which may result // in unconstrained inference variables in the region constraints. It also @@ -191,26 +183,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and // `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`. let region_constraints = if certainty == Certainty::Yes { - // Cannot use `take_registered_region_obligations` as we may compute the response - // inside of a `probe` whenever we have multiple choices inside of the solver. - let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); - let QueryRegionConstraints { outlives, member_constraints } = - self.infcx.with_region_constraints(|region_constraints| { - make_query_region_constraints( - self.interner(), - region_obligations.iter().map(|r_o| { - (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()) - }), - region_constraints, - ) - }); - assert_eq!(member_constraints, vec![]); - let mut seen = FxHashSet::default(); - outlives - .into_iter() - .filter(|(outlives, _)| seen.insert(*outlives)) - .map(|(outlives, _origin)| outlives) - .collect() + self.infcx.make_deduplicated_outlives_constraints() } else { Default::default() }; @@ -240,10 +213,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// the `normalization_nested_goals` pub(super) fn instantiate_and_apply_query_response( &mut self, - param_env: ty::ParamEnv<'tcx>, - original_values: Vec>, - response: CanonicalResponse<'tcx>, - ) -> (NestedNormalizationGoals>, Certainty) { + param_env: I::ParamEnv, + original_values: Vec, + response: CanonicalResponse, + ) -> (NestedNormalizationGoals, Certainty) { let instantiation = Self::compute_query_response_instantiation_values( self.infcx, &original_values, @@ -251,7 +224,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { ); let Response { var_values, external_constraints, certainty } = - response.instantiate(self.interner(), &instantiation); + self.infcx.instantiate_canonical(response, instantiation); Self::unify_query_var_values(self.infcx, param_env, &original_values, var_values); @@ -259,7 +232,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { region_constraints, opaque_types, normalization_nested_goals, - } = external_constraints.deref(); + } = &*external_constraints; self.register_region_constraints(region_constraints); self.register_new_opaque_types(opaque_types); (normalization_nested_goals.clone(), certainty) @@ -268,11 +241,11 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// This returns the canoncial variable values to instantiate the bound variables of /// the canonical response. This depends on the `original_values` for the /// bound variables. - fn compute_query_response_instantiation_values>( - infcx: &InferCtxt<'tcx>, - original_values: &[ty::GenericArg<'tcx>], - response: &Canonical<'tcx, T>, - ) -> CanonicalVarValues> { + fn compute_query_response_instantiation_values>( + infcx: &Infcx, + original_values: &[I::GenericArg], + response: &Canonical, + ) -> CanonicalVarValues { // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the // caller. @@ -294,35 +267,35 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // inference variable of the input right away, which is more performant. let mut opt_values = IndexVec::from_elem_n(None, response.variables.len()); for (original_value, result_value) in iter::zip(original_values, var_values.var_values) { - match result_value.unpack() { - GenericArgKind::Type(t) => { - if let &ty::Bound(debruijn, b) = t.kind() { + match result_value.kind() { + ty::GenericArgKind::Type(t) => { + if let ty::Bound(debruijn, b) = t.kind() { assert_eq!(debruijn, ty::INNERMOST); - opt_values[b.var] = Some(*original_value); + opt_values[b.var()] = Some(*original_value); } } - GenericArgKind::Lifetime(r) => { - if let ty::ReBound(debruijn, br) = *r { + ty::GenericArgKind::Lifetime(r) => { + if let ty::ReBound(debruijn, br) = r.kind() { assert_eq!(debruijn, ty::INNERMOST); - opt_values[br.var] = Some(*original_value); + opt_values[br.var()] = Some(*original_value); } } - GenericArgKind::Const(c) => { - if let ty::ConstKind::Bound(debruijn, b) = c.kind() { + ty::GenericArgKind::Const(c) => { + if let ty::ConstKind::Bound(debruijn, bv) = c.kind() { assert_eq!(debruijn, ty::INNERMOST); - opt_values[b] = Some(*original_value); + opt_values[bv.var()] = Some(*original_value); } } } } - let var_values = infcx.tcx.mk_args_from_iter(response.variables.iter().enumerate().map( - |(index, info)| { + let var_values = infcx.interner().mk_args_from_iter( + response.variables.into_iter().enumerate().map(|(index, info)| { if info.universe() != ty::UniverseIndex::ROOT { // A variable from inside a binder of the query. While ideally these shouldn't // exist at all (see the FIXME at the start of this method), we have to deal with // them for now. - infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| { + infcx.instantiate_canonical_var_with_infer(info, |idx| { ty::UniverseIndex::from(prev_universe.index() + idx.index()) }) } else if info.is_existential() { @@ -333,18 +306,18 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // more placeholders then they should be able to. However the inference variables have // to "come from somewhere", so by equating them with the original values of the caller // later on, we pull them down into their correct universe again. - if let Some(v) = opt_values[BoundVar::from_usize(index)] { + if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] { v } else { - infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe) + infcx.instantiate_canonical_var_with_infer(info, |_| prev_universe) } } else { // For placeholders which were already part of the input, we simply map this // universal bound variable back the placeholder of the input. original_values[info.expect_placeholder_index()] } - }, - )); + }), + ); CanonicalVarValues { var_values } } @@ -363,40 +336,35 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// always relate them structurally here. #[instrument(level = "trace", skip(infcx))] fn unify_query_var_values( - infcx: &InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - original_values: &[ty::GenericArg<'tcx>], - var_values: CanonicalVarValues>, + infcx: &Infcx, + param_env: I::ParamEnv, + original_values: &[I::GenericArg], + var_values: CanonicalVarValues, ) { assert_eq!(original_values.len(), var_values.len()); - let cause = ObligationCause::dummy(); for (&orig, response) in iter::zip(original_values, var_values.var_values) { - let InferOk { value: (), obligations } = infcx - .at(&cause, param_env) - .eq_structurally_relating_aliases(orig, response) - .unwrap(); - assert!(obligations.is_empty()); + let goals = infcx.eq_structurally_relating_aliases(param_env, orig, response).unwrap(); + assert!(goals.is_empty()); } } fn register_region_constraints( &mut self, - outlives: &[ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>], + outlives: &[ty::OutlivesPredicate], ) { for &ty::OutlivesPredicate(lhs, rhs) in outlives { - match lhs.unpack() { - GenericArgKind::Lifetime(lhs) => self.register_region_outlives(lhs, rhs), - GenericArgKind::Type(lhs) => self.register_ty_outlives(lhs, rhs), - GenericArgKind::Const(_) => bug!("const outlives: {lhs:?}: {rhs:?}"), + match lhs.kind() { + ty::GenericArgKind::Lifetime(lhs) => self.register_region_outlives(lhs, rhs), + ty::GenericArgKind::Type(lhs) => self.register_ty_outlives(lhs, rhs), + ty::GenericArgKind::Const(_) => panic!("const outlives: {lhs:?}: {rhs:?}"), } } } - fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)]) { + fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey, I::Ty)]) { for &(key, ty) in opaque_types { - let hidden_ty = ty::OpaqueHiddenType { ty, span: DUMMY_SP }; - self.infcx.inject_new_hidden_type_unchecked(key, hidden_ty); + self.infcx.inject_new_hidden_type_unchecked(key, ty); } } } @@ -412,7 +380,7 @@ pub(in crate::solve) fn make_canonical_state( data: T, ) -> inspect::CanonicalState where - Infcx: IrSolverDelegate, + Infcx: SolverDelegate, I: Interner, T: TypeFoldable, { @@ -426,47 +394,3 @@ where state, ) } - -/// Instantiate a `CanonicalState`. -/// -/// Unlike for query responses, `CanonicalState` also track fresh inference -/// variables created while evaluating a goal. When creating two separate -/// `CanonicalState` during a single evaluation both may reference this -/// fresh inference variable. When instantiating them we now create separate -/// inference variables for it and have to unify them somehow. We do this -/// by extending the `var_values` while building the proof tree. -/// -/// This currently assumes that unifying the var values trivially succeeds. -/// Adding any inference constraints which weren't present when originally -/// computing the canonical query can result in bugs. -#[instrument(level = "trace", skip(infcx, span, param_env))] -pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable>>( - infcx: &InferCtxt<'tcx>, - span: Span, - param_env: ty::ParamEnv<'tcx>, - orig_values: &mut Vec>, - state: inspect::CanonicalState, T>, -) -> T { - // In case any fresh inference variables have been created between `state` - // and the previous instantiation, extend `orig_values` for it. - assert!(orig_values.len() <= state.value.var_values.len()); - for i in orig_values.len()..state.value.var_values.len() { - let unconstrained = match state.value.var_values.var_values[i].unpack() { - ty::GenericArgKind::Lifetime(_) => { - infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)).into() - } - ty::GenericArgKind::Type(_) => infcx.next_ty_var(span).into(), - ty::GenericArgKind::Const(_) => infcx.next_const_var(span).into(), - }; - - orig_values.push(unconstrained); - } - - let instantiation = - EvalCtxt::compute_query_response_instantiation_values(infcx, orig_values, &state); - - let inspect::State { var_values, data } = state.instantiate(infcx.tcx, &instantiation); - - EvalCtxt::unify_query_var_values(infcx, param_env, orig_values, var_values); - data -} diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs similarity index 78% rename from compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs rename to compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c1fca092a08..6d0fee955b9 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1,41 +1,29 @@ -use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir::def_id::DefId; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals}; -use rustc_infer::traits::ObligationCause; -use rustc_macros::{extension, HashStable, HashStable_NoContext, TyDecodable, TyEncodable}; -use rustc_middle::bug; -use rustc_middle::traits::solve::{ - inspect, CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaquesData, QueryResult, -}; -use rustc_middle::ty::AliasRelationDirection; -use rustc_middle::ty::TypeFolder; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; -use rustc_next_trait_solver::infcx::SolverDelegate as IrSolverDelegate; -use rustc_span::DUMMY_SP; -use rustc_type_ir::fold::TypeSuperFoldable; -use rustc_type_ir::inherent::*; -use rustc_type_ir::relate::Relate; -use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use rustc_type_ir::{self as ir, CanonicalVarValues, Interner}; -use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use std::ops::ControlFlow; -use crate::solve::infcx::SolverDelegate; -use crate::traits::coherence; +use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_type_ir::inherent::*; +use rustc_type_ir::relate::Relate; +use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +use rustc_type_ir::{self as ty, CanonicalVarValues, Interner}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; -use super::inspect::ProofTreeBuilder; -use super::{search_graph, GoalEvaluationKind, FIXPOINT_STEP_LIMIT}; -use super::{search_graph::SearchGraph, Goal}; -use super::{GoalSource, SolverMode}; +use crate::infcx::SolverDelegate; +use crate::solve::inspect::{self, ProofTreeBuilder}; +use crate::solve::search_graph::SearchGraph; +use crate::solve::{ + search_graph, CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, + GoalSource, MaybeCause, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, + QueryResult, SolverMode, FIXPOINT_STEP_LIMIT, +}; pub(super) mod canonical; mod probe; -pub struct EvalCtxt<'a, Infcx, I = ::Interner> +pub struct EvalCtxt<'a, Infcx, I = ::Interner> where - Infcx: IrSolverDelegate, + Infcx: SolverDelegate, I: Interner, { /// The inference context that backs (mostly) inference and placeholder terms @@ -112,9 +100,9 @@ pub struct NestedGoals { /// /// Forgetting to replace the RHS with a fresh inference variable when we evaluate /// this goal results in an ICE.. - pub normalizes_to_goals: Vec>>, + pub normalizes_to_goals: Vec>>, /// The rest of the goals which have not yet processed or remain ambiguous. - pub goals: Vec<(GoalSource, ir::solve::Goal)>, + pub goals: Vec<(GoalSource, Goal)>, } impl NestedGoals { @@ -127,14 +115,25 @@ impl NestedGoals { } } -#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] +#[derive(PartialEq, Eq, Debug, Hash, HashStable_NoContext, Clone, Copy)] pub enum GenerateProofTree { Yes, No, } -#[extension(pub trait InferCtxtEvalExt<'tcx>)] -impl<'tcx> InferCtxt<'tcx> { +pub trait SolverDelegateEvalExt: SolverDelegate { + fn evaluate_root_goal( + &self, + goal: Goal::Predicate>, + generate_proof_tree: GenerateProofTree, + ) -> (Result<(bool, Certainty), NoSolution>, Option>); +} + +impl SolverDelegateEvalExt for Infcx +where + Infcx: SolverDelegate, + I: Interner, +{ /// Evaluates a goal from **outside** of the trait solver. /// /// Using this while inside of the solver is wrong as it uses a new @@ -142,17 +141,20 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self))] fn evaluate_root_goal( &self, - goal: Goal<'tcx, ty::Predicate<'tcx>>, + goal: Goal, generate_proof_tree: GenerateProofTree, - ) -> (Result<(bool, Certainty), NoSolution>, Option>>) - { + ) -> (Result<(bool, Certainty), NoSolution>, Option>) { EvalCtxt::enter_root(self, generate_proof_tree, |ecx| { ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) } } -impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { +impl<'a, Infcx, I> EvalCtxt<'a, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ pub(super) fn solver_mode(&self) -> SolverMode { self.search_graph.solver_mode() } @@ -163,17 +165,16 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { /// Creates a root evaluation context and search graph. This should only be /// used from outside of any evaluation, and other methods should be preferred - /// over using this manually (such as [`InferCtxtEvalExt::evaluate_root_goal`]). + /// over using this manually (such as [`SolverDelegateEvalExt::evaluate_root_goal`]). pub(super) fn enter_root( - infcx: &InferCtxt<'tcx>, + infcx: &Infcx, generate_proof_tree: GenerateProofTree, - f: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> R, - ) -> (R, Option>>) { - let mode = if infcx.intercrate { SolverMode::Coherence } else { SolverMode::Normal }; - let mut search_graph = search_graph::SearchGraph::new(mode); + f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> R, + ) -> (R, Option>) { + let mut search_graph = search_graph::SearchGraph::new(infcx.solver_mode()); let mut ecx = EvalCtxt { - infcx: <&SolverDelegate<'tcx>>::from(infcx), + infcx, search_graph: &mut search_graph, nested_goals: NestedGoals::new(), inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree), @@ -181,10 +182,10 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. predefined_opaques_in_body: infcx - .tcx + .interner() .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()), max_input_universe: ty::UniverseIndex::ROOT, - variables: ty::List::empty(), + variables: Default::default(), var_values: CanonicalVarValues::dummy(), is_normalizes_to_goal: false, tainted: Ok(()), @@ -210,24 +211,17 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { /// This function takes care of setting up the inference context, setting the anchor, /// and registering opaques from the canonicalized input. fn enter_canonical( - tcx: TyCtxt<'tcx>, - search_graph: &'a mut search_graph::SearchGraph>, - canonical_input: CanonicalInput<'tcx>, - canonical_goal_evaluation: &mut ProofTreeBuilder>, - f: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>, Goal<'tcx, ty::Predicate<'tcx>>) -> R, + tcx: I, + search_graph: &'a mut search_graph::SearchGraph, + canonical_input: CanonicalInput, + canonical_goal_evaluation: &mut ProofTreeBuilder, + f: impl FnOnce(&mut EvalCtxt<'_, Infcx>, Goal) -> R, ) -> R { - let intercrate = match search_graph.solver_mode() { - SolverMode::Normal => false, - SolverMode::Coherence => true, - }; - let (ref infcx, input, var_values) = tcx - .infer_ctxt() - .intercrate(intercrate) - .with_next_trait_solver(true) - .build_with_canonical(DUMMY_SP, &canonical_input); + let (ref infcx, input, var_values) = + SolverDelegate::build_with_canonical(tcx, search_graph.solver_mode(), &canonical_input); let mut ecx = EvalCtxt { - infcx: <&SolverDelegate<'tcx>>::from(infcx), + infcx, variables: canonical_input.variables, var_values, is_normalizes_to_goal: false, @@ -240,8 +234,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { }; for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { - let hidden_ty = ty::OpaqueHiddenType { ty, span: DUMMY_SP }; - ecx.infcx.inject_new_hidden_type_unchecked(key, hidden_ty); + ecx.infcx.inject_new_hidden_type_unchecked(key, ty); } if !ecx.nested_goals.is_empty() { @@ -256,7 +249,8 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { // instead of taking them. This would cause an ICE here, since we have // assertions against dropping an `InferCtxt` without taking opaques. // FIXME: Once we remove support for the old impl we can remove this. - let _ = infcx.take_opaque_types(); + // FIXME: Could we make `build_with_canonical` into `enter_with_canonical` and call this at the end? + infcx.reset_opaque_types(); result } @@ -268,15 +262,15 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { /// logic of the solver. /// /// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal] - /// if you're inside of the solver or [InferCtxtEvalExt::evaluate_root_goal] if you're + /// if you're inside of the solver or [SolverDelegateEvalExt::evaluate_root_goal] if you're /// outside of it. #[instrument(level = "debug", skip(tcx, search_graph, goal_evaluation), ret)] fn evaluate_canonical_goal( - tcx: TyCtxt<'tcx>, - search_graph: &'a mut search_graph::SearchGraph>, - canonical_input: CanonicalInput<'tcx>, - goal_evaluation: &mut ProofTreeBuilder>, - ) -> QueryResult<'tcx> { + tcx: I, + search_graph: &'a mut search_graph::SearchGraph, + canonical_input: CanonicalInput, + goal_evaluation: &mut ProofTreeBuilder, + ) -> QueryResult { let mut canonical_goal_evaluation = goal_evaluation.new_canonical_goal_evaluation(canonical_input); @@ -315,7 +309,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { &mut self, goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, - goal: Goal<'tcx, ty::Predicate<'tcx>>, + goal: Goal, ) -> Result<(bool, Certainty), NoSolution> { let (normalization_nested_goals, has_changed, certainty) = self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?; @@ -336,8 +330,8 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { &mut self, goal_evaluation_kind: GoalEvaluationKind, _source: GoalSource, - goal: Goal<'tcx, ty::Predicate<'tcx>>, - ) -> Result<(NestedNormalizationGoals>, bool, Certainty), NoSolution> { + goal: Goal, + ) -> Result<(NestedNormalizationGoals, bool, Certainty), NoSolution> { let (orig_values, canonical_goal) = self.canonicalize_goal(goal); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); @@ -377,10 +371,10 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { fn instantiate_response_discarding_overflow( &mut self, - param_env: ty::ParamEnv<'tcx>, - original_values: Vec>, - response: CanonicalResponse<'tcx>, - ) -> (NestedNormalizationGoals>, Certainty, bool) { + param_env: I::ParamEnv, + original_values: Vec, + response: CanonicalResponse, + ) -> (NestedNormalizationGoals, Certainty, bool) { if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty { return (NestedNormalizationGoals::empty(), response.value.certainty, false); } @@ -393,7 +387,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { (normalization_nested_goals, certainty, has_changed) } - fn compute_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> QueryResult<'tcx> { + fn compute_goal(&mut self, goal: Goal) -> QueryResult { let Goal { param_env, predicate } = goal; let kind = predicate.kind(); if let Some(kind) = kind.no_bound_vars() { @@ -429,7 +423,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct }) } ty::PredicateKind::ConstEquate(_, _) => { - bug!("ConstEquate should not be emitted when `-Znext-solver` is active") + panic!("ConstEquate should not be emitted when `-Znext-solver` is active") } ty::PredicateKind::NormalizesTo(predicate) => { self.compute_normalizes_to_goal(Goal { param_env, predicate }) @@ -565,21 +559,16 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { } /// Record impl args in the proof tree for later access by `InspectCandidate`. - pub(crate) fn record_impl_args(&mut self, impl_args: ty::GenericArgsRef<'tcx>) { + pub(crate) fn record_impl_args(&mut self, impl_args: I::GenericArgs) { self.inspect.record_impl_args(self.infcx, self.max_input_universe, impl_args) } -} -impl, I: Interner> EvalCtxt<'_, Infcx> { pub(super) fn interner(&self) -> I { self.infcx.interner() } #[instrument(level = "trace", skip(self))] - pub(super) fn add_normalizes_to_goal( - &mut self, - mut goal: ir::solve::Goal>, - ) { + pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal>) { goal.predicate = goal .predicate .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); @@ -588,11 +577,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { } #[instrument(level = "debug", skip(self))] - pub(super) fn add_goal( - &mut self, - source: GoalSource, - mut goal: ir::solve::Goal, - ) { + pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal) { goal.predicate = goal .predicate .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); @@ -604,7 +589,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { pub(super) fn add_goals( &mut self, source: GoalSource, - goals: impl IntoIterator>, + goals: impl IntoIterator>, ) { for goal in goals { self.add_goal(source, goal); @@ -627,8 +612,8 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { /// If `kind` is an integer inference variable this will still return a ty infer var. pub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term { match kind.kind() { - ir::TermKind::Ty(_) => self.next_ty_infer().into(), - ir::TermKind::Const(_) => self.next_const_infer().into(), + ty::TermKind::Ty(_) => self.next_ty_infer().into(), + ty::TermKind::Const(_) => self.next_const_infer().into(), } } @@ -637,20 +622,17 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { /// This is the case if the `term` does not occur in any other part of the predicate /// and is able to name all other placeholder and inference variables. #[instrument(level = "trace", skip(self), ret)] - pub(super) fn term_is_fully_unconstrained( - &self, - goal: ir::solve::Goal>, - ) -> bool { + pub(super) fn term_is_fully_unconstrained(&self, goal: Goal>) -> bool { let universe_of_term = match goal.predicate.term.kind() { - ir::TermKind::Ty(ty) => { - if let ir::Infer(ir::TyVar(vid)) = ty.kind() { + ty::TermKind::Ty(ty) => { + if let ty::Infer(ty::TyVar(vid)) = ty.kind() { self.infcx.universe_of_ty(vid).unwrap() } else { return false; } } - ir::TermKind::Const(ct) => { - if let ir::ConstKind::Infer(ir::InferConst::Var(vid)) = ct.kind() { + ty::TermKind::Const(ct) => { + if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() { self.infcx.universe_of_ct(vid).unwrap() } else { return false; @@ -658,14 +640,14 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { } }; - struct ContainsTermOrNotNameable<'a, Infcx: IrSolverDelegate, I: Interner> { + struct ContainsTermOrNotNameable<'a, Infcx: SolverDelegate, I: Interner> { term: I::Term, - universe_of_term: ir::UniverseIndex, + universe_of_term: ty::UniverseIndex, infcx: &'a Infcx, } - impl, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> { - fn check_nameable(&self, universe: ir::UniverseIndex) -> ControlFlow<()> { + impl, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> { + fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> { if self.universe_of_term.can_name(universe) { ControlFlow::Continue(()) } else { @@ -674,15 +656,15 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { } } - impl, I: Interner> TypeVisitor + impl, I: Interner> TypeVisitor for ContainsTermOrNotNameable<'_, Infcx, I> { type Result = ControlFlow<()>; fn visit_ty(&mut self, t: I::Ty) -> Self::Result { match t.kind() { - ir::Infer(ir::TyVar(vid)) => { - if let ir::TermKind::Ty(term) = self.term.kind() - && let ir::Infer(ir::TyVar(term_vid)) = term.kind() + ty::Infer(ty::TyVar(vid)) => { + if let ty::TermKind::Ty(term) = self.term.kind() + && let ty::Infer(ty::TyVar(term_vid)) = term.kind() && self.infcx.root_ty_var(vid) == self.infcx.root_ty_var(term_vid) { ControlFlow::Break(()) @@ -690,7 +672,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { self.check_nameable(self.infcx.universe_of_ty(vid).unwrap()) } } - ir::Placeholder(p) => self.check_nameable(p.universe()), + ty::Placeholder(p) => self.check_nameable(p.universe()), _ => { if t.has_non_region_infer() || t.has_placeholders() { t.super_visit_with(self) @@ -703,9 +685,9 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { fn visit_const(&mut self, c: I::Const) -> Self::Result { match c.kind() { - ir::ConstKind::Infer(ir::InferConst::Var(vid)) => { - if let ir::TermKind::Const(term) = self.term.kind() - && let ir::ConstKind::Infer(ir::InferConst::Var(term_vid)) = term.kind() + ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { + if let ty::TermKind::Const(term) = self.term.kind() + && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() && self.infcx.root_const_var(vid) == self.infcx.root_const_var(term_vid) { ControlFlow::Break(()) @@ -713,7 +695,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { self.check_nameable(self.infcx.universe_of_ct(vid).unwrap()) } } - ir::ConstKind::Placeholder(p) => self.check_nameable(p.universe()), + ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe()), _ => { if c.has_non_region_infer() || c.has_placeholders() { c.super_visit_with(self) @@ -741,7 +723,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { lhs: T, rhs: T, ) -> Result<(), NoSolution> { - self.relate(param_env, lhs, ir::Variance::Invariant, rhs) + self.relate(param_env, lhs, ty::Variance::Invariant, rhs) } /// This should be used when relating a rigid alias with another type. @@ -753,8 +735,8 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { pub(super) fn relate_rigid_alias_non_alias( &mut self, param_env: I::ParamEnv, - alias: ir::AliasTerm, - variance: ir::Variance, + alias: ty::AliasTerm, + variance: ty::Variance, term: I::Term, ) -> Result<(), NoSolution> { // NOTE: this check is purely an optimization, the structural eq would @@ -770,7 +752,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { // Alternatively we could modify `Equate` for this case by adding another // variant to `StructurallyRelateAliases`. let identity_args = self.fresh_args_for_item(alias.def_id); - let rigid_ctor = ir::AliasTerm::new(tcx, alias.def_id, identity_args); + let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args); let ctor_term = rigid_ctor.to_term(tcx); let obligations = self.infcx.eq_structurally_relating_aliases(param_env, term, ctor_term)?; @@ -803,7 +785,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { sub: T, sup: T, ) -> Result<(), NoSolution> { - self.relate(param_env, sub, ir::Variance::Covariant, sup) + self.relate(param_env, sub, ty::Variance::Covariant, sup) } #[instrument(level = "trace", skip(self, param_env), ret)] @@ -811,7 +793,7 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { &mut self, param_env: I::ParamEnv, lhs: T, - variance: ir::Variance, + variance: ty::Variance, rhs: T, ) -> Result<(), NoSolution> { let goals = self.infcx.relate(param_env, lhs, variance, rhs)?; @@ -830,20 +812,20 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { param_env: I::ParamEnv, lhs: T, rhs: T, - ) -> Result>, NoSolution> { - self.infcx.relate(param_env, lhs, ir::Variance::Invariant, rhs) + ) -> Result>, NoSolution> { + self.infcx.relate(param_env, lhs, ty::Variance::Invariant, rhs) } pub(super) fn instantiate_binder_with_infer + Copy>( &self, - value: ir::Binder, + value: ty::Binder, ) -> T { self.infcx.instantiate_binder_with_infer(value) } pub(super) fn enter_forall + Copy, U>( &self, - value: ir::Binder, + value: ty::Binder, f: impl FnOnce(T) -> U, ) -> U { self.infcx.enter_forall(value, f) @@ -863,36 +845,29 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { } args } -} -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { - pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) { - self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy()); + pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) { + self.infcx.register_ty_outlives(ty, lt); } - pub(super) fn register_region_outlives(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) { + pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) { // `b : a` ==> `a <= b` - // (inlined from `InferCtxt::region_outlives_predicate`) - self.infcx.sub_regions( - rustc_infer::infer::SubregionOrigin::RelateRegionParamBound(DUMMY_SP), - b, - a, - ); + self.infcx.sub_regions(b, a); } /// Computes the list of goals required for `arg` to be well-formed pub(super) fn well_formed_goals( &self, - param_env: ty::ParamEnv<'tcx>, - arg: ty::GenericArg<'tcx>, - ) -> Option>>> { - crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg) - .map(|obligations| obligations.into_iter().map(|obligation| obligation.into())) + param_env: I::ParamEnv, + arg: I::GenericArg, + ) -> Option>> { + self.infcx.well_formed_goals(param_env, arg) } + /* pub(super) fn is_transmutable( &self, - src_and_dst: rustc_transmute::Types<'tcx>, + src_and_dst: rustc_transmute::Types, assume: rustc_transmute::Assume, ) -> Result { use rustc_transmute::Answer; @@ -906,46 +881,55 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { Answer::No(_) | Answer::If(_) => Err(NoSolution), } } + */ pub(super) fn trait_ref_is_knowable( &mut self, - param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::TraitRef<'tcx>, + param_env: I::ParamEnv, + trait_ref: ty::TraitRef, ) -> Result { let infcx = self.infcx; let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty); - coherence::trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) - .map(|is_knowable| is_knowable.is_ok()) + infcx.trait_ref_is_knowable(trait_ref, lazily_normalize_ty) } - pub(super) fn can_define_opaque_ty(&self, def_id: impl Into) -> bool { - self.infcx.can_define_opaque_ty(def_id) + pub(super) fn fetch_eligible_assoc_item( + &self, + param_env: I::ParamEnv, + goal_trait_ref: ty::TraitRef, + trait_assoc_def_id: I::DefId, + impl_def_id: I::DefId, + ) -> Result, NoSolution> { + self.infcx.fetch_eligible_assoc_item( + param_env, + goal_trait_ref, + trait_assoc_def_id, + impl_def_id, + ) + } + + pub(super) fn can_define_opaque_ty(&self, def_id: I::LocalDefId) -> bool { + self.infcx.defining_opaque_types().contains(&def_id) } pub(super) fn insert_hidden_type( &mut self, - opaque_type_key: OpaqueTypeKey<'tcx>, - param_env: ty::ParamEnv<'tcx>, - hidden_ty: Ty<'tcx>, + opaque_type_key: ty::OpaqueTypeKey, + param_env: I::ParamEnv, + hidden_ty: I::Ty, ) -> Result<(), NoSolution> { let mut goals = Vec::new(); - self.infcx.insert_hidden_type( - opaque_type_key, - DUMMY_SP, - param_env, - hidden_ty, - &mut goals, - )?; + self.infcx.insert_hidden_type(opaque_type_key, param_env, hidden_ty, &mut goals)?; self.add_goals(GoalSource::Misc, goals); Ok(()) } pub(super) fn add_item_bounds_for_hidden_type( &mut self, - opaque_def_id: DefId, - opaque_args: ty::GenericArgsRef<'tcx>, - param_env: ty::ParamEnv<'tcx>, - hidden_ty: Ty<'tcx>, + opaque_def_id: I::DefId, + opaque_args: I::GenericArgs, + param_env: I::ParamEnv, + hidden_ty: I::Ty, ) { let mut goals = Vec::new(); self.infcx.add_item_bounds_for_hidden_type( @@ -962,10 +946,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // current inference context. pub(super) fn unify_existing_opaque_tys( &mut self, - param_env: ty::ParamEnv<'tcx>, - key: ty::OpaqueTypeKey<'tcx>, - ty: Ty<'tcx>, - ) -> Vec> { + param_env: I::ParamEnv, + key: ty::OpaqueTypeKey, + ty: I::Ty, + ) -> Vec> { // FIXME: Super inefficient to be cloning this... let opaques = self.infcx.clone_opaque_types_for_query_response(); @@ -984,7 +968,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { } ecx.eq(param_env, candidate_ty, ty)?; ecx.add_item_bounds_for_hidden_type( - candidate_key.def_id.to_def_id(), + candidate_key.def_id.into(), candidate_key.args, param_env, candidate_ty, @@ -1001,23 +985,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // as an ambiguity rather than no-solution. pub(super) fn try_const_eval_resolve( &self, - param_env: ty::ParamEnv<'tcx>, - unevaluated: ty::UnevaluatedConst<'tcx>, - ) -> Option> { - use rustc_middle::mir::interpret::ErrorHandled; - match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) { - Ok(Some(val)) => Some(ty::Const::new_value( - self.interner(), - val, - self.interner() - .type_of(unevaluated.def) - .instantiate(self.interner(), unevaluated.args), - )), - Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None, - Err(ErrorHandled::Reported(e, _)) => { - Some(ty::Const::new_error(self.interner(), e.into())) - } - } + param_env: I::ParamEnv, + unevaluated: ty::UnevaluatedConst, + ) -> Option { + self.infcx.try_const_eval_resolve(param_env, unevaluated) } } @@ -1030,7 +1001,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs. struct ReplaceAliasWithInfer<'me, 'a, Infcx, I> where - Infcx: IrSolverDelegate, + Infcx: SolverDelegate, I: Interner, { ecx: &'me mut EvalCtxt<'a, Infcx>, @@ -1039,7 +1010,7 @@ where impl TypeFolder for ReplaceAliasWithInfer<'_, '_, Infcx, I> where - Infcx: IrSolverDelegate, + Infcx: SolverDelegate, I: Interner, { fn interner(&self) -> I { @@ -1048,16 +1019,16 @@ where fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { match ty.kind() { - ir::Alias(..) if !ty.has_escaping_bound_vars() => { + ty::Alias(..) if !ty.has_escaping_bound_vars() => { let infer_ty = self.ecx.next_ty_infer(); - let normalizes_to = ir::PredicateKind::AliasRelate( + let normalizes_to = ty::PredicateKind::AliasRelate( ty.into(), infer_ty.into(), - AliasRelationDirection::Equate, + ty::AliasRelationDirection::Equate, ); self.ecx.add_goal( GoalSource::Misc, - ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to), + Goal::new(self.interner(), self.param_env, normalizes_to), ); infer_ty } @@ -1067,16 +1038,16 @@ where fn fold_const(&mut self, ct: I::Const) -> I::Const { match ct.kind() { - ir::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { + ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { let infer_ct = self.ecx.next_const_infer(); - let normalizes_to = ir::PredicateKind::AliasRelate( + let normalizes_to = ty::PredicateKind::AliasRelate( ct.into(), infer_ct.into(), - AliasRelationDirection::Equate, + ty::AliasRelationDirection::Equate, ); self.ecx.add_goal( GoalSource::Misc, - ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to), + Goal::new(self.interner(), self.param_env, normalizes_to), ); infer_ct } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs similarity index 95% rename from compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs rename to compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index 00fe237735b..31edb635415 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -1,13 +1,12 @@ -use crate::solve::assembly::Candidate; - -use super::EvalCtxt; -use rustc_next_trait_solver::infcx::SolverDelegate; -use rustc_next_trait_solver::solve::{ - inspect, BuiltinImplSource, CandidateSource, NoSolution, QueryResult, -}; -use rustc_type_ir::Interner; use std::marker::PhantomData; +use rustc_type_ir::Interner; + +use crate::infcx::SolverDelegate; +use crate::solve::assembly::Candidate; +use crate::solve::inspect; +use crate::solve::{BuiltinImplSource, CandidateSource, EvalCtxt, NoSolution, QueryResult}; + pub(in crate::solve) struct ProbeCtxt<'me, 'a, Infcx, I, F, T> where Infcx: SolverDelegate, diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs similarity index 96% rename from compiler/rustc_trait_selection/src/solve/inspect/build.rs rename to compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index d750cd963de..5fbec4b28d4 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -3,18 +3,20 @@ //! This code is *a bit* of a mess and can hopefully be //! mostly ignored. For a general overview of how it works, //! see the comment on [ProofTreeBuilder]. + use std::marker::PhantomData; use std::mem; -use crate::solve::eval_ctxt::canonical; -use crate::solve::{self, inspect, GenerateProofTree}; -use rustc_middle::bug; -use rustc_next_trait_solver::infcx::SolverDelegate; -use rustc_next_trait_solver::solve::{ - CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, -}; use rustc_type_ir::{self as ty, Interner}; +use crate::infcx::SolverDelegate; +use crate::solve::eval_ctxt::canonical; +use crate::solve::inspect; +use crate::solve::{ + CanonicalInput, Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource, QueryInput, + QueryResult, +}; + /// The core data structure when building proof trees. /// /// In case the current evaluation does not generate a proof @@ -171,7 +173,7 @@ impl WipCanonicalGoalEvaluationStep { for _ in 0..self.probe_depth { match current.steps.last_mut() { Some(WipProbeStep::NestedProbe(p)) => current = p, - _ => bug!(), + _ => panic!(), } } current @@ -294,15 +296,15 @@ impl, I: Interner> ProofTreeBuilder { &mut self, goal: Goal, orig_values: &[I::GenericArg], - kind: solve::GoalEvaluationKind, + kind: GoalEvaluationKind, ) -> ProofTreeBuilder { self.opt_nested(|| match kind { - solve::GoalEvaluationKind::Root => Some(WipGoalEvaluation { + GoalEvaluationKind::Root => Some(WipGoalEvaluation { uncanonicalized_goal: goal, orig_values: orig_values.to_vec(), evaluation: None, }), - solve::GoalEvaluationKind::Nested => None, + GoalEvaluationKind::Nested => None, }) } @@ -414,7 +416,7 @@ impl, I: Interner> ProofTreeBuilder { Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { state.var_values.push(arg.into()); } - Some(s) => bug!("tried to add var values to {s:?}"), + Some(s) => panic!("tried to add var values to {s:?}"), } } @@ -431,7 +433,7 @@ impl, I: Interner> ProofTreeBuilder { })); state.probe_depth += 1; } - Some(s) => bug!("tried to start probe to {s:?}"), + Some(s) => panic!("tried to start probe to {s:?}"), } } @@ -442,7 +444,7 @@ impl, I: Interner> ProofTreeBuilder { let prev = state.current_evaluation_scope().kind.replace(probe_kind); assert_eq!(prev, None); } - _ => bug!(), + _ => panic!(), } } @@ -459,7 +461,7 @@ impl, I: Interner> ProofTreeBuilder { let prev = state.current_evaluation_scope().final_state.replace(final_state); assert_eq!(prev, None); } - _ => bug!(), + _ => panic!(), } } @@ -495,7 +497,7 @@ impl, I: Interner> ProofTreeBuilder { ); state.current_evaluation_scope().steps.push(WipProbeStep::AddGoal(source, goal)) } - _ => bug!(), + _ => panic!(), } } @@ -519,7 +521,7 @@ impl, I: Interner> ProofTreeBuilder { .push(WipProbeStep::RecordImplArgs { impl_args }); } None => {} - _ => bug!(), + _ => panic!(), } } @@ -532,7 +534,7 @@ impl, I: Interner> ProofTreeBuilder { .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty }); } None => {} - _ => bug!(), + _ => panic!(), } } @@ -545,7 +547,7 @@ impl, I: Interner> ProofTreeBuilder { state.var_values.truncate(num_var_values); state.probe_depth -= 1; } - _ => bug!(), + _ => panic!(), } self diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/mod.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/mod.rs new file mode 100644 index 00000000000..65f32f1947f --- /dev/null +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/mod.rs @@ -0,0 +1,4 @@ +pub use rustc_type_ir::solve::inspect::*; + +mod build; +pub(in crate::solve) use build::*; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs similarity index 75% rename from compiler/rustc_trait_selection/src/solve/mod.rs rename to compiler/rustc_next_trait_solver/src/solve/mod.rs index 3b43c0e3e70..6c05394504f 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -14,40 +14,22 @@ //! FIXME(@lcnr): Write that section. If you read this before then ask me //! about it on zulip. -use self::infcx::SolverDelegate; -use rustc_hir::def_id::DefId; -use rustc_infer::infer::canonical::Canonical; -use rustc_infer::traits::query::NoSolution; -use rustc_macros::extension; -use rustc_middle::bug; -use rustc_middle::traits::solve::{ - CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, QueryResult, Response, -}; -use rustc_middle::ty::{ - self, AliasRelationDirection, CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, Ty, - TyCtxt, TypeOutlivesPredicate, UniverseIndex, -}; -use rustc_type_ir::solve::SolverMode; -use rustc_type_ir::{self as ir, Interner}; - mod alias_relate; mod assembly; mod eval_ctxt; -mod fulfill; -mod infcx; pub mod inspect; -mod normalize; mod normalizes_to; mod project_goals; mod search_graph; -mod select; mod trait_goals; -pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt}; -pub use fulfill::{FulfillmentCtxt, NextSolverError}; -pub(crate) use normalize::deeply_normalize_for_diagnostics; -pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes}; -pub use select::InferCtxtSelectExt; +pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt}; +pub use rustc_type_ir::solve::*; + +use rustc_type_ir::inherent::*; +use rustc_type_ir::{self as ty, Interner}; + +use crate::infcx::SolverDelegate; /// How many fixpoint iterations we should attempt inside of the solver before bailing /// with overflow. @@ -66,21 +48,24 @@ enum GoalEvaluationKind { Nested, } -#[extension(trait CanonicalResponseExt)] -impl<'tcx> Canonical<'tcx, Response>> { - fn has_no_inference_or_external_constraints(&self) -> bool { - self.value.external_constraints.region_constraints.is_empty() - && self.value.var_values.is_identity() - && self.value.external_constraints.opaque_types.is_empty() - } +fn has_no_inference_or_external_constraints( + response: ty::Canonical>, +) -> bool { + response.value.external_constraints.region_constraints.is_empty() + && response.value.var_values.is_identity() + && response.value.external_constraints.opaque_types.is_empty() } -impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { +impl<'a, Infcx, I> EvalCtxt<'a, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ #[instrument(level = "trace", skip(self))] fn compute_type_outlives_goal( &mut self, - goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { let ty::OutlivesPredicate(ty, lt) = goal.predicate; self.register_ty_outlives(ty, lt); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) @@ -89,21 +74,18 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { #[instrument(level = "trace", skip(self))] fn compute_region_outlives_goal( &mut self, - goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { let ty::OutlivesPredicate(a, b) = goal.predicate; self.register_region_outlives(a, b); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } #[instrument(level = "trace", skip(self))] - fn compute_coerce_goal( - &mut self, - goal: Goal<'tcx, CoercePredicate<'tcx>>, - ) -> QueryResult<'tcx> { + fn compute_coerce_goal(&mut self, goal: Goal>) -> QueryResult { self.compute_subtype_goal(Goal { param_env: goal.param_env, - predicate: SubtypePredicate { + predicate: ty::SubtypePredicate { a_is_expected: false, a: goal.predicate.a, b: goal.predicate.b, @@ -112,10 +94,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { } #[instrument(level = "trace", skip(self))] - fn compute_subtype_goal( - &mut self, - goal: Goal<'tcx, SubtypePredicate<'tcx>>, - ) -> QueryResult<'tcx> { + fn compute_subtype_goal(&mut self, goal: Goal>) -> QueryResult { if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() { self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } else { @@ -124,8 +103,8 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { } } - fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> { - if self.interner().is_object_safe(trait_def_id) { + fn compute_object_safe_goal(&mut self, trait_def_id: I::DefId) -> QueryResult { + if self.interner().trait_is_object_safe(trait_def_id) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { Err(NoSolution) @@ -133,10 +112,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { } #[instrument(level = "trace", skip(self))] - fn compute_well_formed_goal( - &mut self, - goal: Goal<'tcx, ty::GenericArg<'tcx>>, - ) -> QueryResult<'tcx> { + fn compute_well_formed_goal(&mut self, goal: Goal) -> QueryResult { match self.well_formed_goals(goal.param_env, goal.predicate) { Some(goals) => { self.add_goals(GoalSource::Misc, goals); @@ -149,8 +125,8 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { #[instrument(level = "trace", skip(self))] fn compute_const_evaluatable_goal( &mut self, - Goal { param_env, predicate: ct }: Goal<'tcx, ty::Const<'tcx>>, - ) -> QueryResult<'tcx> { + Goal { param_env, predicate: ct }: Goal, + ) -> QueryResult { match ct.kind() { ty::ConstKind::Unevaluated(uv) => { // We never return `NoSolution` here as `try_const_eval_resolve` emits an @@ -180,7 +156,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { // - `Bound` cannot exist as we don't have a binder around the self Type // - `Expr` is part of `feature(generic_const_exprs)` and is not implemented yet ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Expr(_) => { - bug!("unexpect const kind: {:?}", ct) + panic!("unexpect const kind: {:?}", ct) } } } @@ -188,8 +164,8 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { #[instrument(level = "trace", skip(self), ret)] fn compute_const_arg_has_type_goal( &mut self, - goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>, - ) -> QueryResult<'tcx> { + goal: Goal, + ) -> QueryResult { let (ct, ty) = goal.predicate; let ct_ty = match ct.kind() { @@ -206,7 +182,7 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); } ty::ConstKind::Unevaluated(uv) => { - self.interner().type_of(uv.def).instantiate(self.interner(), uv.args) + self.interner().type_of(uv.def).instantiate(self.interner(), &uv.args) } ty::ConstKind::Expr(_) => unimplemented!( "`feature(generic_const_exprs)` is not supported in the new trait solver" @@ -214,10 +190,10 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { ty::ConstKind::Param(_) => { unreachable!("`ConstKind::Param` should have been canonicalized to `Placeholder`") } - ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), + ty::ConstKind::Bound(_, _) => panic!("escaping bound vars in {:?}", ct), ty::ConstKind::Value(ty, _) => ty, ty::ConstKind::Placeholder(placeholder) => { - placeholder.find_const_ty_from_env(goal.param_env) + self.interner().find_const_ty_from_env(goal.param_env, placeholder) } }; @@ -226,15 +202,19 @@ impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> { } } -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ /// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`. /// /// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`. #[instrument(level = "trace", skip(self), ret)] fn try_merge_responses( &mut self, - responses: &[CanonicalResponse<'tcx>], - ) -> Option> { + responses: &[CanonicalResponse], + ) -> Option> { if responses.is_empty() { return None; } @@ -250,14 +230,14 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { .iter() .find(|response| { response.value.certainty == Certainty::Yes - && response.has_no_inference_or_external_constraints() + && has_no_inference_or_external_constraints(**response) }) .copied() } /// If we fail to merge responses we flounder and return overflow or ambiguity. #[instrument(level = "trace", skip(self), ret)] - fn flounder(&mut self, responses: &[CanonicalResponse<'tcx>]) -> QueryResult<'tcx> { + fn flounder(&mut self, responses: &[CanonicalResponse]) -> QueryResult { if responses.is_empty() { return Err(NoSolution); } @@ -267,7 +247,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { certainty.unify_with(response.value.certainty) }) else { - bug!("expected flounder response to be ambiguous") + panic!("expected flounder response to be ambiguous") }; Ok(self.make_ambiguous_response_no_constraints(maybe_cause)) @@ -281,9 +261,9 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { #[instrument(level = "trace", skip(self, param_env), ret)] fn structurally_normalize_ty( &mut self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - ) -> Result, NoSolution> { + param_env: I::ParamEnv, + ty: I::Ty, + ) -> Result { if let ty::Alias(..) = ty.kind() { let normalized_ty = self.next_ty_infer(); let alias_relate_goal = Goal::new( @@ -292,7 +272,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { ty::PredicateKind::AliasRelate( ty.into(), normalized_ty.into(), - AliasRelationDirection::Equate, + ty::AliasRelationDirection::Equate, ), ); self.add_goal(GoalSource::Misc, alias_relate_goal); @@ -306,15 +286,15 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { fn response_no_constraints_raw( tcx: I, - max_universe: UniverseIndex, + max_universe: ty::UniverseIndex, variables: I::CanonicalVars, certainty: Certainty, -) -> ir::solve::CanonicalResponse { - ir::Canonical { +) -> CanonicalResponse { + ty::Canonical { max_universe, variables, value: Response { - var_values: ir::CanonicalVarValues::make_identity(tcx, variables), + var_values: ty::CanonicalVarValues::make_identity(tcx, variables), // FIXME: maybe we should store the "no response" version in tcx, like // we do for tcx.types and stuff. external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()), diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs similarity index 66% rename from compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs rename to compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index 064018e89b8..9f1917fde84 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -1,14 +1,18 @@ -use crate::solve::infcx::SolverDelegate; -use crate::solve::EvalCtxt; -use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; -use rustc_middle::ty; +use rustc_type_ir::{self as ty, Interner}; -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +use crate::infcx::SolverDelegate; +use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult}; + +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ #[instrument(level = "trace", skip(self), ret)] pub(super) fn normalize_anon_const( &mut self, - goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { if let Some(normalized_const) = self.try_const_eval_resolve( goal.param_env, ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args), diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs similarity index 75% rename from compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs rename to compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 48d45fe510d..8436f3ad484 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -5,17 +5,20 @@ //! 2. equate the self type, and //! 3. instantiate and register where clauses. -use crate::solve::infcx::SolverDelegate; -use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult}; -use rustc_middle::ty; +use rustc_type_ir::{self as ty, Interner}; -use crate::solve::EvalCtxt; +use crate::infcx::SolverDelegate; +use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult}; -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ pub(super) fn normalize_inherent_associated_type( &mut self, - goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { let tcx = self.interner(); let inherent = goal.predicate.alias.expect_ty(tcx); @@ -26,7 +29,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { self.eq( goal.param_env, inherent.self_ty(), - tcx.type_of(impl_def_id).instantiate(tcx, impl_args), + tcx.type_of(impl_def_id).instantiate(tcx, &impl_args), )?; // Equate IAT with the RHS of the project goal @@ -41,12 +44,11 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { self.add_goals( GoalSource::Misc, tcx.predicates_of(inherent.def_id) - .instantiate(tcx, inherent_args) - .into_iter() - .map(|(pred, _)| goal.with(tcx, pred)), + .iter_instantiated(tcx, &inherent_args) + .map(|pred| goal.with(tcx, pred)), ); - let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args); + let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, &inherent_args); self.instantiate_normalizes_to_term(goal, normalized.into()); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs similarity index 63% rename from compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs rename to compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 0aa10afbee7..cbc18449f0a 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -1,35 +1,32 @@ -use crate::traits::specialization_graph::{self, LeafDef, Node}; - -use super::assembly::structural_traits::AsyncCallableRelevantTypes; -use super::assembly::{self, structural_traits, Candidate}; -use super::infcx::SolverDelegate; -use super::{EvalCtxt, GoalSource}; -use rustc_hir::def_id::DefId; -use rustc_hir::LangItem; -use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::inspect::ProbeKind; -use rustc_infer::traits::solve::MaybeCause; -use rustc_infer::traits::Reveal; -use rustc_middle::bug; -use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; -use rustc_middle::traits::BuiltinImplSource; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; -use rustc_middle::ty::NormalizesTo; -use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{TypeVisitableExt, Upcast}; -use rustc_span::{ErrorGuaranteed, DUMMY_SP}; - mod anon_const; mod inherent; mod opaque_types; mod weak_types; -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +use rustc_type_ir::inherent::*; +use rustc_type_ir::lang_items::TraitSolverLangItem; +use rustc_type_ir::Upcast as _; +use rustc_type_ir::{self as ty, Interner, NormalizesTo}; + +use crate::infcx::SolverDelegate; +use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes}; +use crate::solve::assembly::{self, Candidate}; +use crate::solve::inspect::ProbeKind; +use crate::solve::{ + BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, + NoSolution, QueryResult, +}; + +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ #[instrument(level = "trace", skip(self), ret)] pub(super) fn compute_normalizes_to_goal( &mut self, - goal: Goal<'tcx, NormalizesTo<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { self.set_is_normalizes_to_goal(); debug_assert!(self.term_is_fully_unconstrained(goal)); let normalize_result = self @@ -49,10 +46,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// Normalize the given alias by at least one step. If the alias is rigid, this /// returns `NoSolution`. #[instrument(level = "trace", skip(self), ret)] - fn normalize_at_least_one_step( - &mut self, - goal: Goal<'tcx, NormalizesTo<'tcx>>, - ) -> QueryResult<'tcx> { + fn normalize_at_least_one_step(&mut self, goal: Goal>) -> QueryResult { match goal.predicate.alias.kind(self.interner()) { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => { let candidates = self.assemble_and_evaluate_candidates(goal); @@ -72,38 +66,42 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// emit nested `AliasRelate` goals to structurally normalize the alias. pub fn instantiate_normalizes_to_term( &mut self, - goal: Goal<'tcx, NormalizesTo<'tcx>>, - term: ty::Term<'tcx>, + goal: Goal>, + term: I::Term, ) { self.eq(goal.param_env, goal.predicate.term, term) .expect("expected goal term to be fully unconstrained"); } } -impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { - fn self_ty(self) -> Ty<'tcx> { +impl assembly::GoalKind for NormalizesTo +where + Infcx: SolverDelegate, + I: Interner, +{ + fn self_ty(self) -> I::Ty { self.self_ty() } - fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { + fn trait_ref(self, tcx: I) -> ty::TraitRef { self.alias.trait_ref(tcx) } - fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self { self.with_self_ty(tcx, self_ty) } - fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + fn trait_def_id(self, tcx: I) -> I::DefId { self.trait_def_id(tcx) } fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - source: CandidateSource<'tcx>, - goal: Goal<'tcx, Self>, - assumption: ty::Clause<'tcx>, - then: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> QueryResult<'tcx>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + source: CandidateSource, + goal: Goal, + assumption: I::Clause, + then: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult, + ) -> Result, NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.projection_def_id() == goal.predicate.def_id() { let tcx = ecx.interner(); @@ -121,9 +119,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // Add GAT where clauses from the trait's definition ecx.add_goals( GoalSource::Misc, - tcx.predicates_of(goal.predicate.def_id()) - .instantiate_own(tcx, goal.predicate.alias.args) - .map(|(pred, _)| goal.with(tcx, pred)), + tcx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(tcx, &goal.predicate.alias.args) + .map(|pred| goal.with(tcx, pred)), ); then(ecx) @@ -137,24 +135,23 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_impl_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, NormalizesTo<'tcx>>, - impl_def_id: DefId, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal>, + impl_def_id: I::DefId, + ) -> Result, NoSolution> { let tcx = ecx.interner(); let goal_trait_ref = goal.predicate.alias.trait_ref(tcx); - let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; - if !drcx.args_may_unify( - goal.predicate.trait_ref(tcx).args, - impl_trait_header.trait_ref.skip_binder().args, + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + if !ecx.interner().args_may_unify_deep( + goal.predicate.alias.trait_ref(tcx).args, + impl_trait_ref.skip_binder().args, ) { return Err(NoSolution); } // We have to ignore negative impls when projecting. - let impl_polarity = impl_trait_header.polarity; + let impl_polarity = tcx.impl_polarity(impl_def_id); match impl_polarity { ty::ImplPolarity::Negative => return Err(NoSolution), ty::ImplPolarity::Reservation => { @@ -165,30 +162,28 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); - let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args); + let impl_trait_ref = impl_trait_ref.instantiate(tcx, &impl_args); ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?; let where_clause_bounds = tcx .predicates_of(impl_def_id) - .instantiate(tcx, impl_args) - .predicates - .into_iter() + .iter_instantiated(tcx, &impl_args) .map(|pred| goal.with(tcx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); // Add GAT where clauses from the trait's definition ecx.add_goals( GoalSource::Misc, - tcx.predicates_of(goal.predicate.def_id()) - .instantiate_own(tcx, goal.predicate.alias.args) - .map(|(pred, _)| goal.with(tcx, pred)), + tcx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(tcx, &goal.predicate.alias.args) + .map(|pred| goal.with(tcx, pred)), ); // In case the associated item is hidden due to specialization, we have to // return ambiguity this would otherwise be incomplete, resulting in // unsoundness during coherence (#105782). - let Some(assoc_def) = ecx.fetch_eligible_assoc_item_def( + let Some(target_item_def_id) = ecx.fetch_eligible_assoc_item( goal.param_env, goal_trait_ref, goal.predicate.def_id(), @@ -198,21 +193,23 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); }; - let error_response = |ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, reason| { - let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason); + let error_response = |ecx: &mut EvalCtxt<'_, Infcx>, msg: &str| { + let guar = tcx.delay_bug(msg); let error_term = match goal.predicate.alias.kind(tcx) { ty::AliasTermKind::ProjectionTy => Ty::new_error(tcx, guar).into(), - ty::AliasTermKind::ProjectionConst => ty::Const::new_error(tcx, guar).into(), - kind => bug!("expected projection, found {kind:?}"), + ty::AliasTermKind::ProjectionConst => Const::new_error(tcx, guar).into(), + kind => panic!("expected projection, found {kind:?}"), }; ecx.instantiate_normalizes_to_term(goal, error_term); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }; - if !assoc_def.item.defaultness(tcx).has_value() { - return error_response(ecx, "missing value for assoc item in impl"); + if !tcx.has_item_definition(target_item_def_id) { + return error_response(ecx, "missing item"); } + let target_container_def_id = tcx.parent(target_item_def_id); + // Getting the right args here is complex, e.g. given: // - a goal ` as Trait>::Assoc` // - the applicable impl `impl Trait for Vec` @@ -223,39 +220,40 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // // And then map these args to the args of the defining impl of `Assoc`, going // from `[u32, u64]` to `[u32, i32, u64]`. - let associated_item_args = - ecx.translate_args(&assoc_def, goal, impl_def_id, impl_args, impl_trait_ref)?; + let target_args = ecx.translate_args( + goal, + impl_def_id, + impl_args, + impl_trait_ref, + target_container_def_id, + )?; - if !tcx.check_args_compatible(assoc_def.item.def_id, associated_item_args) { - return error_response( - ecx, - "associated item has mismatched generic item arguments", - ); + if !tcx.check_args_compatible(target_item_def_id, target_args) { + return error_response(ecx, "associated item has mismatched arguments"); } // Finally we construct the actual value of the associated type. let term = match goal.predicate.alias.kind(tcx) { ty::AliasTermKind::ProjectionTy => { - tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()) + tcx.type_of(target_item_def_id).map_bound(|ty| ty.into()) } ty::AliasTermKind::ProjectionConst => { - if tcx.features().associated_const_equality { - bug!("associated const projection is not supported yet") + if tcx.features().associated_const_equality() { + panic!("associated const projection is not supported yet") } else { ty::EarlyBinder::bind( - ty::Const::new_error_with_message( + Const::new_error_with_message( tcx, - DUMMY_SP, "associated const projection is not supported yet", ) .into(), ) } } - kind => bug!("expected projection, found {kind:?}"), + kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, associated_item_args)); + ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, &target_args)); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -263,63 +261,60 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { /// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error` /// and succeed. Can experiment with this to figure out what results in better error messages. fn consider_error_guaranteed_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - _guar: ErrorGuaranteed, - ) -> Result>, NoSolution> { + _ecx: &mut EvalCtxt<'_, Infcx>, + _guar: I::ErrorGuaranteed, + ) -> Result, NoSolution> { Err(NoSolution) } fn consider_auto_trait_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - ecx.interner().dcx().span_delayed_bug( - ecx.interner().def_span(goal.predicate.def_id()), - "associated types not allowed on auto traits", - ); + ecx: &mut EvalCtxt<'_, Infcx>, + _goal: Goal, + ) -> Result, NoSolution> { + ecx.interner().delay_bug("associated types not allowed on auto traits"); Err(NoSolution) } fn consider_trait_alias_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("trait aliases do not have associated types: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("trait aliases do not have associated types: {:?}", goal); } fn consider_builtin_sized_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`Sized` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`Sized` does not have an associated type: {:?}", goal); } fn consider_builtin_copy_clone_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`Copy`/`Clone` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal); } fn consider_builtin_pointer_like_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`PointerLike` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`PointerLike` does not have an associated type: {:?}", goal); } fn consider_builtin_fn_ptr_trait_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`FnPtr` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`FnPtr` does not have an associated type: {:?}", goal); } fn consider_builtin_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, goal_kind: ty::ClosureKind, - ) -> Result>, NoSolution> { + ) -> Result, NoSolution> { let tcx = ecx.interner(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( @@ -333,7 +328,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } }; let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| { - ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output]) + ty::TraitRef::new(tcx, tcx.require_lang_item(TraitSolverLangItem::Sized), [output]) }); let pred = tupled_inputs_and_output @@ -359,16 +354,16 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_async_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, goal_kind: ty::ClosureKind, - ) -> Result>, NoSolution> { + ) -> Result, NoSolution> { let tcx = ecx.interner(); let env_region = match goal_kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), // Doesn't matter what this region is - ty::ClosureKind::FnOnce => tcx.lifetimes.re_static, + ty::ClosureKind::FnOnce => Region::new_static(tcx), }; let (tupled_inputs_and_output_and_coroutine, nested_preds) = structural_traits::extract_tupled_inputs_and_output_from_async_callable( @@ -379,7 +374,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { )?; let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound( |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| { - ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output_ty]) + ty::TraitRef::new( + tcx, + tcx.require_lang_item(TraitSolverLangItem::Sized), + [output_ty], + ) }, ); @@ -391,7 +390,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { coroutine_return_ty, }| { let (projection_term, term) = if tcx - .is_lang_item(goal.predicate.def_id(), LangItem::CallOnceFuture) + .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallOnceFuture) { ( ty::AliasTerm::new( @@ -401,34 +400,41 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ), output_coroutine_ty.into(), ) - } else if tcx.is_lang_item(goal.predicate.def_id(), LangItem::CallRefFuture) { - ( - ty::AliasTerm::new( - tcx, - goal.predicate.def_id(), - [ - ty::GenericArg::from(goal.predicate.self_ty()), - tupled_inputs_ty.into(), - env_region.into(), - ], - ), - output_coroutine_ty.into(), - ) - } else if tcx.is_lang_item(goal.predicate.def_id(), LangItem::AsyncFnOnceOutput) + } else if tcx + .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallRefFuture) { ( ty::AliasTerm::new( tcx, goal.predicate.def_id(), [ - ty::GenericArg::from(goal.predicate.self_ty()), + I::GenericArg::from(goal.predicate.self_ty()), + tupled_inputs_ty.into(), + env_region.into(), + ], + ), + output_coroutine_ty.into(), + ) + } else if tcx.is_lang_item( + goal.predicate.def_id(), + TraitSolverLangItem::AsyncFnOnceOutput, + ) { + ( + ty::AliasTerm::new( + tcx, + goal.predicate.def_id(), + [ + I::GenericArg::from(goal.predicate.self_ty()), tupled_inputs_ty.into(), ], ), coroutine_return_ty.into(), ) } else { - bug!("no such associated type in `AsyncFn*`: {:?}", goal.predicate.def_id()) + panic!( + "no such associated type in `AsyncFn*`: {:?}", + goal.predicate.def_id() + ) }; ty::ProjectionPredicate { projection_term, term } }, @@ -450,9 +456,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_async_fn_kind_helper_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let [ closure_fn_kind_ty, goal_kind_ty, @@ -462,7 +468,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { coroutine_captures_by_ref_ty, ] = **goal.predicate.alias.args else { - bug!(); + panic!(); }; // Bail if the upvars haven't been constrained. @@ -497,18 +503,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_tuple_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`Tuple` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`Tuple` does not have an associated type: {:?}", goal); } fn consider_builtin_pointee_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let tcx = ecx.interner(); - let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); + let metadata_def_id = tcx.require_lang_item(TraitSolverLangItem::Metadata); assert_eq!(metadata_def_id, goal.predicate.def_id()); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let metadata_ty = match goal.predicate.self_ty().kind() { @@ -530,16 +536,16 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::CoroutineWitness(..) | ty::Never | ty::Foreign(..) - | ty::Dynamic(_, _, ty::DynStar) => tcx.types.unit, + | ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(tcx), - ty::Error(e) => Ty::new_error(tcx, *e), + ty::Error(e) => Ty::new_error(tcx, e), - ty::Str | ty::Slice(_) => tcx.types.usize, + ty::Str | ty::Slice(_) => Ty::new_usize(tcx), ty::Dynamic(_, _, ty::Dyn) => { - let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); + let dyn_metadata = tcx.require_lang_item(TraitSolverLangItem::DynMetadata); tcx.type_of(dyn_metadata) - .instantiate(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())]) + .instantiate(tcx, &[I::GenericArg::from(goal.predicate.self_ty())]) } ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { @@ -549,32 +555,31 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // exist. Instead, `Pointee` should be a supertrait of `Sized`. let sized_predicate = ty::TraitRef::new( tcx, - tcx.require_lang_item(LangItem::Sized, None), - [ty::GenericArg::from(goal.predicate.self_ty())], + tcx.require_lang_item(TraitSolverLangItem::Sized), + [I::GenericArg::from(goal.predicate.self_ty())], ); // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? ecx.add_goal(GoalSource::Misc, goal.with(tcx, sized_predicate)); - tcx.types.unit + Ty::new_unit(tcx) } - ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() { - None => tcx.types.unit, - Some(tail_def) => { - let tail_ty = tail_def.ty(tcx, args); - Ty::new_projection(tcx, metadata_def_id, [tail_ty]) + ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(tcx) { + None => Ty::new_unit(tcx), + Some(tail_ty) => { + Ty::new_projection(tcx, metadata_def_id, [tail_ty.instantiate(tcx, &args)]) } }, - ty::Adt(_, _) => tcx.types.unit, + ty::Adt(_, _) => Ty::new_unit(tcx), ty::Tuple(elements) => match elements.last() { - None => tcx.types.unit, + None => Ty::new_unit(tcx), Some(&tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]), }, ty::Infer( ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_), ) - | ty::Bound(..) => bug!( + | ty::Bound(..) => panic!( "unexpected self ty `{:?}` when normalizing `::Metadata`", goal.predicate.self_ty() ), @@ -586,11 +591,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_future_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = self_ty.kind() else { return Err(NoSolution); }; @@ -622,11 +627,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = self_ty.kind() else { return Err(NoSolution); }; @@ -658,18 +663,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_fused_iterator_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`FusedIterator` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`FusedIterator` does not have an associated type: {:?}", goal); } fn consider_builtin_async_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = self_ty.kind() else { return Err(NoSolution); }; @@ -685,10 +690,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // coroutine yield ty `Poll>`. let wrapped_expected_ty = Ty::new_adt( tcx, - tcx.adt_def(tcx.require_lang_item(LangItem::Poll, None)), + tcx.adt_def(tcx.require_lang_item(TraitSolverLangItem::Poll)), tcx.mk_args(&[Ty::new_adt( tcx, - tcx.adt_def(tcx.require_lang_item(LangItem::Option, None)), + tcx.adt_def(tcx.require_lang_item(TraitSolverLangItem::Option)), tcx.mk_args(&[expected_ty.into()]), ) .into()]), @@ -701,11 +706,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_coroutine_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = self_ty.kind() else { return Err(NoSolution); }; @@ -717,15 +722,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let coroutine = args.as_coroutine(); - let term = if tcx.is_lang_item(goal.predicate.def_id(), LangItem::CoroutineReturn) { + let term = if tcx + .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineReturn) + { coroutine.return_ty().into() - } else if tcx.is_lang_item(goal.predicate.def_id(), LangItem::CoroutineYield) { + } else if tcx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineYield) { coroutine.yield_ty().into() } else { - bug!( - "unexpected associated item `<{self_ty} as Coroutine>::{}`", - tcx.item_name(goal.predicate.def_id()) - ) + panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id()) }; Self::probe_and_consider_implied_clause( @@ -748,18 +752,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_structural_builtin_unsize_candidates( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Vec>> { - bug!("`Unsize` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Vec> { + panic!("`Unsize` does not have an associated type: {:?}", goal); } fn consider_builtin_discriminant_kind_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let self_ty = goal.predicate.self_ty(); - let discriminant_ty = match *self_ty.kind() { + let discriminant_ty = match self_ty.kind() { ty::Bool | ty::Char | ty::Int(..) @@ -794,7 +798,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) - | ty::Bound(..) => bug!( + | ty::Bound(..) => panic!( "unexpected self ty `{:?}` when normalizing `::Discriminant`", goal.predicate.self_ty() ), @@ -807,11 +811,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_async_destruct_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let self_ty = goal.predicate.self_ty(); - let async_destructor_ty = match *self_ty.kind() { + let async_destructor_ty = match self_ty.kind() { ty::Bool | ty::Char | ty::Int(..) @@ -842,12 +846,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Foreign(..) - | ty::Bound(..) => bug!( + | ty::Bound(..) => panic!( "unexpected self ty `{:?}` when normalizing `::AsyncDestructor`", goal.predicate.self_ty() ), - ty::Pat(..) | ty::Dynamic(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => bug!( + ty::Pat(..) | ty::Dynamic(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => panic!( "`consider_builtin_async_destruct_candidate` is not yet implemented for type: {self_ty:?}" ), }; @@ -860,93 +864,56 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } fn consider_builtin_destruct_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`Destruct` does not have an associated type: {:?}", goal); + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`Destruct` does not have an associated type: {:?}", goal); } fn consider_builtin_transmute_candidate( - _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - bug!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) + _ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { + panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) } } -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ fn translate_args( &mut self, - assoc_def: &LeafDef, - goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, - impl_def_id: DefId, - impl_args: ty::GenericArgsRef<'tcx>, - impl_trait_ref: rustc_type_ir::TraitRef>, - ) -> Result, NoSolution> { + goal: Goal>, + impl_def_id: I::DefId, + impl_args: I::GenericArgs, + impl_trait_ref: rustc_type_ir::TraitRef, + target_container_def_id: I::DefId, + ) -> Result { let tcx = self.interner(); - Ok(match assoc_def.defining_node { - Node::Trait(_) => goal.predicate.alias.args, - Node::Impl(target_impl_def_id) => { - if target_impl_def_id == impl_def_id { - // Same impl, no need to fully translate, just a rebase from - // the trait is sufficient. - goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, impl_args) - } else { - let target_args = self.fresh_args_for_item(target_impl_def_id); - let target_trait_ref = tcx - .impl_trait_ref(target_impl_def_id) - .unwrap() - .instantiate(tcx, target_args); - // Relate source impl to target impl by equating trait refs. - self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?; - // Also add predicates since they may be needed to constrain the - // target impl's params. - self.add_goals( - GoalSource::Misc, - tcx.predicates_of(target_impl_def_id) - .instantiate(tcx, target_args) - .into_iter() - .map(|(pred, _)| goal.with(tcx, pred)), - ); - goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, target_args) - } - } + Ok(if target_container_def_id == impl_trait_ref.def_id { + // Default value from the trait definition. No need to rebase. + goal.predicate.alias.args + } else if target_container_def_id == impl_def_id { + // Same impl, no need to fully translate, just a rebase from + // the trait is sufficient. + goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, impl_args) + } else { + let target_args = self.fresh_args_for_item(target_container_def_id); + let target_trait_ref = + tcx.impl_trait_ref(target_container_def_id).instantiate(tcx, &target_args); + // Relate source impl to target impl by equating trait refs. + self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?; + // Also add predicates since they may be needed to constrain the + // target impl's params. + self.add_goals( + GoalSource::Misc, + tcx.predicates_of(target_container_def_id) + .iter_instantiated(tcx, &target_args) + .map(|pred| goal.with(tcx, pred)), + ); + goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, target_args) }) } - - /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. - /// - /// FIXME: We should merge these 3 implementations as it's likely that they otherwise - /// diverge. - #[instrument(level = "trace", skip(self, param_env), ret)] - fn fetch_eligible_assoc_item_def( - &self, - param_env: ty::ParamEnv<'tcx>, - goal_trait_ref: ty::TraitRef<'tcx>, - trait_assoc_def_id: DefId, - impl_def_id: DefId, - ) -> Result, NoSolution> { - let node_item = - specialization_graph::assoc_def(self.interner(), impl_def_id, trait_assoc_def_id) - .map_err(|ErrorGuaranteed { .. }| NoSolution)?; - - let eligible = if node_item.is_final() { - // Non-specializable items are always projectable. - true - } else { - // Only reveal a specializable default if we're past type-checking - // and the obligation is monomorphic, otherwise passes such as - // transmute checking and polymorphic MIR optimizations could - // get a result which isn't correct for all monomorphizations. - if param_env.reveal() == Reveal::All { - let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); - !poly_trait_ref.still_further_specializable() - } else { - trace!(?node_item.item.def_id, "not eligible due to default"); - false - } - }; - - if eligible { Ok(Some(node_item)) } else { Ok(None) } - } } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs similarity index 64% rename from compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs rename to compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index f7423c367b5..710671b45d0 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -2,20 +2,22 @@ //! behaves differently depending on the param-env's reveal mode and whether //! the opaque is in a defining scope. -use crate::solve::infcx::SolverDelegate; -use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; -use rustc_middle::traits::Reveal; -use rustc_middle::ty; -use rustc_middle::ty::util::NotUniqueParam; +use rustc_index::bit_set::GrowableBitSet; +use rustc_type_ir::inherent::*; +use rustc_type_ir::{self as ty, Interner}; -use crate::solve::{EvalCtxt, SolverMode}; +use crate::infcx::SolverDelegate; +use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode}; -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ pub(super) fn normalize_opaque_type( &mut self, - goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { let tcx = self.interner(); let opaque_ty = goal.predicate.alias; let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); @@ -32,7 +34,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { return Err(NoSolution); } // FIXME: This may have issues when the args contain aliases... - match self.interner().uses_unique_placeholders_ignoring_regions(opaque_ty.args) { + match uses_unique_placeholders_ignoring_regions(self.interner(), opaque_ty.args) { Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => { return self.evaluate_added_goals_and_make_canonical_response( Certainty::AMBIGUOUS, @@ -61,6 +63,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { } // Otherwise, define a new opaque type + // FIXME: should we use `inject_hidden_type_unchecked` here? self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?; self.add_item_bounds_for_hidden_type( opaque_ty.def_id, @@ -83,10 +86,51 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { } (Reveal::All, _) => { // FIXME: Add an assertion that opaque type storage is empty. - let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, opaque_ty.args); + let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, &opaque_ty.args); self.eq(goal.param_env, expected, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } } } + +/// Checks whether each generic argument is simply a unique generic placeholder. +/// +/// FIXME: Interner argument is needed to constrain the `I` parameter. +pub fn uses_unique_placeholders_ignoring_regions( + _interner: I, + args: I::GenericArgs, +) -> Result<(), NotUniqueParam> { + let mut seen = GrowableBitSet::default(); + for arg in args { + match arg.kind() { + // Ignore regions, since we can't resolve those in a canonicalized + // query in the trait solver. + ty::GenericArgKind::Lifetime(_) => {} + ty::GenericArgKind::Type(t) => match t.kind() { + ty::Placeholder(p) => { + if !seen.insert(p.var()) { + return Err(NotUniqueParam::DuplicateParam(t.into())); + } + } + _ => return Err(NotUniqueParam::NotParam(t.into())), + }, + ty::GenericArgKind::Const(c) => match c.kind() { + ty::ConstKind::Placeholder(p) => { + if !seen.insert(p.var()) { + return Err(NotUniqueParam::DuplicateParam(c.into())); + } + } + _ => return Err(NotUniqueParam::NotParam(c.into())), + }, + } + } + + Ok(()) +} + +// FIXME: This should check for dupes and non-params first, then infer vars. +pub enum NotUniqueParam { + DuplicateParam(I::GenericArg), + NotParam(I::GenericArg), +} diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs similarity index 67% rename from compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs rename to compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs index 26d60ffb321..45341917bb2 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs @@ -4,17 +4,20 @@ //! Since a weak alias is never ambiguous, this just computes the `type_of` of //! the alias and registers the where-clauses of the type alias. -use crate::solve::infcx::SolverDelegate; -use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult}; -use rustc_middle::ty; +use rustc_type_ir::{self as ty, Interner}; -use crate::solve::EvalCtxt; +use crate::infcx::SolverDelegate; +use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult}; -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ pub(super) fn normalize_weak_type( &mut self, - goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { let tcx = self.interner(); let weak_ty = goal.predicate.alias; @@ -22,13 +25,11 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { self.add_goals( GoalSource::Misc, tcx.predicates_of(weak_ty.def_id) - .instantiate(tcx, weak_ty.args) - .predicates - .into_iter() + .iter_instantiated(tcx, &weak_ty.args) .map(|pred| goal.with(tcx, pred)), ); - let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args); + let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, &weak_ty.args); self.instantiate_normalizes_to_term(goal, actual.into()); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs similarity index 63% rename from compiler/rustc_trait_selection/src/solve/project_goals.rs rename to compiler/rustc_next_trait_solver/src/solve/project_goals.rs index 839db73a8b3..b20c274b62c 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs @@ -1,16 +1,18 @@ -use crate::solve::GoalSource; +use rustc_type_ir::{self as ty, Interner, ProjectionPredicate}; -use super::infcx::SolverDelegate; -use super::EvalCtxt; -use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; -use rustc_middle::ty::{self, ProjectionPredicate}; +use crate::infcx::SolverDelegate; +use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult}; -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ #[instrument(level = "trace", skip(self), ret)] pub(super) fn compute_projection_goal( &mut self, - goal: Goal<'tcx, ProjectionPredicate<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { let tcx = self.interner(); let projection_term = goal.predicate.projection_term.to_term(tcx); let goal = goal.with( diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs similarity index 98% rename from compiler/rustc_trait_selection/src/solve/search_graph.rs rename to compiler/rustc_next_trait_solver/src/solve/search_graph.rs index 055540d122f..d50ff2f8deb 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -1,19 +1,18 @@ use std::mem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_index::Idx; -use rustc_index::IndexVec; -use rustc_next_trait_solver::infcx::SolverDelegate; -use rustc_next_trait_solver::solve::CacheData; -use rustc_next_trait_solver::solve::{CanonicalInput, Certainty, QueryResult}; -use rustc_session::Limit; +use rustc_index::{Idx, IndexVec}; use rustc_type_ir::inherent::*; use rustc_type_ir::Interner; -use super::inspect; -use super::inspect::ProofTreeBuilder; -use super::SolverMode; -use crate::solve::FIXPOINT_STEP_LIMIT; +use crate::infcx::SolverDelegate; +use crate::solve::inspect::{self, ProofTreeBuilder}; +use crate::solve::{ + CacheData, CanonicalInput, Certainty, QueryResult, SolverMode, FIXPOINT_STEP_LIMIT, +}; + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct Limit(usize); rustc_index::newtype_index! { #[orderable] diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs similarity index 77% rename from compiler/rustc_trait_selection/src/solve/trait_goals.rs rename to compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 0aace43f333..19eee82edc0 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1,60 +1,59 @@ //! Dealing with trait goals, i.e. `T: Trait<'a, U>`. -use super::assembly::structural_traits::AsyncCallableRelevantTypes; -use super::assembly::{self, structural_traits, Candidate}; -use super::infcx::SolverDelegate; -use super::{EvalCtxt, GoalSource, SolverMode}; +use rustc_ast_ir::Movability; use rustc_data_structures::fx::FxIndexSet; -use rustc_hir::def_id::DefId; -use rustc_hir::{LangItem, Movability}; -use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::MaybeCause; -use rustc_infer::traits::util::supertraits; -use rustc_middle::bug; -use rustc_middle::traits::solve::inspect::ProbeKind; -use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; -use rustc_middle::traits::{BuiltinImplSource, Reveal}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; -use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; -use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; -use rustc_span::ErrorGuaranteed; +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, Interner, TraitPredicate, Upcast as _}; -impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { - fn self_ty(self) -> Ty<'tcx> { +use crate::infcx::SolverDelegate; +use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes}; +use crate::solve::assembly::{self, Candidate}; +use crate::solve::inspect::ProbeKind; +use crate::solve::{ + BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, + NoSolution, QueryResult, Reveal, SolverMode, +}; + +impl assembly::GoalKind for TraitPredicate +where + Infcx: SolverDelegate, + I: Interner, +{ + fn self_ty(self) -> I::Ty { self.self_ty() } - fn trait_ref(self, _: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { + fn trait_ref(self, _: I) -> ty::TraitRef { self.trait_ref } - fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self { self.with_self_ty(tcx, self_ty) } - fn trait_def_id(self, _: TyCtxt<'tcx>) -> DefId { + fn trait_def_id(self, _: I) -> I::DefId { self.def_id() } fn consider_impl_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, TraitPredicate<'tcx>>, - impl_def_id: DefId, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal>, + impl_def_id: I::DefId, + ) -> Result, NoSolution> { let tcx = ecx.interner(); - let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); - let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; - if !drcx.args_may_unify( - goal.predicate.trait_ref.args, - impl_trait_header.trait_ref.skip_binder().args, - ) { + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + if !tcx + .args_may_unify_deep(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) + { return Err(NoSolution); } // An upper bound of the certainty of this goal, used to lower the certainty // of reservation impl to ambiguous during coherence. - let impl_polarity = impl_trait_header.polarity; + let impl_polarity = tcx.impl_polarity(impl_def_id); let maximal_certainty = match (impl_polarity, goal.predicate.polarity) { // In intercrate mode, this is ambiguous. But outside of intercrate, // it's not a real impl. @@ -77,14 +76,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); ecx.record_impl_args(impl_args); - let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args); + let impl_trait_ref = impl_trait_ref.instantiate(tcx, &impl_args); ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?; let where_clause_bounds = tcx .predicates_of(impl_def_id) - .instantiate(tcx, impl_args) - .predicates - .into_iter() + .iter_instantiated(tcx, &impl_args) .map(|pred| goal.with(tcx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); @@ -93,21 +90,21 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_error_guaranteed_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - _guar: ErrorGuaranteed, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + _guar: I::ErrorGuaranteed, + ) -> Result, NoSolution> { // FIXME: don't need to enter a probe here. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn probe_and_match_goal_against_assumption( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - source: CandidateSource<'tcx>, - goal: Goal<'tcx, Self>, - assumption: ty::Clause<'tcx>, - then: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> QueryResult<'tcx>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + source: CandidateSource, + goal: Goal, + assumption: I::Clause, + then: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult, + ) -> Result, NoSolution> { if let Some(trait_clause) = assumption.as_trait_clause() { if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity @@ -130,9 +127,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_auto_trait_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -159,7 +156,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { if matches!(goal.param_env.reveal(), Reveal::All) || matches!(ecx.solver_mode(), SolverMode::Coherence) - || ecx.can_define_opaque_ty(opaque_ty.def_id) + || opaque_ty + .def_id + .as_local() + .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id)) { return Err(NoSolution); } @@ -173,9 +173,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_trait_alias_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -185,20 +185,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let nested_obligations = tcx .predicates_of(goal.predicate.def_id()) - .instantiate(tcx, goal.predicate.trait_ref.args); + .iter_instantiated(tcx, &goal.predicate.trait_ref.args) + .map(|p| goal.with(tcx, p)); // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goals( - GoalSource::Misc, - nested_obligations.predicates.into_iter().map(|p| goal.with(tcx, p)), - ); + ecx.add_goals(GoalSource::Misc, nested_obligations); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } fn consider_builtin_sized_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -211,9 +209,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_copy_clone_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -226,28 +224,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_pointer_like_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - // The regions of a type don't affect the size of the type let tcx = ecx.interner(); - // We should erase regions from both the param-env and type, since both - // may have infer regions. Specifically, after canonicalizing and instantiating, - // early bound regions turn into region vars in both the new and old solver. - let key = tcx.erase_regions(goal.param_env.and(goal.predicate.self_ty())); // But if there are inference variables, we have to wait until it's resolved. - if key.has_non_region_infer() { + if (goal.param_env, goal.predicate.self_ty()).has_non_region_infer() { return ecx.forced_ambiguity(MaybeCause::Ambiguity); } - if let Ok(layout) = tcx.layout_of(key) - && layout.layout.is_pointer_like(&tcx.data_layout) - { - // FIXME: We could make this faster by making a no-constraints response + if tcx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } else { @@ -256,9 +246,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_fn_ptr_trait_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let self_ty = goal.predicate.self_ty(); match goal.predicate.polarity { // impl FnPtr for FnPtr {} @@ -287,10 +277,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, goal_kind: ty::ClosureKind, - ) -> Result>, NoSolution> { + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -308,7 +298,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } }; let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| { - ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output]) + ty::TraitRef::new(tcx, tcx.require_lang_item(TraitSolverLangItem::Sized), [output]) }); let pred = tupled_inputs_and_output @@ -328,10 +318,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_async_fn_trait_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, goal_kind: ty::ClosureKind, - ) -> Result>, NoSolution> { + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -343,13 +333,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal.predicate.self_ty(), goal_kind, // This region doesn't matter because we're throwing away the coroutine type - tcx.lifetimes.re_static, + Region::new_static(tcx), )?; let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound( |AsyncCallableRelevantTypes { output_coroutine_ty, .. }| { ty::TraitRef::new( tcx, - tcx.require_lang_item(LangItem::Sized, None), + tcx.require_lang_item(TraitSolverLangItem::Sized), [output_coroutine_ty], ) }, @@ -379,11 +369,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_async_fn_kind_helper_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else { - bug!(); + panic!(); }; let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else { @@ -406,9 +396,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { /// impl Tuple for (T1, .., Tn) {} /// ``` fn consider_builtin_tuple_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -422,9 +412,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_pointee_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -434,14 +424,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_future_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else { + let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -460,14 +450,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else { + let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -486,14 +476,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_fused_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else { + let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -510,14 +500,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_async_iterator_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } - let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else { + let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -536,15 +526,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_coroutine_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } let self_ty = goal.predicate.self_ty(); - let ty::Coroutine(def_id, args) = *self_ty.kind() else { + let ty::Coroutine(def_id, args) = self_ty.kind() else { return Err(NoSolution); }; @@ -568,9 +558,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_discriminant_kind_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -581,9 +571,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_async_destruct_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -594,9 +584,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_destruct_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Result, NoSolution> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -610,10 +600,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } fn consider_builtin_transmute_candidate( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Result>, NoSolution> { - if goal.predicate.polarity != ty::PredicatePolarity::Positive { + _ecx: &mut EvalCtxt<'_, Infcx>, + _goal: Goal, + ) -> Result, NoSolution> { + // TODO: + todo!() + /* if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -641,6 +633,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { )?; ecx.evaluate_added_goals_and_make_canonical_response(certainty) }) + */ } /// ```ignore (builtin impl example) @@ -651,9 +644,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { /// impl<'a, T: Trait + 'a> Unsize for T {} /// ``` fn consider_structural_builtin_unsize_candidates( - ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - goal: Goal<'tcx, Self>, - ) -> Vec>> { + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, + ) -> Vec> { if goal.predicate.polarity != ty::PredicatePolarity::Positive { return vec![]; } @@ -676,7 +669,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let goal = goal.with(ecx.interner(), (a_ty, b_ty)); match (a_ty.kind(), b_ty.kind()) { - (ty::Infer(ty::TyVar(..)), ..) => bug!("unexpected infer {a_ty:?} {b_ty:?}"), + (ty::Infer(ty::TyVar(..)), ..) => panic!("unexpected infer {a_ty:?} {b_ty:?}"), (_, ty::Infer(ty::TyVar(..))) => { result_to_single(ecx.forced_ambiguity(MaybeCause::Ambiguity)) @@ -684,24 +677,24 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`. ( - &ty::Dynamic(a_data, a_region, ty::Dyn), - &ty::Dynamic(b_data, b_region, ty::Dyn), + ty::Dynamic(a_data, a_region, ty::Dyn), + ty::Dynamic(b_data, b_region, ty::Dyn), ) => ecx.consider_builtin_dyn_upcast_candidates( goal, a_data, a_region, b_data, b_region, ), // `T` -> `dyn Trait` unsizing. - (_, &ty::Dynamic(b_region, b_data, ty::Dyn)) => result_to_single( + (_, ty::Dynamic(b_region, b_data, ty::Dyn)) => result_to_single( ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data), ), // `[T; N]` -> `[T]` unsizing - (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { + (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => { result_to_single(ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)) } // `Struct` -> `Struct` where `T: Unsize` - (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) + (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def.is_struct() && a_def == b_def => { result_to_single( @@ -710,7 +703,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } // `(A, B, T)` -> `(A, B, U)` where `T: Unsize` - (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) + (ty::Tuple(a_tys), ty::Tuple(b_tys)) if a_tys.len() == b_tys.len() && !a_tys.is_empty() => { result_to_single(ecx.consider_builtin_tuple_unsize(goal, a_tys, b_tys)) @@ -722,7 +715,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } } -impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { +impl EvalCtxt<'_, Infcx> +where + Infcx: SolverDelegate, + I: Interner, +{ /// Trait upcasting allows for coercions between trait objects: /// ```ignore (builtin impl example) /// trait Super {} @@ -734,12 +731,12 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// ``` fn consider_builtin_dyn_upcast_candidates( &mut self, - goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, - a_data: &'tcx ty::List>, - a_region: ty::Region<'tcx>, - b_data: &'tcx ty::List>, - b_region: ty::Region<'tcx>, - ) -> Vec>> { + goal: Goal, + a_data: I::BoundExistentialPredicates, + a_region: I::Region, + b_data: I::BoundExistentialPredicates, + b_region: I::Region, + ) -> Vec> { let tcx = self.interner(); let Goal { predicate: (a_ty, _b_ty), .. } = goal; @@ -757,7 +754,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { a_data.principal(), )); } else if let Some(a_principal) = a_data.principal() { - for new_a_principal in supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)).skip(1) { + for new_a_principal in + Infcx::elaborate_supertraits(self.interner(), a_principal.with_self_ty(tcx, a_ty)) + .skip(1) + { responses.extend(self.consider_builtin_upcast_to_principal( goal, CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting), @@ -777,15 +777,15 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { fn consider_builtin_unsize_to_dyn_candidate( &mut self, - goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, - b_data: &'tcx ty::List>, - b_region: ty::Region<'tcx>, - ) -> Result>, NoSolution> { + goal: Goal, + b_data: I::BoundExistentialPredicates, + b_region: I::Region, + ) -> Result, NoSolution> { let tcx = self.interner(); let Goal { predicate: (a_ty, _), .. } = goal; // Can only unsize to an object-safe trait. - if b_data.principal_def_id().is_some_and(|def_id| !tcx.is_object_safe(def_id)) { + if b_data.principal_def_id().is_some_and(|def_id| !tcx.trait_is_object_safe(def_id)) { return Err(NoSolution); } @@ -794,7 +794,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // (i.e. the principal, all of the associated types match, and any auto traits) ecx.add_goals( GoalSource::ImplWhereBound, - b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), + b_data.into_iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), ); // The type must be `Sized` to be unsized. @@ -802,7 +802,11 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { GoalSource::ImplWhereBound, goal.with( tcx, - ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [a_ty]), + ty::TraitRef::new( + tcx, + tcx.require_lang_item(TraitSolverLangItem::Sized), + [a_ty], + ), ), ); @@ -814,24 +818,26 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { fn consider_builtin_upcast_to_principal( &mut self, - goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, - source: CandidateSource<'tcx>, - a_data: &'tcx ty::List>, - a_region: ty::Region<'tcx>, - b_data: &'tcx ty::List>, - b_region: ty::Region<'tcx>, - upcast_principal: Option>, - ) -> Result>, NoSolution> { + goal: Goal, + source: CandidateSource, + a_data: I::BoundExistentialPredicates, + a_region: I::Region, + b_data: I::BoundExistentialPredicates, + b_region: I::Region, + upcast_principal: Option>>, + ) -> Result, NoSolution> { let param_env = goal.param_env; // We may upcast to auto traits that are either explicitly listed in // the object type's bounds, or implied by the principal trait ref's // supertraits. - let a_auto_traits: FxIndexSet = a_data + let a_auto_traits: FxIndexSet = a_data .auto_traits() + .into_iter() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { self.interner() .supertrait_def_ids(principal_def_id) + .into_iter() .filter(|def_id| self.interner().trait_is_auto(*def_id)) })) .collect(); @@ -841,9 +847,9 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // having any inference side-effects. We process obligations because // unification may initially succeed due to deferred projection equality. let projection_may_match = - |ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, - source_projection: ty::PolyExistentialProjection<'tcx>, - target_projection: ty::PolyExistentialProjection<'tcx>| { + |ecx: &mut EvalCtxt<'_, Infcx>, + source_projection: ty::Binder>, + target_projection: ty::Binder>| { source_projection.item_def_id() == target_projection.item_def_id() && ecx .probe(|_| ProbeKind::UpcastProjectionCompatibility) @@ -875,7 +881,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { ty::ExistentialPredicate::Projection(target_projection) => { let target_projection = bound.rebind(target_projection); let mut matching_projections = - a_data.projection_bounds().filter(|source_projection| { + a_data.projection_bounds().into_iter().filter(|source_projection| { projection_may_match(ecx, *source_projection, target_projection) }); let Some(source_projection) = matching_projections.next() else { @@ -900,11 +906,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // Also require that a_ty's lifetime outlives b_ty's lifetime. ecx.add_goal( GoalSource::ImplWhereBound, - Goal::new( - ecx.interner(), - param_env, - ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)), - ), + Goal::new(ecx.interner(), param_env, ty::OutlivesPredicate(a_region, b_region)), ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) @@ -921,10 +923,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// `#[rustc_deny_explicit_impl]` in this case. fn consider_builtin_array_unsize( &mut self, - goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, - a_elem_ty: Ty<'tcx>, - b_elem_ty: Ty<'tcx>, - ) -> Result>, NoSolution> { + goal: Goal, + a_elem_ty: I::Ty, + b_elem_ty: I::Ty, + ) -> Result, NoSolution> { self.eq(goal.param_env, a_elem_ty, b_elem_ty)?; self.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) @@ -945,26 +947,25 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// ``` fn consider_builtin_struct_unsize( &mut self, - goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, - def: ty::AdtDef<'tcx>, - a_args: ty::GenericArgsRef<'tcx>, - b_args: ty::GenericArgsRef<'tcx>, - ) -> Result>, NoSolution> { + goal: Goal, + def: I::AdtDef, + a_args: I::GenericArgs, + b_args: I::GenericArgs, + ) -> Result, NoSolution> { let tcx = self.interner(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; - let unsizing_params = tcx.unsizing_params_for_adt(def.did()); + let unsizing_params = tcx.unsizing_params_for_adt(def.def_id()); // We must be unsizing some type parameters. This also implies // that the struct has a tail field. if unsizing_params.is_empty() { return Err(NoSolution); } - let tail_field = def.non_enum_variant().tail(); - let tail_field_ty = tcx.type_of(tail_field.did); + let tail_field_ty = def.struct_tail_ty(tcx).unwrap(); - let a_tail_ty = tail_field_ty.instantiate(tcx, a_args); - let b_tail_ty = tail_field_ty.instantiate(tcx, b_args); + let a_tail_ty = tail_field_ty.instantiate(tcx, &a_args); + let b_tail_ty = tail_field_ty.instantiate(tcx, &b_args); // Instantiate just the unsizing params from B into A. The type after // this instantiation must be equal to B. This is so we don't unsize @@ -973,7 +974,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { a_args .iter() .enumerate() - .map(|(i, a)| if unsizing_params.contains(i as u32) { b_args[i] } else { a }), + .map(|(i, a)| if unsizing_params.contains(i as u32) { b_args[i] } else { *a }), ); let unsized_a_ty = Ty::new_adt(tcx, def, new_a_args); @@ -986,7 +987,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { tcx, ty::TraitRef::new( tcx, - tcx.require_lang_item(LangItem::Unsize, None), + tcx.require_lang_item(TraitSolverLangItem::Unsize), [a_tail_ty, b_tail_ty], ), ), @@ -1007,10 +1008,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// ``` fn consider_builtin_tuple_unsize( &mut self, - goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, - a_tys: &'tcx ty::List>, - b_tys: &'tcx ty::List>, - ) -> Result>, NoSolution> { + goal: Goal, + a_tys: I::Tys, + b_tys: I::Tys, + ) -> Result, NoSolution> { let tcx = self.interner(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; @@ -1029,7 +1030,7 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { tcx, ty::TraitRef::new( tcx, - tcx.require_lang_item(LangItem::Unsize, None), + tcx.require_lang_item(TraitSolverLangItem::Unsize), [a_last_ty, b_last_ty], ), ), @@ -1044,10 +1045,10 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { // the type's constituent types. fn disqualify_auto_trait_candidate_due_to_possible_impl( &mut self, - goal: Goal<'tcx, TraitPredicate<'tcx>>, - ) -> Option>, NoSolution>> { + goal: Goal>, + ) -> Option, NoSolution>> { let self_ty = goal.predicate.self_ty(); - match *self_ty.kind() { + match self_ty.kind() { // Stall int and float vars until they are resolved to a concrete // numerical type. That's because the check for impls below treats // int vars as matching any impl. Even if we filtered such impls, @@ -1065,13 +1066,15 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { | ty::Alias(ty::Projection | ty::Weak | ty::Inherent, ..) | ty::Placeholder(..) => Some(Err(NoSolution)), - ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"), + ty::Infer(_) | ty::Bound(_, _) => panic!("unexpected type `{self_ty:?}`"), // Coroutines have one special built-in candidate, `Unpin`, which // takes precedence over the structural auto trait candidate being // assembled. ty::Coroutine(def_id, _) - if self.interner().is_lang_item(goal.predicate.def_id(), LangItem::Unpin) => + if self + .interner() + .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::Unpin) => { match self.interner().coroutine_movability(def_id) { Movability::Static => Some(Err(NoSolution)), @@ -1144,13 +1147,13 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { /// wrapped in one. fn probe_and_evaluate_goal_for_constituent_tys( &mut self, - source: CandidateSource<'tcx>, - goal: Goal<'tcx, TraitPredicate<'tcx>>, + source: CandidateSource, + goal: Goal>, constituent_tys: impl Fn( - &EvalCtxt<'_, SolverDelegate<'tcx>>, - Ty<'tcx>, - ) -> Result>>, NoSolution>, - ) -> Result>, NoSolution> { + &EvalCtxt<'_, Infcx>, + I::Ty, + ) -> Result>, NoSolution>, + ) -> Result, NoSolution> { self.probe_trait_candidate(source).enter(|ecx| { ecx.add_goals( GoalSource::ImplWhereBound, @@ -1173,8 +1176,8 @@ impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> { #[instrument(level = "trace", skip(self))] pub(super) fn compute_trait_goal( &mut self, - goal: Goal<'tcx, TraitPredicate<'tcx>>, - ) -> QueryResult<'tcx> { + goal: Goal>, + ) -> QueryResult { let candidates = self.assemble_and_evaluate_candidates(goal); self.merge_candidates(candidates) } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/mod.rs b/compiler/rustc_trait_selection/src/solve/inspect/mod.rs deleted file mode 100644 index 60d52305a6b..00000000000 --- a/compiler/rustc_trait_selection/src/solve/inspect/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub use rustc_middle::traits::solve::inspect::*; - -mod build; -pub(in crate::solve) use build::*; - -mod analyse; -pub use analyse::*; diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 4afb9a2339b..c790c737fc9 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashSet; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; -use crate::solve::{CacheData, CanonicalInput, QueryResult}; +use crate::solve::{CacheData, CanonicalInput, QueryResult, Reveal}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty, CollectAndApply, Interner, UpcastFrom}; @@ -29,10 +29,14 @@ pub trait Ty>: + Relate + Flags { + fn new_unit(interner: I) -> Self; + fn new_bool(interner: I) -> Self; fn new_u8(interner: I) -> Self; + fn new_usize(interner: I) -> Self; + fn new_infer(interner: I, var: ty::InferTy) -> Self; fn new_var(interner: I, var: ty::TyVid) -> Self; @@ -109,6 +113,10 @@ pub trait Ty>: matches!(self.kind(), ty::Infer(ty::TyVar(_))) } + fn is_fn_ptr(self) -> bool { + matches!(self.kind(), ty::FnPtr(_)) + } + fn fn_sig(self, interner: I) -> ty::Binder> { match self.kind() { ty::FnPtr(sig) => sig, @@ -128,6 +136,49 @@ pub trait Ty>: _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self), } } + + fn discriminant_ty(self, interner: I) -> I::Ty; + + fn async_destructor_ty(self, interner: I) -> I::Ty; + + /// Returns `true` when the outermost type cannot be further normalized, + /// resolved, or instantiated. This includes all primitive types, but also + /// things like ADTs and trait objects, sice even if their arguments or + /// nested types may be further simplified, the outermost [`ty::TyKind`] or + /// type constructor remains the same. + fn is_known_rigid(self) -> bool { + match self.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(_) => true, + + ty::Error(_) + | ty::Infer(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) => false, + } + } } pub trait Tys>: @@ -202,6 +253,12 @@ pub trait Const>: fn new_expr(interner: I, expr: I::ExprConst) -> Self; + fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self; + + fn new_error_with_message(interner: I, msg: impl ToString) -> Self { + Self::new_error(interner, interner.delay_bug(msg)) + } + fn is_ct_var(self) -> bool { matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_))) } @@ -223,6 +280,37 @@ pub trait GenericArg>: + From + From { + fn as_type(&self) -> Option { + if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None } + } + + fn expect_ty(&self) -> I::Ty { + self.as_type().expect("expected a type") + } + + fn as_const(&self) -> Option { + if let ty::GenericArgKind::Const(c) = self.kind() { Some(c) } else { None } + } + + fn expect_const(&self) -> I::Const { + self.as_const().expect("expected a const") + } + + fn as_region(&self) -> Option { + if let ty::GenericArgKind::Lifetime(c) = self.kind() { Some(c) } else { None } + } + + fn expect_region(&self) -> I::Region { + self.as_region().expect("expected a const") + } + + fn is_non_region_infer(self) -> bool { + match self.kind() { + ty::GenericArgKind::Lifetime(_) => false, + ty::GenericArgKind::Type(ty) => ty.is_ty_var(), + ty::GenericArgKind::Const(ct) => ct.is_ct_var(), + } + } } pub trait Term>: @@ -232,7 +320,7 @@ pub trait Term>: if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None } } - fn expect_type(&self) -> I::Ty { + fn expect_ty(&self) -> I::Ty { self.as_type().expect("expected a type, but found a const") } @@ -250,6 +338,19 @@ pub trait Term>: ty::TermKind::Const(ct) => ct.is_ct_var(), } } + + fn to_alias_term(self) -> Option> { + match self.kind() { + ty::TermKind::Ty(ty) => match ty.kind() { + ty::Alias(_kind, alias_ty) => Some(alias_ty.into()), + _ => None, + }, + ty::TermKind::Const(ct) => match ct.kind() { + ty::ConstKind::Unevaluated(uv) => Some(uv.into()), + _ => None, + }, + } + } } pub trait GenericArgs>: @@ -262,8 +363,17 @@ pub trait GenericArgs>: + Default + Relate { + fn rebase_onto( + self, + interner: I, + source_def_id: I::DefId, + target: I::GenericArgs, + ) -> I::GenericArgs; + fn type_at(self, i: usize) -> I::Ty; + fn region_at(self, i: usize) -> I::Region; + fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs; fn extend_with_error( @@ -303,6 +413,9 @@ pub trait Predicate>: + UpcastFrom> + UpcastFrom> + UpcastFrom>> + + UpcastFrom> + + UpcastFrom> + + UpcastFrom> + IntoKind>> { fn is_coinductive(self, interner: I) -> bool; @@ -318,9 +431,34 @@ pub trait Clause>: + Eq + TypeFoldable // FIXME: Remove these, uplift the `Upcast` impls. + + UpcastFrom> + UpcastFrom>> + + UpcastFrom> + UpcastFrom>> + + IntoKind>> { + fn as_trait_clause(self) -> Option>> { + self.kind() + .map_bound(|clause| { + if let ty::ClauseKind::Trait(t) = clause { + Some(t) + } else { + None + } + }) + .transpose() + } + fn as_projection_clause(self) -> Option>> { + self.kind() + .map_bound(|clause| { + if let ty::ClauseKind::Projection(p) = clause { + Some(p) + } else { + None + } + }) + .transpose() + } } /// Common capabilities of placeholder kinds @@ -352,18 +490,33 @@ pub trait ParamLike { pub trait AdtDef: Copy + Debug + Hash + Eq { fn def_id(self) -> I::DefId; + fn is_struct(self) -> bool; + + /// Returns the type of the struct tail. + /// + /// Expects the `AdtDef` to be a struct. If it is not, then this will panic. + fn struct_tail_ty(self, interner: I) -> Option>; + fn is_phantom_data(self) -> bool; // FIXME: perhaps use `all_fields` and expose `FieldDef`. - fn all_field_tys(self, interner: I) -> ty::EarlyBinder>; + fn all_field_tys(self, interner: I) -> ty::EarlyBinder>; fn sized_constraint(self, interner: I) -> Option>; } +pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { + fn reveal(self) -> Reveal; + + fn caller_bounds(self) -> impl IntoIterator; +} + pub trait Features: Copy { fn generic_const_exprs(self) -> bool; fn coroutine_clone(self) -> bool; + + fn associated_const_equality(self) -> bool; } pub trait EvaluationCache { @@ -392,3 +545,26 @@ pub trait EvaluationCache { available_depth: usize, ) -> Option>; } + +pub trait DefId: Copy + Debug + Hash + Eq + TypeFoldable { + fn as_local(self) -> Option; +} + +pub trait BoundExistentialPredicates: + Copy + + Debug + + Hash + + Eq + + Relate + + IntoIterator>> +{ + fn principal_def_id(self) -> Option; + + fn principal(self) -> Option>>; + + fn auto_traits(self) -> impl IntoIterator; + + fn projection_bounds( + self, + ) -> impl IntoIterator>>; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index b099f63d382..59ca95c09cd 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -1,4 +1,5 @@ use rustc_ast_ir::Movability; +use rustc_index::bit_set::BitSet; use smallvec::SmallVec; use std::fmt::Debug; use std::hash::Hash; @@ -10,7 +11,7 @@ use crate::ir_print::IrPrint; use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; use crate::solve::inspect::CanonicalGoalEvaluationStep; -use crate::solve::{ExternalConstraintsData, SolverMode}; +use crate::solve::{ExternalConstraintsData, PredefinedOpaquesData, SolverMode}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty}; @@ -29,9 +30,8 @@ pub trait Interner: + IrPrint> + IrPrint> { - type DefId: Copy + Debug + Hash + Eq + TypeFoldable; + type DefId: DefId; type LocalDefId: Copy + Debug + Hash + Eq + Into + TypeFoldable; - type AdtDef: AdtDef; type GenericArgs: GenericArgs; type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref; @@ -46,18 +46,45 @@ pub trait Interner: + Default; type BoundVarKind: Copy + Debug + Hash + Eq; - type PredefinedOpaques: Copy + Debug + Hash + Eq; - type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; + type PredefinedOpaques: Copy + + Debug + + Hash + + Eq + + TypeFoldable + + Deref>; + fn mk_predefined_opaques_in_body( + self, + data: PredefinedOpaquesData, + ) -> Self::PredefinedOpaques; + + type DefiningOpaqueTypes: Copy + + Debug + + Hash + + Default + + Eq + + TypeVisitable + + Deref>; type CanonicalGoalEvaluationStepRef: Copy + Debug + Hash + Eq + Deref>; - type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; + type CanonicalVars: Copy + + Debug + + Hash + + Eq + + IntoIterator> + + Deref]>> + + Default; fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars; - type ExternalConstraints: Copy + Debug + Hash + Eq; + type ExternalConstraints: Copy + + Debug + + Hash + + Eq + + TypeFoldable + + Deref>; fn mk_external_constraints( self, data: ExternalConstraintsData, @@ -76,12 +103,7 @@ pub trait Interner: // Things stored inside of tys type ErrorGuaranteed: Copy + Debug + Hash + Eq; - type BoundExistentialPredicates: Copy - + Debug - + Hash - + Eq - + Relate - + IntoIterator>>; + type BoundExistentialPredicates: BoundExistentialPredicates; type AllocId: Copy + Debug + Hash + Eq; type Pat: Copy + Debug + Hash + Eq + Debug + Relate; type Safety: Safety; @@ -103,7 +125,7 @@ pub trait Interner: type PlaceholderRegion: PlaceholderLike; // Predicates - type ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable; + type ParamEnv: ParamEnv; type Predicate: Predicate; type Clause: Clause; type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; @@ -123,9 +145,11 @@ pub trait Interner: + IntoIterator>; fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf; - // FIXME: Remove after uplifting `EarlyBinder` fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder; + type AdtDef: AdtDef; + fn adt_def(self, adt_def_id: Self::DefId) -> Self::AdtDef; + fn alias_ty_kind(self, alias: ty::AliasTy) -> ty::AliasTyKind; fn alias_term_kind(self, alias: ty::AliasTerm) -> ty::AliasTermKind; @@ -143,6 +167,8 @@ pub trait Interner: I: Iterator, T: CollectAndApply; + fn check_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs) -> bool; + fn check_and_mk_args( self, def_id: Self::DefId, @@ -187,6 +213,17 @@ pub trait Interner: def_id: Self::DefId, ) -> ty::EarlyBinder>; + fn predicates_of( + self, + def_id: Self::DefId, + ) -> ty::EarlyBinder>; + + fn own_predicates_of( + self, + def_id: Self::DefId, + ) -> ty::EarlyBinder>; + + // FIXME: Rename this so it's obvious it's only *immediate* super predicates. fn super_predicates_of( self, def_id: Self::DefId, @@ -196,7 +233,64 @@ pub trait Interner: fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId; + fn is_lang_item(self, def_id: Self::DefId, lang_item: TraitSolverLangItem) -> bool; + fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator; + + // FIXME: move `fast_reject` into `rustc_type_ir`. + fn args_may_unify_deep( + self, + obligation_args: Self::GenericArgs, + impl_args: Self::GenericArgs, + ) -> bool; + + fn for_each_relevant_impl( + self, + trait_def_id: Self::DefId, + self_ty: Self::Ty, + f: impl FnMut(Self::DefId), + ); + + fn has_item_definition(self, def_id: Self::DefId) -> bool; + + fn impl_is_default(self, impl_def_id: Self::DefId) -> bool; + + fn impl_trait_ref(self, impl_def_id: Self::DefId) -> ty::EarlyBinder>; + + fn impl_polarity(self, impl_def_id: Self::DefId) -> ty::ImplPolarity; + + fn trait_is_auto(self, trait_def_id: Self::DefId) -> bool; + + fn trait_is_alias(self, trait_def_id: Self::DefId) -> bool; + + fn trait_is_object_safe(self, trait_def_id: Self::DefId) -> bool; + + fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool; + + fn fn_trait_kind_from_def_id(self, trait_def_id: Self::DefId) -> Option; + + fn async_fn_trait_kind_from_def_id(self, trait_def_id: Self::DefId) -> Option; + + fn supertrait_def_ids(self, trait_def_id: Self::DefId) + -> impl IntoIterator; + + fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; + + fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool; + fn coroutine_is_async(self, coroutine_def_id: Self::DefId) -> bool; + fn coroutine_is_gen(self, coroutine_def_id: Self::DefId) -> bool; + fn coroutine_is_async_gen(self, coroutine_def_id: Self::DefId) -> bool; + + fn layout_is_pointer_like(self, param_env: Self::ParamEnv, ty: Self::Ty) -> bool; + + type UnsizingParams: Deref>; + fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams; + + fn find_const_ty_from_env( + self, + param_env: Self::ParamEnv, + placeholder: Self::PlaceholderConst, + ) -> Self::Ty; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index 9a3b324fcd7..cf5ec1ab3fe 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -1,8 +1,36 @@ /// Lang items used by the new trait solver. This can be mapped to whatever internal /// representation of `LangItem`s used in the underlying compiler implementation. pub enum TraitSolverLangItem { - Future, - FutureOutput, + // tidy-alphabetical-start + AsyncDestruct, AsyncFnKindHelper, AsyncFnKindUpvars, + AsyncFnOnceOutput, + AsyncIterator, + CallOnceFuture, + CallRefFuture, + Clone, + Copy, + Coroutine, + CoroutineReturn, + CoroutineYield, + Destruct, + DiscriminantKind, + DynMetadata, + FnPtrTrait, + FusedIterator, + Future, + FutureOutput, + Iterator, + Metadata, + Option, + PointeeTrait, + PointerLike, + Poll, + Sized, + TransmuteTrait, + Tuple, + Unpin, + Unsize, + // tidy-alphabetical-end } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index c0713dc50d2..bf39f920276 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -7,7 +7,7 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen use crate::inherent::*; use crate::lift::Lift; -use crate::upcast::Upcast; +use crate::upcast::{Upcast, UpcastFrom}; use crate::visit::TypeVisitableExt as _; use crate::{self as ty, Interner}; @@ -166,6 +166,12 @@ impl ty::Binder> { } } +impl UpcastFrom> for TraitPredicate { + fn upcast_from(from: TraitRef, _tcx: I) -> Self { + TraitPredicate { trait_ref: from, polarity: PredicatePolarity::Positive } + } +} + impl fmt::Debug for TraitPredicate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // FIXME(effects) printing?