diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index babf99c4c1fe9..8af17d01b0a36 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -15,20 +15,14 @@ fn parent_impl_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness } } -/// Checks whether an item is considered to be `const`. If it is a constructor, it is const. -/// If it is an assoc method or function, -/// return if it has a `const` modifier. If it is an intrinsic, report whether said intrinsic -/// has a `rustc_const_{un,}stable` attribute. Otherwise, panic. +/// Checks whether a function-like definition is considered to be `const`. fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { let node = tcx.hir_node_by_def_id(def_id); match node { - hir::Node::Ctor(hir::VariantData::Tuple(..)) - | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => { - hir::Constness::Const - } - hir::Node::ForeignItem(_) => { - // Foreign items cannot be evaluated at compile-time. + hir::Node::Ctor(hir::VariantData::Tuple(..)) => hir::Constness::Const, + hir::Node::ForeignItem(item) if let hir::ForeignItemKind::Fn(..) = item.kind => { + // Foreign functions cannot be evaluated at compile-time. hir::Constness::NotConst } hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2c2dffe8b88f0..7e7b602c560ba 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -132,6 +132,7 @@ rustc_queries! { } /// Return the span for a definition. + /// /// Contrary to `def_span` below, this query returns the full absolute span of the definition. /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside /// of rustc_middle::hir::source_map. @@ -142,6 +143,7 @@ rustc_queries! { } /// Represents crate as a whole (as distinct from the top-level crate module). + /// /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`), /// we will have to assume that any change means that you need to be recompiled. /// This is because the `hir_crate` query gives you access to all other items. @@ -202,28 +204,40 @@ rustc_queries! { feedable } - /// Given the def_id of a const-generic parameter, computes the associated default const - /// parameter. e.g. `fn example` called on `N` would return `3`. + /// Returns the *default* of the const pararameter given by `DefId`. + /// + /// E.g., given `struct Ty;` this returns `3` for `N`. query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { - desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param) } + desc { |tcx| "computing the default for const parameter `{}`", tcx.def_path_str(param) } cache_on_disk_if { param.is_local() } separate_provide_extern } - /// Returns the [`Ty`][rustc_middle::ty::Ty] of the given [`DefId`]. If the [`DefId`] points - /// to an alias, it will "skip" this alias to return the aliased type. + /// Returns the *type* of the definition given by `DefId`. + /// + /// For type aliases (whether eager or lazy) and associated types, this returns + /// the underlying aliased type (not the corresponding [alias type]). + /// + /// For opaque types, this returns and thus reveals the hidden type! If you + /// want to detect cycle errors use `type_of_opaque` instead. + /// + /// To clarify, for type definitions, this does *not* return the "type of a type" + /// (aka *kind* or *sort*) in the type-theoretical sense! It merely returns + /// the type primarily *associated with* it. /// - /// [`DefId`]: rustc_hir::def_id::DefId + /// # Panics + /// + /// This query will panic if the given definition doesn't (and can't + /// conceptually) have an (underlying) type. + /// + /// [alias type]: rustc_middle::ty::AliasTy query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { desc { |tcx| "{action} `{path}`", - action = { - use rustc_hir::def::DefKind; - match tcx.def_kind(key) { - DefKind::TyAlias => "expanding type alias", - DefKind::TraitAlias => "expanding trait alias", - _ => "computing type of", - } + action = match tcx.def_kind(key) { + DefKind::TyAlias => "expanding type alias", + DefKind::TraitAlias => "expanding trait alias", + _ => "computing type of", }, path = tcx.def_path_str(key), } @@ -232,9 +246,14 @@ rustc_queries! { feedable } - /// Specialized instance of `type_of` that detects cycles that are due to - /// revealing opaque because of an auto trait bound. Unless `CyclePlaceholder` needs - /// to be handled separately, call `type_of` instead. + /// Returns the *hidden type* of the opaque type given by `DefId` unless a cycle occurred. + /// + /// This is a specialized instance of [`Self::type_of`] that detects query cycles. + /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. + /// + /// # Panics + /// + /// This query will panic if the given definition is not an opaque type. query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { desc { |tcx| "computing type of opaque `{path}`", @@ -243,9 +262,22 @@ rustc_queries! { cycle_stash } + /// Returns whether the type alias given by `DefId` is lazy. + /// + /// I.e., if the type alias expands / ought to expand to a [weak] [alias type] + /// instead of the underyling aliased type. + /// + /// Relevant for features `lazy_type_alias` and `type_alias_impl_trait`. + /// + /// # Panics + /// + /// This query *may* panic if the given definition is not a type alias. + /// + /// [weak]: rustc_middle::ty::Weak + /// [alias type]: rustc_middle::ty::AliasTy query type_alias_is_lazy(key: DefId) -> bool { desc { |tcx| - "computing whether `{path}` is a lazy type alias", + "computing whether the type alias `{path}` is lazy", path = tcx.def_path_str(key), } separate_provide_extern @@ -299,8 +331,7 @@ rustc_queries! { desc { "checking lint expectations (RFC 2383)" } } - /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its - /// associated generics. + /// Returns the *generics* of the definition given by `DefId`. query generics_of(key: DefId) -> &'tcx ty::Generics { desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) } arena_cache @@ -309,10 +340,13 @@ rustc_queries! { feedable } - /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the - /// predicates (where-clauses) that must be proven true in order - /// to reference it. This is almost always the "predicates query" - /// that you want. + /// Returns the (elaborated) *predicates* of the definition given by `DefId` + /// that must be proven true at usage sites (and which can be assumed at definition site). + /// + /// This is almost always *the* "predicates query" that you want. + /// + /// **Tip**: You can use `#[rustc_dump_predicates]` on an item to basically print + /// the result of this query for use in UI tests or for debugging purposes. query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } @@ -328,25 +362,24 @@ rustc_queries! { } } - /// Returns the list of bounds that are required to be satisfied - /// by a implementation or definition. For associated types, these - /// must be satisfied for an implementation to be well-formed, - /// and for opaque types, these are required to be satisfied by - /// the hidden-type of the opaque. + /// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId` + /// that must be proven true at definition site (and which can be assumed at usage sites). /// - /// Syntactially, these are the bounds written on the trait's type - /// definition, or those after the `impl` keyword for an opaque: + /// For associated types, these must be satisfied for an implementation + /// to be well-formed, and for opaque types, these are required to be + /// satisfied by the hidden type of the opaque. /// - /// ```ignore (incomplete) - /// type X: Bound + 'lt - /// // ^^^^^^^^^^^ - /// impl Debug + Display - /// // ^^^^^^^^^^^^^^^ - /// ``` + /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. /// - /// `key` is the `DefId` of the associated type or opaque type. + /// Syntactially, these are the bounds written on associated types in trait + /// definitions, or those after the `impl` keyword for an opaque: /// - /// Bounds from the parent (e.g. with nested impl trait) are not included. + /// ```ignore (illustrative) + /// trait Trait { type X: Bound + 'lt; } + /// // ^^^^^^^^^^^ + /// fn function() -> impl Debug + Display { /*...*/ } + /// // ^^^^^^^^^^^^^^^ + /// ``` query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } @@ -354,10 +387,12 @@ rustc_queries! { feedable } - /// The set of item bounds (see [`TyCtxt::explicit_item_bounds`]) that - /// share the `Self` type of the item. These are a subset of the bounds - /// that may explicitly be used for things like closure signature - /// deduction. + /// Returns the explicitly user-written *bounds* that share the `Self` type of the item. + /// + /// These are a subset of the [explicit item bounds] that may explicitly be used for things + /// like closure signature deduction. + /// + /// [explicit item bounds]: Self::explicit_item_bounds query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } @@ -365,26 +400,29 @@ rustc_queries! { feedable } - /// Elaborated version of the predicates from `explicit_item_bounds`. + /// Returns the (elaborated) *bounds* on the associated or opaque type given by `DefId` + /// that must be proven true at definition site (and which can be assumed at usage sites). /// - /// For example: + /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. + /// + /// **Tip**: You can use `#[rustc_dump_item_bounds]` on an item to basically print + /// the result of this query for use in UI tests or for debugging purposes. + /// + /// # Examples /// /// ``` - /// trait MyTrait { - /// type MyAType: Eq + ?Sized; - /// } + /// trait Trait { type Assoc: Eq + ?Sized; } /// ``` /// - /// `explicit_item_bounds` returns `[::MyAType: Eq]`, - /// and `item_bounds` returns + /// While [`Self::explicit_item_bounds`] returns `[::Assoc: Eq]` + /// here, `item_bounds` returns: + /// /// ```text /// [ - /// ::MyAType: Eq, - /// ::MyAType: PartialEq<::MyAType> + /// ::Assoc: Eq, + /// ::Assoc: PartialEq<::Assoc> /// ] /// ``` - /// - /// Bounds from the parent (e.g. with nested impl trait) are not included. query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } @@ -615,27 +653,35 @@ rustc_queries! { desc { "getting wasm import module map" } } - /// Returns everything that looks like a predicate written explicitly - /// by the user on a trait item. + /// Returns the explicitly user-written *predicates and bounds* of the trait given by `DefId`. /// /// Traits are unusual, because predicates on associated types are /// converted into bounds on that type for backwards compatibility: /// + /// ``` /// trait X where Self::U: Copy { type U; } + /// ``` /// /// becomes /// + /// ``` /// trait X { type U: Copy; } + /// ``` /// - /// `explicit_predicates_of` and `explicit_item_bounds` will then take - /// the appropriate subsets of the predicates here. + /// [`Self::explicit_predicates_of`] and [`Self::explicit_item_bounds`] will + /// then take the appropriate subsets of the predicates here. + /// + /// # Panics + /// + /// This query will panic if the given definition is not a trait. query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key) } } - /// Returns the predicates written explicitly by the user. + /// Returns the explicitly user-written *predicates* of the definition given by `DefId` + /// that must be proven true at usage sites (and which can be assumed at definition site). /// - /// You should probably use `predicates_of` unless you're looking for + /// You should probably use [`Self::predicates_of`] unless you're looking for /// predicates with explicit spans for diagnostics purposes. query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } @@ -644,18 +690,24 @@ rustc_queries! { feedable } - /// Returns the inferred outlives predicates (e.g., for `struct - /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). + /// Returns the *inferred outlives-predicates* of the item given by `DefId`. + /// + /// E.g., for `struct Foo<'a, T> { x: &'a T }`, this would return `[T: 'a]`. + /// + /// **Tip**: You can use `#[rustc_outlives]` on an item to basically print the + /// result of this query for use in UI tests or for debugging purposes. query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { - desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) } + desc { |tcx| "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern feedable } - /// Maps from the `DefId` of a trait to the list of super-predicates of the trait, - /// *before* elaboration (so it doesn't contain transitive super-predicates). This - /// is a subset of the full list of predicates. We store these in a separate map + /// Returns the explicitly user-written *super-predicates* of the trait given by `DefId`. + /// + /// These predicates are unelaborated and consequently don't contain transitive super-predicates. + /// + /// This is a subset of the full list of predicates. We store these in a separate map /// because we must evaluate them even during type conversion, often before the full /// predicates are available (note that super-predicates must not be cyclic). query explicit_super_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { @@ -664,8 +716,9 @@ rustc_queries! { separate_provide_extern } - /// The predicates of the trait that are implied during elaboration. This is a - /// superset of the super-predicates of the trait, but a subset of the predicates + /// The predicates of the trait that are implied during elaboration. + /// + /// This is a superset of the super-predicates of the trait, but a subset of the predicates /// of the trait. For regular traits, this includes all super-predicates and their /// associated type bounds. For trait aliases, currently, this includes all of the /// predicates of the trait alias. @@ -745,14 +798,27 @@ rustc_queries! { desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } } - /// Returns the constness of function-like things (tuple struct/variant constructors, functions, - /// methods) + /// Returns the constness of the function-like[^1] definition given by `DefId`. + /// + /// Tuple struct/variant constructors are *always* const, foreign functions are + /// *never* const. The rest is const iff marked with keyword `const` (or rather + /// its parent in the case of associated functions). /// - /// Will ICE if used on things that are always const or never const. + ///
/// - /// **Do not call this function manually.** It is only meant to cache the base data for the + /// **Do not call this query** directly. It is only meant to cache the base data for the /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead. - /// Also note that neither of them takes into account feature gates and stability. + /// + /// Also note that neither of them takes into account feature gates, stability and + /// const predicates/conditions! + /// + ///
+ /// + /// # Panics + /// + /// This query will panic if the given definition is not function-like[^1]. + /// + /// [^1]: Tuple struct/variant constructors, closures and free, associated and foreign functions. query constness(key: DefId) -> hir::Constness { desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } separate_provide_extern @@ -798,13 +864,25 @@ rustc_queries! { separate_provide_extern } - /// Gets a map with the variance of every item; use `variances_of` instead. + /// Gets a map with the variances of every item in the local crate. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::variances_of`] instead. + /// + ///
query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> { arena_cache desc { "computing the variances for items in this crate" } } - /// Maps from the `DefId` of a type or region parameter to its (inferred) variance. + /// Returns the (inferred) variances of the item given by `DefId`. + /// + /// The list of variances corresponds to the list of (early-bound) generic + /// parameters of the item (including its parents). + /// + /// **Tip**: You can use `#[rustc_variance]` on an item to basically print the + /// result of this query for use in UI tests or for debugging purposes. query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } @@ -812,10 +890,16 @@ rustc_queries! { cycle_delay_bug } - /// Maps from thee `DefId` of a type to its (inferred) outlives. + /// Gets a map with the inferred outlives-predicates of every item in the local crate. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::inferred_outlives_of`] instead. + /// + ///
query inferred_outlives_crate(_: ()) -> &'tcx ty::CratePredicatesMap<'tcx> { arena_cache - desc { "computing the inferred outlives predicates for items in this crate" } + desc { "computing the inferred outlives-predicates for items in this crate" } } /// Maps from an impl/trait or struct/variant `DefId` @@ -1038,20 +1122,35 @@ rustc_queries! { } /// Gets a complete map from all types to their inherent impls. - /// Not meant to be used directly outside of coherence. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) { desc { "finding all inherent impls defined in crate" } } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. - /// Not meant to be used directly outside of coherence. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for inherent impls that should not be defined in crate" } ensure_forwards_result_if_red } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. - /// Not meant to be used directly outside of coherence. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for overlap between inherent impls defined in this crate" } ensure_forwards_result_if_red @@ -1089,8 +1188,12 @@ rustc_queries! { } /// Computes the tag (if any) for a given type and variant. + /// /// `None` means that the variant doesn't need a tag (because it is niched). - /// Will panic for uninhabited variants. + /// + /// # Panics + /// + /// This query will panic for uninhabited variants and if the passed type is not an enum. query tag_for_variant( key: (Ty<'tcx>, abi::VariantIdx) ) -> Option { @@ -1099,7 +1202,12 @@ rustc_queries! { /// Evaluates a constant and returns the computed allocation. /// - /// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead. + ///
+ /// + /// **Do not call this query** directly, use [`Self::eval_to_const_value_raw`] or + /// [`Self::eval_to_valtree`] instead. + /// + ///
query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) -> EvalToAllocationRawResult<'tcx> { desc { |tcx| @@ -1120,12 +1228,18 @@ rustc_queries! { feedable } - /// Evaluates const items or anonymous constants - /// (such as enum variant explicit discriminants or array lengths) - /// into a representation suitable for the type system and const generics. + /// Evaluates const items or anonymous constants[^1] into a representation + /// suitable for the type system and const generics. + /// + ///
+ /// + /// **Do not call this** directly, use one of the following wrappers: + /// [`TyCtxt::const_eval_poly`], [`TyCtxt::const_eval_resolve`], + /// [`TyCtxt::const_eval_instance`], or [`TyCtxt::const_eval_global_id`]. + /// + ///
/// - /// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`, - /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. + /// [^1]: Such as enum variant explicit discriminants or array lengths. query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) -> EvalToConstValueResult<'tcx> { desc { |tcx| @@ -1252,13 +1366,13 @@ rustc_queries! { separate_provide_extern } - /// Determines whether an item is annotated with `doc(hidden)`. + /// Determines whether an item is annotated with `#[doc(hidden)]`. query is_doc_hidden(def_id: DefId) -> bool { desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } separate_provide_extern } - /// Determines whether an item is annotated with `doc(notable_trait)`. + /// Determines whether an item is annotated with `#[doc(notable_trait)]`. query is_doc_notable_trait(def_id: DefId) -> bool { desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) } } @@ -1796,13 +1910,22 @@ rustc_queries! { query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet> { desc { |tcx| "testing if a region is late bound inside `{}`", tcx.def_path_str(owner_id) } } - /// For a given item's generic parameter, gets the default lifetimes to be used - /// for each parameter if a trait object were to be passed for that parameter. - /// For example, for `T` in `struct Foo<'a, T>`, this would be `'static`. - /// For `T` in `struct Foo<'a, T: 'a>`, this would instead be `'a`. - /// This query will panic if passed something that is not a type parameter. + /// Returns the *default lifetime* to be used if a trait object type were to be passed for + /// the type parameter given by `DefId`. + /// + /// **Tip**: You can use `#[rustc_object_lifetime_default]` on an item to basically + /// print the result of this query for use in UI tests or for debugging purposes. + /// + /// # Examples + /// + /// - For `T` in `struct Foo<'a, T: 'a>(&'a T);`, this would be `Param('a)` + /// - For `T` in `struct Bar<'a, T>(&'a T);`, this would be `Empty` + /// + /// # Panics + /// + /// This query will panic if the given definition is not a type parameter. query object_lifetime_default(def_id: DefId) -> ObjectLifetimeDefault { - desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(def_id) } + desc { "looking up lifetime defaults for type parameter `{}`", tcx.def_path_str(def_id) } separate_provide_extern } query late_bound_vars_map(owner_id: hir::OwnerId) diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr index cf5d8f614dda2..7f8ed89852522 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr @@ -4,12 +4,12 @@ error[E0391]: cycle detected when computing predicates of `Foo` LL | struct Foo { | ^^^^^^^^^^ | -note: ...which requires computing inferred outlives predicates of `Foo`... +note: ...which requires computing inferred outlives-predicates of `Foo`... --> $DIR/cycle-iat-inside-of-adt.rs:7:1 | LL | struct Foo { | ^^^^^^^^^^ - = note: ...which requires computing the inferred outlives predicates for items in this crate... + = note: ...which requires computing the inferred outlives-predicates for items in this crate... note: ...which requires computing type of `Foo::bar`... --> $DIR/cycle-iat-inside-of-adt.rs:8:5 |