diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 1ef1b39d4aab1..539328f801666 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -83,15 +83,15 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( for trait_projection in collector.types.into_iter().rev() { let impl_opaque_args = trait_projection.args.rebase_onto(tcx, trait_m.def_id, impl_m_args); - let hidden_ty = hidden_tys[&trait_projection.kind.def_id()] - .instantiate(tcx, impl_opaque_args) - .skip_norm_wip(); + let hidden_ty = + hidden_tys[&trait_projection.kind].instantiate(tcx, impl_opaque_args).skip_norm_wip(); // If the hidden type is not an opaque, then we have "refined" the trait signature. - let ty::Alias( - impl_opaque @ ty::AliasTy { kind: ty::Opaque { def_id: impl_opaque_def_id }, .. }, - ) = *hidden_ty.kind() - else { + let impl_opaque = if let ty::Alias(alias) = *hidden_ty.kind() + && let Some(impl_opaque) = alias.try_to_opaque() + { + impl_opaque + } else { report_mismatched_rpitit_signature( tcx, trait_m_sig_with_self_for_diag, @@ -105,7 +105,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( // This opaque also needs to be from the impl method -- otherwise, // it's a refinement to a TAIT. - if !tcx.hir_get_if_local(impl_opaque_def_id).is_some_and(|node| { + if !tcx.hir_get_if_local(impl_opaque.kind).is_some_and(|node| { matches!( node.expect_opaque_ty().origin, hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::FnReturn { parent, .. } @@ -124,13 +124,13 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( } trait_bounds.extend( - tcx.item_bounds(trait_projection.kind.def_id()) + tcx.item_bounds(trait_projection.kind) .iter_instantiated(tcx, trait_projection.args) .map(Unnormalized::skip_norm_wip), ); impl_bounds.extend(elaborate( tcx, - tcx.explicit_item_bounds(impl_opaque_def_id) + tcx.explicit_item_bounds(impl_opaque.kind) .iter_instantiated_copied(tcx, impl_opaque.args) .map(Unnormalized::skip_norm_wip), )); @@ -231,7 +231,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( // is literally unrepresentable in the type system; however, we may be // promising stronger outlives guarantees if we capture *fewer* regions. for (trait_projection, impl_opaque) in pairs { - let impl_variances = tcx.variances_of(impl_opaque.kind.def_id()); + let impl_variances = tcx.variances_of(impl_opaque.kind); let impl_captures: FxIndexSet<_> = impl_opaque .args .iter() @@ -240,7 +240,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( .map(|(arg, _)| arg) .collect(); - let trait_variances = tcx.variances_of(trait_projection.kind.def_id()); + let trait_variances = tcx.variances_of(trait_projection.kind); let mut trait_captures = FxIndexSet::default(); for (arg, variance) in trait_projection.args.iter().zip_eq(trait_variances) { if *variance != ty::Invariant { @@ -252,7 +252,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( if !trait_captures.iter().all(|arg| impl_captures.contains(arg)) { report_mismatched_rpitit_captures( tcx, - impl_opaque.kind.def_id().expect_local(), + impl_opaque.kind.expect_local(), trait_captures, is_internal, ); @@ -262,18 +262,19 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( struct ImplTraitInTraitCollector<'tcx> { tcx: TyCtxt<'tcx>, - types: FxIndexSet>, + types: FxIndexSet>, } impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) { - if let ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = *ty.kind() - && self.tcx.is_impl_trait_in_trait(def_id) + if let ty::Alias(alias) = *ty.kind() + && let Some(proj) = alias.try_to_projection() + && self.tcx.is_impl_trait_in_trait(proj.kind) { if self.types.insert(proj) { for (pred, _) in self .tcx - .explicit_item_bounds(def_id) + .explicit_item_bounds(proj.kind) .iter_instantiated_copied(self.tcx, proj.args) .map(Unnormalized::skip_norm_wip) { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 0b57b4e259a85..e1bbc8f0641de 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -89,7 +89,6 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_types_for_signature; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode, - Unnormalized, }; use rustc_middle::{bug, span_bug}; use rustc_session::errors::feature_err; @@ -487,21 +486,12 @@ fn fn_sig_suggestion<'tcx>( let mut output = sig.output(); let asyncness = if tcx.asyncness(assoc.def_id).is_async() { - output = if let ty::Alias(alias_ty) = *output.kind() - && let Some(output) = tcx - .explicit_item_self_bounds(alias_ty.kind.def_id()) - .iter_instantiated_copied(tcx, alias_ty.args) - .map(Unnormalized::skip_norm_wip) - .find_map(|(bound, _)| { - bound.as_projection_clause()?.no_bound_vars()?.term.as_type() - }) { - output - } else { + output = tcx.get_impl_future_output_ty(output).unwrap_or_else(|| { span_bug!( ident.span, "expected async fn to have `impl Future` output, but it returns {output}" ) - }; + }); "async " } else { "" diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 871aef76704e4..a0aa074d937b2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1359,7 +1359,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )? { TypeRelativePath::AssocItem(alias_term) => { let alias_ty = alias_term.expect_ty(); - let def_id = alias_ty.kind.def_id(); + let def_id = match alias_ty.kind { + ty::AliasTyKind::Projection { def_id } => def_id, + ty::AliasTyKind::Inherent { def_id } => def_id, + kind => bug!("expected projection or inherent alias, got {kind:?}"), + }; let ty = alias_ty.to_ty(tcx); let ty = self.check_param_uses_if_mcg(ty, span, false); Ok((ty, tcx.def_kind(def_id), def_id)) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4465bbc34a562..fa3fc32984a22 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2910,7 +2910,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base: &'tcx hir::Expr<'tcx>, ty: Ty<'tcx>, ) { - let Some(output_ty) = self.err_ctxt().get_impl_future_output_ty(ty) else { + let Some(output_ty) = self.tcx.get_impl_future_output_ty(ty) else { err.span_label(field_ident.span, "unknown field"); return; }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 24e2b030cdc72..84480fd57e3b5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1351,7 +1351,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars)); let ty = match self.tcx.asyncness(fn_id) { ty::Asyncness::Yes => { - self.err_ctxt().get_impl_future_output_ty(ty).unwrap_or_else(|| { + self.tcx.get_impl_future_output_ty(ty).unwrap_or_else(|| { span_bug!( fn_decl.output.span(), "failed to get output type of async function" diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5a1c85c21ca8c..0cad2fb705302 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3878,7 +3878,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, return_type: Option>, ) { - let Some(output_ty) = self.err_ctxt().get_impl_future_output_ty(ty) else { return }; + let Some(output_ty) = self.tcx.get_impl_future_output_ty(ty) else { return }; let output_ty = self.resolve_vars_if_possible(output_ty); let method_exists = self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type); diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index c23bc4adf914c..d1a56d5ab073c 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -380,7 +380,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { .map(|(k, h)| (k, h.ty)) .collect() } - fn opaques_with_sub_unified_hidden_type(&self, ty: ty::TyVid) -> Vec> { + fn opaques_with_sub_unified_hidden_type(&self, ty: ty::TyVid) -> Vec> { self.opaques_with_sub_unified_hidden_type(ty) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0d93e1478c420..033abf135a793 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1111,7 +1111,10 @@ impl<'tcx> InferCtxt<'tcx> { /// Searches for an opaque type key whose hidden type is related to `ty_vid`. /// /// This only checks for a subtype relation, it does not require equality. - pub fn opaques_with_sub_unified_hidden_type(&self, ty_vid: TyVid) -> Vec> { + pub fn opaques_with_sub_unified_hidden_type( + &self, + ty_vid: TyVid, + ) -> Vec> { // Avoid accidentally allowing more code to compile with the old solver. if !self.next_trait_solver() { return vec![]; @@ -1129,11 +1132,15 @@ impl<'tcx> InferCtxt<'tcx> { if let ty::Infer(ty::TyVar(hidden_vid)) = *hidden_ty.ty.kind() { let opaque_sub_vid = type_variables.sub_unification_table_root_var(hidden_vid); if opaque_sub_vid == ty_sub_vid { - return Some(ty::AliasTy::new_from_args( - self.tcx, - ty::Opaque { def_id: key.def_id.into() }, - key.args, - )); + return Some( + ty::AliasTy::new_from_args( + self.tcx, + ty::Opaque { def_id: key.def_id.into() }, + key.args, + ) + .try_to_opaque() + .unwrap(), + ); } } diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index b4594bd60f3ba..bd07bb7f91a27 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -59,8 +59,14 @@ where ty::Alias(ty::AliasTy { kind, args, .. }) => { let tcx = self.tcx; let param_env = self.param_env; + let def_id = match kind { + ty::AliasTyKind::Projection { def_id } + | ty::AliasTyKind::Inherent { def_id } + | ty::AliasTyKind::Opaque { def_id } + | ty::AliasTyKind::Free { def_id } => def_id, + }; let outlives_bounds: Vec<_> = tcx - .item_bounds(kind.def_id()) + .item_bounds(def_id) .iter_instantiated(tcx, args) .map(Unnormalized::skip_norm_wip) .chain(param_env.caller_bounds()) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 8484b7c222955..2c51128933c41 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -236,8 +236,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // And therefore we can safely use structural equality for alias types. (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {} (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {} - (GenericKind::Alias(a1), ty::Alias(a2)) if a1.kind.def_id() == a2.kind.def_id() => { - } + (GenericKind::Alias(a1), ty::Alias(a2)) if a1.kind == a2.kind => {} _ => return None, } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 346a26a685317..c290ba62a3930 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -385,7 +385,12 @@ fn def_id_of_type_cached<'a>(ty: Ty<'a>, visited: &mut SsoHashSet>) -> Op | ty::CoroutineWitness(def_id, _) | ty::Foreign(def_id) => Some(def_id), - ty::Alias(alias) => Some(alias.kind.def_id()), + ty::Alias(alias) => match alias.kind { + ty::AliasTyKind::Projection { def_id } + | ty::AliasTyKind::Inherent { def_id } + | ty::AliasTyKind::Opaque { def_id } + | ty::AliasTyKind::Free { def_id } => Some(def_id), + }, ty::Bool | ty::Char diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c6fa3801fb1bc..32d4678b8ecb8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2704,6 +2704,39 @@ impl<'tcx> TyCtxt<'tcx> { self.opt_rpitit_info(def_id).is_some() } + pub fn get_impl_future_output_ty(self, ty: Ty<'tcx>) -> Option> { + let (def_id, args) = match *ty.kind() { + ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => (def_id, args), + ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) + if self.is_impl_trait_in_trait(def_id) => + { + (def_id, args) + } + _ => return None, + }; + + let future_trait = self.require_lang_item(LangItem::Future, DUMMY_SP); + let item_def_id = self.associated_item_def_ids(future_trait)[0]; + + self.explicit_item_self_bounds(def_id) + .iter_instantiated_copied(self, args) + .map(ty::Unnormalized::skip_norm_wip) + .find_map(|(predicate, _)| { + predicate + .kind() + .map_bound(|kind| match kind { + ty::ClauseKind::Projection(projection_predicate) + if projection_predicate.def_id() == item_def_id => + { + projection_predicate.term.as_type() + } + _ => None, + }) + .no_bound_vars() + .flatten() + }) + } + /// Named module children from all kinds of items, including imports. /// In addition to regular items this list also includes struct and variant constructors, and /// items inside `extern {}` blocks because all of them introduce names into parent module. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3d8ab41b37a31..17b6640bfeb13 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -104,11 +104,12 @@ pub use self::region::{ EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionKind, RegionVid, }; pub use self::sty::{ - AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, - BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, - FnSigKind, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst, - PlaceholderRegion, PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, - TypingModeEqWrapper, Unnormalized, UpvarArgs, + Alias, AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, + BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, + FnSig, FnSigKind, FreeAliasTy, InherentAliasTy, InlineConstArgs, InlineConstArgsParts, + OpaqueAliasTy, ParamConst, ParamTy, PlaceholderConst, PlaceholderRegion, PlaceholderType, + PolyFnSig, ProjectionAliasTy, TyKind, TypeAndMut, TypingMode, TypingModeEqWrapper, + Unnormalized, UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1926930333629..be6505ea1ecb7 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1369,10 +1369,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { self.tcx().opt_rpitit_info(def_id) && let ty::Alias(alias_ty) = self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind() - && alias_ty.kind.def_id() == def_id + && let Some(projection_ty) = alias_ty.try_to_projection() + && projection_ty.kind == def_id && let generics = self.tcx().generics_of(fn_def_id) // FIXME(return_type_notation): We only support lifetime params for now. - && generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime)) + && generics + .own_params + .iter() + .all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime)) { let num_args = generics.count(); Some((fn_def_id, &args[..num_args])) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9db9b1769ab9c..93f0afda372f7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -38,6 +38,11 @@ pub type TyKind<'tcx> = ir::TyKind>; pub type TypeAndMut<'tcx> = ir::TypeAndMut>; pub type AliasTy<'tcx> = ir::AliasTy>; pub type AliasTyKind<'tcx> = ir::AliasTyKind>; +pub type Alias<'tcx, K> = ir::Alias, K>; +pub type ProjectionAliasTy<'tcx> = ir::ProjectionAliasTy>; +pub type InherentAliasTy<'tcx> = ir::InherentAliasTy>; +pub type OpaqueAliasTy<'tcx> = ir::OpaqueAliasTy>; +pub type FreeAliasTy<'tcx> = ir::FreeAliasTy>; pub type FnSig<'tcx> = ir::FnSig>; pub type FnSigKind<'tcx> = ir::FnSigKind>; pub type Binder<'tcx, T> = ir::Binder, T>; @@ -477,12 +482,22 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_alias(tcx: TyCtxt<'tcx>, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> { - debug_assert_matches!( - (alias_ty.kind, tcx.def_kind(alias_ty.kind.def_id())), - (ty::Opaque { .. }, DefKind::OpaqueTy) - | (ty::Projection { .. } | ty::Inherent { .. }, DefKind::AssocTy) - | (ty::Free { .. }, DefKind::TyAlias) - ); + if cfg!(debug_assertions) { + match alias_ty.kind { + ty::AliasTyKind::Projection { def_id } => { + debug_assert_matches!(tcx.def_kind(def_id), DefKind::AssocTy) + } + ty::AliasTyKind::Inherent { def_id } => { + debug_assert_matches!(tcx.def_kind(def_id), DefKind::AssocTy) + } + ty::AliasTyKind::Opaque { def_id } => { + debug_assert_matches!(tcx.def_kind(def_id), DefKind::OpaqueTy) + } + ty::AliasTyKind::Free { def_id } => { + debug_assert_matches!(tcx.def_kind(def_id), DefKind::TyAlias) + } + } + } Ty::new(tcx, Alias(alias_ty)) } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index d89f80eca8303..cc75197b4cf2d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -741,7 +741,7 @@ where candidates: &mut Vec>, consider_self_bounds: AliasBoundKind, ) -> Result<(), RerunNonErased> { - let alias_ty = match self_ty.kind() { + let (alias_ty, def_id) = match self_ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -789,9 +789,12 @@ where return Ok(()); } - ty::Alias( - alias_ty @ AliasTy { kind: ty::Projection { .. } | ty::Opaque { .. }, .. }, - ) => alias_ty, + ty::Alias(alias_ty @ AliasTy { kind: ty::Projection { def_id }, .. }) => { + (alias_ty, def_id.into()) + } + ty::Alias(alias_ty @ AliasTy { kind: ty::Opaque { def_id }, .. }) => { + (alias_ty, def_id.into()) + } ty::Alias(AliasTy { kind: ty::Inherent { .. } | ty::Free { .. }, .. }) => { self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF")); return Ok(()); @@ -802,7 +805,7 @@ where AliasBoundKind::SelfBounds => { for assumption in self .cx() - .item_self_bounds(alias_ty.kind.def_id()) + .item_self_bounds(def_id) .iter_instantiated(self.cx(), alias_ty.args) .map(Unnormalized::skip_norm_wip) { @@ -818,7 +821,7 @@ where AliasBoundKind::NonSelfBounds => { for assumption in self .cx() - .item_non_self_bounds(alias_ty.kind.def_id()) + .item_non_self_bounds(def_id) .iter_instantiated(self.cx(), alias_ty.args) .map(Unnormalized::skip_norm_wip) { @@ -835,12 +838,12 @@ where candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty)); - if !matches!(alias_ty.kind, ty::Projection { .. }) { + let Some(projection_ty) = alias_ty.try_to_projection() else { return Ok(()); - } + }; // Recurse on the self type of the projection. - match self.structurally_normalize_ty(goal.param_env, alias_ty.self_ty()) { + match self.structurally_normalize_ty(goal.param_env, projection_ty.projection_self_ty()) { Ok(next_self_ty) => self.assemble_alias_bound_candidates_recur( next_self_ty, goal, @@ -1072,12 +1075,12 @@ where return Ok(()); } - for &alias_ty in &opaque_types { - debug!("self ty is sub unified with {alias_ty:?}"); + for &opaque_ty in &opaque_types { + debug!("self ty is sub unified with {opaque_ty:?}"); struct ReplaceOpaque { cx: I, - alias_ty: ty::AliasTy, + opaque_ty: ty::OpaqueAliasTy, self_ty: I::Ty, } impl TypeFolder for ReplaceOpaque { @@ -1085,8 +1088,10 @@ where self.cx } fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { - if let ty::Alias(alias_ty) = ty.kind() { - if alias_ty == self.alias_ty { + if let ty::Alias(alias_ty) = ty.kind() + && let Some(opaque_ty) = alias_ty.try_to_opaque() + { + if opaque_ty == self.opaque_ty { return self.self_ty; } } @@ -1103,12 +1108,12 @@ where // in a `?x: Trait` alias-bound candidate. for item_bound in self .cx() - .item_self_bounds(alias_ty.kind.def_id()) - .iter_instantiated(self.cx(), alias_ty.args) + .item_self_bounds(opaque_ty.kind.into()) + .iter_instantiated(self.cx(), opaque_ty.args) .map(Unnormalized::skip_norm_wip) { let assumption = - item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), alias_ty, self_ty }); + item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), opaque_ty, self_ty }); candidates.extend(G::probe_and_match_goal_against_assumption( self, CandidateSource::AliasBound(AliasBoundKind::SelfBounds), diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 75ba3285e13f2..11c8202864a3a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -86,17 +86,24 @@ where let cx = ecx.cx(); let mut candidates = vec![]; - if !ecx.cx().alias_has_const_conditions(alias_ty.kind.def_id()) { + let def_id = match alias_ty.kind { + ty::AliasTyKind::Projection { def_id } => def_id.into(), + ty::AliasTyKind::Inherent { def_id } => def_id.into(), + ty::AliasTyKind::Opaque { def_id } => def_id.into(), + ty::AliasTyKind::Free { def_id } => def_id.into(), + }; + + if !ecx.cx().alias_has_const_conditions(def_id) { return vec![]; } for clause in elaborate::elaborate( cx, - cx.explicit_implied_const_bounds(alias_ty.kind.def_id()) - .iter_instantiated(cx, alias_ty.args) - .map(|trait_ref| { + cx.explicit_implied_const_bounds(def_id).iter_instantiated(cx, alias_ty.args).map( + |trait_ref| { trait_ref.to_host_effect_clause(cx, goal.predicate.constness).skip_norm_wip() - }), + }, + ), ) { candidates.extend(Self::probe_and_match_goal_against_assumption( ecx, @@ -107,16 +114,16 @@ where // Const conditions must hold for the implied const bound to hold. ecx.add_goals( GoalSource::AliasBoundConstCondition, - cx.const_conditions(alias_ty.kind.def_id()) - .iter_instantiated(cx, alias_ty.args) - .map(|trait_ref| { + cx.const_conditions(def_id).iter_instantiated(cx, alias_ty.args).map( + |trait_ref| { goal.with( cx, trait_ref .to_host_effect_clause(cx, goal.predicate.constness) .skip_norm_wip(), ) - }), + }, + ), ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 97aaf076a9d9a..f54166b06e9c9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1578,7 +1578,7 @@ where pub(crate) fn opaques_with_sub_unified_hidden_type( &self, self_ty: I::Ty, - ) -> Vec> { + ) -> Vec> { if let ty::Infer(ty::TyVar(vid)) = self_ty.kind() { self.delegate.opaques_with_sub_unified_hidden_type(vid) } else { diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 4218c21f508d3..f9ee9f4ee779e 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -32,10 +32,14 @@ impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> { cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::AliasTy { args, kind, .. } = self; - crate::ty::AliasTy { - def_id: tables.alias_def(kind.def_id()), - args: args.stable(tables, cx), - } + // rustc_public must change its API once we introduce a variant without a def_id. + let def_id = match *kind { + ty::AliasTyKind::Projection { def_id } + | ty::AliasTyKind::Inherent { def_id } + | ty::AliasTyKind::Opaque { def_id } + | ty::AliasTyKind::Free { def_id } => def_id, + }; + crate::ty::AliasTy { def_id: tables.alias_def(def_id), args: args.stable(tables, cx) } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 99594d68e7428..600bbe84691ef 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -56,7 +56,6 @@ use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPar use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_macros::extension; @@ -207,40 +206,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } - pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { - let (def_id, args) = match *ty.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => (def_id, args), - ty::Alias(ty::AliasTy { kind, args, .. }) - if self.tcx.is_impl_trait_in_trait(kind.def_id()) => - { - (kind.def_id(), args) - } - _ => return None, - }; - - let future_trait = self.tcx.require_lang_item(LangItem::Future, DUMMY_SP); - let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; - - self.tcx - .explicit_item_self_bounds(def_id) - .iter_instantiated_copied(self.tcx, args) - .map(Unnormalized::skip_norm_wip) - .find_map(|(predicate, _)| { - predicate - .kind() - .map_bound(|kind| match kind { - ty::ClauseKind::Projection(projection_predicate) - if projection_predicate.def_id() == item_def_id => - { - projection_predicate.term.as_type() - } - _ => None, - }) - .no_bound_vars() - .flatten() - }) - } - /// Adds a note if the types come from similarly named crates fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) -> bool { match terr { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 50eeb3a243266..c51016e779c4b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -126,12 +126,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { region_def_id: DefId, hir_sig: &hir::FnSig<'_>, ) -> Option { - let fn_ty = self.tcx().type_of(scope_def_id).instantiate_identity().skip_norm_wip(); + let tcx = self.tcx(); + let fn_ty = tcx.type_of(scope_def_id).instantiate_identity().skip_norm_wip(); if let ty::FnDef(_, _) = fn_ty.kind() { - let ret_ty = fn_ty.fn_sig(self.tcx()).output(); + let ret_ty = fn_ty.fn_sig(tcx).output(); let span = hir_sig.decl.output.span(); let future_output = if hir_sig.header.is_async() { - ret_ty.map_bound(|ty| self.cx.get_impl_future_output_ty(ty)).transpose() + ret_ty.map_bound(|ty| tcx.get_impl_future_output_ty(ty)).transpose() } else { None }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 236b5055dce80..7a6a6358ceb33 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -627,19 +627,19 @@ impl Trait for X { diag: &mut Diag<'_>, msg: impl Fn() -> String, body_owner_def_id: Option, - proj_ty: ty::AliasTy<'tcx>, + alias_ty: ty::AliasTy<'tcx>, ty: Ty<'tcx>, ) -> bool { let tcx = self.tcx; // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too. - if !matches!(proj_ty.kind, ty::AliasTyKind::Projection { .. }) { + let Some(proj_ty) = alias_ty.try_to_projection() else { return false; - } + }; let Some(body_owner_def_id) = body_owner_def_id else { return false; }; - let assoc = tcx.associated_item(proj_ty.kind.def_id()); - let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx); + let assoc = tcx.associated_item(proj_ty.kind); + let (trait_ref, assoc_args) = alias_ty.trait_ref_and_own_args(tcx); let Some(item) = tcx.hir_get_if_local(body_owner_def_id) else { return false; }; @@ -648,7 +648,7 @@ impl Trait for X { }; // Get the `DefId` for the type parameter corresponding to `A` in `::Foo`. // This will also work for `impl Trait`. - let ty::Param(param_ty) = *proj_ty.self_ty().kind() else { + let ty::Param(param_ty) = *alias_ty.self_ty().kind() else { return false; }; let generics = tcx.generics_of(body_owner_def_id); @@ -684,7 +684,7 @@ impl Trait for X { _ => return false, }; let parent = tcx.hir_get_parent_item(hir_id).def_id; - self.suggest_constraint(diag, msg, Some(parent.into()), proj_ty, ty) + self.suggest_constraint(diag, msg, Some(parent.into()), alias_ty, ty) } /// An associated type was expected and a different type was found. @@ -719,6 +719,10 @@ impl Trait for X { return; } + let (ty::Projection { def_id } | ty::Inherent { def_id }) = proj_ty.kind else { + panic!("expected projection or inherent alias, found {:?}", proj_ty.kind); + }; + let msg = || { format!( "consider constraining the associated type `{}` to `{}`", @@ -746,9 +750,9 @@ impl Trait for X { let point_at_assoc_fn = if callable_scope && self.point_at_methods_that_satisfy_associated_type( diag, - tcx.parent(proj_ty.kind.def_id()), + tcx.parent(def_id), current_method_ident, - proj_ty.kind.def_id(), + def_id, values.expected, ) { // If we find a suitable associated function that returns the expected type, we @@ -821,7 +825,11 @@ fn foo(&self) -> Self::T { String::new() } ) -> bool { let tcx = self.tcx; - let assoc = tcx.associated_item(proj_ty.kind.def_id()); + let (ty::Projection { def_id } | ty::Inherent { def_id }) = proj_ty.kind else { + panic!("expected projection or inherent alias, found {:?}", proj_ty.kind); + }; + + let assoc = tcx.associated_item(def_id); if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *proj_ty.self_ty().kind() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 516164bb2e58e..c20132ce93e8d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -190,8 +190,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let subdiag = match ( - self.get_impl_future_output_ty(exp_found.expected), - self.get_impl_future_output_ty(exp_found.found), + self.tcx.get_impl_future_output_ty(exp_found.expected), + self.tcx.get_impl_future_output_ty(exp_found.found), ) { (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause .code() diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index c3f4a09b2d431..905a32f19e346 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -128,7 +128,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( msg: &str, err: &mut Diag<'_, G>, fn_sig: Option<&hir::FnSig<'_>>, - projection: Option>, + projection: Option>, trait_pred: ty::PolyTraitPredicate<'tcx>, // When we are dealing with a trait, `super_traits` will be `Some`: // Given `trait T: A + B + C {}` @@ -140,11 +140,8 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( if hir_generics.where_clause_span.from_expansion() || hir_generics.where_clause_span.desugaring_kind().is_some() || projection.is_some_and(|projection| { - (tcx.is_impl_trait_in_trait(projection.kind.def_id()) - && !tcx.features().return_type_notation()) - || tcx - .lookup_stability(projection.kind.def_id()) - .is_some_and(|stab| stab.is_unstable()) + (tcx.is_impl_trait_in_trait(projection.kind) && !tcx.features().return_type_notation()) + || tcx.lookup_stability(projection.kind).is_some_and(|stab| stab.is_unstable()) }) { return; @@ -152,7 +149,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( let generics = tcx.generics_of(item_id); // Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`... if let Some((param, bound_str, fn_sig)) = - fn_sig.zip(projection).and_then(|(sig, p)| match *p.self_ty().kind() { + fn_sig.zip(projection).and_then(|(sig, p)| match *p.projection_self_ty().kind() { // Shenanigans to get the `Trait` from the `impl Trait`. ty::Param(param) => { let param_def = generics.type_param(param, tcx); @@ -479,8 +476,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let self_ty = trait_pred.skip_binder().self_ty(); let (param_ty, projection) = match *self_ty.kind() { ty::Param(_) => (true, None), - ty::Alias(projection @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => { - (false, Some(projection)) + ty::Alias(alias) => { + if let Some(projection) = alias.try_to_projection() { + (false, Some(projection)) + } else { + (false, None) + } } _ => (false, None), }; diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index b657992e2c7a0..2cbae17d69bcd 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -218,7 +218,7 @@ fn evaluate_host_effect_from_conditionally_const_item_bounds<'tcx>( if candidate.is_some() { return Err(EvaluationFailure::Ambiguous); } else { - candidate = Some((data, alias_ty)); + candidate = Some((data, alias_ty, def_id)); } } } @@ -231,12 +231,11 @@ fn evaluate_host_effect_from_conditionally_const_item_bounds<'tcx>( consider_ty = alias_ty.self_ty(); } - if let Some((data, alias_ty)) = candidate { + if let Some((data, alias_ty, def_id)) = candidate { Ok(match_candidate(selcx, obligation, data, true, |selcx, nested| { // An alias bound only holds if we also check the const conditions // of the alias, so we need to register those, too. - let const_conditions = - tcx.const_conditions(alias_ty.kind.def_id()).instantiate(tcx, alias_ty.args); + let const_conditions = tcx.const_conditions(def_id).instantiate(tcx, alias_ty.args); let const_conditions: Vec<_> = const_conditions .into_iter() .map(|(trait_ref, span)| { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 367e2e1b97059..504dedf8902fd 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -223,18 +223,14 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { } fn visit_ty(&mut self, ty: Ty<'tcx>) { - if let ty::Alias( - unshifted_alias_ty @ ty::AliasTy { - kind: ty::Projection { def_id: unshifted_alias_ty_def_id }, - .. - }, - ) = *ty.kind() + if let ty::Alias(unshifted_alias_ty) = *ty.kind() + && let Some(unshifted_alias_ty) = unshifted_alias_ty.try_to_projection() && let Some( ty::ImplTraitInTraitData::Trait { fn_def_id, .. } | ty::ImplTraitInTraitData::Impl { fn_def_id, .. }, - ) = self.tcx.opt_rpitit_info(unshifted_alias_ty_def_id) + ) = self.tcx.opt_rpitit_info(unshifted_alias_ty.kind) && fn_def_id == self.fn_def_id - && self.seen.insert(unshifted_alias_ty_def_id) + && self.seen.insert(unshifted_alias_ty.kind) { // We have entered some binders as we've walked into the // bounds of the RPITIT. Shift these binders back out when @@ -259,14 +255,14 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { // strategy, then just reinterpret the associated type like an opaque :^) let default_ty = self .tcx - .type_of(shifted_alias_ty.kind.def_id()) + .type_of(shifted_alias_ty.kind) .instantiate(self.tcx, shifted_alias_ty.args) .skip_norm_wip(); self.predicates.push( ty::Binder::bind_with_vars( ty::ProjectionPredicate { - projection_term: shifted_alias_ty.into(), + projection_term: shifted_alias_ty.projection_to_alias_ty().into(), term: default_ty.into(), }, self.bound_vars, @@ -280,7 +276,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { // easier to just do this. for bound in self .tcx - .item_bounds(unshifted_alias_ty_def_id) + .item_bounds(unshifted_alias_ty.kind) .iter_instantiated(self.tcx, unshifted_alias_ty.args) .map(Unnormalized::skip_norm_wip) { diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index e61e96c70f2e5..6c8735eb4e5ef 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -502,7 +502,10 @@ pub trait InferCtxtLike: Sized { &self, prev_entries: Self::OpaqueTypeStorageEntries, ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; - fn opaques_with_sub_unified_hidden_type(&self, ty: TyVid) -> Vec>; + fn opaques_with_sub_unified_hidden_type( + &self, + ty: TyVid, + ) -> Vec>; fn register_hidden_type_in_storage( &self, diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 82fa72825d4d4..51d8a8264ac97 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -81,7 +81,7 @@ pub use predicate_kind::*; pub use region_kind::*; pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy}; use rustc_type_ir_macros::GenericTypeVisitable; -pub use ty::{Alias, AliasTerm, AliasTy, UnevaluatedConst}; +pub use ty::{Alias, *}; pub use ty_info::*; pub use ty_kind::*; pub use unnormalized::Unnormalized; diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 2a1cbc3575d85..a346b83fac054 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -264,7 +264,14 @@ pub fn declared_bounds_from_definition( cx: I, alias_ty: AliasTy, ) -> impl Iterator { - let bounds = cx.item_self_bounds(alias_ty.kind.def_id()); + let def_id = match alias_ty.kind { + ty::AliasTyKind::Projection { def_id } => def_id.into(), + ty::AliasTyKind::Inherent { def_id } => def_id.into(), + ty::AliasTyKind::Opaque { def_id } => def_id.into(), + ty::AliasTyKind::Free { def_id } => def_id.into(), + }; + + let bounds = cx.item_self_bounds(def_id); bounds .iter_instantiated(cx, alias_ty.args) .map(Unnormalized::skip_norm_wip) diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 1ce09d7d5b5e8..bdf1efd04afc7 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -213,7 +213,7 @@ impl Relate for ty::AliasTy { a: ty::AliasTy, b: ty::AliasTy, ) -> RelateResult> { - if a.kind.def_id() != b.kind.def_id() { + if a.kind != b.kind { Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.kind.into(), b.kind.into()))) } else { let cx = relation.cx(); diff --git a/compiler/rustc_type_ir/src/ty/alias.rs b/compiler/rustc_type_ir/src/ty/alias.rs index d61c2f2ca7ff7..2ca563c4e7db8 100644 --- a/compiler/rustc_type_ir/src/ty/alias.rs +++ b/compiler/rustc_type_ir/src/ty/alias.rs @@ -53,4 +53,8 @@ impl Alias { pub type AliasTerm = Alias>; pub type AliasTy = Alias>; +pub type ProjectionAliasTy = Alias::TraitAssocTyId>; +pub type InherentAliasTy = Alias::InherentAssocTyId>; +pub type OpaqueAliasTy = Alias::OpaqueTyId>; +pub type FreeAliasTy = Alias::FreeTyAliasId>; pub type UnevaluatedConst = Alias>; diff --git a/compiler/rustc_type_ir/src/ty/mod.rs b/compiler/rustc_type_ir/src/ty/mod.rs index fec25193513c0..29cc14c1a2a8a 100644 --- a/compiler/rustc_type_ir/src/ty/mod.rs +++ b/compiler/rustc_type_ir/src/ty/mod.rs @@ -1,3 +1,3 @@ mod alias; -pub use alias::{Alias, AliasTerm, AliasTy, UnevaluatedConst}; +pub use alias::*; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index c3d52f4a191ac..442c46ffb57b2 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -20,7 +20,10 @@ use crate::inherent::*; use crate::ty::AliasTy; #[cfg(feature = "nightly")] use crate::visit::TypeVisitable; -use crate::{self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, UintTy}; +use crate::{ + self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, OpaqueAliasTy, ProjectionAliasTy, + UintTy, +}; mod closure; @@ -75,12 +78,19 @@ impl AliasTyKind { } } - pub fn def_id(self) -> I::DefId { + // note: there is no reason `try_to_inherent` and `try_to_free` don't exist other than that they + // would simply be unused at this point. make them if you want! + pub fn try_to_projection(self) -> Option { + match self { + AliasTyKind::Projection { def_id } => Some(def_id), + _ => None, + } + } + + pub fn try_to_opaque(self) -> Option { match self { - AliasTyKind::Projection { def_id } => def_id.into(), - AliasTyKind::Inherent { def_id } => def_id.into(), - AliasTyKind::Opaque { def_id } => def_id.into(), - AliasTyKind::Free { def_id } => def_id.into(), + AliasTyKind::Opaque { def_id } => Some(def_id), + _ => None, } } } @@ -430,7 +440,15 @@ impl fmt::Debug for TyKind { impl AliasTy { pub fn new_from_args(interner: I, kind: AliasTyKind, args: I::GenericArgs) -> AliasTy { - interner.debug_assert_args_compatible(kind.def_id(), args); + if cfg!(debug_assertions) { + let def_id = match kind { + AliasTyKind::Projection { def_id } => def_id.into(), + AliasTyKind::Inherent { def_id } => def_id.into(), + AliasTyKind::Opaque { def_id } => def_id.into(), + AliasTyKind::Free { def_id } => def_id.into(), + }; + interner.debug_assert_args_compatible(def_id, args); + } AliasTy { kind, args, _use_alias_new_instead: () } } @@ -451,6 +469,41 @@ impl AliasTy { pub fn to_ty(self, interner: I) -> I::Ty { Ty::new_alias(interner, self) } + + // note: there is no reason `try_to_inherent` and `try_to_free` don't exist other than that they + // would simply be unused at this point. make them if you want! + pub fn try_to_projection(self) -> Option> { + self.kind.try_to_projection().map(|kind| ty::Alias { + kind, + args: self.args, + _use_alias_new_instead: (), + }) + } + + pub fn try_to_opaque(self) -> Option> { + self.kind.try_to_opaque().map(|kind| ty::Alias { + kind, + args: self.args, + _use_alias_new_instead: (), + }) + } +} + +// note: there is no reason `inherent_to_alias_ty`, `opaque_to_alias_ty`, and `free_to_alias_ty` +// don't exist other than that they would simply be unused at this point. make them if you want! +impl ProjectionAliasTy { + pub fn projection_to_alias_ty(self) -> AliasTy { + AliasTy { + kind: AliasTyKind::Projection { def_id: self.kind }, + args: self.args, + _use_alias_new_instead: (), + } + } + + #[track_caller] + pub fn projection_self_ty(self) -> I::Ty { + self.args.type_at(0) + } } /// The following methods work only with (trait) associated type projections. diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index a3e982bb09430..2651be91cc449 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -16,7 +16,6 @@ use clippy_utils::ty::is_must_use_ty; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{is_entrypoint_fn, return_ty, trait_ref_of_method}; use rustc_span::Symbol; -use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use core::ops::ControlFlow; @@ -167,7 +166,7 @@ fn check_needless_must_use( // Ignore async functions unless Future::Output type is a must_use type if sig.header.is_async() { let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); - if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id)) + if let Some(future_ty) = infcx.tcx.get_impl_future_output_ty(return_ty(cx, item_id)) && !is_must_use_ty(cx, future_ty) { return; diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 331c6e23bddd7..d5b0cecf9e918 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -7,7 +7,6 @@ use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefIdSet; use rustc_span::{Span, sym}; -use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::ty::{AdtVariantInfo, approx_ty_size}; @@ -36,7 +35,7 @@ fn result_err_ty<'tcx>( .tcx .infer_ctxt() .build(cx.typing_mode()) - .err_ctxt() + .tcx .get_impl_future_output_ty(ty) { ty = future_output_ty; diff --git a/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs b/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs index 4b188709a8be3..34730dbb098c4 100644 --- a/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs +++ b/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs @@ -149,8 +149,11 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Iden } fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx PathSegment<'tcx>> { - if let ty::Alias(alias_ty) = ty.kind() - && let Some(Node::OpaqueTy(opaque)) = cx.tcx.hir_get_if_local(alias_ty.kind.def_id()) + if let ty::Alias(ty::AliasTy { + kind: ty::Opaque { def_id }, + .. + }) = *ty.kind() + && let Some(Node::OpaqueTy(opaque)) = cx.tcx.hir_get_if_local(def_id) && let OpaqueTyOrigin::AsyncFn { .. } = opaque.origin && let [GenericBound::Trait(trait_ref)] = &opaque.bounds && let Some(segment) = trait_ref.trait_ref.path.segments.last() diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 4f281d745a94e..62a192b7f770f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -247,11 +247,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty]) && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions( cx.typing_env(), - Unnormalized::new_wip(Ty::new_projection_from_args( - cx.tcx, - into_iter_item_proj.kind.def_id(), - into_iter_item_proj.args, - )), + Unnormalized::new_wip(Ty::new_alias(cx.tcx, into_iter_item_proj)), ) { iter_item_ty == into_iter_item_ty diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index f2a54b99170e9..36a13fa59e54b 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -13,7 +13,6 @@ use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::Span; -use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use std::ops::Deref; declare_clippy_lint! { @@ -166,7 +165,7 @@ impl NoEffect { .tcx .infer_ctxt() .build(cx.typing_mode()) - .err_ctxt() + .tcx .get_impl_future_output_ty(ret_ty) { ret_ty = true_ret_ty; diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 60d19ecf68bb5..8cded245fac22 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -20,8 +20,9 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, BoundVarIndexKind, FnSig, GenericArg, - GenericArgKind, GenericArgsRef, IntTy, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, UintTy, Unnormalized, Upcast, VariantDef, VariantDiscr, + GenericArgKind, GenericArgsRef, IntTy, ProjectionAliasTy, Region, RegionKind, TraitRef, Ty, TyCtxt, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Unnormalized, Upcast, VariantDef, + VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol}; @@ -669,12 +670,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option None, } }, - ty::Alias( - proj @ AliasTy { - kind: ty::Projection { .. }, - .. - }, - ) => match cx + ty::Alias(alias) if let Some(proj) = alias.try_to_projection() => match cx .tcx .try_normalize_erasing_regions(cx.typing_env(), Unnormalized::new_wip(ty)) { @@ -728,14 +724,14 @@ fn sig_from_bounds<'tcx>( inputs.map(|ty| ExprFnSig::Trait(ty, output, predicates_id)) } -fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option> { +fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionAliasTy<'tcx>) -> Option> { let mut inputs = None; let mut output = None; let lang_items = cx.tcx.lang_items(); for (pred, _) in cx .tcx - .explicit_item_bounds(ty.kind.def_id()) + .explicit_item_bounds(ty.kind) .iter_instantiated_copied(cx.tcx, ty.args) .map(Unnormalized::skip_norm_wip) { @@ -1097,10 +1093,7 @@ pub fn make_normalized_projection<'tcx>( ); return None; } - match tcx.try_normalize_erasing_regions( - typing_env, - Unnormalized::new_wip(Ty::new_projection_from_args(tcx, ty.kind.def_id(), ty.args)), - ) { + match tcx.try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(Ty::new_alias(tcx, ty))) { Ok(ty) => Some(ty), Err(e) => { debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); @@ -1254,10 +1247,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( } let cause = ObligationCause::dummy(); let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); - match infcx - .at(&cause, param_env) - .query_normalize(Ty::new_projection_from_args(tcx, ty.kind.def_id(), ty.args)) - { + match infcx.at(&cause, param_env).query_normalize(Ty::new_alias(tcx, ty)) { Ok(ty) => Some(ty.value), Err(e) => { debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");