2024-08-11 12:10:36 -04:00
|
|
|
use std::assert_matches::assert_matches;
|
|
|
|
|
|
2024-11-28 22:04:03 -08:00
|
|
|
use hir::Node;
|
2022-09-29 09:31:46 +00:00
|
|
|
use rustc_data_structures::fx::FxIndexSet;
|
|
|
|
|
use rustc_hir as hir;
|
|
|
|
|
use rustc_hir::def::DefKind;
|
|
|
|
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
2024-11-28 22:04:03 -08:00
|
|
|
use rustc_middle::ty::{
|
|
|
|
|
self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
|
|
|
|
|
};
|
2024-05-08 16:40:46 +10:00
|
|
|
use rustc_middle::{bug, span_bug};
|
2024-12-13 10:29:23 +11:00
|
|
|
use rustc_span::{DUMMY_SP, Ident, Span};
|
2024-08-30 09:02:58 +10:00
|
|
|
use tracing::{debug, instrument, trace};
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-10-20 19:49:11 +00:00
|
|
|
use super::item_bounds::explicit_item_bounds_with_filter;
|
2022-09-29 09:31:46 +00:00
|
|
|
use crate::collect::ItemCtxt;
|
|
|
|
|
use crate::constrained_generic_params as cgp;
|
2024-05-30 22:00:44 +03:00
|
|
|
use crate::delegation::inherit_predicates_for_delegation_item;
|
2024-10-19 11:13:11 -04:00
|
|
|
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter, RegionInferReason};
|
2024-07-29 08:13:50 +10:00
|
|
|
|
2022-09-29 09:31:46 +00:00
|
|
|
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
2024-08-24 17:53:42 -04:00
|
|
|
/// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus
|
|
|
|
|
/// inferred constraints concerning which regions outlive other regions.
|
|
|
|
|
#[instrument(level = "debug", skip(tcx))]
|
2022-09-29 09:31:46 +00:00
|
|
|
pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
|
2024-08-24 17:53:42 -04:00
|
|
|
let mut result = tcx.explicit_predicates_of(def_id);
|
|
|
|
|
debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result);
|
|
|
|
|
|
|
|
|
|
let inferred_outlives = tcx.inferred_outlives_of(def_id);
|
|
|
|
|
if !inferred_outlives.is_empty() {
|
|
|
|
|
debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,);
|
|
|
|
|
let inferred_outlives_iter =
|
|
|
|
|
inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span));
|
|
|
|
|
if result.predicates.is_empty() {
|
|
|
|
|
result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
|
|
|
|
|
} else {
|
|
|
|
|
result.predicates = tcx.arena.alloc_from_iter(
|
|
|
|
|
result.predicates.into_iter().copied().chain(inferred_outlives_iter),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
|
|
|
|
|
if tcx.is_trait(def_id) {
|
|
|
|
|
// For traits, add `Self: Trait` predicate. This is
|
|
|
|
|
// not part of the predicates that a user writes, but it
|
|
|
|
|
// is something that one must prove in order to invoke a
|
|
|
|
|
// method or project an associated type.
|
|
|
|
|
//
|
|
|
|
|
// In the chalk setup, this predicate is not part of the
|
|
|
|
|
// "predicates" for a trait item. But it is useful in
|
|
|
|
|
// rustc because if you directly (e.g.) invoke a trait
|
|
|
|
|
// method like `Trait::method(...)`, you must naturally
|
|
|
|
|
// prove that the trait applies to the types that were
|
|
|
|
|
// used, and adding the predicate into this list ensures
|
|
|
|
|
// that this is done.
|
|
|
|
|
//
|
|
|
|
|
// We use a DUMMY_SP here as a way to signal trait bounds that come
|
|
|
|
|
// from the trait itself that *shouldn't* be shown as the source of
|
|
|
|
|
// an obligation and instead be skipped. Otherwise we'd use
|
|
|
|
|
// `tcx.def_span(def_id);`
|
2024-03-06 16:39:02 +11:00
|
|
|
let span = DUMMY_SP;
|
2024-01-07 22:53:50 +00:00
|
|
|
|
2024-05-15 10:08:35 -04:00
|
|
|
result.predicates = tcx.arena.alloc_from_iter(
|
|
|
|
|
result
|
|
|
|
|
.predicates
|
|
|
|
|
.iter()
|
|
|
|
|
.copied()
|
|
|
|
|
.chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))),
|
|
|
|
|
);
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
2024-08-24 17:53:42 -04:00
|
|
|
|
|
|
|
|
debug!("predicates_of({:?}) = {:?}", def_id, result);
|
2022-09-29 09:31:46 +00:00
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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)]
|
2023-03-13 18:54:05 +00:00
|
|
|
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
|
2022-09-29 09:31:46 +00:00
|
|
|
use rustc_hir::*;
|
|
|
|
|
|
2023-06-21 19:09:18 -03:00
|
|
|
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
2023-08-07 23:37:57 +00:00
|
|
|
Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
|
2023-06-21 19:09:18 -03:00
|
|
|
let mut predicates = Vec::new();
|
2023-06-30 19:09:42 +00:00
|
|
|
|
|
|
|
|
// 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.
|
2023-07-11 22:35:29 +01:00
|
|
|
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
|
|
|
|
predicates
|
|
|
|
|
.extend(tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_args));
|
2023-06-30 19:09:42 +00:00
|
|
|
|
|
|
|
|
// We also install bidirectional outlives predicates for the RPITIT
|
|
|
|
|
// to keep the duplicates lifetimes from opaque lowering in sync.
|
2023-08-07 23:37:57 +00:00
|
|
|
// We only need to compute bidirectional outlives for the duplicated
|
|
|
|
|
// opaque lifetimes, which explains the slicing below.
|
2023-06-21 19:09:18 -03:00
|
|
|
compute_bidirectional_outlives_predicates(
|
|
|
|
|
tcx,
|
2024-05-09 20:56:44 -04:00
|
|
|
&tcx.generics_of(def_id.to_def_id()).own_params
|
|
|
|
|
[tcx.generics_of(fn_def_id).own_params.len()..],
|
2023-06-21 19:09:18 -03:00
|
|
|
&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);
|
2023-06-30 18:55:43 +00:00
|
|
|
let trait_assoc_predicates =
|
|
|
|
|
tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
|
2023-06-21 19:09:18 -03:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
2023-06-21 19:09:18 -03:00
|
|
|
let impl_def_id = tcx.parent(fn_def_id);
|
2023-07-11 22:35:29 +01:00
|
|
|
let impl_trait_ref_args =
|
|
|
|
|
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args;
|
2023-06-21 19:09:18 -03:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let impl_assoc_args =
|
|
|
|
|
impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args);
|
2023-06-21 19:09:18 -03:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_args);
|
2023-06-21 19:09:18 -03:00
|
|
|
|
|
|
|
|
return ty::GenericPredicates {
|
|
|
|
|
parent: Some(impl_def_id),
|
|
|
|
|
predicates: tcx.arena.alloc_from_iter(impl_predicates),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None => {}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 19:28:19 +03:00
|
|
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
2023-12-01 05:28:34 -08:00
|
|
|
let node = tcx.hir_node(hir_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-08-26 19:57:59 +03:00
|
|
|
if let Some(sig) = node.fn_sig()
|
|
|
|
|
&& let Some(sig_id) = sig.decl.opt_delegation_sig_id()
|
|
|
|
|
{
|
|
|
|
|
return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-29 09:31:46 +00:00
|
|
|
let mut is_trait = None;
|
|
|
|
|
let mut is_default_impl_trait = None;
|
|
|
|
|
|
2023-03-13 19:06:41 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
|
|
|
|
|
const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
|
|
|
|
|
|
2022-12-12 16:43:38 -03:00
|
|
|
// We use an `IndexSet` to preserve order of insertion.
|
2022-09-29 09:31:46 +00:00
|
|
|
// Preserving the order of insertion is important here so as not to break UI tests.
|
2023-06-22 18:17:13 +00:00
|
|
|
let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-02-11 09:24:35 +01:00
|
|
|
let hir_generics = node.generics().unwrap_or(NO_GENERICS);
|
2024-03-05 12:16:22 +00:00
|
|
|
if let Node::Item(item) = node {
|
|
|
|
|
match item.kind {
|
2023-01-09 16:30:40 +00:00
|
|
|
ItemKind::Impl(impl_) => {
|
2022-11-11 18:08:55 +00:00
|
|
|
if impl_.defaultness.is_default() {
|
2023-07-11 22:35:29 +01:00
|
|
|
is_default_impl_trait = tcx
|
|
|
|
|
.impl_trait_ref(def_id)
|
|
|
|
|
.map(|t| ty::Binder::dummy(t.instantiate_identity()));
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
ItemKind::Trait(_, _, _, _, self_bounds, ..)
|
|
|
|
|
| ItemKind::TraitAlias(_, _, self_bounds) => {
|
2025-03-06 20:36:44 +03:00
|
|
|
is_trait = Some((self_bounds, item.span));
|
2022-11-11 18:08:55 +00:00
|
|
|
}
|
2024-03-05 12:16:22 +00:00
|
|
|
_ => {}
|
|
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
};
|
|
|
|
|
|
2025-03-06 20:36:44 +03:00
|
|
|
if let Node::TraitItem(item) = node {
|
2025-04-04 15:32:00 +03:00
|
|
|
let mut bounds = Vec::new();
|
|
|
|
|
icx.lowerer().add_default_trait_item_bounds(item, &mut bounds);
|
|
|
|
|
predicates.extend(bounds);
|
2025-03-06 20:36:44 +03:00
|
|
|
}
|
|
|
|
|
|
2022-09-29 09:31:46 +00:00
|
|
|
let generics = tcx.generics_of(def_id);
|
|
|
|
|
|
|
|
|
|
// Below we'll consider the bounds on the type parameters (including `Self`)
|
|
|
|
|
// and the explicit where-clauses, but to get the full set of predicates
|
2023-04-19 00:13:53 +00:00
|
|
|
// on a trait we must also consider the bounds that follow the trait's name,
|
|
|
|
|
// like `trait Foo: A + B + C`.
|
2025-02-27 21:19:51 +00:00
|
|
|
if let Some((self_bounds, span)) = is_trait {
|
2025-02-15 22:05:54 +01:00
|
|
|
let mut bounds = Vec::new();
|
2024-10-20 13:39:35 +00:00
|
|
|
icx.lowerer().lower_bounds(
|
2024-06-14 12:16:15 +00:00
|
|
|
tcx.types.self_param,
|
2025-02-27 21:19:51 +00:00
|
|
|
self_bounds,
|
2024-10-20 13:39:35 +00:00
|
|
|
&mut bounds,
|
|
|
|
|
ty::List::empty(),
|
2024-06-14 12:16:15 +00:00
|
|
|
PredicateFilter::All,
|
2023-04-19 00:13:53 +00:00
|
|
|
);
|
2025-02-27 21:19:51 +00:00
|
|
|
icx.lowerer().add_sizedness_bounds(
|
|
|
|
|
&mut bounds,
|
|
|
|
|
tcx.types.self_param,
|
|
|
|
|
self_bounds,
|
|
|
|
|
None,
|
|
|
|
|
Some(def_id),
|
|
|
|
|
span,
|
|
|
|
|
);
|
2025-03-06 20:36:44 +03:00
|
|
|
icx.lowerer().add_default_super_traits(
|
|
|
|
|
def_id,
|
|
|
|
|
&mut bounds,
|
2025-02-27 21:19:51 +00:00
|
|
|
self_bounds,
|
2025-03-06 20:36:44 +03:00
|
|
|
hir_generics,
|
2025-02-27 21:19:51 +00:00
|
|
|
span,
|
2025-03-06 20:36:44 +03:00
|
|
|
);
|
2025-02-15 22:05:54 +01:00
|
|
|
predicates.extend(bounds);
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// In default impls, we can assume that the self type implements
|
|
|
|
|
// the trait. So in:
|
|
|
|
|
//
|
|
|
|
|
// default impl Foo for Bar { .. }
|
|
|
|
|
//
|
2023-10-13 12:57:38 +00:00
|
|
|
// we add a default where clause `Bar: Foo`. We do a similar thing for traits
|
2022-09-29 09:31:46 +00:00
|
|
|
// (see below). Recall that a default impl is not itself an impl, but rather a
|
|
|
|
|
// set of defaults that can be incorporated into another impl.
|
|
|
|
|
if let Some(trait_ref) = is_default_impl_trait {
|
2024-05-15 10:05:25 -04:00
|
|
|
predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-12 16:19:25 +00:00
|
|
|
// Add implicit predicates that should be treated as if the user has written them,
|
|
|
|
|
// including the implicit `T: Sized` for all generic parameters, and `ConstArgHasType`
|
|
|
|
|
// for const params.
|
2024-02-11 09:24:35 +01:00
|
|
|
for param in hir_generics.params {
|
2022-09-29 09:31:46 +00:00
|
|
|
match param.kind {
|
|
|
|
|
GenericParamKind::Lifetime { .. } => (),
|
|
|
|
|
GenericParamKind::Type { .. } => {
|
2024-03-15 03:21:55 +01:00
|
|
|
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
|
2025-02-15 22:05:54 +01:00
|
|
|
let mut bounds = Vec::new();
|
2025-03-06 20:36:44 +03:00
|
|
|
// Implicit bounds are added to type params unless a `?Trait` bound is found
|
2025-02-27 21:19:51 +00:00
|
|
|
icx.lowerer().add_sizedness_bounds(
|
|
|
|
|
&mut bounds,
|
|
|
|
|
param_ty,
|
|
|
|
|
&[],
|
|
|
|
|
Some((param.def_id, hir_generics.predicates)),
|
|
|
|
|
None,
|
|
|
|
|
param.span,
|
|
|
|
|
);
|
2025-03-06 20:36:44 +03:00
|
|
|
icx.lowerer().add_default_traits(
|
2022-09-29 09:31:46 +00:00
|
|
|
&mut bounds,
|
2022-12-26 04:19:27 +00:00
|
|
|
param_ty,
|
2022-09-29 09:31:46 +00:00
|
|
|
&[],
|
2024-02-11 09:24:35 +01:00
|
|
|
Some((param.def_id, hir_generics.predicates)),
|
2022-09-29 09:31:46 +00:00
|
|
|
param.span,
|
|
|
|
|
);
|
|
|
|
|
trace!(?bounds);
|
2025-02-15 22:05:54 +01:00
|
|
|
predicates.extend(bounds);
|
2022-09-29 09:31:46 +00:00
|
|
|
trace!(?predicates);
|
|
|
|
|
}
|
2023-08-29 21:50:01 +00:00
|
|
|
hir::GenericParamKind::Const { .. } => {
|
2024-11-19 05:01:59 +00:00
|
|
|
let param_def_id = param.def_id.to_def_id();
|
2025-02-25 00:06:38 +00:00
|
|
|
let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
|
2024-11-19 05:01:59 +00:00
|
|
|
let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
|
2024-05-15 10:08:35 -04:00
|
|
|
predicates
|
|
|
|
|
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trace!(?predicates);
|
2024-06-12 16:19:25 +00:00
|
|
|
// Add inline `<T: Foo>` bounds and bounds in the where clause.
|
2024-02-11 09:24:35 +01:00
|
|
|
for predicate in hir_generics.predicates {
|
2024-11-25 16:38:35 +08:00
|
|
|
match predicate.kind {
|
|
|
|
|
hir::WherePredicateKind::BoundPredicate(bound_pred) => {
|
2024-08-26 15:03:30 -04:00
|
|
|
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
|
|
|
|
|
|
2024-11-25 16:38:35 +08:00
|
|
|
let bound_vars = tcx.late_bound_vars(predicate.hir_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
// Keep the type around in a dummy predicate, in case of no bounds.
|
|
|
|
|
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
|
|
|
|
|
// is still checked for WF.
|
|
|
|
|
if bound_pred.bounds.is_empty() {
|
|
|
|
|
if let ty::Param(_) = ty.kind() {
|
|
|
|
|
// This is a `where T:`, which can be in the HIR from the
|
|
|
|
|
// transformation that moves `?Sized` to `T`'s declaration.
|
|
|
|
|
// We can skip the predicate because type parameters are
|
|
|
|
|
// trivially WF, but also we *should*, to avoid exposing
|
|
|
|
|
// users who never wrote `where Type:,` themselves, to
|
|
|
|
|
// compiler/tooling bugs from not handling WF predicates.
|
|
|
|
|
} else {
|
|
|
|
|
let span = bound_pred.bounded_ty.span;
|
|
|
|
|
let predicate = ty::Binder::bind_with_vars(
|
2023-06-22 18:17:13 +00:00
|
|
|
ty::ClauseKind::WellFormed(ty.into()),
|
2022-09-29 09:31:46 +00:00
|
|
|
bound_vars,
|
|
|
|
|
);
|
2024-05-15 10:05:25 -04:00
|
|
|
predicates.insert((predicate.upcast(tcx), span));
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-15 22:05:54 +01:00
|
|
|
let mut bounds = Vec::new();
|
2024-10-20 13:39:35 +00:00
|
|
|
icx.lowerer().lower_bounds(
|
2023-04-18 23:55:05 +00:00
|
|
|
ty,
|
2024-10-20 03:01:49 +00:00
|
|
|
bound_pred.bounds,
|
2023-04-18 23:55:05 +00:00
|
|
|
&mut bounds,
|
|
|
|
|
bound_vars,
|
2024-10-19 11:13:11 -04:00
|
|
|
PredicateFilter::All,
|
2023-04-18 23:55:05 +00:00
|
|
|
);
|
2025-02-15 22:05:54 +01:00
|
|
|
predicates.extend(bounds);
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
2024-11-25 16:38:35 +08:00
|
|
|
hir::WherePredicateKind::RegionPredicate(region_pred) => {
|
2024-06-04 13:36:28 +00:00
|
|
|
let r1 = icx
|
|
|
|
|
.lowerer()
|
|
|
|
|
.lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
|
2022-09-29 09:31:46 +00:00
|
|
|
predicates.extend(region_pred.bounds.iter().map(|bound| {
|
|
|
|
|
let (r2, span) = match bound {
|
2024-06-04 13:36:28 +00:00
|
|
|
hir::GenericBound::Outlives(lt) => (
|
|
|
|
|
icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
|
|
|
|
|
lt.ident.span,
|
|
|
|
|
),
|
2023-12-15 03:19:46 +00:00
|
|
|
bound => {
|
|
|
|
|
span_bug!(
|
|
|
|
|
bound.span(),
|
|
|
|
|
"lifetime param bounds must be outlives, but found {bound:?}"
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
};
|
2024-05-15 10:08:35 -04:00
|
|
|
let pred =
|
|
|
|
|
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx);
|
2022-09-29 09:31:46 +00:00
|
|
|
(pred, span)
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-25 16:38:35 +08:00
|
|
|
hir::WherePredicateKind::EqPredicate(..) => {
|
2022-09-29 09:31:46 +00:00
|
|
|
// FIXME(#20041)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-09 09:01:57 +02:00
|
|
|
if tcx.features().generic_const_exprs() {
|
2024-11-28 22:04:03 -08:00
|
|
|
predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut predicates: Vec<_> = predicates.into_iter().collect();
|
|
|
|
|
|
|
|
|
|
// Subtle: before we store the predicates into the tcx, we
|
|
|
|
|
// sort them so that predicates like `T: Foo<Item=U>` come
|
2022-11-16 20:34:16 +00:00
|
|
|
// before uses of `U`. This avoids false ambiguity errors
|
2022-09-29 09:31:46 +00:00
|
|
|
// in trait checking. See `setup_constraining_predicates`
|
|
|
|
|
// for details.
|
|
|
|
|
if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
|
2023-07-11 22:35:29 +01:00
|
|
|
let self_ty = tcx.type_of(def_id).instantiate_identity();
|
|
|
|
|
let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
|
2022-09-29 09:31:46 +00:00
|
|
|
cgp::setup_constraining_predicates(
|
|
|
|
|
tcx,
|
|
|
|
|
&mut predicates,
|
|
|
|
|
trait_ref,
|
2024-02-08 14:08:58 +01:00
|
|
|
&mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
|
2022-09-29 09:31:46 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-11 18:08:55 +00:00
|
|
|
// Opaque types duplicate some of their generic parameters.
|
|
|
|
|
// We create bi-directional Outlives predicates between the original
|
|
|
|
|
// and the duplicated parameter, to ensure that they do not get out of sync.
|
2024-08-09 20:43:30 -07:00
|
|
|
if let Node::OpaqueTy(..) = node {
|
2024-05-09 20:56:44 -04:00
|
|
|
compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
|
2022-11-11 18:08:55 +00:00
|
|
|
debug!(?predicates);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-29 09:31:46 +00:00
|
|
|
ty::GenericPredicates {
|
|
|
|
|
parent: generics.parent,
|
|
|
|
|
predicates: tcx.arena.alloc_from_iter(predicates),
|
|
|
|
|
}
|
2023-06-22 17:40:59 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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>,
|
2023-08-07 23:37:57 +00:00
|
|
|
opaque_own_params: &[ty::GenericParamDef],
|
2023-06-22 17:40:59 -03:00
|
|
|
predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
|
|
|
|
) {
|
2023-08-07 23:37:57 +00:00
|
|
|
for param in opaque_own_params {
|
2024-03-06 18:48:13 +00:00
|
|
|
let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
|
2025-04-08 10:51:41 +08:00
|
|
|
if let ty::ReEarlyParam(..) = orig_lifetime.kind() {
|
2023-11-14 13:13:27 +00:00
|
|
|
let dup_lifetime = ty::Region::new_early_param(
|
|
|
|
|
tcx,
|
|
|
|
|
ty::EarlyParamRegion { index: param.index, name: param.name },
|
2023-08-07 23:37:57 +00:00
|
|
|
);
|
|
|
|
|
let span = tcx.def_span(param.def_id);
|
|
|
|
|
predicates.push((
|
|
|
|
|
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
|
2024-05-15 10:05:25 -04:00
|
|
|
.upcast(tcx),
|
2023-08-07 23:37:57 +00:00
|
|
|
span,
|
|
|
|
|
));
|
|
|
|
|
predicates.push((
|
|
|
|
|
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
|
2024-05-15 10:05:25 -04:00
|
|
|
.upcast(tcx),
|
2023-08-07 23:37:57 +00:00
|
|
|
span,
|
|
|
|
|
));
|
2023-06-22 17:40:59 -03:00
|
|
|
}
|
|
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
2024-11-28 22:04:03 -08:00
|
|
|
#[instrument(level = "debug", skip(tcx, predicates), ret)]
|
|
|
|
|
fn const_evaluatable_predicates_of<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-09-29 09:31:46 +00:00
|
|
|
def_id: LocalDefId,
|
2024-11-28 22:04:03 -08:00
|
|
|
predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
|
|
|
|
|
) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
|
2022-09-29 09:31:46 +00:00
|
|
|
struct ConstCollector<'tcx> {
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-06-22 18:17:13 +00:00
|
|
|
preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
2024-11-28 22:04:03 -08:00
|
|
|
fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
|
|
|
|
|
let hir_id = tcx.local_def_id_to_hir_id(def);
|
|
|
|
|
let (_, parent_node) = tcx
|
2025-02-21 07:54:35 +11:00
|
|
|
.hir_parent_iter(hir_id)
|
2024-11-28 22:04:03 -08:00
|
|
|
.skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
|
|
|
|
|
.next()
|
|
|
|
|
.unwrap();
|
|
|
|
|
matches!(
|
|
|
|
|
parent_node,
|
|
|
|
|
Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
|
|
|
|
|
fn visit_const(&mut self, c: ty::Const<'tcx>) {
|
|
|
|
|
if let ty::ConstKind::Unevaluated(uv) = c.kind() {
|
|
|
|
|
if is_const_param_default(self.tcx, uv.def.expect_local()) {
|
|
|
|
|
// Do not look into const param defaults,
|
|
|
|
|
// these get checked when they are actually instantiated.
|
|
|
|
|
//
|
|
|
|
|
// We do not want the following to error:
|
|
|
|
|
//
|
|
|
|
|
// struct Foo<const N: usize, const M: usize = { N + 1 }>;
|
|
|
|
|
// struct Bar<const N: usize>(Foo<N, 3>);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-11-28 22:04:03 -08:00
|
|
|
let span = self.tcx.def_span(uv.def);
|
|
|
|
|
self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
|
|
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-24 19:28:19 +03:00
|
|
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
2023-12-01 05:28:34 -08:00
|
|
|
let node = tcx.hir_node(hir_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
|
|
|
|
|
let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
|
2024-11-28 22:04:03 -08:00
|
|
|
|
|
|
|
|
for (clause, _sp) in predicates {
|
|
|
|
|
clause.visit_with(&mut collector);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-09 16:30:40 +00:00
|
|
|
if let hir::Node::Item(item) = node
|
2024-11-28 22:04:03 -08:00
|
|
|
&& let hir::ItemKind::Impl(_) = item.kind
|
2023-01-09 16:30:40 +00:00
|
|
|
{
|
2024-11-28 22:04:03 -08:00
|
|
|
if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
|
|
|
|
|
debug!("visit impl trait_ref");
|
|
|
|
|
of_trait.instantiate_identity().visit_with(&mut collector);
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
2024-11-28 22:04:03 -08:00
|
|
|
debug!("visit self_ty");
|
|
|
|
|
let self_ty = tcx.type_of(def_id);
|
|
|
|
|
self_ty.instantiate_identity().visit_with(&mut collector);
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) {
|
2024-11-28 22:04:03 -08:00
|
|
|
debug!("visit fn sig");
|
|
|
|
|
let fn_sig = tcx.fn_sig(def_id);
|
|
|
|
|
let fn_sig = fn_sig.instantiate_identity();
|
|
|
|
|
debug!(?fn_sig);
|
|
|
|
|
fn_sig.visit_with(&mut collector);
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collector.preds
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(super) fn trait_explicit_predicates_and_bounds(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
) -> ty::GenericPredicates<'_> {
|
|
|
|
|
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
|
2023-03-13 18:54:05 +00:00
|
|
|
gather_explicit_predicates_of(tcx, def_id)
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(super) fn explicit_predicates_of<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-03-13 18:54:05 +00:00
|
|
|
def_id: LocalDefId,
|
2022-09-29 09:31:46 +00:00
|
|
|
) -> 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`.
|
2023-03-13 18:54:05 +00:00
|
|
|
let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
|
2023-07-11 22:35:29 +01:00
|
|
|
let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
|
|
|
|
|
let is_assoc_item_ty = |ty: Ty<'tcx>| {
|
|
|
|
|
// For a predicate from a where clause to become a bound on an
|
|
|
|
|
// associated type:
|
2023-07-11 22:35:29 +01:00
|
|
|
// * It must use the identity args of the item.
|
2022-12-12 16:46:18 -03:00
|
|
|
// * We're in the scope of the trait, so we can't name any
|
|
|
|
|
// parameters of the GAT. That means that all we need to
|
2023-07-11 22:35:29 +01:00
|
|
|
// check are that the args of the projection are the
|
|
|
|
|
// identity args of the trait.
|
2022-09-29 09:31:46 +00:00
|
|
|
// * It must be an associated type for this trait (*not* a
|
|
|
|
|
// supertrait).
|
2022-11-26 21:51:55 +00:00
|
|
|
if let ty::Alias(ty::Projection, projection) = ty.kind() {
|
2023-07-11 22:35:29 +01:00
|
|
|
projection.args == trait_identity_args
|
2023-05-23 03:33:43 +00:00
|
|
|
// FIXME(return_type_notation): This check should be more robust
|
|
|
|
|
&& !tcx.is_impl_trait_in_trait(projection.def_id)
|
2023-03-13 18:54:05 +00:00
|
|
|
&& tcx.associated_item(projection.def_id).container_id(tcx)
|
|
|
|
|
== def_id.to_def_id()
|
2022-09-29 09:31:46 +00:00
|
|
|
} else {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let predicates: Vec<_> = predicates_and_bounds
|
|
|
|
|
.predicates
|
|
|
|
|
.iter()
|
|
|
|
|
.copied()
|
|
|
|
|
.filter(|(pred, _)| match pred.kind().skip_binder() {
|
2023-06-22 18:17:13 +00:00
|
|
|
ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
|
2024-05-13 10:00:38 -04:00
|
|
|
ty::ClauseKind::Projection(proj) => {
|
|
|
|
|
!is_assoc_item_ty(proj.projection_term.self_ty())
|
|
|
|
|
}
|
2023-06-22 18:17:13 +00:00
|
|
|
ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
|
2022-09-29 09:31:46 +00:00
|
|
|
_ => true,
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
if predicates.len() == predicates_and_bounds.predicates.len() {
|
|
|
|
|
predicates_and_bounds
|
|
|
|
|
} else {
|
|
|
|
|
ty::GenericPredicates {
|
|
|
|
|
parent: predicates_and_bounds.parent,
|
|
|
|
|
predicates: tcx.arena.alloc_slice(&predicates),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2024-05-24 12:19:33 -04:00
|
|
|
if matches!(def_kind, DefKind::AnonConst)
|
2024-10-09 09:01:57 +02:00
|
|
|
&& tcx.features().generic_const_exprs()
|
2024-05-24 12:19:33 -04:00
|
|
|
&& let Some(defaulted_param_def_id) =
|
2025-04-02 07:04:24 +11:00
|
|
|
tcx.hir_opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
|
2024-05-24 12:19:33 -04:00
|
|
|
{
|
|
|
|
|
// In `generics_of` we set the generics' parent to be our parent's parent which means that
|
|
|
|
|
// we lose out on the predicates of our actual parent if we dont return those predicates here.
|
|
|
|
|
// (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
|
|
|
|
|
//
|
|
|
|
|
// struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
|
|
|
|
|
// ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
|
|
|
|
|
// ^^^ explicit_predicates_of on
|
|
|
|
|
// parent item we dont have set as the
|
|
|
|
|
// parent of generics returned by `generics_of`
|
|
|
|
|
//
|
|
|
|
|
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
|
|
|
|
|
// and we would be calling `explicit_predicates_of(Foo)` here
|
|
|
|
|
let parent_def_id = tcx.local_parent(def_id);
|
|
|
|
|
let parent_preds = tcx.explicit_predicates_of(parent_def_id);
|
|
|
|
|
|
|
|
|
|
// If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
|
|
|
|
|
// will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
|
|
|
|
|
// to #106994 is implemented.
|
|
|
|
|
let filtered_predicates = parent_preds
|
|
|
|
|
.predicates
|
|
|
|
|
.into_iter()
|
|
|
|
|
.filter(|(pred, _)| {
|
|
|
|
|
if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
|
|
|
|
|
match ct.kind() {
|
|
|
|
|
ty::ConstKind::Param(param_const) => {
|
|
|
|
|
let defaulted_param_idx = tcx
|
|
|
|
|
.generics_of(parent_def_id)
|
|
|
|
|
.param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
|
|
|
|
|
param_const.index < defaulted_param_idx
|
2023-02-17 09:32:33 +00:00
|
|
|
}
|
2024-05-24 12:19:33 -04:00
|
|
|
_ => bug!(
|
|
|
|
|
"`ConstArgHasType` in `predicates_of`\
|
|
|
|
|
that isn't a `Param` const"
|
|
|
|
|
),
|
2023-02-17 09:32:33 +00:00
|
|
|
}
|
2024-05-24 12:19:33 -04:00
|
|
|
} else {
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.cloned();
|
|
|
|
|
return GenericPredicates {
|
|
|
|
|
parent: parent_preds.parent,
|
|
|
|
|
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
|
|
|
|
|
};
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
gather_explicit_predicates_of(tcx, def_id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Ensures that the super-predicates of the trait with a `DefId`
|
2024-02-11 09:22:52 +01:00
|
|
|
/// of `trait_def_id` are lowered and stored. This also ensures that
|
|
|
|
|
/// the transitive super-predicates are lowered.
|
2024-08-29 00:17:40 -04:00
|
|
|
pub(super) fn explicit_super_predicates_of<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-03-13 18:54:05 +00:00
|
|
|
trait_def_id: LocalDefId,
|
2024-08-29 00:17:40 -04:00
|
|
|
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
|
2023-02-02 20:37:02 +00:00
|
|
|
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-29 00:17:40 -04:00
|
|
|
pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2025-04-08 12:23:07 +10:00
|
|
|
(trait_def_id, assoc_ident): (DefId, Ident),
|
2024-08-29 00:17:40 -04:00
|
|
|
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
|
2024-10-26 19:25:10 +00:00
|
|
|
implied_predicates_with_filter(
|
|
|
|
|
tcx,
|
|
|
|
|
trait_def_id,
|
2025-04-08 12:23:07 +10:00
|
|
|
PredicateFilter::SelfTraitThatDefines(assoc_ident),
|
2024-10-26 19:25:10 +00:00
|
|
|
)
|
2023-02-02 20:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-29 00:17:40 -04:00
|
|
|
pub(super) fn explicit_implied_predicates_of<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-02-02 20:37:02 +00:00
|
|
|
trait_def_id: LocalDefId,
|
2024-08-29 00:17:40 -04:00
|
|
|
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
|
2023-06-14 18:08:47 +00:00
|
|
|
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
|
|
|
|
|
},
|
|
|
|
|
)
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Ensures that the super-predicates of the trait with a `DefId`
|
2024-02-11 09:22:52 +01:00
|
|
|
/// of `trait_def_id` are lowered and stored. This also ensures that
|
|
|
|
|
/// the transitive super-predicates are lowered.
|
2024-08-29 00:17:40 -04:00
|
|
|
pub(super) fn implied_predicates_with_filter<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-02-02 20:37:02 +00:00
|
|
|
trait_def_id: DefId,
|
|
|
|
|
filter: PredicateFilter,
|
2024-08-29 00:17:40 -04:00
|
|
|
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
|
2023-03-13 19:06:41 +00:00
|
|
|
let Some(trait_def_id) = trait_def_id.as_local() else {
|
2025-04-08 12:23:07 +10:00
|
|
|
// if `assoc_ident` is None, then the query should've been redirected to an
|
2023-03-13 19:06:41 +00:00
|
|
|
// external provider
|
2024-10-26 19:25:10 +00:00
|
|
|
assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_));
|
2024-06-27 12:01:49 -04:00
|
|
|
return tcx.explicit_super_predicates_of(trait_def_id);
|
2023-03-13 19:06:41 +00:00
|
|
|
};
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-03-14 21:05:06 +03:00
|
|
|
let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
|
|
|
|
|
bug!("trait_def_id {trait_def_id:?} is not an item");
|
2023-03-13 19:06:41 +00:00
|
|
|
};
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-10-20 13:39:35 +00:00
|
|
|
let (generics, superbounds) = match item.kind {
|
2023-03-13 19:06:41 +00:00
|
|
|
hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
|
2023-03-13 19:06:41 +00:00
|
|
|
_ => span_bug!(item.span, "super_predicates invoked on non-trait"),
|
|
|
|
|
};
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2023-03-13 19:06:41 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, trait_def_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2023-03-13 19:06:41 +00:00
|
|
|
let self_param_ty = tcx.types.self_param;
|
2025-02-15 22:05:54 +01:00
|
|
|
let mut bounds = Vec::new();
|
2024-10-20 13:39:35 +00:00
|
|
|
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
|
2025-03-06 20:36:44 +03:00
|
|
|
match filter {
|
|
|
|
|
PredicateFilter::All
|
|
|
|
|
| PredicateFilter::SelfOnly
|
|
|
|
|
| PredicateFilter::SelfTraitThatDefines(_)
|
|
|
|
|
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
|
|
|
|
icx.lowerer().add_default_super_traits(
|
|
|
|
|
trait_def_id,
|
|
|
|
|
&mut bounds,
|
|
|
|
|
superbounds,
|
|
|
|
|
generics,
|
|
|
|
|
item.span,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
//`ConstIfConst` is only interested in `~const` bounds.
|
|
|
|
|
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
|
|
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-10-26 19:01:27 +00:00
|
|
|
let where_bounds_that_match =
|
|
|
|
|
icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
|
2023-06-14 18:08:47 +00:00
|
|
|
|
2023-03-13 19:06:41 +00:00
|
|
|
// Combine the two lists to form the complete set of superbounds:
|
2023-06-22 18:17:13 +00:00
|
|
|
let implied_bounds =
|
2025-02-15 22:05:54 +01:00
|
|
|
&*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match));
|
2023-02-02 20:37:02 +00:00
|
|
|
debug!(?implied_bounds);
|
2023-03-13 19:06:41 +00:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
// Now require that immediate supertraits are lowered, which will, in
|
2023-05-04 17:24:13 +00:00
|
|
|
// turn, reach indirect supertraits, so we detect cycles now instead of
|
2024-02-21 19:05:45 +00:00
|
|
|
// overflowing during elaboration. Same for implied predicates, which
|
|
|
|
|
// make sure we walk into associated type bounds.
|
|
|
|
|
match filter {
|
|
|
|
|
PredicateFilter::SelfOnly => {
|
|
|
|
|
for &(pred, span) in implied_bounds {
|
|
|
|
|
debug!("superbound: {:?}", pred);
|
|
|
|
|
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
2024-03-21 15:45:28 -04:00
|
|
|
&& bound.polarity == ty::PredicatePolarity::Positive
|
2024-02-21 19:05:45 +00:00
|
|
|
{
|
2024-06-27 12:01:49 -04:00
|
|
|
tcx.at(span).explicit_super_predicates_of(bound.def_id());
|
2024-02-21 19:05:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-19 08:57:49 +00:00
|
|
|
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
|
2024-02-21 19:05:45 +00:00
|
|
|
for &(pred, span) in implied_bounds {
|
|
|
|
|
debug!("superbound: {:?}", pred);
|
|
|
|
|
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
2024-03-21 15:45:28 -04:00
|
|
|
&& bound.polarity == ty::PredicatePolarity::Positive
|
2024-02-21 19:05:45 +00:00
|
|
|
{
|
2024-06-27 12:01:49 -04:00
|
|
|
tcx.at(span).explicit_implied_predicates_of(bound.def_id());
|
2024-02-21 19:05:45 +00:00
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-02-21 19:05:45 +00:00
|
|
|
_ => {}
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
2023-03-13 19:06:41 +00:00
|
|
|
|
2024-09-21 11:37:20 -04:00
|
|
|
assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
|
|
|
|
|
|
2024-08-29 00:17:40 -04:00
|
|
|
ty::EarlyBinder::bind(implied_bounds)
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-21 11:37:20 -04:00
|
|
|
// Make sure when elaborating supertraits, probing for associated types, etc.,
|
2024-10-27 17:05:40 +00:00
|
|
|
// we really truly are elaborating clauses that have `ty` as their self type.
|
2024-09-21 11:37:20 -04:00
|
|
|
// This is very important since downstream code relies on this being correct.
|
|
|
|
|
pub(super) fn assert_only_contains_predicates_from<'tcx>(
|
|
|
|
|
filter: PredicateFilter,
|
|
|
|
|
bounds: &'tcx [(ty::Clause<'tcx>, Span)],
|
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
|
) {
|
|
|
|
|
if !cfg!(debug_assertions) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
match filter {
|
2024-10-26 19:25:10 +00:00
|
|
|
PredicateFilter::SelfOnly => {
|
2024-09-21 11:37:20 -04:00
|
|
|
for (clause, _) in bounds {
|
|
|
|
|
match clause.kind().skip_binder() {
|
|
|
|
|
ty::ClauseKind::Trait(trait_predicate) => {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
trait_predicate.self_ty(),
|
|
|
|
|
ty,
|
2024-10-20 19:49:11 +00:00
|
|
|
"expected `Self` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
2024-09-21 11:37:20 -04:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
ty::ClauseKind::Projection(projection_predicate) => {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
projection_predicate.self_ty(),
|
|
|
|
|
ty,
|
2024-10-20 19:49:11 +00:00
|
|
|
"expected `Self` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
2024-09-21 11:37:20 -04:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
ty::ClauseKind::TypeOutlives(outlives_predicate) => {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
outlives_predicate.0, ty,
|
2024-10-20 19:49:11 +00:00
|
|
|
"expected `Self` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
2024-09-21 11:37:20 -04:00
|
|
|
);
|
|
|
|
|
}
|
2024-12-10 02:28:02 +00:00
|
|
|
ty::ClauseKind::HostEffect(host_effect_predicate) => {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
host_effect_predicate.self_ty(),
|
|
|
|
|
ty,
|
|
|
|
|
"expected `Self` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-09-21 11:37:20 -04:00
|
|
|
|
|
|
|
|
ty::ClauseKind::RegionOutlives(_)
|
|
|
|
|
| ty::ClauseKind::ConstArgHasType(_, _)
|
|
|
|
|
| ty::ClauseKind::WellFormed(_)
|
2024-12-10 02:28:02 +00:00
|
|
|
| ty::ClauseKind::ConstEvaluatable(_) => {
|
2024-09-21 11:37:20 -04:00
|
|
|
bug!(
|
2024-10-20 19:49:11 +00:00
|
|
|
"unexpected non-`Self` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-26 19:25:10 +00:00
|
|
|
PredicateFilter::SelfTraitThatDefines(_) => {
|
|
|
|
|
for (clause, _) in bounds {
|
|
|
|
|
match clause.kind().skip_binder() {
|
|
|
|
|
ty::ClauseKind::Trait(trait_predicate) => {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
trait_predicate.self_ty(),
|
|
|
|
|
ty,
|
|
|
|
|
"expected `Self` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ty::ClauseKind::Projection(_)
|
|
|
|
|
| ty::ClauseKind::TypeOutlives(_)
|
|
|
|
|
| ty::ClauseKind::RegionOutlives(_)
|
|
|
|
|
| ty::ClauseKind::ConstArgHasType(_, _)
|
|
|
|
|
| ty::ClauseKind::WellFormed(_)
|
|
|
|
|
| ty::ClauseKind::ConstEvaluatable(_)
|
|
|
|
|
| ty::ClauseKind::HostEffect(..) => {
|
|
|
|
|
bug!(
|
|
|
|
|
"unexpected non-`Self` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-20 19:49:11 +00:00
|
|
|
PredicateFilter::ConstIfConst => {
|
|
|
|
|
for (clause, _) in bounds {
|
|
|
|
|
match clause.kind().skip_binder() {
|
|
|
|
|
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
|
|
|
|
|
trait_ref: _,
|
2024-10-29 23:42:59 +00:00
|
|
|
constness: ty::BoundConstness::Maybe,
|
2024-10-20 19:49:11 +00:00
|
|
|
}) => {}
|
|
|
|
|
_ => {
|
|
|
|
|
bug!(
|
|
|
|
|
"unexpected non-`HostEffect` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PredicateFilter::SelfConstIfConst => {
|
|
|
|
|
for (clause, _) in bounds {
|
|
|
|
|
match clause.kind().skip_binder() {
|
|
|
|
|
ty::ClauseKind::HostEffect(pred) => {
|
|
|
|
|
assert_eq!(
|
2024-10-29 23:42:59 +00:00
|
|
|
pred.constness,
|
|
|
|
|
ty::BoundConstness::Maybe,
|
2024-10-20 19:49:11 +00:00
|
|
|
"expected `~const` predicate when computing `{filter:?}` \
|
|
|
|
|
implied bounds: {clause:?}",
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
pred.trait_ref.self_ty(),
|
|
|
|
|
ty,
|
|
|
|
|
"expected `Self` predicate when computing `{filter:?}` \
|
|
|
|
|
implied bounds: {clause:?}"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
bug!(
|
|
|
|
|
"unexpected non-`HostEffect` predicate when computing \
|
|
|
|
|
`{filter:?}` implied bounds: {clause:?}"
|
2024-09-21 11:37:20 -04:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-29 09:31:46 +00:00
|
|
|
/// Returns the predicates defined on `item_def_id` of the form
|
|
|
|
|
/// `X: Foo` where `X` is the type parameter `def_id`.
|
|
|
|
|
#[instrument(level = "trace", skip(tcx))]
|
2024-08-29 00:17:40 -04:00
|
|
|
pub(super) fn type_param_predicates<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2025-04-08 12:23:07 +10:00
|
|
|
(item_def_id, def_id, assoc_ident): (LocalDefId, LocalDefId, Ident),
|
2024-08-29 00:17:40 -04:00
|
|
|
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
|
2024-10-30 22:30:28 +00:00
|
|
|
match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
|
|
|
|
|
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
|
2025-04-08 12:23:07 +10:00
|
|
|
return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_ident));
|
2024-10-30 22:30:28 +00:00
|
|
|
}
|
|
|
|
|
Some(ty::ImplTraitInTraitData::Impl { .. }) => {
|
|
|
|
|
unreachable!("should not be lowering bounds on RPITIT in impl")
|
|
|
|
|
}
|
|
|
|
|
None => {}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
// In the HIR, bounds can derive from two places. Either
|
2022-09-29 09:31:46 +00:00
|
|
|
// written inline like `<T: Foo>` or in a where-clause like
|
|
|
|
|
// `where T: Foo`.
|
|
|
|
|
|
2023-11-24 19:28:19 +03:00
|
|
|
let param_id = tcx.local_def_id_to_hir_id(def_id);
|
2025-02-17 14:17:57 +11:00
|
|
|
let param_owner = tcx.hir_ty_param_owner(def_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
|
|
|
|
|
// Don't look for bounds where the type parameter isn't in scope.
|
2023-03-13 19:06:41 +00:00
|
|
|
let parent = if item_def_id == param_owner {
|
2024-10-26 19:25:10 +00:00
|
|
|
// FIXME: Shouldn't this be unreachable?
|
2022-09-29 09:31:46 +00:00
|
|
|
None
|
|
|
|
|
} else {
|
2023-03-13 19:06:41 +00:00
|
|
|
tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
|
2022-09-29 09:31:46 +00:00
|
|
|
};
|
|
|
|
|
|
2024-08-29 00:17:40 -04:00
|
|
|
let result = if let Some(parent) = parent {
|
|
|
|
|
let icx = ItemCtxt::new(tcx, parent);
|
2025-04-08 12:23:07 +10:00
|
|
|
icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident)
|
2024-08-29 00:17:40 -04:00
|
|
|
} else {
|
|
|
|
|
ty::EarlyBinder::bind(&[] as &[_])
|
|
|
|
|
};
|
2022-09-29 09:31:46 +00:00
|
|
|
let mut extend = None;
|
|
|
|
|
|
2023-11-24 19:28:19 +03:00
|
|
|
let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
|
2022-09-29 09:31:46 +00:00
|
|
|
|
2024-03-05 12:16:22 +00:00
|
|
|
let hir_node = tcx.hir_node(item_hir_id);
|
2024-08-29 00:17:40 -04:00
|
|
|
let Some(hir_generics) = hir_node.generics() else {
|
|
|
|
|
return result;
|
|
|
|
|
};
|
2024-10-26 19:25:10 +00:00
|
|
|
|
2024-03-05 12:16:22 +00:00
|
|
|
if let Node::Item(item) = hir_node
|
2024-10-27 17:05:40 +00:00
|
|
|
&& let hir::ItemKind::Trait(..) = item.kind
|
2024-03-05 12:16:22 +00:00
|
|
|
// Implied `Self: Trait` and supertrait bounds.
|
|
|
|
|
&& param_id == item_hir_id
|
|
|
|
|
{
|
|
|
|
|
let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
|
2024-05-15 10:05:25 -04:00
|
|
|
extend = Some((identity_trait_ref.upcast(tcx), item.span));
|
2024-03-05 12:16:22 +00:00
|
|
|
}
|
2022-09-29 09:31:46 +00:00
|
|
|
|
|
|
|
|
let icx = ItemCtxt::new(tcx, item_def_id);
|
2024-10-26 19:25:10 +00:00
|
|
|
let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics(
|
|
|
|
|
hir_generics,
|
|
|
|
|
def_id,
|
2025-04-08 12:23:07 +10:00
|
|
|
PredicateFilter::SelfTraitThatDefines(assoc_ident),
|
2024-10-26 19:25:10 +00:00
|
|
|
));
|
2024-08-29 00:17:40 -04:00
|
|
|
|
2024-10-27 17:05:40 +00:00
|
|
|
let bounds =
|
|
|
|
|
&*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates));
|
|
|
|
|
|
|
|
|
|
// Double check that the bounds *only* contain `SelfTy: Trait` preds.
|
|
|
|
|
let self_ty = match tcx.def_kind(def_id) {
|
|
|
|
|
DefKind::TyParam => Ty::new_param(
|
|
|
|
|
tcx,
|
|
|
|
|
tcx.generics_of(item_def_id)
|
|
|
|
|
.param_def_id_to_index(tcx, def_id.to_def_id())
|
|
|
|
|
.expect("expected generic param to be owned by item"),
|
|
|
|
|
tcx.item_name(def_id.to_def_id()),
|
|
|
|
|
),
|
|
|
|
|
DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param,
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
};
|
|
|
|
|
assert_only_contains_predicates_from(
|
2025-04-08 12:23:07 +10:00
|
|
|
PredicateFilter::SelfTraitThatDefines(assoc_ident),
|
2024-10-27 17:05:40 +00:00
|
|
|
bounds,
|
|
|
|
|
self_ty,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
ty::EarlyBinder::bind(bounds)
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> ItemCtxt<'tcx> {
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Finds bounds from `hir::Generics`.
|
|
|
|
|
///
|
|
|
|
|
/// This requires scanning through the HIR.
|
|
|
|
|
/// We do this to avoid having to lower *all* the bounds, which would create artificial cycles.
|
|
|
|
|
/// Instead, we can only lower the bounds for a type parameter `X` if `X::Foo` is used.
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "trace", skip(self, hir_generics))]
|
2024-03-15 03:21:55 +01:00
|
|
|
fn probe_ty_param_bounds_in_generics(
|
2022-09-29 09:31:46 +00:00
|
|
|
&self,
|
2024-02-11 09:24:35 +01:00
|
|
|
hir_generics: &'tcx hir::Generics<'tcx>,
|
2022-11-06 18:26:36 +00:00
|
|
|
param_def_id: LocalDefId,
|
2023-06-14 18:08:47 +00:00
|
|
|
filter: PredicateFilter,
|
2023-06-22 18:17:13 +00:00
|
|
|
) -> Vec<(ty::Clause<'tcx>, Span)> {
|
2025-02-15 22:05:54 +01:00
|
|
|
let mut bounds = Vec::new();
|
2023-04-18 20:57:16 +00:00
|
|
|
|
2024-02-11 09:24:35 +01:00
|
|
|
for predicate in hir_generics.predicates {
|
2024-11-25 16:38:35 +08:00
|
|
|
let hir_id = predicate.hir_id;
|
|
|
|
|
let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else {
|
2023-04-18 20:57:16 +00:00
|
|
|
continue;
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-26 19:01:27 +00:00
|
|
|
match filter {
|
|
|
|
|
_ if predicate.is_param_bound(param_def_id.to_def_id()) => {
|
|
|
|
|
// Ok
|
|
|
|
|
}
|
|
|
|
|
PredicateFilter::All => {
|
|
|
|
|
// Ok
|
|
|
|
|
}
|
|
|
|
|
PredicateFilter::SelfOnly
|
2024-10-26 19:25:10 +00:00
|
|
|
| PredicateFilter::SelfTraitThatDefines(_)
|
2024-10-26 19:01:27 +00:00
|
|
|
| PredicateFilter::SelfConstIfConst
|
|
|
|
|
| PredicateFilter::SelfAndAssociatedTypeBounds => continue,
|
|
|
|
|
PredicateFilter::ConstIfConst => unreachable!(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
|
2023-04-18 20:57:16 +00:00
|
|
|
|
2024-11-25 16:38:35 +08:00
|
|
|
let bound_vars = self.tcx.late_bound_vars(hir_id);
|
2024-10-20 13:39:35 +00:00
|
|
|
self.lowerer().lower_bounds(
|
2023-04-18 20:57:16 +00:00
|
|
|
bound_ty,
|
2024-10-20 03:01:49 +00:00
|
|
|
predicate.bounds,
|
2023-04-18 20:57:16 +00:00
|
|
|
&mut bounds,
|
|
|
|
|
bound_vars,
|
2024-10-19 11:13:11 -04:00
|
|
|
filter,
|
2023-04-18 20:57:16 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-15 22:05:54 +01:00
|
|
|
bounds
|
2022-09-29 09:31:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-10-20 19:49:11 +00:00
|
|
|
|
|
|
|
|
pub(super) fn const_conditions<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
) -> ty::ConstConditions<'tcx> {
|
2024-10-23 16:53:59 +00:00
|
|
|
if !tcx.is_conditionally_const(def_id) {
|
|
|
|
|
bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
|
2024-10-20 19:49:11 +00:00
|
|
|
}
|
|
|
|
|
|
2024-12-05 16:36:30 +00:00
|
|
|
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
|
|
|
|
// RPITITs inherit const conditions of their parent fn
|
|
|
|
|
Some(
|
|
|
|
|
ty::ImplTraitInTraitData::Impl { fn_def_id }
|
|
|
|
|
| ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
|
|
|
|
|
) => return tcx.const_conditions(fn_def_id),
|
|
|
|
|
None => {}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-20 19:49:11 +00:00
|
|
|
let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
|
|
|
|
|
{
|
|
|
|
|
Node::Item(item) => match item.kind {
|
|
|
|
|
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
|
2025-01-04 11:30:31 +01:00
|
|
|
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => {
|
2024-10-20 19:49:11 +00:00
|
|
|
(generics, Some((item.owner_id.def_id, supertraits)), false)
|
|
|
|
|
}
|
2024-10-23 16:53:59 +00:00
|
|
|
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
|
2024-10-20 19:49:11 +00:00
|
|
|
},
|
|
|
|
|
// While associated types are not really const, we do allow them to have `~const`
|
|
|
|
|
// bounds and where clauses. `const_conditions` is responsible for gathering
|
|
|
|
|
// these up so we can check them in `compare_type_predicate_entailment`, and
|
|
|
|
|
// in `HostEffect` goal computation.
|
|
|
|
|
Node::TraitItem(item) => match item.kind {
|
|
|
|
|
hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
|
|
|
|
|
(item.generics, None, true)
|
|
|
|
|
}
|
2024-10-23 16:53:59 +00:00
|
|
|
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
|
2024-10-20 19:49:11 +00:00
|
|
|
},
|
|
|
|
|
Node::ImplItem(item) => match item.kind {
|
2024-10-23 16:53:59 +00:00
|
|
|
hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => {
|
|
|
|
|
(item.generics, None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
|
|
|
|
|
}
|
|
|
|
|
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
|
2024-10-20 19:49:11 +00:00
|
|
|
},
|
2024-10-23 16:53:59 +00:00
|
|
|
Node::ForeignItem(item) => match item.kind {
|
|
|
|
|
hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false),
|
|
|
|
|
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
|
|
|
|
|
},
|
2024-11-19 20:29:01 +00:00
|
|
|
Node::OpaqueTy(opaque) => match opaque.origin {
|
|
|
|
|
hir::OpaqueTyOrigin::FnReturn { parent, .. } => return tcx.const_conditions(parent),
|
|
|
|
|
hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => {
|
|
|
|
|
unreachable!()
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-10-23 16:53:59 +00:00
|
|
|
// N.B. Tuple ctors are unconditionally constant.
|
|
|
|
|
Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
|
|
|
|
|
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
|
2024-10-20 19:49:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let icx = ItemCtxt::new(tcx, def_id);
|
2025-02-15 22:05:54 +01:00
|
|
|
let mut bounds = Vec::new();
|
2024-10-20 19:49:11 +00:00
|
|
|
|
|
|
|
|
for pred in generics.predicates {
|
2024-11-25 16:38:35 +08:00
|
|
|
match pred.kind {
|
|
|
|
|
hir::WherePredicateKind::BoundPredicate(bound_pred) => {
|
2024-10-20 19:49:11 +00:00
|
|
|
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
|
2024-11-25 16:38:35 +08:00
|
|
|
let bound_vars = tcx.late_bound_vars(pred.hir_id);
|
2024-10-20 19:49:11 +00:00
|
|
|
icx.lowerer().lower_bounds(
|
|
|
|
|
ty,
|
|
|
|
|
bound_pred.bounds.iter(),
|
|
|
|
|
&mut bounds,
|
|
|
|
|
bound_vars,
|
|
|
|
|
PredicateFilter::ConstIfConst,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
|
2025-02-15 22:05:54 +01:00
|
|
|
// We've checked above that the trait is conditionally const.
|
|
|
|
|
bounds.push((
|
|
|
|
|
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
|
|
|
|
|
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
2024-10-20 19:49:11 +00:00
|
|
|
DUMMY_SP,
|
2025-02-15 22:05:54 +01:00
|
|
|
));
|
2024-10-20 19:49:11 +00:00
|
|
|
|
|
|
|
|
icx.lowerer().lower_bounds(
|
|
|
|
|
tcx.types.self_param,
|
2025-01-10 07:08:28 +01:00
|
|
|
supertraits,
|
2024-10-20 19:49:11 +00:00
|
|
|
&mut bounds,
|
|
|
|
|
ty::List::empty(),
|
|
|
|
|
PredicateFilter::ConstIfConst,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ty::ConstConditions {
|
|
|
|
|
parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
|
2025-02-15 22:05:54 +01:00
|
|
|
predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| {
|
2024-10-20 19:49:11 +00:00
|
|
|
(
|
|
|
|
|
clause.kind().map_bound(|clause| match clause {
|
|
|
|
|
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
|
|
|
|
|
trait_ref,
|
2024-10-29 23:42:59 +00:00
|
|
|
constness: ty::BoundConstness::Maybe,
|
2024-10-20 19:49:11 +00:00
|
|
|
}) => trait_ref,
|
|
|
|
|
_ => bug!("converted {clause:?}"),
|
|
|
|
|
}),
|
|
|
|
|
span,
|
|
|
|
|
)
|
|
|
|
|
})),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-19 20:30:58 +00:00
|
|
|
pub(super) fn explicit_implied_const_bounds<'tcx>(
|
2024-10-20 19:49:11 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
|
2024-10-23 16:53:59 +00:00
|
|
|
if !tcx.is_conditionally_const(def_id) {
|
2025-03-01 12:23:33 +08:00
|
|
|
bug!(
|
|
|
|
|
"explicit_implied_const_bounds invoked for item that is not conditionally const: {def_id:?}"
|
|
|
|
|
);
|
2024-10-23 16:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
2024-12-05 16:36:30 +00:00
|
|
|
let bounds = 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 { .. }) => {
|
2024-10-20 19:49:11 +00:00
|
|
|
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
|
|
|
|
|
}
|
2024-12-05 16:36:30 +00:00
|
|
|
Some(ty::ImplTraitInTraitData::Impl { .. }) => {
|
|
|
|
|
span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
|
|
|
|
|
}
|
|
|
|
|
None => match tcx.hir_node_by_def_id(def_id) {
|
|
|
|
|
Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
|
|
|
|
|
implied_predicates_with_filter(
|
|
|
|
|
tcx,
|
|
|
|
|
def_id.to_def_id(),
|
|
|
|
|
PredicateFilter::SelfConstIfConst,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
|
|
|
|
|
| Node::OpaqueTy(_) => {
|
|
|
|
|
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
|
|
|
|
|
}
|
|
|
|
|
_ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"),
|
|
|
|
|
},
|
2024-10-20 19:49:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bounds.map_bound(|bounds| {
|
|
|
|
|
&*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
|
|
|
|
|
(
|
|
|
|
|
clause.kind().map_bound(|clause| match clause {
|
|
|
|
|
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
|
|
|
|
|
trait_ref,
|
2024-10-29 23:42:59 +00:00
|
|
|
constness: ty::BoundConstness::Maybe,
|
2024-10-20 19:49:11 +00:00
|
|
|
}) => trait_ref,
|
|
|
|
|
_ => bug!("converted {clause:?}"),
|
|
|
|
|
}),
|
|
|
|
|
span,
|
|
|
|
|
)
|
|
|
|
|
}))
|
|
|
|
|
})
|
|
|
|
|
}
|