diff options
| author | lcnr <rust@lcnr.de> | 2023-03-14 14:19:06 +0100 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2023-03-21 09:57:20 +0100 |
| commit | 791ce0b7b5d03649bc9014d5b0abb78f3c6f2cfd (patch) | |
| tree | 4a321c50deba262c65a0dc552fbfaca8cc70de14 /compiler | |
| parent | 84c47b8279b39e165dfebeb529eb6d92592e4f8d (diff) | |
| download | rust-791ce0b7b5d03649bc9014d5b0abb78f3c6f2cfd.tar.gz rust-791ce0b7b5d03649bc9014d5b0abb78f3c6f2cfd.zip | |
remove some trait solver helpers
they add more complexity then they are worth. It's confusing which of these helpers should be used in which context.
Diffstat (limited to 'compiler')
30 files changed, 194 insertions, 286 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7c88205da3b..75a3dd0c0f3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -24,6 +24,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::ObligationCtxt; use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; @@ -760,20 +761,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { else { return; }; // Try to find predicates on *generic params* that would allow copying `ty` let infcx = tcx.infer_ctxt().build(); - let copy_did = infcx.tcx.require_lang_item(LangItem::Copy, Some(span)); - let cause = ObligationCause::new( - span, - self.mir_def_id(), - rustc_infer::traits::ObligationCauseCode::MiscObligation, - ); - let errors = rustc_trait_selection::traits::fully_solve_bound( - &infcx, - cause, - self.param_env, - // Erase any region vids from the type, which may not be resolved - infcx.tcx.erase_regions(ty), - copy_did, - ); + let ocx = ObligationCtxt::new(&infcx); + let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span)); + let cause = ObligationCause::misc(span, self.mir_def_id()); + + ocx.register_bound(cause, self.param_env, infcx.tcx.erase_regions(ty), copy_did); + let errors = ocx.select_all_or_error(); // Only emit suggestion if all required predicates are on generic let predicates: Result<Vec<_>, _> = errors diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 611abb01238..9f543b71c5f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1078,7 +1078,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.param_env, tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)), def_id, - DUMMY_SP, ) } _ => false, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index bb4b7ad50b8..6758cba2eed 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -9,7 +9,7 @@ use rustc_middle::mir; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; use rustc_trait_selection::traits::{ - self, ImplSource, Obligation, ObligationCause, SelectionContext, + self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, }; use super::ConstCx; @@ -184,7 +184,10 @@ impl Qualif for NeedsNonConstDrop { } // If we had any errors, then it's bad - !traits::fully_solve_obligations(&infcx, impl_src.nested_obligations()).is_empty() + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligations(impl_src.nested_obligations()); + let errors = ocx.select_all_or_error(); + !errors.is_empty() } fn in_adt_inherently<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 8c364a4f3b2..f7aaa7a159f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -59,6 +59,7 @@ fn equate_intrinsic_type<'tcx>( require_same_types( tcx, &cause, + ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env? tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()), fty, ); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 0e1cf3e6c6a..e57996a4676 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -11,13 +11,14 @@ use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, RegionResolutionError}; use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt}; +use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason, }; -use rustc_trait_selection::traits::predicate_for_trait_def; +use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; @@ -334,19 +335,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef )) .emit(); } else { - let errors = traits::fully_solve_obligations( - &infcx, - coerced_fields.into_iter().map(|field| { - predicate_for_trait_def( - tcx, - param_env, - cause.clone(), + let ocx = ObligationCtxt::new(&infcx); + for field in coerced_fields { + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::Binder::dummy(tcx.mk_trait_ref( dispatch_from_dyn_trait, - 0, [field.ty(tcx, substs_a), field.ty(tcx, substs_b)], - ) - }), - ); + )), + )); + } + let errors = ocx.select_all_or_error(); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors); } @@ -583,10 +584,12 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn }; // Register an obligation for `A: Trait<B>`. + let ocx = ObligationCtxt::new(&infcx); let cause = traits::ObligationCause::misc(span, impl_did); - let predicate = - predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]); - let errors = traits::fully_solve_obligation(&infcx, predicate); + let obligation = + Obligation::new(tcx, cause, param_env, tcx.mk_trait_ref(trait_def_id, [source, target])); + ocx.register_obligation(obligation); + let errors = ocx.select_all_or_error(); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors); } diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index e330fcc7857..bdd033c5f5f 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -7,7 +7,7 @@ use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::def_id::LocalDefId; -use rustc_trait_selection::traits; +use rustc_trait_selection::traits::{self, ObligationCtxt}; pub fn provide(providers: &mut Providers) { *providers = Providers { diagnostic_hir_wf_check, ..*providers }; @@ -66,35 +66,35 @@ fn diagnostic_hir_wf_check<'tcx>( impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { let infcx = self.tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); + let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); let cause = traits::ObligationCause::new( ty.span, self.def_id, traits::ObligationCauseCode::WellFormed(None), ); - let errors = traits::fully_solve_obligation( - &infcx, - traits::Obligation::new( - self.tcx, - cause, - self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())), - ), - ); - if !errors.is_empty() { - debug!("Wf-check got errors for {:?}: {:?}", ty, errors); - for error in errors { - if error.obligation.predicate == self.predicate { - // Save the cause from the greatest depth - this corresponds - // to picking more-specific types (e.g. `MyStruct<u8>`) - // over less-specific types (e.g. `Option<MyStruct<u8>>`) - if self.depth >= self.cause_depth { - self.cause = Some(error.obligation.cause); - self.cause_depth = self.depth - } + + ocx.register_obligation(traits::Obligation::new( + self.tcx, + cause, + self.param_env, + ty::PredicateKind::WellFormed(tcx_ty.into()), + )); + + for error in ocx.select_all_or_error() { + debug!("Wf-check got error for {:?}: {:?}", ty, error); + if error.obligation.predicate == self.predicate { + // Save the cause from the greatest depth - this corresponds + // to picking more-specific types (e.g. `MyStruct<u8>`) + // over less-specific types (e.g. `Option<MyStruct<u8>>`) + if self.depth >= self.cause_depth { + self.cause = Some(error.obligation.cause); + self.cause_depth = self.depth } } } + self.depth += 1; intravisit::walk_ty(self, ty); self.depth -= 1; diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 08786fe9b1e..a3d045c80d1 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -102,7 +102,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_hir as hir; use rustc_hir::Node; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_macros::fluent_messages; use rustc_middle::middle; use rustc_middle::ty::query::Providers; @@ -113,7 +113,7 @@ use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::ops::Not; @@ -160,24 +160,21 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi fn require_same_types<'tcx>( tcx: TyCtxt<'tcx>, cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, -) -> bool { +) { let infcx = &tcx.infer_ctxt().build(); - let param_env = ty::ParamEnv::empty(); - let errors = match infcx.at(cause, param_env).eq(DefineOpaqueTypes::No, expected, actual) { - Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations), + let ocx = ObligationCtxt::new(infcx); + match ocx.eq(cause, param_env, expected, actual) { + Ok(()) => { + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(&errors); + } + } Err(err) => { infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit(); - return false; - } - }; - - match &errors[..] { - [] => true, - errors => { - infcx.err_ctxt().report_fulfillment_errors(errors); - false } } } @@ -296,6 +293,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return; } + // Main should have no WC, so empty param env is OK here. + let param_env = ty::ParamEnv::empty(); let expected_return_type; if let Some(term_did) = tcx.lang_items().termination() { let return_ty = main_fnsig.output(); @@ -306,8 +305,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { } let return_ty = return_ty.skip_binder(); let infcx = tcx.infer_ctxt().build(); - // Main should have no WC, so empty param env is OK here. - let param_env = ty::ParamEnv::empty(); let cause = traits::ObligationCause::new( return_ty_span, main_diagnostics_def_id, @@ -343,6 +340,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { main_diagnostics_def_id, ObligationCauseCode::MainFunctionType, ), + param_env, se_ty, tcx.mk_fn_ptr(main_fnsig), ); @@ -417,6 +415,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { start_def_id, ObligationCauseCode::StartFunctionType, ), + ty::ParamEnv::empty(), // start should not have any where bounds. se_ty, tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()), ); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index ecbe4a97dd9..5235710a266 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -668,7 +668,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) { if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty) - && !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span) + && !self.type_is_sized_modulo_regions(self.param_env, output_ty) { let descr = match maybe_def { DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id), diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 316c2a7eeeb..d28b3b3ce7b 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -96,7 +96,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let t = self.resolve_vars_if_possible(t); t.error_reported()?; - if self.type_is_sized_modulo_regions(self.param_env, t, span) { + if self.type_is_sized_modulo_regions(self.param_env, t) { return Ok(Some(PointerKind::Thin)); } @@ -722,7 +722,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty); - if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty, self.span) + if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty) && !self.cast_ty.has_infer_types() { self.report_cast_to_unsized_type(fcx); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index a27905ea46c..8fa3bcd68c3 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -46,7 +46,7 @@ use rustc_hir::Expr; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; -use rustc_infer::traits::Obligation; +use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, @@ -597,13 +597,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // and almost never more than 3. By using a SmallVec we avoid an // allocation, at the (very small) cost of (occasionally) having to // shift subsequent elements down when removing the front element. - let mut queue: SmallVec<[_; 4]> = smallvec![traits::predicate_for_trait_def( + let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new( self.tcx, - self.fcx.param_env, cause, - coerce_unsized_did, - 0, - [coerce_source, coerce_target] + self.fcx.param_env, + self.tcx.mk_trait_ref(coerce_unsized_did, [coerce_source, coerce_target]) )]; let mut has_unsized_tuple_coercion = false; @@ -651,9 +649,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let self_ty = trait_pred.skip_binder().self_ty(); let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty(); debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred); - match (&self_ty.kind(), &unsize_ty.kind()) { - (ty::Infer(ty::TyVar(v)), ty::Dynamic(..)) - if self.type_var_is_sized(*v) => + match (self_ty.kind(), unsize_ty.kind()) { + (&ty::Infer(ty::TyVar(v)), ty::Dynamic(..)) + if self.type_var_is_sized(v) => { debug!("coerce_unsized: have sized infer {:?}", v); coercion.obligations.push(obligation); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index f65f16e317d..06e857ec3ca 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1480,7 +1480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // For this suggestion to make sense, the type would need to be `Copy`, // or we have to be moving out of a `Box<T>` - if self.type_is_copy_modulo_regions(self.param_env, expected, sp) + if self.type_is_copy_modulo_regions(self.param_env, expected) // FIXME(compiler-errors): We can actually do this if the checked_ty is // `steps` layers of boxes, not just one, but this is easier and most likely. || (checked_ty.is_box() && steps == 1) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 9aa6c7f103f..c62c1553d6f 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -867,10 +867,7 @@ fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, place_with_id: &PlaceWithHirId<'tcx>, ) -> ConsumeMode { - if !mc.type_is_copy_modulo_regions( - place_with_id.place.ty(), - mc.tcx().hir().span(place_with_id.hir_id), - ) { + if !mc.type_is_copy_modulo_regions(place_with_id.place.ty()) { ConsumeMode::Move } else { ConsumeMode::Copy diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 7a09ea40d79..7273b93b676 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1011,11 +1011,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut suggest_copied_or_cloned = || { let expr_inner_ty = substs.type_at(0); let expected_inner_ty = expected_substs.type_at(0); - if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind() - && self.can_eq(self.param_env, *ty, expected_inner_ty) + if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind() + && self.can_eq(self.param_env, ty, expected_inner_ty) { let def_path = self.tcx.def_path_str(adt_def.did()); - if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) { + if self.type_is_copy_modulo_regions(self.param_env, ty) { diag.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( @@ -1029,9 +1029,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions( self, self.param_env, - *ty, + ty, clone_did, - expr.span ) { diag.span_suggestion_verbose( diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 9a8d7ca9e33..95e5483abf3 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -120,8 +120,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.infcx.tcx } - pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) + pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { + self.infcx.type_is_copy_modulo_regions(self.param_env, ty) } fn resolve_vars_if_possible<T>(&self, value: T) -> T diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 37783bc91bb..8a83bb58573 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -21,7 +21,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{self, FulfillmentError}; +use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt}; use rustc_type_ir::sty::TyKind::*; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -434,7 +434,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.type_is_copy_modulo_regions( self.param_env, *lhs_deref_ty, - lhs_expr.span, ) { suggest_deref_binop(*lhs_deref_ty); } @@ -776,7 +775,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (None, Some(trait_did)) => { let (obligation, _) = self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types)); - Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation)) + // FIXME: This should potentially just add the obligation to the `FnCtxt` + let ocx = ObligationCtxt::new(&self.infcx); + ocx.register_obligation(obligation); + Err(ocx.select_all_or_error()) } } } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 4a432328c4d..84fe21825d7 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // closures. We want to make sure any adjustment that might make us move the place into // the closure gets handled. let (place, capture_kind) = - restrict_precision_for_drop_types(self, place, capture_kind, usage_span); + restrict_precision_for_drop_types(self, place, capture_kind); capture_info.capture_kind = capture_kind; (place, capture_info) @@ -1822,9 +1822,8 @@ fn restrict_precision_for_drop_types<'a, 'tcx>( fcx: &'a FnCtxt<'a, 'tcx>, mut place: Place<'tcx>, mut curr_mode: ty::UpvarCapture, - span: Span, ) -> (Place<'tcx>, ty::UpvarCapture) { - let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty(), span); + let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty()); if let (false, UpvarCapture::ByValue) = (is_copy_type, curr_mode) { for i in 0..place.projections.len() { diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index a3367ae4a9f..cb7711034ed 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -11,6 +11,7 @@ use rustc_hir as hir; use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause}; use rustc_middle::ty::{self, List}; use rustc_span::{sym, Span}; +use rustc_trait_selection::traits::ObligationCtxt; declare_lint! { /// The `for_loops_over_fallibles` lint checks for `for` loops over `Option` or `Result` values. @@ -136,20 +137,23 @@ fn suggest_question_mark<'tcx>( let ty = substs.type_at(0); let infcx = cx.tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); + let body_def_id = cx.tcx.hir().body_owner_def_id(body_id); let cause = ObligationCause::new( span, body_def_id, rustc_infer::traits::ObligationCauseCode::MiscObligation, ); - let errors = rustc_trait_selection::traits::fully_solve_bound( - &infcx, + + ocx.register_bound( cause, + // FIXME: using the empty param env is wrong, should use the one from `body_id`. ty::ParamEnv::empty(), // Erase any region vids from the type, which may not be resolved infcx.tcx.erase_regions(ty), into_iterator_did, ); - errors.is_empty() + ocx.select_all_or_error().is_empty() } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 298b2c3073c..6ba3ab097de 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1128,6 +1128,13 @@ impl<'tcx, T> ToPredicate<'tcx, T> for T { } } +impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1142,6 +1149,13 @@ impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { } } +impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index baeb2718cae..90d78658f96 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -5,7 +5,7 @@ use crate::build::Builder; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -66,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> { let tcx = self.tcx; let ty = place.ty(&self.local_decls, tcx).ty; - if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, DUMMY_SP) { + if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty) { Operand::Move(place) } else { Operand::Copy(place) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index ff88d001351..274c2f06137 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,14 +1,14 @@ use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::Obligation; use rustc_middle::mir::{self, Field}; use rustc_middle::thir::{FieldPat, Pat, PatKind}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint; use rustc_span::Span; -use rustc_trait_selection::traits::predicate_for_trait_def; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation}; +use rustc_trait_selection::traits::{self, ObligationCause}; use std::cell::Cell; @@ -189,17 +189,15 @@ impl<'tcx> ConstToPat<'tcx> { // using `PartialEq::eq` in this scenario in the past.) let partial_eq_trait_id = self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span)); - let obligation: PredicateObligation<'_> = predicate_for_trait_def( + let partial_eq_obligation = Obligation::new( self.tcx(), + ObligationCause::dummy(), self.param_env, - ObligationCause::misc(self.span, self.id.owner.def_id), - partial_eq_trait_id, - 0, - [ty, ty], + self.tcx().mk_trait_ref(partial_eq_trait_id, [ty, ty]), ); - // FIXME: should this call a `predicate_must_hold` variant instead? - let has_impl = self.infcx.predicate_may_hold(&obligation); + // FIXME: should this call a `predicate_must_hold` variant instead? + let has_impl = self.infcx.predicate_may_hold(&partial_eq_obligation); // Note: To fix rust-lang/rust#65466, we could just remove this type // walk hack for function pointers, and unconditionally error diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 9b47c7299bb..911cc0b88c4 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -8,26 +8,16 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryRes use rustc_middle::traits::query::Fallible; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, ToPredicate}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; use std::fmt::Debug; pub use rustc_infer::infer::*; pub trait InferCtxtExt<'tcx> { - fn type_is_copy_modulo_regions( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - ) -> bool; + fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; - fn type_is_sized_modulo_regions( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - ) -> bool; + fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; /// Check whether a `ty` implements given trait(trait_def_id). /// The inputs are: @@ -46,13 +36,9 @@ pub trait InferCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> traits::EvaluationResult; } + impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { - fn type_is_copy_modulo_regions( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - ) -> bool { + fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.resolve_vars_if_possible(ty); if !(param_env, ty).needs_infer() { @@ -65,17 +51,12 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. - traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) + traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id) } - fn type_is_sized_modulo_regions( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - ) -> bool { + fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let lang_item = self.tcx.require_lang_item(LangItem::Sized, None); - traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item, span) + traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item) } #[instrument(level = "debug", skip(self, params), ret)] diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 1870d3a2daf..dbf6775afc2 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -180,8 +180,9 @@ impl<'tcx> AutoTraitFinder<'tcx> { // At this point, we already have all of the bounds we need. FulfillmentContext is used // to store all of the necessary region/lifetime bounds in the InferContext, as well as // an additional sanity check. - let errors = - super::fully_solve_bound(&infcx, ObligationCause::dummy(), full_env, ty, trait_did); + let ocx = ObligationCtxt::new(&infcx); + ocx.register_bound(ObligationCause::dummy(), full_env, ty, trait_did); + let errors = ocx.select_all_or_error(); if !errors.is_empty() { panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors); } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f4cfe4ec0b0..572d20b5368 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -383,7 +383,10 @@ fn resolve_negative_obligation<'tcx>( }; let param_env = o.param_env; - if !super::fully_solve_obligation(&infcx, o).is_empty() { + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligation(o); + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { return false; } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index bfeda88a6d4..b27a3929078 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -30,7 +30,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; -use rustc_span::def_id::{DefId, CRATE_DEF_ID}; +use rustc_span::def_id::DefId; use rustc_span::Span; use std::fmt::Debug; @@ -63,9 +63,7 @@ pub use self::util::{ elaborate_trait_ref, elaborate_trait_refs, }; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; -pub use self::util::{ - get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices, -}; +pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices}; pub use self::util::{ supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type, SupertraitDefIds, Supertraits, @@ -131,29 +129,23 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, def_id: DefId, - span: Span, ) -> bool { let trait_ref = ty::Binder::dummy(infcx.tcx.mk_trait_ref(def_id, [ty])); - pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const(), span) + pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const()) } -#[instrument(level = "debug", skip(infcx, param_env, span, pred), ret)] +/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist? +/// +/// Ping me on zulip if you want to use this method and need help with finding +/// an appropriate replacement. +#[instrument(level = "debug", skip(infcx, param_env, pred), ret)] fn pred_known_to_hold_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>, - span: Span, ) -> bool { let has_non_region_infer = pred.has_non_region_infer(); - let obligation = Obligation { - param_env, - // We can use a dummy node-id here because we won't pay any mind - // to region obligations that arise (there shouldn't really be any - // anyhow). - cause: ObligationCause::misc(span, CRATE_DEF_ID), - recursion_depth: 0, - predicate: pred.to_predicate(infcx.tcx), - }; + let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred); let result = infcx.evaluate_obligation_no_overflow(&obligation); debug!(?result); @@ -166,14 +158,13 @@ fn pred_known_to_hold_modulo_regions<'tcx>( // this function's result remains infallible, we must confirm // that guess. While imperfect, I believe this is sound. - // FIXME(@lcnr): this function doesn't seem right. - // // The handling of regions in this area of the code is terrible, // see issue #29149. We should be able to improve on this with // NLL. - let errors = fully_solve_obligation(infcx, obligation); - - match &errors[..] { + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligation(obligation); + let errors = ocx.select_all_or_error(); + match errors.as_slice() { [] => true, errors => { debug!(?errors); @@ -389,43 +380,6 @@ where Ok(resolved_value) } -/// Process an obligation (and any nested obligations that come from it) to -/// completion, returning any errors -pub fn fully_solve_obligation<'tcx>( - infcx: &InferCtxt<'tcx>, - obligation: PredicateObligation<'tcx>, -) -> Vec<FulfillmentError<'tcx>> { - fully_solve_obligations(infcx, [obligation]) -} - -/// Process a set of obligations (and any nested obligations that come from them) -/// to completion -pub fn fully_solve_obligations<'tcx>( - infcx: &InferCtxt<'tcx>, - obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>, -) -> Vec<FulfillmentError<'tcx>> { - let ocx = ObligationCtxt::new(infcx); - ocx.register_obligations(obligations); - ocx.select_all_or_error() -} - -/// Process a bound (and any nested obligations that come from it) to completion. -/// This is a convenience function for traits that have no generic arguments, such -/// as auto traits, and builtin traits like Copy or Sized. -pub fn fully_solve_bound<'tcx>( - infcx: &InferCtxt<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - bound: DefId, -) -> Vec<FulfillmentError<'tcx>> { - let tcx = infcx.tcx; - let trait_ref = tcx.mk_trait_ref(bound, [ty]); - let obligation = Obligation::new(tcx, cause, param_env, ty::Binder::dummy(trait_ref)); - - fully_solve_obligation(infcx, obligation) -} - /// Normalizes the predicates and checks whether they hold in an empty environment. If this /// returns true, then either normalize encountered an error or one of the predicates did not /// hold. Used when creating vtables to check for unsatisfiable methods. diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 6cb64ad574f..bac02f2d383 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -1,7 +1,7 @@ use crate::infer::InferCtxt; use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use crate::traits::query::NoSolution; -use crate::traits::ObligationCause; +use crate::traits::{ObligationCause, ObligationCtxt}; use rustc_data_structures::fx::FxIndexSet; use rustc_middle::ty::{self, ParamEnv, Ty}; use rustc_span::def_id::LocalDefId; @@ -71,22 +71,23 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { if let Some(constraints) = constraints { debug!(?constraints); + if !constraints.member_constraints.is_empty() { + span_bug!(span, "{:#?}", constraints.member_constraints); + } + // Instantiation may have produced new inference variables and constraints on those // variables. Process these constraints. + let ocx = ObligationCtxt::new(self); let cause = ObligationCause::misc(span, body_id); - let errors = super::fully_solve_obligations( - self, - constraints.outlives.iter().map(|constraint| { - self.query_outlives_constraint_to_obligation( - *constraint, - cause.clone(), - param_env, - ) - }), - ); - if !constraints.member_constraints.is_empty() { - span_bug!(span, "{:#?}", constraints.member_constraints); + for &constraint in &constraints.outlives { + ocx.register_obligation(self.query_outlives_constraint_to_obligation( + constraint, + cause.clone(), + param_env, + )); } + + let errors = ocx.select_all_or_error(); if !errors.is_empty() { self.tcx.sess.delay_span_bug( span, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 6bf3ed0d0e2..8f1b05c1190 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -1,8 +1,8 @@ use crate::infer::canonical::query_response; use crate::infer::{InferCtxt, InferOk}; -use crate::traits; use crate::traits::query::type_op::TypeOpOutput; use crate::traits::query::Fallible; +use crate::traits::ObligationCtxt; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_span::source_map::DUMMY_SP; @@ -73,7 +73,9 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( ); let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?; - let errors = traits::fully_solve_obligations(infcx, obligations); + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations); + let errors = ocx.select_all_or_error(); if !errors.is_empty() { infcx.tcx.sess.diagnostic().delay_span_bug( DUMMY_SP, @@ -82,9 +84,7 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( } let region_obligations = infcx.take_registered_region_obligations(); - let region_constraint_data = infcx.take_and_reset_region_constraints(); - let region_constraints = query_response::make_query_region_constraints( infcx.tcx, region_obligations diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3d5dd18f4c1..eb354bc3f50 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -18,7 +18,7 @@ use rustc_session::config::TraitSolver; use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; -use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def}; +use crate::traits::util::{self, closure_trait_ref_and_return_type}; use crate::traits::vtable::{ count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset, VtblSegment, @@ -253,15 +253,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let cause = obligation.derived_cause(BuiltinDerivedObligation); - ensure_sufficient_stack(|| { - self.collect_predicates_for_types( - obligation.param_env, - cause, - obligation.recursion_depth + 1, - trait_def, - nested, - ) - }) + self.collect_predicates_for_types( + obligation.param_env, + cause, + obligation.recursion_depth + 1, + trait_def, + nested, + ) } else { vec![] }; @@ -1118,14 +1116,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested.extend(obligations); // Construct the nested `TailField<T>: Unsize<TailField<U>>` predicate. - nested.push(predicate_for_trait_def( + let tail_unsize_obligation = obligation.with( tcx, - obligation.param_env, - obligation.cause.clone(), - obligation.predicate.def_id(), - obligation.recursion_depth + 1, - [source_tail, target_tail], - )); + tcx.mk_trait_ref(obligation.predicate.def_id(), [source_tail, target_tail]), + ); + nested.push(tail_unsize_obligation); } // `(.., T)` -> `(.., U)` @@ -1147,17 +1142,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|_| Unimplemented)?; nested.extend(obligations); - // Construct the nested `T: Unsize<U>` predicate. - nested.push(ensure_sufficient_stack(|| { - predicate_for_trait_def( - tcx, - obligation.param_env, - obligation.cause.clone(), - obligation.predicate.def_id(), - obligation.recursion_depth + 1, - [a_last, b_last], - ) - })); + // Add a nested `T: Unsize<U>` predicate. + let last_unsize_obligation = obligation + .with(tcx, tcx.mk_trait_ref(obligation.predicate.def_id(), [a_last, b_last])); + nested.push(last_unsize_obligation); } _ => bug!("source: {source}, target: {target}"), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index bc1c72da1e1..d9b2b7dbe16 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -17,7 +17,7 @@ use super::project; use super::project::normalize_with_depth_to; use super::project::ProjectionTyObligation; use super::util; -use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; +use super::util::closure_trait_ref_and_return_type; use super::wf; use super::{ ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, @@ -2440,15 +2440,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> { placeholder_ty, ) }); - let placeholder_obligation = predicate_for_trait_def( + + let obligation = Obligation::new( self.tcx(), - param_env, cause.clone(), - trait_def_id, - recursion_depth, - [normalized_ty], + param_env, + self.tcx().mk_trait_ref(trait_def_id, [normalized_ty]), ); - obligations.push(placeholder_obligation); + obligations.push(obligation); obligations }) .collect() diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index ab4c36975a0..00c9a352258 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,11 +1,11 @@ use super::NormalizeExt; -use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext}; +use super::{ObligationCause, PredicateObligation, SelectionContext}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferOk; +use rustc_middle::ty::SubstsRef; use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::ty::{GenericArg, SubstsRef}; use rustc_span::Span; use smallvec::SmallVec; @@ -218,33 +218,6 @@ pub fn impl_subject_and_oblig<'a, 'tcx>( (subject, impl_obligations) } -pub fn predicate_for_trait_ref<'tcx>( - tcx: TyCtxt<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - recursion_depth: usize, -) -> PredicateObligation<'tcx> { - Obligation { - cause, - param_env, - recursion_depth, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), - } -} - -pub fn predicate_for_trait_def<'tcx>( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - trait_def_id: DefId, - recursion_depth: usize, - params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, -) -> PredicateObligation<'tcx> { - let trait_ref = tcx.mk_trait_ref(trait_def_id, params); - predicate_for_trait_ref(tcx, cause, param_env, trait_ref, recursion_depth) -} - /// Casts a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index d3169b6d962..3b1abdcb24f 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -3,7 +3,6 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::DUMMY_SP; use rustc_trait_selection::traits; fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { @@ -30,7 +29,7 @@ fn is_item_raw<'tcx>( let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(item, None); let infcx = tcx.infer_ctxt().build(); - traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id, DUMMY_SP) + traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id) } pub(crate) fn provide(providers: &mut ty::query::Providers) { |
