diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 28c5c505f79..46011c1f43e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -1010,7 +1010,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { clauses.iter().any(|pred| { match pred.kind().skip_binder() { ty::ClauseKind::Trait(data) if data.self_ty() == ty => {} - ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {} + ty::ClauseKind::Projection(data) + if data.projection_term.self_ty() == ty => {} _ => return false, } tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region)) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index db223f9d80f..0a6aa751ed7 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2205,7 +2205,7 @@ fn param_env_with_gat_bounds<'tcx>( _ => predicates.push( ty::Binder::bind_with_vars( ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args), + projection_term: ty::AliasTerm::new(tcx, trait_ty.def_id, rebased_args), term: normalize_impl_ty.into(), }, bound_vars, diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index eb0ffc19d45..c7462a6ee49 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -343,9 +343,10 @@ fn bounds_from_generic_predicates<'tcx>( let mut projections_str = vec![]; for projection in &projections { let p = projection.skip_binder(); - let alias_ty = p.projection_ty; - if bound == tcx.parent(alias_ty.def_id) && alias_ty.self_ty() == ty { - let name = tcx.item_name(alias_ty.def_id); + if bound == tcx.parent(p.projection_term.def_id) + && p.projection_term.self_ty() == ty + { + let name = tcx.item_name(p.projection_term.def_id); projections_str.push(format!("{} = {}", name, p.term)); } } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 02291cc603e..67f578373e0 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -39,7 +39,7 @@ fn associated_type_bounds<'tcx>( let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| { match pred.kind().skip_binder() { ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty, - ty::ClauseKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty, + ty::ClauseKind::Projection(proj) => proj.projection_term.self_ty() == item_ty, ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty, _ => false, } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 7e82571d172..8948e60b6dc 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -445,7 +445,9 @@ pub(super) fn explicit_predicates_of<'tcx>( .copied() .filter(|(pred, _)| match pred.kind().skip_binder() { ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()), - ty::ClauseKind::Projection(proj) => !is_assoc_item_ty(proj.projection_ty.self_ty()), + ty::ClauseKind::Projection(proj) => { + !is_assoc_item_ty(proj.projection_term.self_ty()) + } ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0), _ => true, }) diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 3b8bb0731fb..ccf0c7bf2c1 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -197,7 +197,7 @@ pub fn setup_constraining_predicates<'tcx>( // Special case: watch out for some kind of sneaky attempt // to project out an associated type defined by this very // trait. - let unbound_trait_ref = projection.projection_ty.trait_ref(tcx); + let unbound_trait_ref = projection.projection_term.trait_ref(tcx); if Some(unbound_trait_ref) == impl_trait_ref { continue; } @@ -207,7 +207,7 @@ pub fn setup_constraining_predicates<'tcx>( // `<::Baz as Iterator>::Output = ::Output` // Then the projection only applies if `T` is known, but it still // does not determine `U`. - let inputs = parameters_for(tcx, projection.projection_ty, true); + let inputs = parameters_for(tcx, projection.projection_term, true); let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p)); if !relies_only_on_inputs { continue; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index de12475678c..41e3abd7451 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -326,7 +326,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) .or_insert(binding.span); - let projection_ty = if let ty::AssocKind::Fn = assoc_kind { + let projection_term = if let ty::AssocKind::Fn = assoc_kind { let mut emitted_bad_param_err = None; // If we have an method return type bound, then we need to instantiate // the method's early bound params with suitable late-bound params. @@ -380,7 +380,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() && tcx.is_impl_trait_in_trait(alias_ty.def_id) { - alias_ty + alias_ty.into() } else { return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit { span: binding.span, @@ -424,7 +424,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Note that we're indeed also using `AliasTy` (alias *type*) for associated // *constants* to represent *const projections*. Alias *term* would be a more // appropriate name but alas. - ty::AliasTy::new(tcx, assoc_item.def_id, alias_args) + ty::AliasTerm::new(tcx, assoc_item.def_id, alias_args) }); // Provide the resolved type of the associated constant to `type_of(AnonConst)`. @@ -461,7 +461,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // for<'a> ::Item = &'a str // <-- 'a is bad // for<'a> >::Output = &'a str // <-- 'a is ok let late_bound_in_projection_ty = - tcx.collect_constrained_late_bound_regions(projection_ty); + tcx.collect_constrained_late_bound_regions(projection_term); let late_bound_in_term = tcx.collect_referenced_late_bound_regions(trait_ref.rebind(term)); debug!(?late_bound_in_projection_ty); @@ -490,8 +490,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds.push_projection_bound( tcx, - projection_ty - .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), + projection_term.map_bound(|projection_term| ty::ProjectionPredicate { + projection_term, + term, + }), binding.span, ); } @@ -501,6 +503,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into // a trait predicate, since we only want to add predicates for the `Self` type. if !only_self_bounds.0 { + let projection_ty = projection_term + .map_bound(|projection_term| projection_term.expect_ty(self.tcx())); // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty` // parameter to have a skipped binder. let param_ty = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder()); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 38dfa8d57d3..8f68a670d01 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -627,23 +627,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { let pred = bound_predicate.rebind(pred); // `::Item = String`. - let projection_ty = pred.skip_binder().projection_ty; + let projection_term = pred.skip_binder().projection_term; let args_with_infer_self = tcx.mk_args_from_iter( std::iter::once(Ty::new_var(tcx, ty::TyVid::ZERO).into()) - .chain(projection_ty.args.iter().skip(1)), + .chain(projection_term.args.iter().skip(1)), ); let quiet_projection_ty = - ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self); + ty::AliasTerm::new(tcx, projection_term.def_id, args_with_infer_self); let term = pred.skip_binder().term; - let obligation = format!("{projection_ty} = {term}"); + let obligation = format!("{projection_term} = {term}"); let quiet = format!("{quiet_projection_ty} = {term}"); - bound_span_label(projection_ty.self_ty(), &obligation, &quiet); - Some((obligation, projection_ty.self_ty())) + bound_span_label(projection_term.self_ty(), &obligation, &quiet); + Some((obligation, projection_term.self_ty())) } ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => { let p = poly_trait_ref.trait_ref; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 37d4d4ec355..a64a7a2e5bd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -280,11 +280,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let existential_projections = projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); + assert_eq!(b.projection_term.self_ty(), dummy_self); // Like for trait refs, verify that `dummy_self` did not leak inside default type // parameters. - let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { + let references_self = b.projection_term.args.iter().skip(1).any(|arg| { if arg.walk().any(|arg| arg == dummy_self.into()) { return true; } @@ -294,7 +294,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let guar = tcx .dcx() .span_delayed_bug(span, "trait object projection bounds reference `Self`"); - b.projection_ty = replace_dummy_self_with_error(tcx, b.projection_ty, guar); + b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar); } ty::ExistentialProjection::erase_self_ty(tcx, b) 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 6dd59a62a7a..61357d6504c 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 @@ -258,23 +258,23 @@ fn unconstrained_parent_impl_args<'tcx>( // unconstrained parameters. for (clause, _) in impl_generic_predicates.predicates.iter() { if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() { - let projection_ty = proj.projection_ty; - let projected_ty = proj.term; + let projection_term = proj.projection_term; + let projected_term = proj.term; - let unbound_trait_ref = projection_ty.trait_ref(tcx); + let unbound_trait_ref = projection_term.trait_ref(tcx); if Some(unbound_trait_ref) == impl_trait_ref { continue; } - unconstrained_parameters.extend(cgp::parameters_for(tcx, projection_ty, true)); + unconstrained_parameters.extend(cgp::parameters_for(tcx, projection_term, true)); - for param in cgp::parameters_for(tcx, projected_ty, false) { + for param in cgp::parameters_for(tcx, projected_term, false) { if !unconstrained_parameters.contains(¶m) { constrained_params.insert(param.0); } } - unconstrained_parameters.extend(cgp::parameters_for(tcx, projected_ty, true)); + unconstrained_parameters.extend(cgp::parameters_for(tcx, projected_term, true)); } } @@ -495,11 +495,11 @@ fn check_specialization_on<'tcx>( .emit()) } } - ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => Err(tcx + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_term, term }) => Err(tcx .dcx() .struct_span_err( span, - format!("cannot specialize on associated type `{projection_ty} == {term}`",), + format!("cannot specialize on associated type `{projection_term} == {term}`",), ) .emit()), ty::ClauseKind::ConstArgHasType(..) => { diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 27fdea01c2b..cfc7ecf8580 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -166,7 +166,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc } } ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty: ty::AliasTy { args, .. }, + projection_term: ty::AliasTerm { args, .. }, term, }) => { for arg in &args[1..] { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index defb557867b..fe2a335c016 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -574,7 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.misc(span), self.param_env, ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new( + projection_term: ty::AliasTerm::new( self.tcx, fn_once_output_def_id, [arg_ty.into(), fn_sig.inputs()[0].into(), const_param], diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index f52f95db6d3..4a308d85c8d 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -414,7 +414,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // many viable options, so pick the most restrictive. let trait_def_id = match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { - Some(data.projection_ty.trait_def_id(self.tcx)) + Some(data.projection_term.trait_def_id(self.tcx)) } ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => Some(data.def_id()), _ => None, @@ -475,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => return None, } - let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1); + let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1); let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); debug!(?arg_param_ty); @@ -930,7 +930,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Check that this is a projection from the `Future` trait. - let trait_def_id = predicate.projection_ty.trait_def_id(self.tcx); + let trait_def_id = predicate.projection_term.trait_def_id(self.tcx); let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(cause_span)); if trait_def_id != future_trait { debug!("deduce_future_output_from_projection: not a future"); @@ -940,11 +940,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The `Future` trait has only one associated item, `Output`, // so check that this is what we see. let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0]; - if output_assoc_item != predicate.projection_ty.def_id { + if output_assoc_item != predicate.projection_term.def_id { span_bug!( cause_span, "projecting associated item `{:?}` from future, which is not Output `{:?}`", - predicate.projection_ty.def_id, + predicate.projection_term.def_id, output_assoc_item, ); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index c3525f175da..4edc11d7ab1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -37,7 +37,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ClauseKind::Trait(pred) => { (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) } - ty::ClauseKind::Projection(pred) => (pred.projection_ty.args.to_vec(), None), + ty::ClauseKind::Projection(pred) => (pred.projection_term.args.to_vec(), None), ty::ClauseKind::ConstArgHasType(arg, ty) => (vec![ty.into(), arg.into()], None), ty::ClauseKind::ConstEvaluatable(e) => (vec![e.into()], None), _ => return false, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 2ef254f644f..ac1e26df870 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.type_matches_expected_vid(expected_vid, data.self_ty()) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { - self.type_matches_expected_vid(expected_vid, data.projection_ty.self_ty()) + self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty()) } ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 0483bd03576..6d931d15008 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => { + ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::Opaque, _) => { for unsatisfied in unsatisfied_predicates.iter() { if is_iterator_predicate(unsatisfied.0, self.tcx) { return true; @@ -787,26 +787,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { let pred = bound_predicate.rebind(pred); // `::Item = String`. - let projection_ty = pred.skip_binder().projection_ty; + let projection_term = pred.skip_binder().projection_term; let args_with_infer_self = tcx.mk_args_from_iter( iter::once(Ty::new_var(tcx, ty::TyVid::ZERO).into()) - .chain(projection_ty.args.iter().skip(1)), + .chain(projection_term.args.iter().skip(1)), ); - let quiet_projection_ty = - ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self); + let quiet_projection_term = + ty::AliasTerm::new(tcx, projection_term.def_id, args_with_infer_self); let term = pred.skip_binder().term; - let obligation = format!("{projection_ty} = {term}"); + let obligation = format!("{projection_term} = {term}"); let quiet = with_forced_trimmed_paths!(format!( "{} = {}", - quiet_projection_ty, term + quiet_projection_term, term )); - bound_span_label(projection_ty.self_ty(), &obligation, &quiet); - Some((obligation, projection_ty.self_ty())) + bound_span_label(projection_term.self_ty(), &obligation, &quiet); + Some((obligation, projection_term.self_ty())) } ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => { let p = poly_trait_ref.trait_ref; diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 0f21d3966c4..830d472e1b8 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -430,6 +430,20 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { } impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> { + fn to_trace( + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Self, + b: Self, + ) -> TypeTrace<'tcx> { + TypeTrace { + cause: cause.clone(), + values: Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())), + } + } +} + +impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> { fn to_trace( cause: &ObligationCause<'tcx>, a_is_expected: bool, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 3488517a4ef..f17bc2f0ae1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -410,7 +410,7 @@ impl<'tcx> InferCtxt<'tcx> { .kind() .map_bound(|kind| match kind { ty::ClauseKind::Projection(projection_predicate) - if projection_predicate.projection_ty.def_id == item_def_id => + if projection_predicate.projection_term.def_id == item_def_id => { projection_predicate.term.ty() } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index ce82296a8aa..0a7f2369a83 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -403,7 +403,7 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { pub enum ValuePairs<'tcx> { Regions(ExpectedFound>), Terms(ExpectedFound>), - Aliases(ExpectedFound>), + Aliases(ExpectedFound>), TraitRefs(ExpectedFound>), PolySigs(ExpectedFound>), ExistentialTraitRef(ExpectedFound>), diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 703bd5ae90b..8eb3185673b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -588,7 +588,7 @@ impl<'tcx> InferCtxt<'tcx> { && !tcx.is_impl_trait_in_trait(projection_ty.def_id) && !self.next_trait_solver() => { - self.infer_projection( + self.projection_ty_to_infer( param_env, projection_ty, cause.clone(), diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index 041838ffc16..16786347980 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -12,7 +12,7 @@ impl<'tcx> InferCtxt<'tcx> { /// of the given projection. This allows us to proceed with projections /// while they cannot be resolved yet due to missing information or /// simply due to the lack of access to the trait resolution machinery. - pub fn infer_projection( + pub fn projection_ty_to_infer( &self, param_env: ty::ParamEnv<'tcx>, projection_ty: ty::AliasTy<'tcx>, @@ -24,7 +24,7 @@ impl<'tcx> InferCtxt<'tcx> { let def_id = projection_ty.def_id; let ty_var = self.next_ty_var(self.tcx.def_span(def_id)); let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection( - ty::ProjectionPredicate { projection_ty, term: ty_var.into() }, + ty::ProjectionPredicate { projection_term: projection_ty.into(), term: ty_var.into() }, ))); let obligation = Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 5880ca788bc..e7ed2fe9b49 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -101,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> { // instead create a new inference variable `?normalized_source`, emitting // `Projection(normalized_source, ?ty_normalized)` and `?normalized_source <: generalized_ty`. relation.register_predicates([ty::ProjectionPredicate { - projection_ty: data, + projection_term: data.into(), term: generalized_ty.into(), }]); } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 85510cf2dcc..f77a92bf9bc 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -27,7 +27,7 @@ pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::project::MismatchedProjectionTypes; pub(crate) use self::project::UndoLog; pub use self::project::{ - Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey, + Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey, ProjectionCacheStorage, Reveal, }; pub use rustc_middle::traits::*; diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index c6ffba59638..c1cfa5ca6b7 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -8,7 +8,7 @@ use rustc_data_structures::{ snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage}, undo_log::Rollback, }; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty; pub use rustc_middle::traits::{EvaluationResult, Reveal}; @@ -26,7 +26,7 @@ pub struct Normalized<'tcx, T> { pub obligations: Vec>, } -pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>; +pub type NormalizedTerm<'tcx> = Normalized<'tcx, ty::Term<'tcx>>; impl<'tcx, T> Normalized<'tcx, T> { pub fn with(self, value: U) -> Normalized<'tcx, U> { @@ -77,13 +77,13 @@ pub struct ProjectionCacheStorage<'tcx> { #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ProjectionCacheKey<'tcx> { - ty: ty::AliasTy<'tcx>, + term: ty::AliasTerm<'tcx>, param_env: ty::ParamEnv<'tcx>, } impl<'tcx> ProjectionCacheKey<'tcx> { - pub fn new(ty: ty::AliasTy<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - Self { ty, param_env } + pub fn new(term: ty::AliasTerm<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { + Self { term, param_env } } } @@ -94,7 +94,7 @@ pub enum ProjectionCacheEntry<'tcx> { Recur, Error, NormalizedTy { - ty: Normalized<'tcx, ty::Term<'tcx>>, + ty: NormalizedTerm<'tcx>, /// If we were able to successfully evaluate the /// corresponding cache entry key during predicate /// evaluation, then this field stores the final @@ -175,11 +175,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { } /// Indicates that `key` was normalized to `value`. - pub fn insert_term( - &mut self, - key: ProjectionCacheKey<'tcx>, - value: Normalized<'tcx, ty::Term<'tcx>>, - ) { + pub fn insert_term(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTerm<'tcx>) { debug!( "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}", key, value diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 1d2e12ec575..eda40e4a011 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -107,8 +107,11 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { return; } - let proj_ty = - Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); + let proj_ty = Ty::new_projection( + cx.tcx, + proj.projection_term.def_id, + proj.projection_term.args, + ); // For every instance of the projection type in the bounds, // replace them with the term we're assigning to the associated // type in our opaque type. @@ -123,8 +126,8 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // with `impl Send: OtherTrait`. for (assoc_pred, assoc_pred_span) in cx .tcx - .explicit_item_bounds(proj.projection_ty.def_id) - .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) + .explicit_item_bounds(proj.projection_term.def_id) + .iter_instantiated_copied(cx.tcx, proj.projection_term.args) { let assoc_pred = assoc_pred.fold_with(proj_replacer); let Ok(assoc_pred) = traits::fully_normalize( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f9d1a77c3d9..e831db1a41b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -132,6 +132,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>; type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>; type ProjectionPredicate = ty::ProjectionPredicate<'tcx>; + type AliasTerm = ty::AliasTerm<'tcx>; type NormalizesTo = ty::NormalizesTo<'tcx>; type SubtypePredicate = ty::SubtypePredicate<'tcx>; type CoercePredicate = ty::CoercePredicate<'tcx>; diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 0dc835671d5..4de7d532c96 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -294,10 +294,10 @@ impl FlagComputation { self.add_ty(b); } ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty, + projection_term, term, })) => { - self.add_alias_ty(projection_ty); + self.add_alias_term(projection_term); self.add_term(term); } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { @@ -313,7 +313,7 @@ impl FlagComputation { } ty::PredicateKind::Ambiguous => {} ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => { - self.add_alias_ty(alias); + self.add_alias_term(alias); self.add_term(term); } ty::PredicateKind::AliasRelate(t1, t2, _) => { @@ -410,6 +410,10 @@ impl FlagComputation { self.add_args(alias_ty.args); } + fn add_alias_term(&mut self, alias_term: ty::AliasTerm<'_>) { + self.add_args(alias_term.args); + } + fn add_args(&mut self, args: &[GenericArg<'_>]) { for kind in args { match kind.unpack() { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4d3b92bf2af..02f6f4da4f1 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -110,11 +110,11 @@ pub use self::region::{ }; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ - AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, - ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, - CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs, - InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, - VarianceDiagInfo, + AliasTerm, AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, + CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, + CoroutineClosureArgs, CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, + InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, + UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -630,14 +630,14 @@ impl<'tcx> Term<'tcx> { } /// This function returns the inner `AliasTy` for a `ty::Alias` or `ConstKind::Unevaluated`. - pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option> { + pub fn to_alias_term(self) -> Option> { match self.unpack() { TermKind::Ty(ty) => match *ty.kind() { - ty::Alias(_kind, alias_ty) => Some(alias_ty), + ty::Alias(_kind, alias_ty) => Some(alias_ty.into()), _ => None, }, TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(AliasTy::new(tcx, uv.def, uv.args)), + ConstKind::Unevaluated(uv) => Some(uv.into()), _ => None, }, } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index c1de23b2498..e78856517b2 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -503,7 +503,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { /// Returns the `DefId` of the trait of the associated item being projected. #[inline] pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - self.skip_binder().projection_ty.trait_def_id(tcx) + self.skip_binder().projection_term.trait_def_id(tcx) } /// Get the [PolyTraitRef] required for this projection to be well formed. @@ -516,7 +516,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { // This is because here `self` has a `Binder` and so does our // return value, so we are preserving the number of binding // levels. - self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) + self.map_bound(|predicate| predicate.projection_term.trait_ref(tcx)) } pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { @@ -529,7 +529,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. pub fn projection_def_id(&self) -> DefId { // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().projection_ty.def_id + self.skip_binder().projection_term.def_id } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index be9525a083c..edd5bef33d5 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1277,7 +1277,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { fn pretty_print_inherent_projection( &mut self, - alias_ty: ty::AliasTy<'tcx>, + alias_ty: ty::AliasTerm<'tcx>, ) -> Result<(), PrintError> { let def_key = self.tcx().def_key(alias_ty.def_id); self.path_generic_args( @@ -3111,7 +3111,7 @@ define_print! { } ty::ProjectionPredicate<'tcx> { - p!(print(self.projection_ty), " == "); + p!(print(self.projection_term), " == "); cx.reset_type_limit(); p!(print(self.term)) } @@ -3206,20 +3206,28 @@ define_print_and_forward_display! { } ty::AliasTy<'tcx> { - if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) { - p!(pretty_print_inherent_projection(*self)) - } else { - // If we're printing verbosely, or don't want to invoke queries - // (`is_impl_trait_in_trait`), then fall back to printing the def path. - // This is likely what you want if you're debugging the compiler anyways. - if !(cx.should_print_verbose() || with_reduced_queries()) - && cx.tcx().is_impl_trait_in_trait(self.def_id) - { - return cx.pretty_print_opaque_impl_type(self.def_id, self.args); - } else { - p!(print_def_path(self.def_id, self.args)); - } + let alias_term: ty::AliasTerm<'tcx> = (*self).into(); + p!(print(alias_term)) + } + ty::AliasTerm<'tcx> { + match self.kind(cx.tcx()) { + ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)), + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::WeakTy + | ty::AliasTermKind::OpaqueTy + | ty::AliasTermKind::UnevaluatedConst => { + // If we're printing verbosely, or don't want to invoke queries + // (`is_impl_trait_in_trait`), then fall back to printing the def path. + // This is likely what you want if you're debugging the compiler anyways. + if !(cx.should_print_verbose() || with_reduced_queries()) + && cx.tcx().is_impl_trait_in_trait(self.def_id) + { + return cx.pretty_print_opaque_impl_type(self.def_id, self.args); + } else { + p!(print_def_path(self.def_id, self.args)); + } + } } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 417edda10ca..32d420f96a2 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -246,6 +246,34 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> { } } +impl<'tcx> Relate<'tcx> for ty::AliasTerm<'tcx> { + fn relate>( + relation: &mut R, + a: ty::AliasTerm<'tcx>, + b: ty::AliasTerm<'tcx>, + ) -> RelateResult<'tcx, ty::AliasTerm<'tcx>> { + if a.def_id != b.def_id { + Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id))) + } else { + let args = match relation.tcx().def_kind(a.def_id) { + DefKind::OpaqueTy => relate_args_with_variances( + relation, + a.def_id, + relation.tcx().variances_of(a.def_id), + a.args, + b.args, + false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle + )?, + DefKind::AssocTy | DefKind::AssocConst | DefKind::TyAlias => { + relate_args_invariantly(relation, a.args, b.args)? + } + def => bug!("unknown alias DefKind: {def:?}"), + }; + Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args)) + } + } +} + impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { fn relate>( relation: &mut R, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index dc071b295aa..6abd685343b 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -410,7 +410,7 @@ TrivialTypeTraversalImpls! { crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, - crate::ty::AliasKind, + crate::ty::AliasTyKind, crate::ty::Placeholder, crate::ty::Placeholder, crate::ty::Placeholder, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1fc8eefd65f..7aca09c5cfb 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -22,7 +22,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi::{self, Abi}; -use std::assert_matches::debug_assert_matches; +use std::assert_matches::{assert_matches, debug_assert_matches}; use std::borrow::Cow; use std::iter; use std::ops::{ControlFlow, Deref, Range}; @@ -1105,7 +1105,228 @@ where } } -/// Represents the projection of an associated type. +/// Represents the unprojected term of a projection goal. +/// +/// * For a projection, this would be `>::N<...>`. +/// * For an inherent projection, this would be `Ty::N<...>`. +/// * For an opaque type, there is no explicit syntax. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct AliasTerm<'tcx> { + /// The parameters of the associated or opaque item. + /// + /// For a projection, these are the generic parameters for the trait and the + /// GAT parameters, if there are any. + /// + /// For an inherent projection, they consist of the self type and the GAT parameters, + /// if there are any. + /// + /// For RPIT the generic parameters are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. + pub args: GenericArgsRef<'tcx>, + + /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether + /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if + /// this is an opaque. + /// + /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the + /// underlying type if the type is an opaque. + /// + /// Note that if this is an associated type, this is not the `DefId` of the + /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`, + /// aka. `tcx.parent(def_id)`. + pub def_id: DefId, + + /// This field exists to prevent the creation of `AliasTy` without using + /// [AliasTy::new]. + _use_alias_term_new_instead: (), +} + +// FIXME: Remove these when we uplift `AliasTerm` +use crate::ty::{DebugWithInfcx, InferCtxtLike, WithInfcx}; +impl<'tcx> std::fmt::Debug for AliasTerm<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + WithInfcx::with_no_infcx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx> for AliasTerm<'tcx> { + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + f.debug_struct("AliasTerm") + .field("args", &this.map(|data| data.args)) + .field("def_id", &this.data.def_id) + .finish() + } +} + +impl<'tcx> rustc_type_ir::inherent::AliasTerm> for AliasTerm<'tcx> { + fn new( + interner: TyCtxt<'tcx>, + trait_def_id: DefId, + args: impl IntoIterator>>, + ) -> Self { + AliasTerm::new(interner, trait_def_id, args) + } + + fn def_id(self) -> DefId { + self.def_id + } + + fn args(self) -> ty::GenericArgsRef<'tcx> { + self.args + } + + fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId { + self.trait_def_id(interner) + } + + fn self_ty(self) -> Ty<'tcx> { + self.self_ty() + } + + fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + self.with_self_ty(tcx, self_ty) + } +} + +impl<'tcx> AliasTerm<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: impl IntoIterator>>, + ) -> AliasTerm<'tcx> { + let args = tcx.check_and_mk_args(def_id, args); + AliasTerm { def_id, args, _use_alias_term_new_instead: () } + } + + pub fn expect_ty(self, tcx: TyCtxt<'tcx>) -> AliasTy<'tcx> { + assert_matches!( + self.kind(tcx), + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::OpaqueTy + | ty::AliasTermKind::WeakTy + | ty::AliasTermKind::InherentTy + ); + ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () } + } + + pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTermKind { + match tcx.def_kind(self.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) { + ty::AliasTermKind::InherentTy + } else { + ty::AliasTermKind::ProjectionTy + } + } + DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, + DefKind::TyAlias => ty::AliasTermKind::WeakTy, + DefKind::AssocConst | DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst, + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } +} + +/// The following methods work only with (trait) associated type projections. +impl<'tcx> AliasTerm<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.args.type_at(0) + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + AliasTerm::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), + ) + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + match tcx.def_kind(self.def_id) { + DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), + kind => bug!("expected a projection AliasTy; found {kind:?}"), + } + } + + /// Extracts the underlying trait reference from this projection. + /// For example, if this is a projection of `::Item`, + /// then this function would return a `T: Iterator` trait reference. + /// + /// NOTE: This will drop the args for generic associated types + /// consider calling [Self::trait_ref_and_own_args] to get those + /// as well. + pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { + let def_id = self.trait_def_id(tcx); + ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id))) + } + + /// Extracts the underlying trait reference and own args from this projection. + /// For example, if this is a projection of `::Item<'a>`, + /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args + pub fn trait_ref_and_own_args( + self, + tcx: TyCtxt<'tcx>, + ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { + debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst)); + let trait_def_id = self.trait_def_id(tcx); + let trait_generics = tcx.generics_of(trait_def_id); + ( + ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)), + &self.args[trait_generics.count()..], + ) + } + + pub fn to_term(self, tcx: TyCtxt<'tcx>) -> ty::Term<'tcx> { + match self.kind(tcx) { + ty::AliasTermKind::ProjectionTy => Ty::new_alias( + tcx, + ty::Projection, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::InherentTy => Ty::new_alias( + tcx, + ty::Inherent, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::OpaqueTy => Ty::new_alias( + tcx, + ty::Opaque, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::WeakTy => Ty::new_alias( + tcx, + ty::Weak, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::UnevaluatedConst => ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new(self.def_id, self.args), + tcx.type_of(self.def_id).instantiate(tcx, self.args), + ) + .into(), + } + } +} + +impl<'tcx> From> for AliasTerm<'tcx> { + fn from(ty: AliasTy<'tcx>) -> Self { + AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () } + } +} + +impl<'tcx> From> for AliasTerm<'tcx> { + fn from(ct: ty::UnevaluatedConst<'tcx>) -> Self { + AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () } + } +} + +/// Represents the projection of an associated, opaque, or lazy-type-alias type. /// /// * For a projection, this would be `>::N<...>`. /// * For an inherent projection, this would be `Ty::N<...>`. @@ -1113,7 +1334,7 @@ where #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct AliasTy<'tcx> { - /// The parameters of the associated or opaque item. + /// The parameters of the associated or opaque type. /// /// For a projection, these are the generic parameters for the trait and the /// GAT parameters, if there are any. @@ -1142,36 +1363,6 @@ pub struct AliasTy<'tcx> { _use_alias_ty_new_instead: (), } -impl<'tcx> rustc_type_ir::inherent::AliasTy> for AliasTy<'tcx> { - fn new( - interner: TyCtxt<'tcx>, - trait_def_id: DefId, - args: impl IntoIterator>>, - ) -> Self { - AliasTy::new(interner, trait_def_id, args) - } - - fn def_id(self) -> DefId { - self.def_id - } - - fn args(self) -> ty::GenericArgsRef<'tcx> { - self.args - } - - fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId { - self.trait_def_id(interner) - } - - fn self_ty(self) -> Ty<'tcx> { - self.self_ty() - } - - fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - self.with_self_ty(tcx, self_ty) - } -} - impl<'tcx> AliasTy<'tcx> { pub fn new( tcx: TyCtxt<'tcx>, @@ -1182,7 +1373,7 @@ impl<'tcx> AliasTy<'tcx> { ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () } } - pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { + pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTyKind { match tcx.def_kind(self.def_id) { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = @@ -1199,24 +1390,7 @@ impl<'tcx> AliasTy<'tcx> { /// Whether this alias type is an opaque. pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool { - matches!(self.opt_kind(tcx), Some(ty::Opaque)) - } - - /// FIXME: rename `AliasTy` to `AliasTerm` and always handle - /// constants. This function can then be removed. - pub fn opt_kind(self, tcx: TyCtxt<'tcx>) -> Option { - match tcx.def_kind(self.def_id) { - DefKind::AssocTy - if let DefKind::Impl { of_trait: false } = - tcx.def_kind(tcx.parent(self.def_id)) => - { - Some(ty::Inherent) - } - DefKind::AssocTy => Some(ty::Projection), - DefKind::OpaqueTy => Some(ty::Opaque), - DefKind::TyAlias => Some(ty::Weak), - _ => None, - } + matches!(self.kind(tcx), ty::Opaque) } pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { @@ -1224,7 +1398,7 @@ impl<'tcx> AliasTy<'tcx> { } } -/// The following methods work only with associated type projections. +/// The following methods work only with (trait) associated type projections. impl<'tcx> AliasTy<'tcx> { pub fn self_ty(self) -> Ty<'tcx> { self.args.type_at(0) @@ -1233,10 +1407,7 @@ impl<'tcx> AliasTy<'tcx> { pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) } -} -/// The following methods work only with trait associated type projections. -impl<'tcx> AliasTy<'tcx> { pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { match tcx.def_kind(self.def_id) { DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), @@ -1541,7 +1712,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_alias( tcx: TyCtxt<'tcx>, - kind: ty::AliasKind, + kind: ty::AliasTyKind, alias_ty: ty::AliasTy<'tcx>, ) -> Ty<'tcx> { debug_assert_matches!( diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6ad4f492f74..04ce3de8874 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1086,7 +1086,7 @@ impl<'tcx> TypeFolder> for OpaqueTypeExpander<'tcx> { { p.kind() .rebind(ty::ProjectionPredicate { - projection_ty: projection_pred.projection_ty.fold_with(self), + projection_term: projection_pred.projection_term.fold_with(self), // Don't fold the term on the RHS of the projection predicate. // This is because for default trait methods with RPITITs, we // install a `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))` diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 80eadb9abdc..ee820226ff3 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -534,8 +534,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { } // If projection of Discriminant then compare with `Ty::discriminant_ty` - if let ty::Alias(ty::AliasKind::Projection, ty::AliasTy { args, def_id, .. }) = - expected_ty.kind() + if let ty::Alias(ty::Projection, ty::AliasTy { args, def_id, .. }) = expected_ty.kind() && Some(*def_id) == self.tcx.lang_items().discriminant_type() && args.first().unwrap().as_type().unwrap().discriminant_ty(self.tcx) == operand_ty { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index c8143015583..f631ae76de5 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -117,7 +117,7 @@ where if V::SHALLOW { V::Result::output() } else { args.visit_with(self) } } - fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result { + fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result { let tcx = self.def_id_visitor.tcx(); let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx); try_visit!(self.visit_trait(trait_ref)); @@ -135,9 +135,12 @@ where ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { self.visit_trait(trait_ref) } - ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { + ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term: projection_ty, + term, + }) => { try_visit!(term.visit_with(self)); - self.visit_projection_ty(projection_ty) + self.visit_projection_term(projection_ty) } ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self), ty::ClauseKind::RegionOutlives(..) => V::Result::output(), @@ -226,7 +229,7 @@ where return if V::SHALLOW { V::Result::output() } else if kind == ty::Projection { - self.visit_projection_ty(data) + self.visit_projection_term(data.into()) } else { V::Result::from_branch( data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()), diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index c442d33cf86..ec44b4c16fe 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -9,7 +9,7 @@ use stable_mir::ty::{ use crate::rustc_smir::{alloc, Stable, Tables}; -impl<'tcx> Stable<'tcx> for ty::AliasKind { +impl<'tcx> Stable<'tcx> for ty::AliasTyKind { type T = stable_mir::ty::AliasKind; fn stable(&self, _: &mut Tables<'_>) -> Self::T { match self { @@ -29,6 +29,14 @@ impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> { } } +impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> { + type T = stable_mir::ty::AliasTerm; + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + let ty::AliasTerm { args, def_id, .. } = self; + stable_mir::ty::AliasTerm { def_id: tables.alias_def(*def_id), args: args.stable(tables) } + } +} + impl<'tcx> Stable<'tcx> for ty::DynKind { type T = stable_mir::ty::DynKind; @@ -715,9 +723,9 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { type T = stable_mir::ty::ProjectionPredicate; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - let ty::ProjectionPredicate { projection_ty, term } = self; + let ty::ProjectionPredicate { projection_term: projection_ty, term } = self; stable_mir::ty::ProjectionPredicate { - projection_ty: projection_ty.stable(tables), + projection_term: projection_ty.stable(tables), term: term.unpack().stable(tables), } } diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index e079809aecc..65cc0a45857 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -29,7 +29,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; // Structurally normalize the lhs. - let lhs = if let Some(alias) = lhs.to_alias_ty(self.tcx()) { + let lhs = if let Some(alias) = lhs.to_alias_term() { let term = self.next_term_infer_of_kind(lhs); self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term })); term @@ -38,7 +38,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }; // Structurally normalize the rhs. - let rhs = if let Some(alias) = rhs.to_alias_ty(self.tcx()) { + let rhs = if let Some(alias) = rhs.to_alias_term() { let term = self.next_term_infer_of_kind(rhs); self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term })); term @@ -56,7 +56,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ty::AliasRelationDirection::Equate => ty::Variance::Invariant, ty::AliasRelationDirection::Subtype => ty::Variance::Covariant, }; - match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) { + match (lhs.to_alias_term(), rhs.to_alias_term()) { (None, None) => { self.relate(param_env, lhs, variance, rhs)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index eeaef028cdb..1474f8a679b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -698,7 +698,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( old_ty, None, "{} has two generic parameters: {} and {}", - proj.projection_ty, + proj.projection_term, proj.term, old_ty.unwrap() ); @@ -739,7 +739,11 @@ impl<'tcx> TypeFolder> for ReplaceProjectionWith<'_, 'tcx> { // FIXME: Technically this equate could be fallible... self.nested.extend( self.ecx - .eq_and_get_goals(self.param_env, alias_ty, proj.projection_ty) + .eq_and_get_goals( + self.param_env, + alias_ty, + proj.projection_term.expect_ty(self.ecx.tcx()), + ) .expect("expected to be able to unify goal projection with dyn's projection"), ); proj.term.ty().unwrap() diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 8614c17cabf..06c30bb82cf 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -747,7 +747,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { pub(super) fn relate_rigid_alias_non_alias( &mut self, param_env: ty::ParamEnv<'tcx>, - alias: ty::AliasTy<'tcx>, + alias: ty::AliasTerm<'tcx>, variance: ty::Variance, term: ty::Term<'tcx>, ) -> Result<(), NoSolution> { @@ -764,13 +764,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // Alternatively we could modify `Equate` for this case by adding another // variant to `StructurallyRelateAliases`. let identity_args = self.fresh_args_for_item(alias.def_id); - let rigid_ctor = ty::AliasTy::new(tcx, alias.def_id, identity_args); - let ctor_ty = rigid_ctor.to_ty(tcx); + let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args); + let ctor_term = rigid_ctor.to_term(tcx); let InferOk { value: (), obligations } = self .infcx .at(&ObligationCause::dummy(), param_env) - .trace(term, ctor_ty.into()) - .eq_structurally_relating_aliases(term, ctor_ty.into())?; + .trace(term, ctor_term) + .eq_structurally_relating_aliases(term, ctor_term)?; debug_assert!(obligations.is_empty()); self.relate(param_env, alias, variance, rigid_ctor) } else { diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 1ac1827bf1c..5d5161e092e 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -7,7 +7,7 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::TraitEngineExt; use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine}; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex}; +use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex}; use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; @@ -63,7 +63,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { }; self.at.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(data), + OverflowCause::DeeplyNormalize(data.into()), self.at.cause.span, true, |_| {}, @@ -108,7 +108,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { let recursion_limit = tcx.recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.at.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(ty::AliasTy::new(tcx, uv.def, uv.args)), + OverflowCause::DeeplyNormalize(uv.into()), self.at.cause.span, true, |_| {}, @@ -122,10 +122,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { tcx, self.at.cause.clone(), self.at.param_env, - ty::NormalizesTo { - alias: AliasTy::new(tcx, uv.def, uv.args), - term: new_infer_ct.into(), - }, + ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() }, ); let result = if infcx.predicate_may_hold(&obligation) { diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs index 439f9eec831..353bdb9caff 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs @@ -15,7 +15,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, ) -> QueryResult<'tcx> { let tcx = self.tcx(); - let inherent = goal.predicate.alias; + let inherent = goal.predicate.alias.expect_ty(tcx); let impl_def_id = tcx.parent(inherent.def_id); let impl_args = self.fresh_args_for_item(impl_def_id); diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 8d5c5d2a063..9dd76e55235 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -40,19 +40,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Ok(res) => Ok(res), Err(NoSolution) => { let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal; - if alias.opt_kind(self.tcx()).is_some() { - self.relate_rigid_alias_non_alias( - param_env, - alias, - ty::Variance::Invariant, - term, - )?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } else { - // FIXME(generic_const_exprs): we currently do not support rigid - // unevaluated constants. - Err(NoSolution) - } + self.relate_rigid_alias_non_alias(param_env, alias, ty::Variance::Invariant, term)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } } @@ -132,7 +121,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ecx.eq( goal.param_env, goal.predicate.alias, - assumption_projection_pred.projection_ty, + assumption_projection_pred.projection_term, )?; ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); @@ -373,7 +362,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let pred = tupled_inputs_and_output .map_bound(|(inputs, output)| ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new( + projection_term: ty::AliasTerm::new( tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs], @@ -425,9 +414,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { output_coroutine_ty, coroutine_return_ty, }| { - let (projection_ty, term) = match tcx.item_name(goal.predicate.def_id()) { + let (projection_term, term) = match tcx.item_name(goal.predicate.def_id()) { sym::CallOnceFuture => ( - ty::AliasTy::new( + ty::AliasTerm::new( tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), tupled_inputs_ty], @@ -435,7 +424,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { output_coroutine_ty.into(), ), sym::CallRefFuture => ( - ty::AliasTy::new( + ty::AliasTerm::new( tcx, goal.predicate.def_id(), [ @@ -447,7 +436,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { output_coroutine_ty.into(), ), sym::Output => ( - ty::AliasTy::new( + ty::AliasTerm::new( tcx, goal.predicate.def_id(), [ @@ -459,7 +448,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ), name => bug!("no such associated type: {name}"), }; - ty::ProjectionPredicate { projection_ty, term } + ty::ProjectionPredicate { projection_term, term } }, ) .to_predicate(tcx); @@ -636,7 +625,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), + projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), term, } .to_predicate(tcx), @@ -668,7 +657,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), + projection_term: ty::AliasTerm::new(ecx.tcx(), goal.predicate.def_id(), [self_ty]), term, } .to_predicate(tcx), @@ -752,7 +741,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new( + projection_term: ty::AliasTerm::new( ecx.tcx(), goal.predicate.def_id(), [self_ty, coroutine.resume_ty()], diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 74b3db71e78..0f1be1072a8 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -11,19 +11,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, ProjectionPredicate<'tcx>>, ) -> QueryResult<'tcx> { let tcx = self.tcx(); - let projection_term = match goal.predicate.term.unpack() { - ty::TermKind::Ty(_) => goal.predicate.projection_ty.to_ty(tcx).into(), - ty::TermKind::Const(_) => ty::Const::new_unevaluated( - tcx, - ty::UnevaluatedConst::new( - goal.predicate.projection_ty.def_id, - goal.predicate.projection_ty.args, - ), - tcx.type_of(goal.predicate.projection_ty.def_id) - .instantiate(tcx, goal.predicate.projection_ty.args), - ) - .into(), - }; + let projection_term = goal.predicate.projection_term.to_term(tcx); let goal = goal.with( tcx, ty::PredicateKind::AliasRelate( diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 053de2c673b..60562acfe93 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -540,11 +540,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { finished_map } - fn is_param_no_infer(&self, args: GenericArgsRef<'_>) -> bool { + fn is_param_no_infer(&self, args: GenericArgsRef<'tcx>) -> bool { self.is_of_param(args.type_at(0)) && !args.types().any(|t| t.has_infer_types()) } - pub fn is_of_param(&self, ty: Ty<'_>) -> bool { + pub fn is_of_param(&self, ty: Ty<'tcx>) -> bool { match ty.kind() { ty::Param(_) => true, ty::Alias(ty::Projection, p) => self.is_of_param(p.self_ty()), @@ -552,9 +552,9 @@ impl<'tcx> AutoTraitFinder<'tcx> { } } - fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool { + fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'tcx>) -> bool { if let Some(ty) = p.term().skip_binder().ty() { - matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_ty) + matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_term.expect_ty(self.tcx)) } else { false } @@ -612,7 +612,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // an inference variable. // Additionally, we check if we've seen this predicate before, // to avoid rendering duplicate bounds to the user. - if self.is_param_no_infer(p.skip_binder().projection_ty.args) + if self.is_param_no_infer(p.skip_binder().projection_term.args) && !p.term().skip_binder().has_infer_types() && is_new_pred { @@ -684,7 +684,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // and turn them into an explicit negative impl for our type. debug!("Projecting and unifying projection predicate {:?}", predicate); - match project::poly_project_and_unify_type(selcx, &obligation.with(self.tcx, p)) + match project::poly_project_and_unify_term(selcx, &obligation.with(self.tcx, p)) { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { debug!( diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 59725ce9de0..9069456b6e7 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -1095,11 +1095,11 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) if matches!( - infcx.tcx.def_kind(proj.projection_ty.def_id), + infcx.tcx.def_kind(proj.projection_term.def_id), DefKind::AssocTy | DefKind::AssocConst ) => { - proj.projection_ty.trait_ref(infcx.tcx) + proj.projection_term.trait_ref(infcx.tcx) } _ => return, }; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index ea1752a6e98..efa7c3959c3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1104,9 +1104,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .iter() .find_map(|pred| { if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() - && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() + && Some(proj.projection_term.def_id) == self.tcx.lang_items().fn_once_output() // args tuple will always be args[1] - && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind() + && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() { Some(( DefIdOrName::DefId(def_id), @@ -1148,10 +1148,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; param_env.caller_bounds().iter().find_map(|pred| { if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() - && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() - && proj.projection_ty.self_ty() == found + && Some(proj.projection_term.def_id) == self.tcx.lang_items().fn_once_output() + && proj.projection_term.self_ty() == found // args tuple will always be args[1] - && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind() + && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() { Some(( name, @@ -3845,11 +3845,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && let Some(found) = failed_pred.skip_binder().term.ty() { type_diffs = vec![Sorts(ty::error::ExpectedFound { - expected: Ty::new_alias( - self.tcx, - ty::Projection, - where_pred.skip_binder().projection_ty, - ), + expected: where_pred + .skip_binder() + .projection_term + .expect_ty(self.tcx) + .to_ty(self.tcx), found, })]; } @@ -4274,7 +4274,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // This corresponds to `::Item = _`. let projection = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(self.tcx, proj.def_id, args), + projection_term: ty::AliasTerm::new(self.tcx, proj.def_id, args), term: ty.into(), }), )); @@ -4971,7 +4971,7 @@ fn point_at_assoc_type_restriction( let ty::ClauseKind::Projection(proj) = clause else { return; }; - let name = tcx.item_name(proj.projection_ty.def_id); + let name = tcx.item_name(proj.projection_term.def_id); let mut predicates = generics.predicates.iter().peekable(); let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None; while let Some(pred) = predicates.next() { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 08ffe37b8b4..8f6e997e3b7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -62,7 +62,7 @@ use super::{ pub use rustc_infer::traits::error_reporting::*; pub enum OverflowCause<'tcx> { - DeeplyNormalize(ty::AliasTy<'tcx>), + DeeplyNormalize(ty::AliasTerm<'tcx>), TraitSolver(ty::Predicate<'tcx>), } @@ -246,10 +246,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let mut err = match cause { - OverflowCause::DeeplyNormalize(alias_ty) => { - let alias_ty = self.resolve_vars_if_possible(alias_ty); - let kind = alias_ty.opt_kind(self.tcx).map_or("alias", |k| k.descr()); - let alias_str = with_short_path(self.tcx, alias_ty); + OverflowCause::DeeplyNormalize(alias_term) => { + let alias_term = self.resolve_vars_if_possible(alias_term); + let kind = alias_term.kind(self.tcx).descr(); + let alias_str = with_short_path(self.tcx, alias_term); struct_span_code_err!( self.dcx(), span, @@ -1468,7 +1468,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); let param_env = ty::ParamEnv::empty(); - self.can_eq(param_env, goal.projection_ty, assumption.projection_ty) + self.can_eq(param_env, goal.projection_term, assumption.projection_term) && self.can_eq(param_env, goal.term, assumption.term) } @@ -1583,23 +1583,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::BoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); - let unnormalized_term = match data.term.unpack() { - ty::TermKind::Ty(_) => Ty::new_projection( - self.tcx, - data.projection_ty.def_id, - data.projection_ty.args, - ) - .into(), - ty::TermKind::Const(ct) => ty::Const::new_unevaluated( - self.tcx, - ty::UnevaluatedConst { - def: data.projection_ty.def_id, - args: data.projection_ty.args, - }, - ct.ty(), - ) - .into(), - }; + let unnormalized_term = data.projection_term.to_term(self.tcx); // FIXME(-Znext-solver): For diagnostic purposes, it would be nice // to deeply normalize this type. let normalized_term = @@ -1664,13 +1648,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return None; }; - let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?; + let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_term.def_id)?; let trait_assoc_ident = trait_assoc_item.ident(self.tcx); let mut associated_items = vec![]; self.tcx.for_each_relevant_impl( - self.tcx.trait_of_item(proj.projection_ty.def_id)?, - proj.projection_ty.self_ty(), + self.tcx.trait_of_item(proj.projection_term.def_id)?, + proj.projection_term.self_ty(), |impl_def_id| { associated_items.extend( self.tcx @@ -1739,11 +1723,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { normalized_ty: ty::Term<'tcx>, expected_ty: ty::Term<'tcx>, ) -> Option { - let trait_def_id = pred.projection_ty.trait_def_id(self.tcx); - let self_ty = pred.projection_ty.self_ty(); + let trait_def_id = pred.projection_term.trait_def_id(self.tcx); + let self_ty = pred.projection_term.self_ty(); with_forced_trimmed_paths! { - if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() { + if Some(pred.projection_term.def_id) == self.tcx.lang_items().fn_once_output() { let fn_kind = self_ty.prefix_string(self.tcx); let item = match self_ty.kind() { ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(), @@ -2622,14 +2606,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } if let Err(guar) = - self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_ty.def_id)) + self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_term.def_id)) { // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. return guar; } let arg = data - .projection_ty + .projection_term .args .iter() .chain(Some(data.term.into_arg())) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e3497c646db..dc32db09034 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -770,13 +770,13 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { } } - match project::poly_project_and_unify_type(&mut self.selcx, &project_obligation) { + match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) { ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)), ProjectAndUnifyResult::FailedNormalization => { stalled_on.clear(); stalled_on.extend(args_infer_vars( &self.selcx, - project_obligation.predicate.map_bound(|pred| pred.projection_ty.args), + project_obligation.predicate.map_bound(|pred| pred.projection_term.args), )); ProcessResult::Unchanged } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 56f8b4b9cdb..2325e45467e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -51,7 +51,7 @@ pub use self::object_safety::hir_ty_lowering_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; pub use self::object_safety::object_safety_violations_for_assoc_item; pub use self::object_safety::ObjectSafetyViolation; -pub use self::project::{normalize_inherent_projection, normalize_projection_type}; +pub use self::project::{normalize_inherent_projection, normalize_projection_ty}; pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::specialization_graph::FutureCompatOverlapError; diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 43f4fa8e81c..d10aee2d4e2 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -213,7 +213,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx let recursion_limit = self.interner().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(data), + OverflowCause::DeeplyNormalize(data.into()), self.cause.span, true, |_| {}, @@ -238,7 +238,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx // register an obligation to *later* project, since we know // there won't be bound vars there. let data = data.fold_with(self); - let normalized_ty = project::normalize_projection_type( + let normalized_ty = project::normalize_projection_ty( self.selcx, self.param_env, data, @@ -273,10 +273,10 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx let (data, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); let data = data.fold_with(self); - let normalized_ty = project::opt_normalize_projection_type( + let normalized_ty = project::opt_normalize_projection_term( self.selcx, self.param_env, - data, + data.into(), self.cause.clone(), self.depth, self.obligations, @@ -309,7 +309,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx let recursion_limit = self.interner().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( - OverflowCause::DeeplyNormalize(data), + OverflowCause::DeeplyNormalize(data.into()), self.cause.span, false, |diag| { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 75e43bc8f5d..41080b3d9d3 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -305,7 +305,7 @@ fn predicate_references_self<'tcx>( // // This is ALT2 in issue #56288, see that for discussion of the // possible alternatives. - data.projection_ty.args[1..].iter().any(has_self_ty).then_some(sp) + data.projection_term.args[1..].iter().any(has_self_ty).then_some(sp) } ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index f092f42dacf..20b5a81bb0e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -12,7 +12,7 @@ use super::PredicateObligation; use super::Selection; use super::SelectionContext; use super::SelectionError; -use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey}; +use super::{Normalized, NormalizedTerm, ProjectionCacheEntry, ProjectionCacheKey}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::traits::ImplSource; @@ -43,7 +43,7 @@ pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPre pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>; -pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>; +pub type ProjectionTermObligation<'tcx> = Obligation<'tcx, ty::AliasTerm<'tcx>>; pub(super) struct InProgress; @@ -181,7 +181,7 @@ pub(super) enum ProjectAndUnifyResult<'tcx> { /// If successful, this may result in additional obligations. Also returns /// the projection cache key used to track these additional obligations. #[instrument(level = "debug", skip(selcx))] -pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( +pub(super) fn poly_project_and_unify_term<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &PolyProjectionObligation<'tcx>, ) -> ProjectAndUnifyResult<'tcx> { @@ -192,7 +192,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); - match project_and_unify_type(selcx, &placeholder_obligation) { + match project_and_unify_term(selcx, &placeholder_obligation) { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e), ProjectAndUnifyResult::Holds(obligations) if old_universe != new_universe @@ -234,17 +234,17 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( /// /// See [poly_project_and_unify_type] for an explanation of the return value. #[instrument(level = "debug", skip(selcx))] -fn project_and_unify_type<'cx, 'tcx>( +fn project_and_unify_term<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionObligation<'tcx>, ) -> ProjectAndUnifyResult<'tcx> { let mut obligations = vec![]; let infcx = selcx.infcx; - let normalized = match opt_normalize_projection_type( + let normalized = match opt_normalize_projection_term( selcx, obligation.param_env, - obligation.predicate.projection_ty, + obligation.predicate.projection_term, obligation.cause.clone(), obligation.recursion_depth, &mut obligations, @@ -290,7 +290,7 @@ fn project_and_unify_type<'cx, 'tcx>( /// there are unresolved type variables in the projection, we will /// instantiate it with a fresh type variable `$X` and generate a new /// obligation `::Item == $X` for later. -pub fn normalize_projection_type<'a, 'b, 'tcx>( +pub fn normalize_projection_ty<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, projection_ty: ty::AliasTy<'tcx>, @@ -298,10 +298,10 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( depth: usize, obligations: &mut Vec>, ) -> Term<'tcx> { - opt_normalize_projection_type( + opt_normalize_projection_term( selcx, param_env, - projection_ty, + projection_ty.into(), cause.clone(), depth, obligations, @@ -313,7 +313,10 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( // and a deferred predicate to resolve this when more type // information is available. - selcx.infcx.infer_projection(param_env, projection_ty, cause, depth + 1, obligations).into() + selcx + .infcx + .projection_ty_to_infer(param_env, projection_ty, cause, depth + 1, obligations) + .into() }) } @@ -328,10 +331,10 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( /// function takes an obligations vector and appends to it directly, which is /// slightly uglier but avoids the need for an extra short-lived allocation. #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] -pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>( +pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::AliasTy<'tcx>, + projection_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, depth: usize, obligations: &mut Vec>, @@ -343,8 +346,8 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>( // mode, which could lead to using incorrect cache results. let use_cache = !selcx.is_intercrate(); - let projection_ty = infcx.resolve_vars_if_possible(projection_ty); - let cache_key = ProjectionCacheKey::new(projection_ty, param_env); + let projection_term = infcx.resolve_vars_if_possible(projection_term); + let cache_key = ProjectionCacheKey::new(projection_term, param_env); // FIXME(#20304) For now, I am caching here, which is good, but it // means we don't capture the type variables that are created in @@ -410,14 +413,14 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>( } Err(ProjectionCacheEntry::Error) => { debug!("opt_normalize_projection_type: found error"); - let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); + let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); obligations.extend(result.obligations); return Ok(Some(result.value.into())); } } let obligation = - Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_ty); + Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_term); match project(selcx, &obligation) { Ok(Projected::Progress(Progress { @@ -480,7 +483,7 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>( if use_cache { infcx.inner.borrow_mut().projection_cache().error(cache_key); } - let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); + let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); obligations.extend(result.obligations); Ok(Some(result.value.into())) } @@ -509,19 +512,33 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>( fn normalize_to_error<'a, 'tcx>( selcx: &SelectionContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::AliasTy<'tcx>, + projection_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, depth: usize, -) -> NormalizedTy<'tcx> { - let trait_ref = ty::Binder::dummy(projection_ty.trait_ref(selcx.tcx())); +) -> NormalizedTerm<'tcx> { + let trait_ref = ty::Binder::dummy(projection_term.trait_ref(selcx.tcx())); + let new_value = match projection_term.kind(selcx.tcx()) { + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::InherentTy + | ty::AliasTermKind::OpaqueTy + | ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(), + ty::AliasTermKind::UnevaluatedConst => selcx + .infcx + .next_const_var( + selcx + .tcx() + .type_of(projection_term.def_id) + .instantiate(selcx.tcx(), projection_term.args), + cause.span, + ) + .into(), + }; let trait_obligation = Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate(selcx.tcx()), }; - let tcx = selcx.infcx.tcx; - let new_value = selcx.infcx.next_ty_var(tcx.def_span(projection_ty.def_id)); Normalized { value: new_value, obligations: vec![trait_obligation] } } @@ -675,7 +692,7 @@ impl<'tcx> Progress<'tcx> { #[instrument(level = "info", skip(selcx))] fn project<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, ) -> Result, ProjectionError<'tcx>> { if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) { // This should really be an immediate error, but some existing code @@ -750,7 +767,7 @@ fn project<'cx, 'tcx>( /// there that can answer this question. fn assemble_candidates_from_param_env<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { assemble_candidates_from_predicates( @@ -775,7 +792,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>( /// Here, for example, we could conclude that the result is `i32`. fn assemble_candidates_from_trait_def<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { debug!("assemble_candidates_from_trait_def(..)"); @@ -833,7 +850,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( /// `dyn Iterator: Iterator` again. fn assemble_candidates_from_object_ty<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { debug!("assemble_candidates_from_object_ty(..)"); @@ -877,7 +894,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( )] fn assemble_candidates_from_predicates<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>, env_predicates: impl Iterator>, @@ -925,7 +942,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( #[instrument(level = "debug", skip(selcx, obligation, candidate_set))] fn assemble_candidates_from_impls<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { // If we are resolving `>::Item == Type`, @@ -1253,7 +1270,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( fn confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, candidate: ProjectionCandidate<'tcx>, ) -> Progress<'tcx> { debug!(?obligation, ?candidate, "confirm_candidate"); @@ -1285,7 +1302,7 @@ fn confirm_candidate<'cx, 'tcx>( fn confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, impl_source: Selection<'tcx>, ) -> Progress<'tcx> { match impl_source { @@ -1333,7 +1350,7 @@ fn confirm_select_candidate<'cx, 'tcx>( fn confirm_coroutine_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1377,7 +1394,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( }; let predicate = ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), + projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args), term: ty.into(), }; @@ -1388,7 +1405,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( fn confirm_future_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1421,7 +1438,7 @@ fn confirm_future_candidate<'cx, 'tcx>( debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output); let predicate = ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), + projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args), term: return_ty.into(), }; @@ -1432,7 +1449,7 @@ fn confirm_future_candidate<'cx, 'tcx>( fn confirm_iterator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1463,7 +1480,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item); let predicate = ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), + projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args), term: yield_ty.into(), }; @@ -1474,7 +1491,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( fn confirm_async_iterator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let ty::Coroutine(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() @@ -1513,7 +1530,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( let item_ty = args.type_at(0); let predicate = ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(tcx, obligation.predicate.def_id, trait_ref.args), + projection_term: ty::AliasTerm::new(tcx, obligation.predicate.def_id, trait_ref.args), term: item_ty.into(), }; @@ -1524,7 +1541,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( fn confirm_builtin_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, data: Vec>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); @@ -1582,8 +1599,10 @@ fn confirm_builtin_candidate<'cx, 'tcx>( bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate); }; - let predicate = - ty::ProjectionPredicate { projection_ty: ty::AliasTy::new(tcx, item_def_id, args), term }; + let predicate = ty::ProjectionPredicate { + projection_term: ty::AliasTerm::new(tcx, item_def_id, args), + term, + }; confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) .with_addl_obligations(obligations) @@ -1592,7 +1611,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( fn confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); @@ -1628,7 +1647,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( fn confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); @@ -1727,7 +1746,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( fn confirm_callable_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, fn_sig: ty::PolyFnSig<'tcx>, flag: util::TupleArgumentsFlag, fn_host_effect: ty::Const<'tcx>, @@ -1748,7 +1767,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( fn_host_effect, ) .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new(tcx, fn_once_output_def_id, trait_ref.args), + projection_term: ty::AliasTerm::new(tcx, fn_once_output_def_id, trait_ref.args), term: ret_type.into(), }); @@ -1757,7 +1776,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( fn confirm_async_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); @@ -1836,13 +1855,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( sym::Output => sig.return_ty, name => bug!("no such associated type: {name}"), }; - let projection_ty = match item_name { - sym::CallOnceFuture | sym::Output => ty::AliasTy::new( + let projection_term = match item_name { + sym::CallOnceFuture | sym::Output => ty::AliasTerm::new( tcx, obligation.predicate.def_id, [self_ty, sig.tupled_inputs_ty], ), - sym::CallRefFuture => ty::AliasTy::new( + sym::CallRefFuture => ty::AliasTerm::new( tcx, obligation.predicate.def_id, [ty::GenericArg::from(self_ty), sig.tupled_inputs_ty.into(), env_region.into()], @@ -1851,7 +1870,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( }; args.coroutine_closure_sig() - .rebind(ty::ProjectionPredicate { projection_ty, term: term.into() }) + .rebind(ty::ProjectionPredicate { projection_term, term: term.into() }) } ty::FnDef(..) | ty::FnPtr(..) => { let bound_sig = self_ty.fn_sig(tcx); @@ -1871,13 +1890,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( } name => bug!("no such associated type: {name}"), }; - let projection_ty = match item_name { - sym::CallOnceFuture | sym::Output => ty::AliasTy::new( + let projection_term = match item_name { + sym::CallOnceFuture | sym::Output => ty::AliasTerm::new( tcx, obligation.predicate.def_id, [self_ty, Ty::new_tup(tcx, sig.inputs())], ), - sym::CallRefFuture => ty::AliasTy::new( + sym::CallRefFuture => ty::AliasTerm::new( tcx, obligation.predicate.def_id, [ @@ -1889,7 +1908,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( name => bug!("no such associated type: {name}"), }; - bound_sig.rebind(ty::ProjectionPredicate { projection_ty, term: term.into() }) + bound_sig.rebind(ty::ProjectionPredicate { projection_term, term: term.into() }) } ty::Closure(_, args) => { let args = args.as_closure(); @@ -1910,11 +1929,11 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( } name => bug!("no such associated type: {name}"), }; - let projection_ty = match item_name { + let projection_term = match item_name { sym::CallOnceFuture | sym::Output => { - ty::AliasTy::new(tcx, obligation.predicate.def_id, [self_ty, sig.inputs()[0]]) + ty::AliasTerm::new(tcx, obligation.predicate.def_id, [self_ty, sig.inputs()[0]]) } - sym::CallRefFuture => ty::AliasTy::new( + sym::CallRefFuture => ty::AliasTerm::new( tcx, obligation.predicate.def_id, [ty::GenericArg::from(self_ty), sig.inputs()[0].into(), env_region.into()], @@ -1922,7 +1941,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( name => bug!("no such associated type: {name}"), }; - bound_sig.rebind(ty::ProjectionPredicate { projection_ty, term: term.into() }) + bound_sig.rebind(ty::ProjectionPredicate { projection_term, term: term.into() }) } _ => bug!("expected callable type for AsyncFn candidate"), }; @@ -1933,7 +1952,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: Vec>, ) -> Progress<'tcx> { let [ @@ -1950,7 +1969,7 @@ fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( }; let predicate = ty::ProjectionPredicate { - projection_ty: ty::AliasTy::new( + projection_term: ty::AliasTerm::new( selcx.tcx(), obligation.predicate.def_id, obligation.predicate.args, @@ -1972,7 +1991,7 @@ fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( fn confirm_param_env_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidate: bool, ) -> Progress<'tcx> { @@ -1986,7 +2005,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( poly_cache_entry, ); - let cache_projection = cache_entry.projection_ty; + let cache_projection = cache_entry.projection_term; let mut nested_obligations = Vec::new(); let obligation_projection = obligation.predicate; let obligation_projection = ensure_sufficient_stack(|| { @@ -2041,7 +2060,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( fn confirm_impl_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); @@ -2102,7 +2121,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( // associated type itself. fn assoc_ty_own_obligations<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, nested: &mut Vec>, ) { let tcx = selcx.tcx(); @@ -2164,7 +2183,7 @@ impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { // from a specific call to `opt_normalize_projection_type` - if // there's no precise match, the original cache entry is "stranded" // anyway. - infcx.resolve_vars_if_possible(predicate.projection_ty), + infcx.resolve_vars_if_possible(predicate.projection_term), obligation.param_env, ) }) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 8b39c23da56..1b5ffeebc01 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -222,7 +222,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> .infcx .err_ctxt() .build_overflow_error( - OverflowCause::DeeplyNormalize(data), + OverflowCause::DeeplyNormalize(data.into()), self.cause.span, true, ) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 40d206b92b8..19968fd362f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -944,7 +944,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } self.infcx.probe(|_| { - let ty = traits::normalize_projection_type( + let ty = traits::normalize_projection_ty( self, param_env, ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7aa2aabed7f..d665f3c3907 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -8,7 +8,7 @@ use self::SelectionCandidate::*; use super::coherence::{self, Conflict}; use super::const_evaluatable; use super::project; -use super::project::ProjectionTyObligation; +use super::project::ProjectionTermObligation; use super::util; use super::util::closure_trait_ref_and_return_type; use super::wf; @@ -808,7 +808,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { let data = bound_predicate.rebind(data); let project_obligation = obligation.with(self.tcx(), data); - match project::poly_project_and_unify_type(self, &project_obligation) { + match project::poly_project_and_unify_term(self, &project_obligation) { ProjectAndUnifyResult::Holds(mut subobligations) => { 'compute_res: { // If we've previously marked this projection as 'complete', then @@ -1733,7 +1733,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// in cases like #91762. pub(super) fn match_projection_projections( &mut self, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTermObligation<'tcx>, env_predicate: PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidates: bool, ) -> ProjectionMatchesProjection { @@ -1752,12 +1752,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - infer_predicate.projection_ty, + infer_predicate.projection_term, &mut nested_obligations, ) }) } else { - infer_predicate.projection_ty + infer_predicate.projection_term }; let is_match = self diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 562a82cc73d..8a0ce3c1f98 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -165,11 +165,8 @@ pub fn clause_obligations<'tcx>( wf.compute(ty.into()); } ty::ClauseKind::Projection(t) => { - wf.compute_alias(t.projection_ty); - wf.compute(match t.term.unpack() { - ty::TermKind::Ty(ty) => ty.into(), - ty::TermKind::Const(c) => c.into(), - }) + wf.compute_alias_term(t.projection_term); + wf.compute(t.term.into_arg()); } ty::ClauseKind::ConstArgHasType(ct, ty) => { wf.compute(ct.into()); @@ -439,7 +436,37 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes the obligations required for an alias (except inherent) to be WF /// into `self.out`. - fn compute_alias(&mut self, data: ty::AliasTy<'tcx>) { + fn compute_alias_ty(&mut self, data: ty::AliasTy<'tcx>) { + // A projection is well-formed if + // + // (a) its predicates hold (*) + // (b) its args are wf + // + // (*) The predicates of an associated type include the predicates of + // the trait that it's contained in. For example, given + // + // trait A: Clone { + // type X where T: Copy; + // } + // + // The predicates of `<() as A>::X` are: + // [ + // `(): Sized` + // `(): Clone` + // `(): A` + // `i32: Sized` + // `i32: Clone` + // `i32: Copy` + // ] + let obligations = self.nominal_obligations(data.def_id, data.args); + self.out.extend(obligations); + + self.compute_projection_args(data.args); + } + + /// Pushes the obligations required for an alias (except inherent) to be WF + /// into `self.out`. + fn compute_alias_term(&mut self, data: ty::AliasTerm<'tcx>) { // A projection is well-formed if // // (a) its predicates hold (*) @@ -698,7 +725,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } ty::Alias(ty::Projection | ty::Opaque | ty::Weak, data) => { - self.compute_alias(data); + self.compute_alias_ty(data); return; // Subtree handled by compute_projection. } ty::Alias(ty::Inherent, data) => { diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 559c05eb3e7..fee13078250 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -34,14 +34,8 @@ fn normalize_canonicalized_projection_ty<'tcx>( let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); let mut obligations = vec![]; - let answer = traits::normalize_projection_type( - selcx, - param_env, - goal, - cause, - 0, - &mut obligations, - ); + let answer = + traits::normalize_projection_ty(selcx, param_env, goal, cause, 0, &mut obligations); ocx.register_obligations(obligations); // #112047: With projections and opaques, we are able to create opaques that // are recursive (given some generic parameters of the opaque's type variables). diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index fa1085c7cd7..87fcd3602e0 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -214,7 +214,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { self.predicates.push( ty::Binder::bind_with_vars( ty::ProjectionPredicate { - projection_ty: shifted_alias_ty, + projection_term: shifted_alias_ty.into(), term: default_ty.into(), }, self.bound_vars, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index a50967a3b18..5e981636438 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -90,8 +90,7 @@ pub trait BoundVars { fn has_no_bound_vars(&self) -> bool; } -// FIXME: Uplift `AliasTy` -pub trait AliasTy: Copy + DebugWithInfcx + Hash + Eq + Sized { +pub trait AliasTerm: Copy + DebugWithInfcx + Hash + Eq + Sized { fn new( interner: I, trait_def_id: I::DefId, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 17d9f4242fd..af0e833b9e9 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -39,7 +39,7 @@ pub trait Interner: // Kinds of tys type Ty: Ty; type Tys: Copy + Debug + Hash + Eq + IntoIterator; - type AliasTy: AliasTy; + type AliasTy: Copy + DebugWithInfcx + Hash + Eq + Sized; type ParamTy: Copy + Debug + Hash + Eq; type BoundTy: Copy + Debug + Hash + Eq; type PlaceholderTy: PlaceholderLike; @@ -74,6 +74,7 @@ pub trait Interner: type RegionOutlivesPredicate: Copy + Debug + Hash + Eq; type TypeOutlivesPredicate: Copy + Debug + Hash + Eq; type ProjectionPredicate: Copy + Debug + Hash + Eq; + type AliasTerm: AliasTerm; type NormalizesTo: Copy + Debug + Hash + Eq; type SubtypePredicate: Copy + Debug + Hash + Eq; type CoercePredicate: Copy + Debug + Hash + Eq; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 04cacd987d0..4560a54da82 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -54,7 +54,7 @@ pub use predicate_kind::*; pub use region_kind::*; pub use ty_info::*; pub use ty_kind::*; -pub use AliasKind::*; +pub use AliasTyKind::*; pub use DynKind::*; pub use InferTy::*; pub use RegionKind::*; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index f84f8f47c67..7f746492ea0 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -1,6 +1,7 @@ use std::fmt; -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +#[cfg(feature = "nightly")] +use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::inherent::*; @@ -283,7 +284,7 @@ impl ExistentialProjection { debug_assert!(!self_ty.has_escaping_bound_vars()); ProjectionPredicate { - projection_ty: I::AliasTy::new( + projection_term: I::AliasTerm::new( tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args), @@ -294,16 +295,47 @@ impl ExistentialProjection { pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate) -> Self { // Assert there is a Self. - projection_predicate.projection_ty.args().type_at(0); + projection_predicate.projection_term.args().type_at(0); Self { - def_id: projection_predicate.projection_ty.def_id(), - args: tcx.mk_args(&projection_predicate.projection_ty.args()[1..]), + def_id: projection_predicate.projection_term.def_id(), + args: tcx.mk_args(&projection_predicate.projection_term.args()[1..]), term: projection_predicate.term, } } } +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +pub enum AliasTermKind { + /// A projection `::AssocType`. + /// Can get normalized away if monomorphic enough. + ProjectionTy, + /// An associated type in an inherent `impl` + InherentTy, + /// An opaque type (usually from `impl Trait` in type aliases or function return types) + /// Can only be normalized away in RevealAll mode + OpaqueTy, + /// A type alias that actually checks its trait bounds. + /// Currently only used if the type alias references opaque types. + /// Can always be normalized away. + WeakTy, + /// UwU + UnevaluatedConst, +} + +impl AliasTermKind { + pub fn descr(self) -> &'static str { + match self { + AliasTermKind::ProjectionTy => "associated type", + AliasTermKind::InherentTy => "inherent associated type", + AliasTermKind::OpaqueTy => "opaque type", + AliasTermKind::WeakTy => "type alias", + AliasTermKind::UnevaluatedConst => "unevaluated constant", + } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// @@ -327,31 +359,31 @@ impl ExistentialProjection { #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct ProjectionPredicate { - pub projection_ty: I::AliasTy, + pub projection_term: I::AliasTerm, pub term: I::Term, } impl ProjectionPredicate { pub fn self_ty(self) -> I::Ty { - self.projection_ty.self_ty() + self.projection_term.self_ty() } pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate { - Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } + Self { projection_term: self.projection_term.with_self_ty(tcx, self_ty), ..self } } pub fn trait_def_id(self, tcx: I) -> I::DefId { - self.projection_ty.trait_def_id(tcx) + self.projection_term.trait_def_id(tcx) } pub fn def_id(self) -> I::DefId { - self.projection_ty.def_id() + self.projection_term.def_id() } } impl fmt::Debug for ProjectionPredicate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term) + write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_term, self.term) } } @@ -368,7 +400,7 @@ impl fmt::Debug for ProjectionPredicate { #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct NormalizesTo { - pub alias: I::AliasTy, + pub alias: I::AliasTerm, pub term: I::Term, } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index d67327926ff..6e544d0e6ac 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -31,7 +31,7 @@ pub enum DynKind { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] -pub enum AliasKind { +pub enum AliasTyKind { /// A projection `::AssocType`. /// Can get normalized away if monomorphic enough. Projection, @@ -46,13 +46,13 @@ pub enum AliasKind { Weak, } -impl AliasKind { +impl AliasTyKind { pub fn descr(self) -> &'static str { match self { - AliasKind::Projection => "associated type", - AliasKind::Inherent => "inherent associated type", - AliasKind::Opaque => "opaque type", - AliasKind::Weak => "type alias", + AliasTyKind::Projection => "associated type", + AliasTyKind::Inherent => "inherent associated type", + AliasTyKind::Opaque => "opaque type", + AliasTyKind::Weak => "type alias", } } } @@ -201,7 +201,7 @@ pub enum TyKind { /// A projection, opaque type, weak type alias, or inherent associated type. /// All of these types are represented as pairs of def-id and args, and can /// be normalized, so they are grouped conceptually. - Alias(AliasKind, I::AliasTy), + Alias(AliasTyKind, I::AliasTy), /// A type parameter; for example, `T` in `fn f(x: T) {}`. Param(I::ParamTy), diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index bc6fb34493a..56251613840 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -897,6 +897,12 @@ pub struct AliasTy { pub args: GenericArgs, } +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct AliasTerm { + pub def_id: AliasDef, + pub args: GenericArgs, +} + pub type PolyFnSig = Binder; #[derive(Clone, Debug, Eq, PartialEq)] @@ -1350,7 +1356,7 @@ pub type TypeOutlivesPredicate = OutlivesPredicate; #[derive(Clone, Debug, Eq, PartialEq)] pub struct ProjectionPredicate { - pub projection_ty: AliasTy, + pub projection_term: AliasTerm, pub term: TermKind, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 90f2e3d09fe..0ab23d159a6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -453,7 +453,15 @@ fn clean_projection_predicate<'tcx>( cx: &mut DocContext<'tcx>, ) -> WherePredicate { WherePredicate::EqPredicate { - lhs: clean_projection(pred.map_bound(|p| p.projection_ty), cx, None), + lhs: clean_projection( + pred.map_bound(|p| { + // FIXME: This needs to be made resilient for `AliasTerm`s that + // are associated consts. + p.projection_term.expect_ty(cx.tcx) + }), + cx, + None, + ), rhs: clean_middle_term(pred.map_bound(|p| p.term), cx), } } @@ -838,7 +846,7 @@ fn clean_ty_generics<'tcx>( } } ty::ClauseKind::Projection(p) => { - if let ty::Param(param) = p.projection_ty.self_ty().kind() { + if let ty::Param(param) = p.projection_term.self_ty().kind() { projection = Some(bound_p.rebind(p)); return Some(param.index); } @@ -857,7 +865,15 @@ fn clean_ty_generics<'tcx>( bounds.extend(pred.get_bounds().into_iter().flatten().cloned()); if let Some(proj) = projection - && let lhs = clean_projection(proj.map_bound(|p| p.projection_ty), cx, None) + && let lhs = clean_projection( + proj.map_bound(|p| { + // FIXME: This needs to be made resilient for `AliasTerm`s that + // are associated consts. + p.projection_term.expect_ty(cx.tcx) + }), + cx, + None, + ) && let Some((_, trait_did, name)) = lhs.projection() { impl_trait_proj.entry(param_idx).or_default().push(( @@ -2126,7 +2142,10 @@ pub(crate) fn clean_middle_ty<'tcx>( // HACK(compiler-errors): Doesn't actually matter what self // type we put here, because we're only using the GAT's args. .with_self_ty(cx.tcx, cx.tcx.types.self_param) - .projection_ty + .projection_term + // FIXME: This needs to be made resilient for `AliasTerm`s + // that are associated consts. + .expect_ty(cx.tcx) }), cx, ), @@ -2284,10 +2303,12 @@ fn clean_middle_opaque_bounds<'tcx>( .iter() .filter_map(|bound| { if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() { - if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() { + if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() { Some(TypeBinding { assoc: projection_to_path_segment( - bound.kind().rebind(proj.projection_ty), + // FIXME: This needs to be made resilient for `AliasTerm`s that + // are associated consts. + bound.kind().rebind(proj.projection_term.expect_ty(cx.tcx)), cx, ), kind: TypeBindingKind::Equality { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index d3347466be9..ae9aa83efd6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -417,7 +417,7 @@ fn get_input_traits_and_projections<'tcx>( } }, ClauseKind::Projection(projection_predicate) => { - if projection_predicate.projection_ty.self_ty() == input { + if projection_predicate.projection_term.self_ty() == input { projection_predicates.push(projection_predicate); } }, diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index e6c6a15b8d4..8de5caf32b7 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -320,11 +320,11 @@ fn is_mixed_projection_predicate<'tcx>( && (term_param_ty.index as usize) < generics.parent_count { // The inner-most self type is a type parameter from the current function. - let mut projection_ty = projection_predicate.projection_ty; + let mut projection_ty = projection_predicate.projection_term; loop { - match projection_ty.self_ty().kind() { + match *projection_ty.self_ty().kind() { ty::Alias(ty::Projection, inner_projection_ty) => { - projection_ty = *inner_projection_ty; + projection_ty = inner_projection_ty.into(); }, ty::Param(param_ty) => { return (param_ty.index as usize) >= generics.parent_count; @@ -404,14 +404,11 @@ fn replace_types<'tcx>( // The `replaced.insert(...)` check provides some protection against infinite loops. if replaced.insert(param_ty.index) { for projection_predicate in projection_predicates { - if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx) + if projection_predicate.projection_term.self_ty() == param_ty.to_ty(cx.tcx) && let Some(term_ty) = projection_predicate.term.ty() && let ty::Param(term_param_ty) = term_ty.kind() { - let projection = cx.tcx.mk_ty_from_kind(ty::Alias( - ty::Projection, - projection_predicate.projection_ty.with_self_ty(cx.tcx, new_ty), - )); + let projection = projection_predicate.projection_term.with_self_ty(cx.tcx, new_ty).expect_ty(cx.tcx).to_ty(cx.tcx); if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) && args[term_param_ty.index as usize] != GenericArg::from(projected_ty) diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index 214b69dc925..f0d1458a59b 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -66,7 +66,7 @@ fn get_projection_pred<'tcx>( let projection_pred = cx .tcx .instantiate_bound_regions_with_erased(proj_pred.kind().rebind(pred)); - if projection_pred.projection_ty.args == trait_pred.trait_ref.args { + if projection_pred.projection_term.args == trait_pred.trait_ref.args { return Some(projection_pred); } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 97bba8648c5..e3ab42c3107 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -795,7 +795,7 @@ fn sig_from_bounds<'tcx>( inputs = Some(i); }, ty::ClauseKind::Projection(p) - if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty => + if Some(p.projection_term.def_id) == lang_items.fn_once_output() && p.projection_term.self_ty() == ty => { if output.is_some() { // Multiple different fn trait impls. Is this even allowed? @@ -834,7 +834,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option } inputs = Some(i); }, - ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => { + ty::ClauseKind::Projection(p) if Some(p.projection_term.def_id) == lang_items.fn_once_output() => { if output.is_some() { // Multiple different fn trait impls. Is this even allowed? return None;