diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c4c54620e04e9..b54c614587a1e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -167,7 +167,7 @@ fn do_mir_borrowck<'tcx>( let tcx = infcx.tcx; let infcx = BorrowckInferCtxt::new(infcx); - let param_env = tcx.param_env(def); + let param_env = tcx.param_env_body_post_hir_typeck(def); let mut local_names = IndexVec::from_elem(None, &input_body.local_decls); for var_debug_info in &input_body.var_debug_info { diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index a4394ddc01c5a..37cece4e98813 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -308,7 +308,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( )); } - let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values); + let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, param_env, opaque_type_values); NllOutput { regioncx, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4970ece5e7deb..d23e2ec17c5c6 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -8,7 +8,7 @@ use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::ObligationCtxt; @@ -17,6 +17,124 @@ use crate::session_diagnostics::NonGenericOpaqueTypeParam; use super::RegionInferenceContext; impl<'tcx> RegionInferenceContext<'tcx> { + /// region to pass to `infer_opaque_definition_from_instantiation`. + #[instrument(level = "debug", skip(self, infcx), ret)] + fn infer_opaque_types_next( + &self, + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> FxIndexMap> { + let mut result: FxIndexMap> = FxIndexMap::default(); + + let member_constraints: FxIndexMap<_, _> = self + .member_constraints + .all_indices() + .map(|ci| (self.member_constraints[ci].key, ci)) + .collect(); + debug!(?member_constraints); + + for predicate in param_env.caller_bounds() { + let (opaque_ty, concrete_ty) = match predicate.kind().skip_binder() { + ty::PredicateKind::DefineOpaque(opaque_ty, concrete_ty) => { + assert!(!opaque_ty.has_escaping_bound_vars()); + assert!(!concrete_ty.has_escaping_bound_vars()); + (opaque_ty, concrete_ty) + } + _ => continue, + }; + + let substs = opaque_ty.substs; + let opaque_type_key = OpaqueTypeKey { def_id: opaque_ty.def_id.expect_local(), substs }; + + let mut subst_regions = vec![self.universal_regions.fr_static]; + + let to_universal_region = |vid, subst_regions: &mut Vec<_>| { + trace!(?vid); + let scc = self.constraint_sccs.scc(vid); + trace!(?scc); + match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| { + self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?) + }) { + Some(region) => { + let vid = self.universal_regions.to_region_vid(region); + subst_regions.push(vid); + region + } + None => { + subst_regions.push(vid); + infcx.tcx.mk_re_error_with_message( + DUMMY_SP, + "opaque type with non-universal region substs", + ) + } + } + }; + + // Start by inserting universal regions from the member_constraint choice regions. + // This will ensure they get precedence when folding the regions in the concrete type. + if let Some(&ci) = member_constraints.get(&opaque_type_key) { + for &vid in self.member_constraints.choice_regions(ci) { + to_universal_region(vid, &mut subst_regions); + } + } + debug!(?subst_regions); + + // Next, insert universal regions from substs, so we can translate regions that appear + // in them but are not subject to member constraints, for instance closure substs. + let universal_substs = infcx.tcx.fold_regions(substs, |region, _| { + if let ty::RePlaceholder(..) = region.kind() { + // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. + return region; + } + let vid = self.to_region_vid(region); + to_universal_region(vid, &mut subst_regions) + }); + debug!(?universal_substs); + debug!(?subst_regions); + + // Deduplicate the set of regions while keeping the chosen order. + let subst_regions = subst_regions.into_iter().collect::>(); + debug!(?subst_regions); + + let universal_concrete_type = + infcx.tcx.fold_regions(concrete_ty, |region, _| match *region { + ty::ReVar(vid) => subst_regions + .iter() + .find(|ur_vid| self.eval_equal(vid, **ur_vid)) + .and_then(|ur_vid| self.definitions[*ur_vid].external_name) + .unwrap_or(infcx.tcx.lifetimes.re_erased), + _ => region, + }); + debug!(?universal_concrete_type); + + let opaque_type_key = + OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs }; + let ty = infcx.infer_opaque_definition_from_instantiation( + opaque_type_key, + OpaqueHiddenType { span: DUMMY_SP, ty: universal_concrete_type }, + OpaqueTyOrigin::TyAlias, + ); + // Sometimes two opaque types are the same only after we remap the generic parameters + // back to the opaque type definition. E.g. we may have `OpaqueType` mapped to `(X, Y)` + // and `OpaqueType` mapped to `(Y, X)`, and those are the same, but we only know that + // once we convert the generic parameters to those of the opaque type. + if let Some(prev) = result.get_mut(&opaque_type_key.def_id) { + if prev.ty != ty { + let guar = ty.error_reported().err().unwrap_or_else(|| { + prev.report_mismatch(&OpaqueHiddenType { ty, span: DUMMY_SP }, infcx.tcx) + }); + prev.ty = infcx.tcx.ty_error(guar); + } + // Pick a better span if there is one. + // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. + prev.span = prev.span; + } else { + result.insert(opaque_type_key.def_id, OpaqueHiddenType { ty, span: DUMMY_SP }); + } + } + result + } + /// Resolve any opaque types that were encountered while borrow checking /// this item. This is then used to get the type in the `type_of` query. /// @@ -60,8 +178,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn infer_opaque_types( &self, infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, opaque_ty_decls: FxIndexMap, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>, ) -> FxIndexMap> { + if infcx.tcx.trait_solver_next() { + assert!(opaque_ty_decls.is_empty()); + return self.infer_opaque_types_next(infcx, param_env); + } let mut result: FxIndexMap> = FxIndexMap::default(); let member_constraints: FxIndexMap<_, _> = self @@ -263,6 +386,10 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { return self.tcx.ty_error(guar); } + if self.tcx.trait_solver_next() { + return definition_ty; + } + // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs` // on stable and we'd break that. let OpaqueTyOrigin::TyAlias = origin else { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index def192f6e1042..aa4407c1e3b72 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1480,6 +1480,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { | ty::PredicateKind::Coerce(_) | ty::PredicateKind::ConstEvaluatable(_) | ty::PredicateKind::ConstEquate(_, _) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::TypeWellFormedFromEnv(_) | ty::PredicateKind::Ambiguous => bug!(), } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 61b66ae2593be..ec3b097c7cb8a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -395,6 +395,10 @@ fn check_opaque_meets_bounds<'tcx>( span: Span, origin: &hir::OpaqueTyOrigin, ) { + if tcx.trait_solver_next() { + return; + } + let defining_use_anchor = match *origin { hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did, hir::OpaqueTyOrigin::TyAlias => def_id, diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 5cca2dacb5c7f..fafc4f8e2bdad 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -523,6 +523,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 357deb07b8f31..bffa9a1ac1a65 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -63,6 +63,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index cbedbad1f3864..c0b29c7de1ff3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -679,6 +679,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // code is looking for a self type of an unresolved // inference variable. | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, }, diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 4110b176b41b1..3d7f40f2316dd 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -4,13 +4,16 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::HirIdMap; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, OpaqueTypeKey, ToPredicate, Ty, TyCtxt}; use rustc_span::def_id::LocalDefIdMap; -use rustc_span::{self, Span}; +use rustc_span::{self, sym, Span}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _}; +use rustc_type_ir::AliasKind; use std::cell::RefCell; use std::ops::Deref; @@ -99,6 +102,76 @@ impl<'tcx> Inherited<'tcx> { } } + /// The `param_env` used to typeck this item. + /// + /// `-Ztrait-solver=next` needs the inference context to construct + /// the `param_env` for typeck. + pub(super) fn typeck_param_env(&self, def_id: LocalDefId) -> ty::ParamEnv<'tcx> { + let tcx = self.tcx; + let param_env = tcx.param_env(def_id); + let param_env = if tcx.has_attr(def_id, sym::rustc_do_not_const_check) { + param_env.without_const() + } else { + param_env + }; + + if tcx.trait_solver_next() { + let opaques = tcx.opaque_types_defined_by(def_id).subst_identity(); + if !opaques.is_empty() { + let mut needed_item_bounds = Vec::new(); + + let define_opaques = opaques + .iter() + .map(|ty| match *ty.kind() { + ty::Alias(AliasKind::Opaque, alias_ty) => { + let def_id = alias_ty.def_id; + let ty_var = self.infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::OpaqueTypeInference(def_id), + span: self.tcx.def_span(def_id), + }); + + needed_item_bounds.push(( + OpaqueTypeKey { + def_id: def_id.expect_local(), + substs: alias_ty.substs, + }, + ty_var, + )); + ty::PredicateKind::DefineOpaque(alias_ty, ty_var) + } + _ => bug!("unexpected defined opaque: {opaques:?}"), + }) + .map(|kind| kind.to_predicate(tcx)); + + let param_env = ty::ParamEnv::new( + tcx.mk_predicates_from_iter( + param_env.caller_bounds().iter().chain(define_opaques), + ), + param_env.reveal(), + param_env.constness(), + ); + + for (key, hidden_ty) in needed_item_bounds { + let mut obligations = Vec::new(); + self.infcx.add_item_bounds_for_hidden_type( + key, + ObligationCause::dummy(), + param_env, + hidden_ty, + &mut obligations, + ); + self.register_predicates(obligations); + } + + param_env + } else { + param_env + } + } else { + param_env + } + } + #[instrument(level = "debug", skip(self))] pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) { if obligation.has_escaping_bound_vars() { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index a2a4362e2f518..e91d1ac3086ea 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -73,7 +73,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config; use rustc_session::Session; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_span::{sym, Span}; +use rustc_span::Span; fluent_messages! { "../messages.ftl" } @@ -189,14 +189,10 @@ fn typeck_with_fallback<'tcx>( span_bug!(span, "can't type-check body of {:?}", def_id); }); let body = tcx.hir().body(body_id); - - let param_env = tcx.param_env(def_id); - let param_env = if tcx.has_attr(def_id, sym::rustc_do_not_const_check) { - param_env.without_const() - } else { - param_env - }; let inh = Inherited::new(tcx, def_id); + // `-Ztrait-solver=next` needs the inference context to construct + // the `param_env` for typeck. + let param_env = inh.typeck_param_env(def_id); let mut fcx = FnCtxt::new(&inh, param_env, def_id); if let Some(hir::FnSig { header, decl, .. }) = fn_sig { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index a0e978b0c1074..649ce670497ff 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -845,6 +845,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index cf95d4f04bb92..4f7e92f54453f 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableEx use rustc_middle::ty::TypeckResults; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::mem; use std::ops::ControlFlow; @@ -551,8 +551,37 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + fn visit_opaque_types_next(&mut self) { + for predicate in self.fcx.param_env.caller_bounds() { + let (opaque_ty, hidden_ty) = match predicate.kind().skip_binder() { + ty::PredicateKind::DefineOpaque(opaque_ty, hidden_ty) => { + assert!(!opaque_ty.has_escaping_bound_vars()); + assert!(!hidden_ty.has_escaping_bound_vars()); + (opaque_ty, hidden_ty) + } + _ => continue, + }; + + let opaque_ty = self.resolve(opaque_ty, &DUMMY_SP); + let hidden_ty = self.resolve(hidden_ty, &DUMMY_SP); + + self.typeck_results + .defined_opaque_types + .push(ty::DefinedOpaqueType { opaque_ty, hidden_ty }); + } + } + #[instrument(skip(self), level = "debug")] fn visit_opaque_types(&mut self) { + if self.tcx().trait_solver_next() { + let opaque_type_storage = self.fcx.infcx.take_opaque_types(); + if !opaque_type_storage.is_empty() { + bug!("used old opaque type storage in new solver"); + } + + return self.visit_opaque_types_next(); + } + let opaque_types = self.fcx.infcx.take_opaque_types(); for (opaque_type_key, decl) in opaque_types { let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span); diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index c9e13be02ff9a..a13530a2b32b0 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -125,9 +125,7 @@ impl<'tcx> InferCtxt<'tcx> { bug!() } - (_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _) - if self.tcx.trait_solver_next() => - { + (_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => { relation.register_type_relate_obligation(a, b); Ok(a) } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index f90f7674b55b1..b51fd0cfac1d8 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -104,7 +104,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) if self.fields.define_opaque_types == DefineOpaqueTypes::Yes - && def_id.is_local() => + && def_id.is_local() + && !self.tcx().trait_solver_next() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index 7f4c141b97af2..61dbaa1e88e2f 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -110,7 +110,9 @@ where ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b), (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() => + if this.define_opaque_types() == DefineOpaqueTypes::Yes + && def_id.is_local() + && !infcx.tcx.trait_solver_next() => { this.register_obligations( infcx diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1cfdb791cd6ae..a8c35f60c1edc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -6,6 +6,7 @@ pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; pub use combine::ObligationEmittingRelation; +use rustc_middle::ty::tls; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; @@ -204,6 +205,7 @@ impl<'tcx> InferCtxtInner<'tcx> { #[inline] pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { + tls::with(|tcx| assert!(!tcx.trait_solver_next())); self.opaque_type_storage.with_log(&mut self.undo_log) } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 9f7b26b87f459..6dc790c040270 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -509,16 +509,23 @@ where (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)), + (ty::Alias(..), _) | (_, ty::Alias(..)) if infcx.tcx.trait_solver_next() => { + infcx.super_combine_tys(self, a, b) + } + + // This behavior is only there for the old solver. ( &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), - ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| { - self.tcx().sess.delay_span_bug( - self.delegate.span(), - "failure to relate an opaque to itself should result in an error later on", - ); - if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) } - }), + ) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => { + infcx.super_combine_tys(self, a, b).or_else(|err| { + self.tcx().sess.delay_span_bug( + self.delegate.span(), + "failure to relate an opaque to itself should result in an error later on", + ); + if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) } + }) + } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) if def_id.is_local() => diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 334395945ea96..3a7282d624f47 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -2,7 +2,7 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{DefineOpaqueTypes, InferResult}; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{DefiningAnchor, InferCtxt, InferOk}; -use crate::traits; +use crate::traits::{self, PredicateObligation}; use hir::def_id::{DefId, LocalDefId}; use hir::OpaqueTyOrigin; use rustc_data_structures::fx::FxIndexMap; @@ -48,9 +48,15 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, param_env: ty::ParamEnv<'tcx>, ) -> InferOk<'tcx, T> { + // We handle opaque types differently in the new solver. + if self.tcx.trait_solver_next() { + return InferOk { value, obligations: vec![] }; + } + if !value.has_opaque_types() { return InferOk { value, obligations: vec![] }; } + let mut obligations = vec![]; let replace_opaque_type = |def_id: DefId| { def_id.as_local().map_or(false, |def_id| self.opaque_type_origin(def_id).is_some()) @@ -517,9 +523,6 @@ impl<'tcx> InferCtxt<'tcx> { origin: hir::OpaqueTyOrigin, a_is_expected: bool, ) -> InferResult<'tcx, ()> { - let tcx = self.tcx; - let OpaqueTypeKey { def_id, substs } = opaque_type_key; - // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, @@ -529,7 +532,7 @@ impl<'tcx> InferCtxt<'tcx> { let mut obligations = vec![]; let prev = self.inner.borrow_mut().opaque_types().register( - OpaqueTypeKey { def_id, substs }, + opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }, origin, ); @@ -540,6 +543,26 @@ impl<'tcx> InferCtxt<'tcx> { .obligations; } + self.add_item_bounds_for_hidden_type( + opaque_type_key, + cause, + param_env, + hidden_ty, + &mut obligations, + ); + + Ok(InferOk { value: (), obligations }) + } + + pub fn add_item_bounds_for_hidden_type( + &self, + OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + hidden_ty: Ty<'tcx>, + obligations: &mut Vec>, + ) { + let tcx = self.tcx; let item_bounds = tcx.explicit_item_bounds(def_id); for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) { @@ -551,14 +574,15 @@ impl<'tcx> InferCtxt<'tcx> { // FIXME(RPITIT): Don't replace RPITITs with inference vars. ty::Alias(ty::Projection, projection_ty) if !projection_ty.has_escaping_bound_vars() - && !tcx.is_impl_trait_in_trait(projection_ty.def_id) => + && !tcx.is_impl_trait_in_trait(projection_ty.def_id) + && !tcx.trait_solver_next() => { self.infer_projection( param_env, projection_ty, cause.clone(), 0, - &mut obligations, + obligations, ) } // Replace all other mentions of the same opaque type with the hidden type, @@ -583,10 +607,10 @@ impl<'tcx> InferCtxt<'tcx> { predicate.kind().skip_binder() { if projection.term.references_error() { - // No point on adding these obligations since there's a type error involved. - return Ok(InferOk { value: (), obligations: vec![] }); + // No point on adding any obligations since there's a type error involved. + obligations.clear(); + return; } - trace!("{:#?}", projection.term); } // Require that the predicate holds for the concrete type. debug!(?predicate); @@ -597,7 +621,6 @@ impl<'tcx> InferCtxt<'tcx> { predicate, )); } - Ok(InferOk { value: (), obligations }) } } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 8a44d5031596f..b936991e0ad74 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -35,6 +35,7 @@ pub fn explicit_outlives_bounds<'tcx>( | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate( diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 3766c250a9c70..c50aa06a0f98b 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -131,7 +131,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) if self.fields.define_opaque_types == DefineOpaqueTypes::Yes - && def_id.is_local() => + && def_id.is_local() + && !self.tcx().trait_solver_next() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index ef01d5d513bbc..424ec42d5f349 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -323,7 +323,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { .map(|predicate| elaboratable.child(predicate)), ); } - ty::PredicateKind::TypeWellFormedFromEnv(..) => { + ty::PredicateKind::TypeWellFormedFromEnv(..) | ty::PredicateKind::DefineOpaque(..) => { // Nothing to elaborate } ty::PredicateKind::Ambiguous => {} diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index aeb791901bd23..2baf0fb3bea19 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1607,6 +1607,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { // FIXME(generic_const_exprs): `ConstEvaluatable` can be written ConstEvaluatable(..) | ConstEquate(..) | + DefineOpaque(..) | Ambiguous | TypeWellFormedFromEnv(..) => continue, }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index be2657d25a694..2864c4c8c1abb 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -236,6 +236,15 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } + query opaque_types_defined_by( + key: LocalDefId + ) -> ty::EarlyBinder<&'tcx ty::List>> { + desc { + |tcx| "computing the opaque types defined by `{}`", + tcx.def_path_str(key.to_def_id()) + } + } + /// Returns the list of bounds that can be used for /// `SelectionCandidate::ProjectionCandidate(_)` and /// `ProjectionTyCandidate::TraitDef`. @@ -1227,6 +1236,10 @@ rustc_queries! { feedable } + query param_env_body_post_hir_typeck(def_id: LocalDefId) -> ty::ParamEnv<'tcx> { + desc { |tcx| "computing the post-typeck predicates of `{}`", tcx.def_path_str(def_id) } + } + /// Like `param_env`, but returns the `ParamEnv` in `Reveal::All` mode. /// Prefer this over `tcx.param_env(def_id).with_reveal_all_normalized(tcx)`, /// as this method is more efficient. diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 68002bfcfbd13..23ecd25261d5d 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -287,6 +287,10 @@ impl FlagComputation { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { self.add_ty(ty); } + ty::PredicateKind::DefineOpaque(opaque, ty) => { + self.add_alias_ty(opaque); + self.add_ty(ty); + } ty::PredicateKind::Ambiguous => {} ty::PredicateKind::AliasRelate(t1, t2, _) => { self.add_term(t1); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index db6b35026a8e7..cf46780f18056 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -103,8 +103,8 @@ pub use self::sty::{ pub use self::trait_def::TraitDef; pub use self::typeck_results::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, - GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType, - UserTypeAnnotationIndex, + DefinedOpaqueType, GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, + UserType, UserTypeAnnotationIndex, }; pub mod _match; @@ -550,6 +550,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Coerce(_) | PredicateKind::ConstEvaluatable(_) | PredicateKind::ConstEquate(_, _) + | PredicateKind::DefineOpaque(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(_) => true, } @@ -632,6 +633,15 @@ pub enum PredicateKind<'tcx> { /// Only used for Chalk. TypeWellFormedFromEnv(Ty<'tcx>), + /// We're currently in a context which defines the opaque type as the given type. + /// + /// This is only ever found as a clause in the environment. Unlike `Projection` clauses + /// the resulting type may get set to be equal to the opaque type if we end up not + /// defining the opaque type. + /// + /// FIXME(type_alias_impl_trait): This is currently only used for RPIT. + DefineOpaque(AliasTy<'tcx>, Ty<'tcx>), + /// A marker predicate that is always ambiguous. /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. Ambiguous, @@ -1001,13 +1011,10 @@ impl<'tcx> Term<'tcx> { /// /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly /// deal with constants. - pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option> { + pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option> { match self.unpack() { - TermKind::Ty(ty) => match ty.kind() { - ty::Alias(kind, alias_ty) => match kind { - AliasKind::Projection => Some(*alias_ty), - AliasKind::Opaque => None, - }, + TermKind::Ty(ty) => match *ty.kind() { + ty::Alias(_kind, alias_ty) => Some(alias_ty), _ => None, }, TermKind::Const(ct) => match ct.kind() { @@ -1252,6 +1259,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(Clause::TypeOutlives(..)) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::DefineOpaque(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } @@ -1273,6 +1281,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(Clause::TypeOutlives(..)) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::DefineOpaque(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } @@ -1294,6 +1303,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::DefineOpaque(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2aced27f7bbdc..697476b56af88 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2880,6 +2880,9 @@ define_print_and_forward_display! { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { p!("the type `", print(ty), "` is found in the environment") } + ty::PredicateKind::DefineOpaque(opaque, ty) => { + p!("defining `", print(opaque), "` to be `", print(ty), "`") + } ty::PredicateKind::Ambiguous => p!("ambiguous"), ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 29a3bc8bb9756..0508b5534dbb6 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -175,6 +175,9 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) } + ty::PredicateKind::DefineOpaque(opaque, ty) => { + write!(f, "DefineOpaque({opaque:?}, {ty:?})") + } ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), ty::PredicateKind::AliasRelate(t1, t2, dir) => { write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 5a0571f4bb7cb..76a2fc059d637 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -157,6 +157,8 @@ pub struct TypeckResults<'tcx> { /// even if they are only set in dead code (which doesn't show up in MIR). pub concrete_opaque_types: FxIndexMap>, + pub defined_opaque_types: Vec>, + /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>, @@ -213,6 +215,13 @@ pub struct TypeckResults<'tcx> { offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec)>, } +#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct DefinedOpaqueType<'tcx> { + pub opaque_ty: ty::AliasTy<'tcx>, + pub hidden_ty: Ty<'tcx>, +} + /// Whenever a value may be live across a generator yield, the type of that value winds up in the /// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such /// captured types that can be useful for diagnostics. In particular, it stores the span that @@ -276,6 +285,7 @@ impl<'tcx> TypeckResults<'tcx> { used_trait_imports: Lrc::new(Default::default()), tainted_by_errors: None, concrete_opaque_types: Default::default(), + defined_opaque_types: Default::default(), closure_min_captures: Default::default(), closure_fake_reads: Default::default(), rvalue_scopes: Default::default(), diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index c607c7fd5f4a7..77e924833f2fd 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -179,6 +179,7 @@ where | ty::PredicateKind::Coerce(_) | ty::PredicateKind::ConstEquate(_, _) | ty::PredicateKind::TypeWellFormedFromEnv(_) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) => bug!("unexpected predicate: {:?}", predicate), } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 63a73f8d50d93..f0f8cb4c25b1b 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -289,6 +289,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::ConstEvaluatable(_) | ty::PredicateKind::ConstEquate(_, _) => { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } + ty::PredicateKind::DefineOpaque(..) => { + bug!("DefineOpaque should only be used as an assumption: {goal:?}"); + } ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 32bd10f0beba5..1e843e3215ad2 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -133,12 +133,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::ConstEvaluatable(_) - | ty::PredicateKind::TypeWellFormedFromEnv(_) | ty::PredicateKind::Ambiguous => { FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, ) } + ty::PredicateKind::DefineOpaque(..) + | ty::PredicateKind::TypeWellFormedFromEnv(_) => { + bug!("unexpected goal: {goal:?}") + } }, root_obligation: obligation, }); diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index d94679fef2833..1427268f8291f 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -24,6 +24,7 @@ mod assembly; mod canonicalize; mod eval_ctxt; mod fulfill; +mod opaques; mod project_goals; mod search_graph; mod trait_goals; @@ -212,7 +213,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ); } - match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) { + match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) { (None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"), // RHS is not a projection, only way this is true is if LHS normalizes-to RHS diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs new file mode 100644 index 0000000000000..a4770009c7a80 --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/opaques.rs @@ -0,0 +1,68 @@ +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; +use rustc_middle::traits::Reveal; +use rustc_middle::ty::{self, ProjectionPredicate}; + +use super::{EvalCtxt, SolverMode}; + +impl<'tcx> EvalCtxt<'_, 'tcx> { + pub(super) fn normalize_opaque_type( + &mut self, + goal: Goal<'tcx, ProjectionPredicate<'tcx>>, + ) -> QueryResult<'tcx> { + let tcx = self.tcx(); + let opaque_ty = goal.predicate.projection_ty; + let expected = goal.predicate.term.ty().unwrap(); + let mut candidates = Vec::new(); + + candidates.extend( + match goal.param_env.reveal() { + // Failing to reveal opaque types has to result in + // ambiguity during coherence. + Reveal::UserFacing => match self.solver_mode() { + SolverMode::Normal => Err(NoSolution), + SolverMode::Coherence => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + }, + Reveal::All => self.probe(|this| { + let actual = tcx.type_of(opaque_ty.def_id).subst(tcx, opaque_ty.substs); + this.eq(goal.param_env, expected, actual)?; + this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }), + } + .ok(), + ); + + for assumption in goal.param_env.caller_bounds().iter() { + match assumption.kind().skip_binder() { + ty::PredicateKind::DefineOpaque(env_opaque_ty, actual) => { + let result = self.probe(|this| { + this.eq(goal.param_env, opaque_ty, env_opaque_ty)?; + this.eq(goal.param_env, expected, actual)?; + this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }); + candidates.extend(result.ok()); + } + + ty::PredicateKind::Clause(_) + | ty::PredicateKind::WellFormed(_) + | ty::PredicateKind::ObjectSafe(_) + | ty::PredicateKind::ClosureKind(_, _, _) + | ty::PredicateKind::Subtype(_) + | ty::PredicateKind::Coerce(_) + | ty::PredicateKind::ConstEvaluatable(_) + | ty::PredicateKind::ConstEquate(_, _) + | ty::PredicateKind::TypeWellFormedFromEnv(_) + | ty::PredicateKind::Ambiguous + | ty::PredicateKind::AliasRelate(_, _, _) => {} + } + } + + if let Some(result) = self.try_merge_responses(&candidates) { + Ok(result) + } else { + self.flounder(&candidates) + } + } +} diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index f0840e0443c19..1199e68f17961 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -30,8 +30,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // `U` and equate it with `u32`. This means that we don't need a separate // projection cache in the solver. if self.term_is_fully_unconstrained(goal) { - let candidates = self.assemble_and_evaluate_candidates(goal); - self.merge_candidates(candidates) + match goal.predicate.projection_ty.kind(self.tcx()) { + ty::AliasKind::Projection => { + let candidates = self.assemble_and_evaluate_candidates(goal); + self.merge_candidates(candidates) + } + ty::AliasKind::Opaque => self.normalize_opaque_type(goal), + } } else { self.set_normalizes_to_hack_goal(goal); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index e82672e836870..a2d7bb17e106e 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -834,8 +834,10 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::Subtype(..) // FIXME(generic_const_exprs): you can absolutely add this as a where clauses | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} + | ty::PredicateKind::Coerce(..) => {} + ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => { + bug!("predicate should only exist in the environment: {bound_predicate:?}") + } ty::PredicateKind::Ambiguous => return false, }; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 69b3c1e7effbf..c3c8ea07b41ca 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1058,9 +1058,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"), - ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!( + ty::PredicateKind::DefineOpaque(..) + | ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!( span, - "TypeWellFormedFromEnv predicate should only exist in the environment" + "predicate should only exist in the environment: {bound_predicate:?}" ), ty::PredicateKind::AliasRelate(..) => span_bug!( diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 43196d1e6297d..7f4b52b21755c 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -365,6 +365,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, + ty::PredicateKind::DefineOpaque(..) => { + bug!("DefineOpaque should only be used as an assumption") + } ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } @@ -633,6 +636,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, + ty::PredicateKind::DefineOpaque(..) => { + bug!("DefineOpaque should only be used as an assumption") + } ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 384b6ae93a12a..053b8ca039a38 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -347,6 +347,7 @@ fn predicate_references_self<'tcx>( // FIXME(generic_const_exprs): this can mention `Self` | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } @@ -395,6 +396,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::AliasRelate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => false, }) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9890e990eebf0..ca76408fdda43 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -968,6 +968,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } + ty::PredicateKind::DefineOpaque(..) => { + bug!("DefineOpaque should only be used as an assumption") + } ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for chalk") } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 40e19abc0d06a..5bce2e30ef74e 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -182,6 +182,7 @@ pub fn predicate_obligations<'tcx>( | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}") } @@ -926,6 +927,7 @@ pub(crate) fn required_region_bounds<'tcx>( | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 4d225e36b22cd..7ba7090a9c7e9 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -138,6 +138,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), }; @@ -232,6 +233,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::ConstEquate(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) @@ -676,9 +678,10 @@ impl<'tcx> LowerInto<'tcx, Option { - bug!("unexpected predicate {}", &self) + bug!("unexpected predicate {self}") } }; value.map(|value| chalk_ir::Binders::new(binders, value)) @@ -812,6 +815,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index f5bba14d2fb9c..a9146c92d64a4 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -109,8 +109,9 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) + | ty::PredicateKind::DefineOpaque(..) + | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} // We need to search through *all* WellFormed predicates diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 5da0f16c2bf05..88be29e3c3381 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -69,6 +69,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => true, } diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 9d5a72a73cd49..4c3845d1f8542 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -32,6 +32,7 @@ pub mod instance; mod layout; mod layout_sanity_check; mod needs_drop; +mod opaque_types; pub mod representability; mod structural_match; mod ty; @@ -46,6 +47,7 @@ pub fn provide(providers: &mut Providers) { implied_bounds::provide(providers); layout::provide(providers); needs_drop::provide(providers); + opaque_types::provide(providers); representability::provide(providers); ty::provide(providers); instance::provide(providers); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs new file mode 100644 index 0000000000000..08b5e88c10ac1 --- /dev/null +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -0,0 +1,79 @@ +use rustc_hir::{def::DefKind, def_id::LocalDefId}; +use rustc_middle::ty::util::IgnoreRegions; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_type_ir::AliasKind; +use std::ops::ControlFlow; + +struct OpaqueTypeCollector<'tcx> { + tcx: TyCtxt<'tcx>, + opaques: Vec>, +} + +impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + match t.kind() { + ty::Alias(AliasKind::Opaque, alias_ty) => { + if self.tcx.uses_unique_generic_params(alias_ty.substs, IgnoreRegions::No).is_ok() { + self.opaques.push(t); + ControlFlow::Continue(()) + } else { + warn!(?t, "opaque types with non-unique params in sig: {t:?}"); + t.super_visit_with(self) + } + } + _ => t.super_visit_with(self), + } + } +} + +fn opaque_types_defined_by<'tcx>( + tcx: TyCtxt<'tcx>, + item: LocalDefId, +) -> ty::EarlyBinder<&'tcx ty::List>> { + // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT. + match tcx.def_kind(item) { + DefKind::Fn | DefKind::AssocFn => { + let sig = tcx.fn_sig(item).subst_identity(); + let mut collector = OpaqueTypeCollector { tcx, opaques: Vec::new() }; + sig.visit_with(&mut collector); + + let defined_opaques = tcx.mk_type_list(&collector.opaques); + ty::EarlyBinder(defined_opaques) + } + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::Const + | DefKind::ConstParam + | DefKind::Static(_) + | DefKind::Ctor(_, _) + | DefKind::AssocConst + | DefKind::Macro(_) + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Impl { .. } + | DefKind::Closure + | DefKind::Generator => ty::EarlyBinder(ty::List::empty()), + } +} + +pub(super) fn provide(providers: &mut ty::query::Providers) { + *providers = ty::query::Providers { opaque_types_defined_by, ..*providers }; +} diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index cb06c7acff02a..f7a023a5724eb 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -446,6 +446,36 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> ty::ParamEnv<'tcx> { + let param_env = tcx.param_env(def_id); + let typeck_results = tcx.typeck(def_id); + if typeck_results.defined_opaque_types.is_empty() { + param_env + } else { + let define_opaques = typeck_results + .defined_opaque_types + .iter() + .map(|defined_opaque_type| { + ty::PredicateKind::DefineOpaque( + defined_opaque_type.opaque_ty, + defined_opaque_type.hidden_ty, + ) + }) + .map(|kind| kind.to_predicate(tcx)); + + let param_env = ty::ParamEnv::new( + tcx.mk_predicates_from_iter(param_env.caller_bounds().iter().chain(define_opaques)), + param_env.reveal(), + param_env.constness(), + ); + + param_env + } +} + fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { tcx.param_env(def_id).with_reveal_all_normalized(tcx) } @@ -572,6 +602,7 @@ pub fn provide(providers: &mut ty::query::Providers) { asyncness, adt_sized_constraint, param_env, + param_env_body_post_hir_typeck, param_env_reveal_all_normalized, instance_def_size_estimate, issue33140_self_ty, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1531e7fc7b91d..41fa1312622a8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -320,6 +320,7 @@ pub(crate) fn clean_predicate<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::DefineOpaque(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index ecd712f32dc1f..1db49151077a3 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -21,35 +21,6 @@ type McfResult = Result<(), (Span, Cow<'static, str>)>; pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { let def_id = body.source.def_id(); - let mut current = def_id; - loop { - let predicates = tcx.predicates_of(current); - for (predicate, _) in predicates.predicates { - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause( - ty::Clause::RegionOutlives(_) - | ty::Clause::TypeOutlives(_) - | ty::Clause::Projection(_) - | ty::Clause::Trait(..) - | ty::Clause::ConstArgHasType(..), - ) - | ty::PredicateKind::WellFormed(_) - | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, - ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), - ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"), - ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"), - ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"), - ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"), - ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"), - } - } - match predicates.parent { - Some(parent) => current = parent, - None => break, - } - } for local in &body.local_decls { check_ty(tcx, local.ty, local.source_info.span)?;