From 631cd5845e8de329d0e227aaa707d7ea228b8f8f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:20:29 +0200 Subject: Merging upstream version 1.70.0+dfsg1. Signed-off-by: Daniel Baumann --- .../rustc_hir_analysis/src/collect/generics_of.rs | 16 +- .../rustc_hir_analysis/src/collect/item_bounds.rs | 76 +++++--- .../src/collect/predicates_of.rs | 200 +++++++++++++-------- .../src/collect/resolve_bound_vars.rs | 78 ++++++-- compiler/rustc_hir_analysis/src/collect/type_of.rs | 141 ++++++++------- 5 files changed, 321 insertions(+), 190 deletions(-) (limited to 'compiler/rustc_hir_analysis/src/collect') diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 127d4fa90..119933697 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -5,16 +5,16 @@ use hir::{ }; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { +pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); let parent_def_id = match node { @@ -121,7 +121,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(parent_def_id.to_def_id()) } Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => { - Some(tcx.typeck_root_def_id(def_id)) + Some(tcx.typeck_root_def_id(def_id.to_def_id())) } // Exclude `GlobalAsm` here which cannot have generics. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) @@ -140,7 +140,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } } Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => { - Some(tcx.typeck_root_def_id(def_id)) + Some(tcx.typeck_root_def_id(def_id.to_def_id())) } Node::Item(item) => match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { @@ -189,7 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let opt_self = Some(ty::GenericParamDef { index: 0, name: kw::SelfUpper, - def_id, + def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, @@ -326,7 +326,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { index: next_index(), name: Symbol::intern(arg), - def_id, + def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, })); @@ -339,7 +339,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { params.push(ty::GenericParamDef { index: next_index(), name: Symbol::intern(""), - def_id, + def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, }); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 9cf3ff65a..2e56d2463 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -3,8 +3,8 @@ use crate::astconv::AstConv; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, DefIdTree, TyCtxt}; -use rustc_span::def_id::DefId; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; /// For associated types we include both bounds written on the type @@ -16,12 +16,12 @@ use rustc_span::Span; /// `hr-associated-type-bound-1.rs`. fn associated_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, - assoc_item_def_id: DefId, + assoc_item_def_id: LocalDefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { let item_ty = tcx.mk_projection( - assoc_item_def_id, + assoc_item_def_id.to_def_id(), InternalSubsts::identity_for_item(tcx, assoc_item_def_id), ); @@ -30,8 +30,8 @@ fn associated_type_bounds<'tcx>( // Associated types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); - let trait_def_id = tcx.parent(assoc_item_def_id); - let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); + let trait_def_id = tcx.local_parent(assoc_item_def_id); + let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id); let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| { match pred.kind().skip_binder() { @@ -45,7 +45,11 @@ fn associated_type_bounds<'tcx>( }); let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent)); - debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds); + debug!( + "associated_type_bounds({}) = {:?}", + tcx.def_path_str(assoc_item_def_id.to_def_id()), + all_bounds + ); all_bounds } @@ -56,19 +60,12 @@ fn associated_type_bounds<'tcx>( #[instrument(level = "trace", skip(tcx), ret)] fn opaque_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, - opaque_def_id: DefId, + opaque_def_id: LocalDefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], + item_ty: Ty<'tcx>, span: Span, - in_trait: bool, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries!({ - let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id); - let item_ty = if in_trait { - tcx.mk_projection(opaque_def_id, substs) - } else { - tcx.mk_opaque(opaque_def_id, substs) - }; - let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds); // Opaque types are implicitly sized unless a `?Sized` bound is found @@ -81,9 +78,31 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, - def_id: DefId, + def_id: LocalDefId, ) -> &'_ [(ty::Predicate<'_>, Span)] { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.opt_rpitit_info(def_id.to_def_id()) { + // RPITIT's bounds are the same as opaque type bounds, but with + // a projection self type. + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item(); + let opaque_ty = item.expect_opaque_ty(); + return opaque_type_bounds( + tcx, + opaque_def_id.expect_local(), + opaque_ty.bounds, + tcx.mk_projection( + def_id.to_def_id(), + ty::InternalSubsts::identity_for_item(tcx, def_id), + ), + item.span, + ); + } + // These should have been fed! + Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(), + None => {} + } + + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); match tcx.hir().get(hir_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(bounds, _), @@ -94,7 +113,15 @@ pub(super) fn explicit_item_bounds( kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }), span, .. - }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait), + }) => { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() { + tcx.mk_projection(def_id.to_def_id(), substs) + } else { + tcx.mk_opaque(def_id.to_def_id(), substs) + }; + opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) + } _ => bug!("item_bounds called on {:?}", def_id), } } @@ -103,12 +130,9 @@ pub(super) fn item_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<&'_ ty::List>> { - let bounds = tcx.mk_predicates_from_iter( - util::elaborate_predicates( - tcx, - tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), - ) - .map(|obligation| obligation.predicate), - ); + let bounds = tcx.mk_predicates_from_iter(util::elaborate( + tcx, + tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), + )); ty::EarlyBinder(bounds) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2badd66e3..9358ed612 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -62,15 +62,16 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. #[instrument(level = "trace", skip(tcx), ret)] -fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { +fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); let mut is_trait = None; let mut is_default_impl_trait = None; + // FIXME: Should ItemCtxt take a LocalDefId? let icx = ItemCtxt::new(tcx, def_id); const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty(); @@ -99,7 +100,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP | ItemKind::Union(_, generics) => generics, ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => { - is_trait = Some(ty::TraitRef::identity(tcx, def_id)); + is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id())); generics } ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics, @@ -124,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // on a trait we need to add in the supertrait bounds and bounds found on // associated types. if let Some(_trait_ref) = is_trait { - predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); + predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned()); } // In default impls, we can assume that the self type implements @@ -253,7 +254,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } if tcx.features().generic_const_exprs { - predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local())); + predicates.extend(const_evaluatable_predicates_of(tcx, def_id)); } let mut predicates: Vec<_> = predicates.into_iter().collect(); @@ -392,18 +393,18 @@ pub(super) fn trait_explicit_predicates_and_bounds( def_id: LocalDefId, ) -> ty::GenericPredicates<'_> { assert_eq!(tcx.def_kind(def_id), DefKind::Trait); - gather_explicit_predicates_of(tcx, def_id.to_def_id()) + gather_explicit_predicates_of(tcx, def_id) } pub(super) fn explicit_predicates_of<'tcx>( tcx: TyCtxt<'tcx>, - def_id: DefId, + def_id: LocalDefId, ) -> ty::GenericPredicates<'tcx> { let def_kind = tcx.def_kind(def_id); if let DefKind::Trait = def_kind { // Remove bounds on associated types from the predicates, they will be // returned by `explicit_item_bounds`. - let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local()); + let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id); let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id); let is_assoc_item_ty = |ty: Ty<'tcx>| { @@ -418,7 +419,8 @@ pub(super) fn explicit_predicates_of<'tcx>( // supertrait). if let ty::Alias(ty::Projection, projection) = ty.kind() { projection.substs == trait_identity_substs - && tcx.associated_item(projection.def_id).container_id(tcx) == def_id + && tcx.associated_item(projection.def_id).container_id(tcx) + == def_id.to_def_id() } else { false } @@ -449,7 +451,7 @@ pub(super) fn explicit_predicates_of<'tcx>( } } else { if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = tcx.hir().get_parent_item(hir_id); if let Some(defaulted_param_def_id) = @@ -532,89 +534,136 @@ pub(super) fn explicit_predicates_of<'tcx>( } } +#[derive(Copy, Clone, Debug)] +pub enum PredicateFilter { + /// All predicates may be implied by the trait + All, + + /// Only traits that reference `Self: ..` are implied by the trait + SelfOnly, + + /// Only traits that reference `Self: ..` and define an associated type + /// with the given ident are implied by the trait + SelfThatDefines(Ident), +} + /// Ensures that the super-predicates of the trait with a `DefId` /// of `trait_def_id` are converted and stored. This also ensures that /// the transitive super-predicates are converted. pub(super) fn super_predicates_of( tcx: TyCtxt<'_>, - trait_def_id: DefId, + trait_def_id: LocalDefId, +) -> ty::GenericPredicates<'_> { + implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly) +} + +pub(super) fn super_predicates_that_define_assoc_type( + tcx: TyCtxt<'_>, + (trait_def_id, assoc_name): (DefId, Ident), +) -> ty::GenericPredicates<'_> { + implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name)) +} + +pub(super) fn implied_predicates_of( + tcx: TyCtxt<'_>, + trait_def_id: LocalDefId, ) -> ty::GenericPredicates<'_> { - tcx.super_predicates_that_define_assoc_type((trait_def_id, None)) + if tcx.is_trait_alias(trait_def_id.to_def_id()) { + implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All) + } else { + tcx.super_predicates_of(trait_def_id) + } } /// Ensures that the super-predicates of the trait with a `DefId` /// of `trait_def_id` are converted and stored. This also ensures that /// the transitive super-predicates are converted. -pub(super) fn super_predicates_that_define_assoc_type( +pub(super) fn implied_predicates_with_filter( tcx: TyCtxt<'_>, - (trait_def_id, assoc_name): (DefId, Option), + trait_def_id: DefId, + filter: PredicateFilter, ) -> ty::GenericPredicates<'_> { - if trait_def_id.is_local() { - debug!("local trait"); - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); - - let Node::Item(item) = tcx.hir().get(trait_hir_id) else { - bug!("trait_node_id {} is not an item", trait_hir_id); - }; + let Some(trait_def_id) = trait_def_id.as_local() else { + // if `assoc_name` is None, then the query should've been redirected to an + // external provider + assert!(matches!(filter, PredicateFilter::SelfThatDefines(_))); + return tcx.super_predicates_of(trait_def_id); + }; - let (generics, bounds) = match item.kind { - hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits), - _ => span_bug!(item.span, "super_predicates invoked on non-trait"), - }; + let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id); - let icx = ItemCtxt::new(tcx, trait_def_id); + let Node::Item(item) = tcx.hir().get(trait_hir_id) else { + bug!("trait_node_id {} is not an item", trait_hir_id); + }; - // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. - let self_param_ty = tcx.types.self_param; - let superbounds1 = if let Some(assoc_name) = assoc_name { - icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name) - } else { - icx.astconv().compute_bounds(self_param_ty, bounds) - }; + let (generics, bounds) = match item.kind { + hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits), + _ => span_bug!(item.span, "super_predicates invoked on non-trait"), + }; - let superbounds1 = superbounds1.predicates(); - - // Convert any explicit superbounds in the where-clause, - // e.g., `trait Foo where Self: Bar`. - // In the case of trait aliases, however, we include all bounds in the where-clause, - // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` - // as one of its "superpredicates". - let is_trait_alias = tcx.is_trait_alias(trait_def_id); - let superbounds2 = icx.type_parameter_bounds_in_generics( - generics, - item.owner_id.def_id, - self_param_ty, - OnlySelfBounds(!is_trait_alias), - assoc_name, - ); + let icx = ItemCtxt::new(tcx, trait_def_id); + + let self_param_ty = tcx.types.self_param; + let (superbounds, where_bounds_that_match) = match filter { + PredicateFilter::All => ( + // Convert the bounds that follow the colon (or equal in trait aliases) + icx.astconv().compute_bounds(self_param_ty, bounds), + // Also include all where clause bounds + icx.type_parameter_bounds_in_generics( + generics, + item.owner_id.def_id, + self_param_ty, + OnlySelfBounds(false), + None, + ), + ), + PredicateFilter::SelfOnly => ( + // Convert the bounds that follow the colon (or equal in trait aliases) + icx.astconv().compute_bounds(self_param_ty, bounds), + // Include where clause bounds for `Self` + icx.type_parameter_bounds_in_generics( + generics, + item.owner_id.def_id, + self_param_ty, + OnlySelfBounds(true), + None, + ), + ), + PredicateFilter::SelfThatDefines(assoc_name) => ( + // Convert the bounds that follow the colon (or equal) that reference the associated name + icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name), + // Include where clause bounds for `Self` that reference the associated name + icx.type_parameter_bounds_in_generics( + generics, + item.owner_id.def_id, + self_param_ty, + OnlySelfBounds(true), + Some(assoc_name), + ), + ), + }; - // Combine the two lists to form the complete set of superbounds: - let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); - debug!(?superbounds); + // Combine the two lists to form the complete set of superbounds: + let implied_bounds = &*tcx + .arena + .alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match)); + debug!(?implied_bounds); + // Now require that immediate supertraits are converted, + // which will, in turn, reach indirect supertraits. + if matches!(filter, PredicateFilter::SelfOnly) { // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. - if assoc_name.is_none() { - // Now require that immediate supertraits are converted, - // which will, in turn, reach indirect supertraits. - for &(pred, span) in superbounds { - debug!("superbound: {:?}", pred); - if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = - pred.kind().skip_binder() - { - tcx.at(span).super_predicates_of(bound.def_id()); - } + for &(pred, span) in implied_bounds { + debug!("superbound: {:?}", pred); + if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() { + tcx.at(span).super_predicates_of(bound.def_id()); } } - - ty::GenericPredicates { parent: None, predicates: superbounds } - } else { - // if `assoc_name` is None, then the query should've been redirected to an - // external provider - assert!(assoc_name.is_some()); - tcx.super_predicates_of(trait_def_id) } + + ty::GenericPredicates { parent: None, predicates: implied_bounds } } /// Returns the predicates defined on `item_def_id` of the form @@ -622,7 +671,7 @@ pub(super) fn super_predicates_that_define_assoc_type( #[instrument(level = "trace", skip(tcx))] pub(super) fn type_param_predicates( tcx: TyCtxt<'_>, - (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), + (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident), ) -> ty::GenericPredicates<'_> { use rustc_hir::*; @@ -637,21 +686,21 @@ pub(super) fn type_param_predicates( let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)); // Don't look for bounds where the type parameter isn't in scope. - let parent = if item_def_id == param_owner.to_def_id() { + let parent = if item_def_id == param_owner { None } else { - tcx.generics_of(item_def_id).parent + tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local()) }; let mut result = parent .map(|parent| { let icx = ItemCtxt::new(tcx, parent); - icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name) + icx.get_type_parameter_bounds(DUMMY_SP, def_id, assoc_name) }) .unwrap_or_default(); let mut extend = None; - let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()); + let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id); let ast_generics = match tcx.hir().get(item_hir_id) { Node::TraitItem(item) => &item.generics, @@ -673,7 +722,8 @@ pub(super) fn type_param_predicates( ItemKind::Trait(_, _, generics, ..) => { // Implied `Self: Trait` and supertrait bounds. if param_id == item_hir_id { - let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); + let identity_trait_ref = + ty::TraitRef::identity(tcx, item_def_id.to_def_id()); extend = Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 65a9052a6..e758fe95d 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -17,7 +17,7 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeNa use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::*; -use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; @@ -1051,9 +1051,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } } -fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault { +fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault { debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam); - let param_def_id = param_def_id.expect_local(); let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else { bug!("expected GenericParam for object_lifetime_default"); }; @@ -1427,25 +1426,25 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if let ResolvedArg::LateBound(..) = def && crossed_anon_const { let use_span = self.tcx.hir().span(hir_id); let def_span = self.tcx.def_span(param_def_id); - match self.tcx.def_kind(param_def_id) { + let guar = match self.tcx.def_kind(param_def_id) { DefKind::ConstParam => { self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const { use_span, def_span, - }); + }) } DefKind::TyParam => { self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type { use_span, def_span, - }); + }) } _ => unreachable!(), - } - return; + }; + self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + } else { + self.map.defs.insert(hir_id, def); } - - self.map.defs.insert(hir_id, def); return; } @@ -1462,7 +1461,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { depth: usize, generic_args: &'tcx hir::GenericArgs<'tcx>, ) { - if generic_args.parenthesized { + if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { self.visit_fn_like_elision( generic_args.inputs(), Some(generic_args.bindings[0].ty()), @@ -1641,7 +1640,59 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }, s: self.scope, }; - if let Some(type_def_id) = type_def_id { + // If the binding is parenthesized, then this must be `feature(return_type_notation)`. + // In that case, introduce a binder over all of the function's early and late bound vars. + // + // For example, given + // ``` + // trait Foo { + // async fn x<'r, T>(); + // } + // ``` + // and a bound that looks like: + // `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>` + // this is going to expand to something like: + // `for<'a> for<'r, T> >::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`. + if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { + let bound_vars = if let Some(type_def_id) = type_def_id + && self.tcx.def_kind(type_def_id) == DefKind::Trait + // FIXME(return_type_notation): We could bound supertrait methods. + && let Some(assoc_fn) = self + .tcx + .associated_items(type_def_id) + .find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id) + { + self.tcx + .generics_of(assoc_fn.def_id) + .params + .iter() + .map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region( + ty::BoundRegionKind::BrNamed(param.def_id, param.name), + ), + ty::GenericParamDefKind::Type { .. } => ty::BoundVariableKind::Ty( + ty::BoundTyKind::Param(param.def_id, param.name), + ), + ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const, + }) + .chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars()) + .collect() + } else { + self.tcx.sess.delay_span_bug( + binding.ident.span, + "bad return type notation here", + ); + vec![] + }; + self.with(scope, |this| { + let scope = Scope::Supertrait { bound_vars, s: this.scope }; + this.with(scope, |this| { + let (bound_vars, _) = this.poly_trait_ref_binder_info(); + this.record_late_bound_vars(binding.hir_id, bound_vars); + this.visit_assoc_type_binding(binding) + }); + }); + } else if let Some(type_def_id) = type_def_id { let bound_vars = BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident); self.with(scope, |this| { @@ -1698,8 +1749,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if trait_defines_associated_type_named(def_id) { break Some(bound_vars.into_iter().collect()); } - let predicates = - tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name))); + let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name)); let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 50073d94e..c173bd913 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -8,9 +8,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{ - self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt, -}; +use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -62,7 +60,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .find(|(_, node)| matches!(node, OwnerNode::Item(_))) .unwrap() .0 - .to_def_id(); + .def_id; let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>; let ty = item_ctxt.ast_ty_to_ty(hir_ty); @@ -243,24 +241,46 @@ fn get_path_containing_arg_in_pat<'hir>( arg_path } -pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> { - let def_id = def_id.expect_local(); +pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder> { + // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl + // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the + // associated type in the impl. + if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = + tcx.opt_rpitit_info(def_id.to_def_id()) + { + match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { + Ok(map) => { + let assoc_item = tcx.associated_item(def_id); + return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]); + } + Err(_) => { + return ty::EarlyBinder(tcx.ty_error_with_message( + DUMMY_SP, + "Could not collect return position impl trait in trait tys", + )); + } + } + } + use rustc_hir::*; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let icx = ItemCtxt::new(tcx, def_id.to_def_id()); + let icx = ItemCtxt::new(tcx, def_id); let output = match tcx.hir().get(hir_id) { Node::TraitItem(item) => match item.kind { TraitItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } TraitItemKind::Const(ty, body_id) => body_id .and_then(|body_id| { - is_suggestable_infer_ty(ty) - .then(|| infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant",)) + is_suggestable_infer_ty(ty).then(|| { + infer_placeholder_type( + tcx, def_id, body_id, ty.span, item.ident, "constant", + ) + }) }) .unwrap_or_else(|| icx.to_ty(ty)), TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty), @@ -271,7 +291,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> Node::ImplItem(item) => match item.kind { ImplItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } ImplItemKind::Const(ty, body_id) => { @@ -316,22 +336,23 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> } } ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty), - ItemKind::Impl(hir::Impl { self_ty, .. }) => { - match self_ty.find_self_aliases() { - spans if spans.len() > 0 => { - let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () }); - tcx.ty_error(guar) - }, - _ => icx.to_ty(*self_ty), + ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() { + spans if spans.len() > 0 => { + let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { + span: spans.into(), + note: (), + }); + tcx.ty_error(guar) } + _ => icx.to_ty(*self_ty), }, ItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { let def = tcx.adt_def(def_id); - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_adt(def, substs) } ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { @@ -344,8 +365,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> in_trait, .. }) => { - if in_trait { - assert!(tcx.impl_defaultness(owner).has_value()); + if in_trait && !tcx.impl_defaultness(owner).has_value() { + span_bug!( + tcx.def_span(def_id), + "tried to get type of this RPITIT with no definition" + ); } find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) } @@ -368,7 +392,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> Node::ForeignItem(foreign_item) => match foreign_item.kind { ForeignItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } ForeignItemKind::Static(t, _) => icx.to_ty(t), @@ -380,7 +404,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity() } VariantData::Tuple(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id.to_def_id(), substs) } }, @@ -413,7 +437,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. }) if anon_const.hir_id == hir_id => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let substs = InternalSubsts::identity_for_item(tcx, def_id); substs.as_inline_const().ty() } @@ -434,15 +458,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) } - Node::TypeBinding( - TypeBinding { - hir_id: binding_id, - kind: TypeBindingKind::Equality { term: Term::Const(e) }, - ident, - .. - }, - ) if let Node::TraitRef(trait_ref) = - tcx.hir().get_parent(*binding_id) + Node::TypeBinding(TypeBinding { + hir_id: binding_id, + kind: TypeBindingKind::Equality { term: Term::Const(e) }, + ident, + .. + }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id) && e.hir_id == hir_id => { let Some(trait_def_id) = trait_ref.trait_def_id() else { @@ -456,7 +477,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> def_id.to_def_id(), ); if let Some(assoc_item) = assoc_item { - tcx.type_of(assoc_item.def_id).subst_identity() + tcx.type_of(assoc_item.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic") } else { // FIXME(associated_const_equality): add a useful error message here. tcx.ty_error_with_message( @@ -466,10 +489,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> } } - Node::TypeBinding( - TypeBinding { hir_id: binding_id, gen_args, kind, ident, .. }, - ) if let Node::TraitRef(trait_ref) = - tcx.hir().get_parent(*binding_id) + Node::TypeBinding(TypeBinding { + hir_id: binding_id, + gen_args, + kind, + ident, + .. + }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id) && let Some((idx, _)) = gen_args.args.iter().enumerate().find(|(_, arg)| { if let GenericArg::Const(ct) = arg { @@ -498,15 +524,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> }, def_id.to_def_id(), ); - if let Some(param) - = assoc_item.map(|item| &tcx.generics_of(item.def_id).params[idx]).filter(|param| param.kind.is_ty_or_const()) + if let Some(assoc_item) = assoc_item + && let param = &tcx.generics_of(assoc_item.def_id).params[idx] + && matches!(param.kind, ty::GenericParamDefKind::Const { .. }) { - tcx.type_of(param.def_id).subst_identity() + tcx.type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic") } else { // FIXME(associated_const_equality): add a useful error message here. tcx.ty_error_with_message( DUMMY_SP, - "Could not find associated const on trait", + "Could not find const param on associated item", ) } } @@ -574,7 +603,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T found: Option>, /// In the presence of dead code, typeck may figure out a hidden type - /// while borrowck will now. We collect these cases here and check at + /// while borrowck will not. We collect these cases here and check at /// the end that we actually found a type that matches (modulo regions). typeck_types: Vec>, } @@ -746,7 +775,7 @@ fn find_opaque_ty_constraints_for_rpit( // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; debug!(?concrete_opaque_types); - for &(def_id, concrete_type) in concrete_opaque_types { + for (&def_id, &concrete_type) in concrete_opaque_types { if def_id != self.def_id { // Ignore constraints for other opaque types. continue; @@ -842,28 +871,6 @@ fn infer_placeholder_type<'a>( item_ident: Ident, kind: &'static str, ) -> Ty<'a> { - // Attempts to make the type nameable by turning FnDefs into FnPtrs. - struct MakeNameable<'tcx> { - tcx: TyCtxt<'tcx>, - } - - impl<'tcx> TypeFolder> for MakeNameable<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty = match *ty.kind() { - ty::FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) - } - _ => ty, - }; - - ty.super_fold_with(self) - } - } - let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id); // If this came from a free `const` or `static mut?` item, -- cgit v1.2.3