summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/collect
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_hir_analysis/src/collect
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/collect')
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs59
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs57
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs328
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs73
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs89
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs131
6 files changed, 462 insertions, 275 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index ed60998ec..ccc9f8084 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -9,7 +9,7 @@ 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;
+use rustc_span::{sym, Span};
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*;
@@ -50,7 +50,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// We do not allow generic parameters in anon consts if we are inside
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
None
- } else if tcx.lazy_normalization() {
+ } else if tcx.features().generic_const_exprs {
let parent_node = tcx.hir().get_parent(hir_id);
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
&& constant.hir_id == hir_id
@@ -101,6 +101,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: generics.has_self,
has_late_bound_regions: generics.has_late_bound_regions,
+ host_effect_index: None,
};
} else {
// HACK(eddyb) this provides the correct generics when
@@ -123,9 +124,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
{
Some(parent_def_id.to_def_id())
}
- Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
- 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), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
@@ -142,11 +140,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
}
}
- Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
+ Node::ConstBlock(_)
+ | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
}
Node::Item(item) => match item.kind {
- ItemKind::OpaqueTy(hir::OpaqueTy {
+ ItemKind::OpaqueTy(&hir::OpaqueTy {
origin:
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
in_trait,
@@ -228,10 +227,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
let has_self = opt_self.is_some();
let mut parent_has_self = false;
let mut own_start = has_self as u32;
+ let mut host_effect_index = None;
let parent_count = parent_def_id.map_or(0, |def_id| {
let generics = tcx.generics_of(def_id);
assert!(!has_self);
parent_has_self = generics.has_self;
+ host_effect_index = generics.host_effect_index;
own_start = generics.count() as u32;
generics.parent_count + generics.params.len()
});
@@ -253,11 +254,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
- let mut i = 0;
+ let mut i: u32 = 0;
let mut next_index = || {
let prev = i;
i += 1;
- prev as u32 + type_start
+ prev + type_start
};
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
@@ -297,7 +298,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
})
}
GenericParamKind::Const { default, .. } => {
- if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
+ let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host);
+
+ if !matches!(allow_defaults, Defaults::Allowed)
+ && default.is_some()
+ // `rustc_host` effect params are allowed to have defaults.
+ && !is_host_param
+ {
tcx.sess.span_err(
param.span,
"defaults for const parameters are only allowed in \
@@ -305,8 +312,18 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
);
}
+ let index = next_index();
+
+ if is_host_param {
+ if let Some(idx) = host_effect_index {
+ bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
+ }
+
+ host_effect_index = Some(parent_count + index as usize);
+ }
+
Some(ty::GenericParamDef {
- index: next_index(),
+ index,
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
@@ -339,17 +356,14 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
// provide junk type parameter defs for const blocks.
- if let Node::AnonConst(_) = node {
- let parent_node = tcx.hir().get_parent(hir_id);
- if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
- params.push(ty::GenericParamDef {
- index: next_index(),
- name: Symbol::intern("<const_ty>"),
- def_id: def_id.to_def_id(),
- pure_wrt_drop: false,
- kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
- });
- }
+ if let Node::ConstBlock(_) = node {
+ params.push(ty::GenericParamDef {
+ index: next_index(),
+ name: Symbol::intern("<const_ty>"),
+ def_id: def_id.to_def_id(),
+ pure_wrt_drop: false,
+ kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
+ });
}
let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
@@ -361,6 +375,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: has_self || parent_has_self,
has_late_bound_regions: has_late_bound_regions(tcx, node),
+ host_effect_index,
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 948b903e5..57f74172e 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -1,5 +1,5 @@
use super::ItemCtxt;
-use crate::astconv::{AstConv, OnlySelfBounds};
+use crate::astconv::{AstConv, PredicateFilter};
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
@@ -19,32 +19,34 @@ fn associated_type_bounds<'tcx>(
assoc_item_def_id: LocalDefId,
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
- let item_ty = tcx.mk_projection(
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
+ let item_ty = Ty::new_projection(
+ tcx,
assoc_item_def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
);
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
- let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
// 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.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() {
- ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => tr.self_ty() == item_ty,
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => {
- proj.projection_ty.self_ty() == item_ty
- }
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => outlives.0 == item_ty,
+ 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::TypeOutlives(outlives) => outlives.0 == item_ty,
_ => false,
- }
- });
+ })
+ .map(|(clause, span)| (clause, span));
- let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent));
+ let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
debug!(
"associated_type_bounds({}) = {:?}",
tcx.def_path_str(assoc_item_def_id.to_def_id()),
@@ -64,33 +66,34 @@ fn opaque_type_bounds<'tcx>(
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
item_ty: Ty<'tcx>,
span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
ty::print::with_no_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id);
- let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
// Opaque types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds);
- tcx.arena.alloc_from_iter(bounds.predicates())
+ tcx.arena.alloc_from_iter(bounds.clauses())
})
}
pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
-) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> {
+) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
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 ty::EarlyBinder(opaque_type_bounds(
+ return ty::EarlyBinder::bind(opaque_type_bounds(
tcx,
opaque_def_id.expect_local(),
opaque_ty.bounds,
- tcx.mk_projection(
+ Ty::new_projection(
+ tcx,
def_id.to_def_id(),
ty::InternalSubsts::identity_for_item(tcx, def_id),
),
@@ -116,25 +119,23 @@ pub(super) fn explicit_item_bounds(
}) => {
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)
+ Ty::new_projection(tcx, def_id.to_def_id(), substs)
} else {
- tcx.mk_opaque(def_id.to_def_id(), substs)
+ Ty::new_opaque(tcx, def_id.to_def_id(), substs)
};
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
_ => bug!("item_bounds called on {:?}", def_id),
};
- ty::EarlyBinder(bounds)
+ ty::EarlyBinder::bind(bounds)
}
pub(super) fn item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
-) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
+) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
- tcx.mk_predicates_from_iter(util::elaborate(
- tcx,
- bounds.iter().map(|&(bound, _span)| bound),
- ))
+ tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
})
}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index e5b5dae55..129366641 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,8 +1,8 @@
-use crate::astconv::{AstConv, OnlySelfBounds};
+use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
-use hir::{HirId, Node};
+use hir::{HirId, Lifetime, Node};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
@@ -10,9 +10,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, ToPredicate};
+use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
use rustc_span::symbol::{sym, Ident};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{Span, Symbol, DUMMY_SP};
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -62,6 +62,67 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
+ match tcx.opt_rpitit_info(def_id.to_def_id()) {
+ Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
+ let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
+ let opaque_ty_node = tcx.hir().get(opaque_ty_id);
+ let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
+ bug!("unexpected {opaque_ty_node:?}")
+ };
+
+ let mut predicates = Vec::new();
+
+ // RPITITs should inherit the predicates of their parent. This is
+ // both to ensure that the RPITITs are only instantiated when the
+ // parent predicates would hold, and also so that the param-env
+ // inherits these predicates as assumptions.
+ let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+ predicates.extend(
+ tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_substs),
+ );
+
+ // We also install bidirectional outlives predicates for the RPITIT
+ // to keep the duplicates lifetimes from opaque lowering in sync.
+ compute_bidirectional_outlives_predicates(
+ tcx,
+ def_id,
+ lifetime_mapping.iter().map(|(lifetime, def_id)| {
+ (*lifetime, (*def_id, lifetime.ident.name, lifetime.ident.span))
+ }),
+ tcx.generics_of(def_id.to_def_id()),
+ &mut predicates,
+ );
+
+ return ty::GenericPredicates {
+ parent: Some(tcx.parent(def_id.to_def_id())),
+ predicates: tcx.arena.alloc_from_iter(predicates),
+ };
+ }
+
+ Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
+ let assoc_item = tcx.associated_item(def_id);
+ let trait_assoc_predicates =
+ tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
+
+ let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+ let impl_def_id = tcx.parent(fn_def_id);
+ let impl_trait_ref_substs =
+ tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity().substs;
+
+ let impl_assoc_substs =
+ impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
+
+ let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_substs);
+
+ return ty::GenericPredicates {
+ parent: Some(impl_def_id),
+ predicates: tcx.arena.alloc_from_iter(impl_predicates),
+ };
+ }
+
+ None => {}
+ }
+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let node = tcx.hir().get(hir_id);
@@ -75,7 +136,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// We use an `IndexSet` to preserve order of insertion.
// Preserving the order of insertion is important here so as not to break UI tests.
- let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
+ let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
let ast_generics = match node {
Node::TraitItem(item) => item.generics,
@@ -125,8 +186,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
if let Some(self_bounds) = is_trait {
predicates.extend(
icx.astconv()
- .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
- .predicates(),
+ .compute_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
+ .clauses(),
);
}
@@ -175,22 +236,24 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
param.span,
);
trace!(?bounds);
- predicates.extend(bounds.predicates());
+ predicates.extend(bounds.clauses());
trace!(?predicates);
}
GenericParamKind::Const { .. } => {
let name = param.name.ident().name;
let param_const = ty::ParamConst::new(index, name);
- let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity();
+ let ct_ty = tcx
+ .type_of(param.def_id.to_def_id())
+ .no_bound_vars()
+ .expect("const parameters cannot be generic");
- let ct = tcx.mk_const(param_const, ct_ty);
+ let ct = ty::Const::new_param(tcx, param_const, ct_ty);
- let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
- ty::Clause::ConstArgHasType(ct, ct_ty),
- ))
- .to_predicate(tcx);
- predicates.insert((predicate, param.span));
+ predicates.insert((
+ ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
+ param.span,
+ ));
index += 1;
}
@@ -219,7 +282,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
} else {
let span = bound_pred.bounded_ty.span;
let predicate = ty::Binder::bind_with_vars(
- ty::PredicateKind::WellFormed(ty.into()),
+ ty::ClauseKind::WellFormed(ty.into()),
bound_vars,
);
predicates.insert((predicate.to_predicate(tcx), span));
@@ -234,7 +297,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bound_vars,
OnlySelfBounds(false),
);
- predicates.extend(bounds.predicates());
+ predicates.extend(bounds.clauses());
}
hir::WherePredicate::RegionPredicate(region_pred) => {
@@ -246,11 +309,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
_ => bug!(),
};
- let pred = ty::Binder::dummy(ty::PredicateKind::Clause(
- ty::Clause::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
- ))
- .to_predicate(icx.tcx);
-
+ let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+ .to_predicate(icx.tcx);
(pred, span)
}))
}
@@ -293,39 +353,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bug!("unexpected {opaque_ty_node:?}")
};
debug!(?lifetimes);
- for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
- let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
- let orig_region = icx.astconv().ast_region_to_region(&arg, None);
- if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
- // Only early-bound regions can point to the original generic parameter.
- continue;
- }
- let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
- let dup_def = duplicate.def_id.to_def_id();
-
- let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
-
- let dup_region = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: dup_def,
- index: dup_index,
- name: duplicate.name.ident().name,
- });
- predicates.push((
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
- ty::OutlivesPredicate(orig_region, dup_region),
- )))
- .to_predicate(icx.tcx),
- duplicate.span,
- ));
- predicates.push((
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
- ty::OutlivesPredicate(dup_region, orig_region),
- )))
- .to_predicate(icx.tcx),
- duplicate.span,
- ));
- }
+ let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
+ .map(|(arg, dup)| {
+ let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
+ (**arg, dup)
+ })
+ .filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
+ .map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
+
+ compute_bidirectional_outlives_predicates(
+ tcx,
+ def_id,
+ lifetime_mapping,
+ generics,
+ &mut predicates,
+ );
debug!(?predicates);
}
@@ -335,13 +378,53 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
}
+/// Opaques have duplicated lifetimes and we need to compute bidirectional outlives predicates to
+/// enforce that these lifetimes stay in sync.
+fn compute_bidirectional_outlives_predicates<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ item_def_id: LocalDefId,
+ lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
+ generics: &Generics,
+ predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
+) {
+ let icx = ItemCtxt::new(tcx, item_def_id);
+
+ for (arg, (dup_def, name, span)) in lifetime_mapping {
+ let orig_region = icx.astconv().ast_region_to_region(&arg, None);
+ if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
+ // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
+ // show up in the opaque's parent's substs.
+ continue;
+ }
+
+ let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
+
+ let dup_region = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
+ );
+
+ predicates.push((
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
+ .to_predicate(tcx),
+ span,
+ ));
+
+ predicates.push((
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
+ .to_predicate(tcx),
+ span,
+ ));
+ }
+}
+
fn const_evaluatable_predicates_of(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
-) -> FxIndexSet<(ty::Predicate<'_>, Span)> {
+) -> FxIndexSet<(ty::Clause<'_>, Span)> {
struct ConstCollector<'tcx> {
tcx: TyCtxt<'tcx>,
- preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
+ preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
}
impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
@@ -349,11 +432,8 @@ fn const_evaluatable_predicates_of(
let ct = ty::Const::from_anon_const(self.tcx, c.def_id);
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
let span = self.tcx.def_span(c.def_id);
- self.preds.insert((
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
- .to_predicate(self.tcx),
- span,
- ));
+ self.preds
+ .insert((ty::ClauseKind::ConstEvaluatable(ct).to_predicate(self.tcx), span));
}
}
@@ -441,13 +521,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
.iter()
.copied()
.filter(|(pred, _)| match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => !is_assoc_item_ty(tr.self_ty()),
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => {
- !is_assoc_item_ty(proj.projection_ty.self_ty())
- }
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => {
- !is_assoc_item_ty(outlives.0)
- }
+ 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::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
_ => true,
})
.collect();
@@ -460,7 +536,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
}
} else {
- if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
+ if matches!(def_kind, DefKind::AnonConst) && tcx.features().generic_const_exprs {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = tcx.hir().get_parent_item(hir_id);
@@ -488,9 +564,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
.predicates
.into_iter()
.filter(|(pred, _)| {
- if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) =
- pred.kind().skip_binder()
- {
+ if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
match ct.kind() {
ty::ConstKind::Param(param_const) => {
let defaulted_param_idx = tcx
@@ -544,19 +618,6 @@ 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.
@@ -578,11 +639,15 @@ pub(super) fn implied_predicates_of(
tcx: TyCtxt<'_>,
trait_def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
- 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)
- }
+ implied_predicates_with_filter(
+ tcx,
+ trait_def_id.to_def_id(),
+ if tcx.is_trait_alias(trait_def_id.to_def_id()) {
+ PredicateFilter::All
+ } else {
+ PredicateFilter::SelfAndAssociatedTypeBounds
+ },
+ )
}
/// Ensures that the super-predicates of the trait with a `DefId`
@@ -615,48 +680,18 @@ pub(super) fn implied_predicates_with_filter(
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, OnlySelfBounds(false)),
- // 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, OnlySelfBounds(true)),
- // 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_item(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),
- ),
- ),
- };
+ let superbounds = icx.astconv().compute_bounds(self_param_ty, bounds, filter);
+
+ let where_bounds_that_match = icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ filter,
+ );
// Combine the two lists to form the complete set of superbounds:
let implied_bounds =
- &*tcx.arena.alloc_from_iter(superbounds.predicates().chain(where_bounds_that_match));
+ &*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match));
debug!(?implied_bounds);
// Now require that immediate supertraits are converted, which will, in
@@ -665,7 +700,7 @@ pub(super) fn implied_predicates_with_filter(
if matches!(filter, PredicateFilter::SelfOnly) {
for &(pred, span) in implied_bounds {
debug!("superbound: {:?}", pred);
- if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder()
+ if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
&& bound.polarity == ty::ImplPolarity::Positive
{
tcx.at(span).super_predicates_of(bound.def_id());
@@ -684,6 +719,7 @@ pub(super) fn type_param_predicates(
(item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident),
) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
+ use rustc_middle::ty::Ty;
// In the AST, bounds can derive from two places. Either
// written inline like `<T: Foo>` or in a where-clause like
@@ -693,7 +729,7 @@ pub(super) fn type_param_predicates(
let param_owner = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(param_owner);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
- let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id));
+ let ty = Ty::new_param(tcx, 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 {
@@ -721,7 +757,7 @@ pub(super) fn type_param_predicates(
ItemKind::Fn(.., generics, _)
| ItemKind::Impl(&hir::Impl { generics, .. })
| ItemKind::TyAlias(_, generics)
- | ItemKind::OpaqueTy(OpaqueTy {
+ | ItemKind::OpaqueTy(&OpaqueTy {
generics,
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
@@ -757,12 +793,11 @@ pub(super) fn type_param_predicates(
ast_generics,
def_id,
ty,
- OnlySelfBounds(true),
- Some(assoc_name),
+ PredicateFilter::SelfThatDefines(assoc_name),
)
.into_iter()
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => data.self_ty().is_param(index),
+ ty::ClauseKind::Trait(data) => data.self_ty().is_param(index),
_ => false,
}),
);
@@ -782,9 +817,8 @@ impl<'tcx> ItemCtxt<'tcx> {
ast_generics: &'tcx hir::Generics<'tcx>,
param_def_id: LocalDefId,
ty: Ty<'tcx>,
- only_self_bounds: OnlySelfBounds,
- assoc_name: Option<Ident>,
- ) -> Vec<(ty::Predicate<'tcx>, Span)> {
+ filter: PredicateFilter,
+ ) -> Vec<(ty::Clause<'tcx>, Span)> {
let mut bounds = Bounds::default();
for predicate in ast_generics.predicates {
@@ -792,9 +826,23 @@ impl<'tcx> ItemCtxt<'tcx> {
continue;
};
+ let (only_self_bounds, assoc_name) = match filter {
+ PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
+ (OnlySelfBounds(false), None)
+ }
+ PredicateFilter::SelfOnly => (OnlySelfBounds(true), None),
+ PredicateFilter::SelfThatDefines(assoc_name) => {
+ (OnlySelfBounds(true), Some(assoc_name))
+ }
+ };
+
+ // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
+ // want to only consider predicates with `Self: ...`, but we don't want
+ // `OnlySelfBounds(true)` since we want to collect the nested associated
+ // type bound as well.
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
ty
- } else if !only_self_bounds.0 {
+ } else if matches!(filter, PredicateFilter::All) {
self.to_ty(predicate.bounded_ty)
} else {
continue;
@@ -813,7 +861,7 @@ impl<'tcx> ItemCtxt<'tcx> {
);
}
- bounds.predicates().collect()
+ bounds.clauses().collect()
}
#[instrument(level = "trace", skip(self))]
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 794812a5c..acd0bcd8e 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -22,7 +22,7 @@ use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use std::fmt;
use crate::errors;
@@ -338,7 +338,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::TraitRefBoundary { .. } => {
// We should only see super trait lifetimes if there is a `Binder` above
- assert!(supertrait_bound_vars.is_empty());
+ // though this may happen when we call `poly_trait_ref_binder_info` with
+ // an (erroneous, #113423) associated return type bound in an impl header.
+ if !supertrait_bound_vars.is_empty() {
+ self.tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ format!(
+ "found supertrait lifetimes without a binder to append \
+ them to: {supertrait_bound_vars:?}"
+ ),
+ );
+ }
break (vec![], BinderScopeType::Normal);
}
@@ -556,7 +566,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
});
}
}
- hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+ hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
generics,
..
@@ -1344,12 +1354,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Binder {
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
} => {
- let mut err = self.tcx.sess.struct_span_err(
- lifetime_ref.ident.span,
- "`impl Trait` can only mention lifetimes bound at the fn or impl level",
- );
- err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
- err.emit();
+ self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
+ span: lifetime_ref.ident.span,
+ param_span: self.tcx.def_span(region_def_id),
+ });
return;
}
Scope::Root { .. } => break,
@@ -1379,6 +1387,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let mut late_depth = 0;
let mut scope = self.scope;
let mut crossed_anon_const = false;
+
let result = loop {
match *scope {
Scope::Body { s, .. } => {
@@ -1446,6 +1455,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
return;
}
+ // We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
+ // AST-based resolution does not care for impl-trait desugaring, which are the
+ // responsibility of lowering. This may create a mismatch between the resolution
+ // AST found (`param_def_id`) which points to HRTB, and what HIR allows.
+ // ```
+ // fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
+ // ```
+ //
+ // In such case, walk back the binders to diagnose it properly.
+ let mut scope = self.scope;
+ loop {
+ match *scope {
+ Scope::Binder {
+ where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
+ } => {
+ let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
+ DefKind::TyParam => errors::LateBoundInApit::Type {
+ span: self.tcx.hir().span(hir_id),
+ param_span: self.tcx.def_span(param_def_id),
+ },
+ DefKind::ConstParam => errors::LateBoundInApit::Const {
+ span: self.tcx.hir().span(hir_id),
+ param_span: self.tcx.def_span(param_def_id),
+ },
+ kind => {
+ bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
+ }
+ });
+ self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+ return;
+ }
+ Scope::Root { .. } => break,
+ Scope::Binder { s, .. }
+ | Scope::Body { s, .. }
+ | Scope::Elision { s, .. }
+ | Scope::ObjectLifetimeDefault { s, .. }
+ | Scope::Supertrait { s, .. }
+ | Scope::TraitRefBoundary { s, .. }
+ | Scope::AnonConstBoundary { s } => {
+ scope = s;
+ }
+ }
+ }
+
self.tcx.sess.delay_span_bug(
self.tcx.hir().span(hir_id),
format!("could not resolve {param_def_id:?}"),
@@ -1761,7 +1814,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+ ty::ClauseKind::Trait(data) => {
// The order here needs to match what we would get from `subst_supertrait`
let pred_bound_vars = bound_predicate.bound_vars();
let mut all_bound_vars = bound_vars.clone();
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 8e082d3c5..3755342ae 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -16,6 +16,7 @@ mod opaque;
fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
use hir::*;
+ use rustc_middle::ty::Ty;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() };
@@ -25,21 +26,15 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let (generics, arg_idx) = match parent_node {
// Easy case: arrays repeat expressions.
- Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
+ Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
if constant.hir_id() == hir_id =>
{
return tcx.types.usize
}
- Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
+ Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
return tcx.typeck(def_id).node_type(e.hir_id)
}
- Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
- if anon_const.hir_id == hir_id =>
- {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- return substs.as_inline_const().ty()
- }
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
@@ -73,7 +68,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
) =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find trait");
+ return Ty::new_error_with_message(tcx,tcx.def_span(def_id), "Could not find trait");
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
@@ -85,7 +80,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
.expect("const parameter types cannot be generic")
} else {
// FIXME(associated_const_equality): add a useful error message here.
- tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find associated const on trait")
+ Ty::new_error_with_message(tcx,tcx.def_span(def_id), "Could not find associated const on trait")
}
}
@@ -105,7 +100,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
// arm would handle this.
//
// I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
- Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
+ Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
// Find the Item containing the associated type so we can create an ItemCtxt.
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
// ty which is a fully resolved projection.
@@ -143,7 +138,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
(generics, arg_index)
} else {
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
@@ -160,7 +155,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
// As there is no relevant param for `def_id`, we simply return
// `None` here.
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unable to find type-dependent def for {:?}", parent_node_id),
);
@@ -180,12 +175,12 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
(tcx.generics_of(type_dependent_def), idx)
}
- Node::Ty(&Ty { kind: TyKind::Path(_), .. })
+ Node::Ty(&hir::Ty { kind: TyKind::Path(_), .. })
| Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
| Node::TraitRef(..)
| Node::Pat(_) => {
let path = match parent_node {
- Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
+ Node::Ty(&hir::Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
| Node::TraitRef(&TraitRef { path, .. }) => &*path,
Node::Expr(&Expr {
kind:
@@ -201,14 +196,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
);
}
}
_ => {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unexpected const parent path {:?}", parent_node),
);
@@ -230,7 +225,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
.position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg)))
}) else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
"no arg matching AnonConst in path",
);
@@ -239,7 +234,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let generics = match tcx.res_generics_def_id(segment.res) {
Some(def_id) => tcx.generics_of(def_id),
None => {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
);
@@ -249,7 +244,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
(generics, arg_index)
}
- _ => return tcx.ty_error_with_message(
+ _ => return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unexpected const parent in type_of(): {parent_node:?}"),
),
@@ -275,7 +270,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
{
tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
} else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(
+ tcx,
tcx.def_span(def_id),
format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
);
@@ -311,6 +307,9 @@ fn get_path_containing_arg_in_pat<'hir>(
}
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty<'_>> {
+ use rustc_hir::*;
+ use rustc_middle::ty::Ty;
+
// 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.
@@ -323,7 +322,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
return map[&assoc_item.trait_item_def_id.unwrap()];
}
Err(_) => {
- return ty::EarlyBinder(tcx.ty_error_with_message(
+ return ty::EarlyBinder::bind(Ty::new_error_with_message(
+ tcx,
DUMMY_SP,
"Could not collect return position impl trait in trait tys",
));
@@ -331,8 +331,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
}
}
- use rustc_hir::*;
-
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let icx = ItemCtxt::new(tcx, def_id);
@@ -341,13 +339,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::TraitItem(item) => match item.kind {
TraitItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, 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",
+ tcx,
+ def_id,
+ body_id,
+ ty.span,
+ item.ident,
+ "associated constant",
)
})
})
@@ -361,11 +364,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::ImplItem(item) => match item.kind {
ImplItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
ImplItemKind::Const(ty, body_id) => {
if is_suggestable_infer_ty(ty) {
- infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
+ infer_placeholder_type(
+ tcx,
+ def_id,
+ body_id,
+ ty.span,
+ item.ident,
+ "associated constant",
+ )
} else {
icx.to_ty(ty)
}
@@ -411,31 +421,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
span: spans.into(),
note: (),
});
- tcx.ty_error(guar)
+ Ty::new_error(tcx, guar)
}
_ => icx.to_ty(*self_ty),
},
ItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, 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);
- tcx.mk_adt(def, substs)
+ Ty::new_adt(tcx, def, substs)
}
ItemKind::OpaqueTy(OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
}) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
// Opaque types desugared from `impl Trait`.
- ItemKind::OpaqueTy(OpaqueTy {
+ ItemKind::OpaqueTy(&OpaqueTy {
origin:
hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
in_trait,
..
}) => {
- if in_trait && !tcx.impl_defaultness(owner).has_value() {
+ if in_trait && !tcx.defaultness(owner).has_value() {
span_bug!(
tcx.def_span(def_id),
"tried to get type of this RPITIT with no definition"
@@ -463,10 +473,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::ForeignItem(foreign_item) => match foreign_item.kind {
ForeignItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
ForeignItemKind::Static(t, _) => icx.to_ty(t),
- ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()),
+ ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
},
Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def {
@@ -475,7 +485,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
}
VariantData::Tuple(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
},
@@ -487,6 +497,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
+ Node::ConstBlock(_) => {
+ let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ substs.as_inline_const().ty()
+ }
+
Node::GenericParam(param) => match &param.kind {
GenericParamKind::Type { default: Some(ty), .. }
| GenericParamKind::Const { ty, .. } => icx.to_ty(ty),
@@ -497,7 +512,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
bug!("unexpected sort of node in type_of(): {:?}", x);
}
};
- ty::EarlyBinder(output)
+ ty::EarlyBinder::bind(output)
}
fn infer_placeholder_type<'a>(
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index f7c5b4467..957a6bb34 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -1,3 +1,4 @@
+use rustc_errors::StashKey;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
@@ -5,7 +6,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::DUMMY_SP;
-use crate::errors::UnconstrainedOpaqueType;
+use crate::errors::{TaitForwardCompat, UnconstrainedOpaqueType};
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
/// laid for "higher-order pattern unification".
@@ -59,7 +60,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
}
}
- let Some(hidden) = locator.found else {
+ if let Some(hidden) = locator.found {
+ // Only check against typeck if we didn't already error
+ if !hidden.ty.references_error() {
+ for concrete_type in locator.typeck_types {
+ if concrete_type.ty != tcx.erase_regions(hidden.ty)
+ && !(concrete_type, hidden).references_error()
+ {
+ hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+ }
+ }
+ }
+
+ hidden.ty
+ } else {
let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id),
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
@@ -70,21 +84,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
_ => "item",
},
});
- return tcx.ty_error(reported);
- };
-
- // Only check against typeck if we didn't already error
- if !hidden.ty.references_error() {
- for concrete_type in locator.typeck_types {
- if concrete_type.ty != tcx.erase_regions(hidden.ty)
- && !(concrete_type, hidden).references_error()
- {
- hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
- }
- }
+ Ty::new_error(tcx, reported)
}
-
- hidden.ty
}
struct TaitConstraintLocator<'tcx> {
@@ -127,16 +128,41 @@ impl TaitConstraintLocator<'_> {
// ```
let tables = self.tcx.typeck(item_def_id);
if let Some(guar) = tables.tainted_by_errors {
- self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
+ self.found =
+ Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
return;
}
- let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
+
+ let mut constrained = false;
+ for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
+ if opaque_type_key.def_id != self.def_id {
+ continue;
+ }
+ constrained = true;
+ if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) {
+ self.tcx.sess.emit_err(TaitForwardCompat {
+ span: hidden_type.span,
+ item_span: self
+ .tcx
+ .def_ident_span(item_def_id)
+ .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
+ });
+ }
+ let concrete_type =
+ self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
+ opaque_type_key,
+ self.tcx,
+ true,
+ ));
+ if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
+ self.typeck_types.push(concrete_type);
+ }
+ }
+
+ if !constrained {
debug!("no constraints in typeck results");
return;
};
- if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
- self.typeck_types.push(typeck_hidden_ty);
- }
// Use borrowck to get the type with unerased regions.
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
@@ -146,7 +172,7 @@ impl TaitConstraintLocator<'_> {
if let Some(prev) = &mut self.found {
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
- prev.ty = self.tcx.ty_error(guar);
+ prev.ty = Ty::new_error(self.tcx, guar);
}
} else {
self.found = Some(concrete_type);
@@ -190,17 +216,45 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
}
}
-pub(super) fn find_opaque_ty_constraints_for_rpit(
- tcx: TyCtxt<'_>,
+pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
+ tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
owner_def_id: LocalDefId,
) -> Ty<'_> {
- let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+ let tables = tcx.typeck(owner_def_id);
- if let Some(concrete) = concrete {
+ // Check that all of the opaques we inferred during HIR are compatible.
+ // FIXME: We explicitly don't check that the types inferred during HIR
+ // typeck are compatible with the one that we infer during borrowck,
+ // because that one actually sometimes has consts evaluated eagerly so
+ // using strict type equality will fail.
+ let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
+ if tables.tainted_by_errors.is_none() {
+ for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
+ if opaque_type_key.def_id != def_id {
+ continue;
+ }
+ let concrete_type = tcx.erase_regions(
+ hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
+ );
+ if let Some(prev) = &mut hir_opaque_ty {
+ if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
+ prev.report_mismatch(&concrete_type, def_id, tcx).stash(
+ tcx.def_span(opaque_type_key.def_id),
+ StashKey::OpaqueHiddenTypeMismatch,
+ );
+ }
+ } else {
+ hir_opaque_ty = Some(concrete_type);
+ }
+ }
+ }
+
+ let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+ if let Some(mir_opaque_ty) = mir_opaque_ty {
let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
debug!(?scope);
- let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
+ let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty };
match tcx.hir().get(scope) {
Node::Item(it) => intravisit::walk_item(&mut locator, it),
@@ -208,27 +262,28 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
- }
- concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
- let table = tcx.typeck(owner_def_id);
- if let Some(guar) = table.tainted_by_errors {
- // Some error in the
- // owner fn prevented us from populating
+ mir_opaque_ty.ty
+ } else {
+ if let Some(guar) = tables.tainted_by_errors {
+ // Some error in the owner fn prevented us from populating
// the `concrete_opaque_types` table.
- tcx.ty_error(guar)
+ Ty::new_error(tcx, guar)
} else {
- table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+ // Fall back to the RPIT we inferred during HIR typeck
+ if let Some(hir_opaque_ty) = hir_opaque_ty {
+ hir_opaque_ty.ty
+ } else {
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the
// no values of the hidden type ever being constructed,
// so we can just make the hidden type be `!`.
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
- tcx.mk_diverging_default()
- })
+ Ty::new_diverging_default(tcx)
+ }
}
- })
+ }
}
struct RpitConstraintChecker<'tcx> {