diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index b63f51138c326..cf204cff6b3a7 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -26,7 +26,6 @@ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::AssertKind; use rustc_middle::mir::*; -use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 38bb5a3143b35..9d5ec228d827b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -557,6 +557,29 @@ impl<'tcx> InferCtxt<'tcx> { Ok(InferOk { value: (), obligations }) } + /// Registers an opaque's hidden type -- only should be used when the opaque + /// can be defined. For something more fallible -- checks the anchors, tries + /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`. + pub fn register_hidden_type_in_new_solver( + &self, + opaque_type_key: OpaqueTypeKey<'tcx>, + param_env: ty::ParamEnv<'tcx>, + hidden_ty: Ty<'tcx>, + ) -> InferResult<'tcx, ()> { + assert!(self.tcx.trait_solver_next()); + let origin = self + .opaque_type_origin(opaque_type_key.def_id) + .expect("should be called for defining usages only"); + self.register_hidden_type( + opaque_type_key, + ObligationCause::dummy(), + param_env, + hidden_ty, + origin, + true, + ) + } + pub fn add_item_bounds_for_hidden_type( &self, OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 32a8bda2663da..f91c672775301 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -1,4 +1,4 @@ -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -192,13 +192,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { for &(a, b) in &input.predefined_opaques_in_body.opaque_types { let InferOk { value: (), obligations } = infcx - .handle_opaque_type( - tcx.mk_opaque(a.def_id.to_def_id(), a.substs), - b, - true, - &ObligationCause::dummy(), - input.goal.param_env, - ) + .register_hidden_type_in_new_solver(a, input.goal.param_env, b) .expect("expected opaque type instantiation to succeed"); // We're only registering opaques already defined by the caller, // so we're not responsible for proving that they satisfy their @@ -727,19 +721,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - pub(super) fn can_define_opaque_ty(&mut self, def_id: DefId) -> bool { - let Some(def_id) = def_id.as_local() else { return false; }; + pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool { self.infcx.opaque_type_origin(def_id).is_some() } pub(super) fn register_opaque_ty( &mut self, - a: Ty<'tcx>, + a: ty::OpaqueTypeKey<'tcx>, b: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result<(), NoSolution> { let InferOk { value: (), obligations } = - self.infcx.handle_opaque_type(a, b, true, &ObligationCause::dummy(), param_env)?; + self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?; self.add_goals(obligations.into_iter().map(|obligation| obligation.into())); Ok(()) } @@ -749,17 +742,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { pub(super) fn unify_existing_opaque_tys( &mut self, param_env: ty::ParamEnv<'tcx>, - key: ty::AliasTy<'tcx>, + key: ty::OpaqueTypeKey<'tcx>, ty: Ty<'tcx>, ) -> Vec> { - let Some(def_id) = key.def_id.as_local() else { return vec![]; }; - // FIXME: Super inefficient to be cloning this... let opaques = self.infcx.clone_opaque_types_for_query_response(); let mut values = vec![]; for (candidate_key, candidate_ty) in opaques { - if candidate_key.def_id != def_id { + if candidate_key.def_id != key.def_id { continue; } values.extend(self.probe(|ecx| { diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 8d12c7edfe3b8..fdb209fbff871 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -15,11 +15,11 @@ use rustc_index::IndexVec; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; +use rustc_infer::infer::InferOk; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{ ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput, }; -use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty}; use rustc_span::DUMMY_SP; use std::iter; @@ -179,13 +179,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let Response { var_values, external_constraints, certainty } = response.substitute(self.tcx(), &substitution); - let mut nested_goals = - self.unify_query_var_values(param_env, &original_values, var_values)?; + let nested_goals = self.unify_query_var_values(param_env, &original_values, var_values)?; let ExternalConstraintsData { region_constraints, opaque_types } = external_constraints.deref(); self.register_region_constraints(region_constraints); - nested_goals.extend(self.register_opaque_types(param_env, opaque_types)?); + self.register_opaque_types(param_env, opaque_types)?; Ok((certainty, nested_goals)) } @@ -310,24 +309,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, param_env: ty::ParamEnv<'tcx>, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)], - ) -> Result>>, NoSolution> { - let mut nested_goals = vec![]; + ) -> Result<(), NoSolution> { for &(a, b) in opaque_types { - nested_goals.extend( - self.infcx - .handle_opaque_type( - self.tcx().mk_opaque(a.def_id.to_def_id(), a.substs), - b, - true, - &ObligationCause::dummy(), - param_env, - )? - .into_obligations() - .into_iter() - .map(Goal::from), - ); + let InferOk { value: (), obligations } = + self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?; + // It's sound to drop these obligations, since the normalizes-to goal + // is responsible for proving these obligations. + let _ = obligations; } - - Ok(nested_goals) + Ok(()) } } diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs index f97f54e760e33..54557aeb9a2dd 100644 --- a/compiler/rustc_trait_selection/src/solve/opaques.rs +++ b/compiler/rustc_trait_selection/src/solve/opaques.rs @@ -18,10 +18,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { match goal.param_env.reveal() { Reveal::UserFacing => match self.solver_mode() { SolverMode::Normal => { + let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else { + return Err(NoSolution); + }; + let opaque_ty = + ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs }; // FIXME: at some point we should call queries without defining // new opaque types but having the existing opaque type definitions. // This will require moving this below "Prefer opaques registered already". - if !self.can_define_opaque_ty(opaque_ty.def_id) { + if !self.can_define_opaque_ty(opaque_ty_def_id) { return Err(NoSolution); } // FIXME: This may have issues when the substs contain aliases... @@ -47,8 +52,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } // Otherwise, define a new opaque type - let opaque_ty = tcx.mk_opaque(opaque_ty.def_id, opaque_ty.substs); - self.register_opaque_ty(expected, opaque_ty, goal.param_env)?; + self.register_opaque_ty(opaque_ty, expected, goal.param_env)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } SolverMode::Coherence => {