diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3d154a93fb2da..9c646642187f7 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -13,7 +13,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::PredicateOrigin; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; +use rustc_middle::resolver_outputs::ResolverAstLowering; +use rustc_middle::ty::TyCtxt; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1fd7cc6647037..87ed6225a5f86 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -62,10 +62,7 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_middle::{ - span_bug, - ty::{ResolverAstLowering, TyCtxt}, -}; +use rustc_middle::{resolver_outputs::ResolverAstLowering, span_bug, ty::TyCtxt}; use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DesugaringKind; diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 3989fc486193e..241768dea2665 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -2,8 +2,8 @@ use super::ResolverAstLoweringExt; use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; use rustc_ast::{FnRetTy, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind}; use rustc_hir::def::LifetimeRes; +use rustc_middle::resolver_outputs::ResolverAstLowering; use rustc_middle::span_bug; -use rustc_middle::ty::ResolverAstLowering; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 48401eabd1ed1..30073c65d5830 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -17,6 +17,7 @@ use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintSto use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; +use rustc_middle::resolver_outputs::{ResolverAstLowering, ResolverOutputs}; use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_mir_build as mir_build; @@ -557,7 +558,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P fn resolver_for_lowering<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { +) -> &'tcx Steal<(ResolverAstLowering, Lrc)> { let arenas = Resolver::arenas(); let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); @@ -567,7 +568,7 @@ fn resolver_for_lowering<'tcx>( // Make sure we don't mutate the cstore from here on. tcx.untracked().cstore.leak(); - let ty::ResolverOutputs { + let ResolverOutputs { global_ctxt: untracked_resolutions, ast_lowering: untracked_resolver_for_lowering, } = resolver.into_outputs(); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a310cbb80293a..f11b64344c518 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -17,6 +17,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE} use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc_hir::diagnostic_items::DiagnosticItems; use rustc_index::{Idx, IndexVec}; +use rustc_middle::cache::CReaderCacheKey; use rustc_middle::metadata::ModChild; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; @@ -379,7 +380,7 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> { { let tcx = self.tcx(); - let key = ty::CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand }; + let key = CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand }; if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) { return ty; diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 6a1a2a061ddd6..88c573586f792 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -31,13 +31,13 @@ macro_rules! arena_types { [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, [] resolver: rustc_data_structures::steal::Steal<( - rustc_middle::ty::ResolverAstLowering, + rustc_middle::resolver_outputs::ResolverAstLowering, rustc_data_structures::sync::Lrc, )>, [] output_filenames: std::sync::Arc, [] metadata_loader: rustc_data_structures::steal::Steal>, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, - [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, + [] resolutions: rustc_middle::resolver_outputs::ResolverGlobalCtxt, [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, [decode] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, diff --git a/compiler/rustc_middle/src/cache.rs b/compiler/rustc_middle/src/cache.rs new file mode 100644 index 0000000000000..3383cd8cd8e86 --- /dev/null +++ b/compiler/rustc_middle/src/cache.rs @@ -0,0 +1,9 @@ +use rustc_hir::def_id::CrateNum; + +/// Contains information needed to resolve types and (in the future) look up +/// the types of AST nodes. +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct CReaderCacheKey { + pub cnum: Option, + pub pos: usize, +} diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e9172e767e036..63d01528b4ac2 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -91,6 +91,7 @@ pub mod query; pub mod arena; #[macro_use] pub mod dep_graph; +pub mod cache; pub(crate) mod error; pub mod hir; pub mod infer; @@ -98,6 +99,7 @@ pub mod lint; pub mod metadata; pub mod middle; pub mod mir; +pub mod resolver_outputs; pub mod thir; pub mod traits; pub mod ty; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9fad2816b0d84..3d34cb65aef5e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -37,13 +37,13 @@ rustc_queries! { desc { "perform lints prior to macro expansion" } } - query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { + query resolutions(_: ()) -> &'tcx crate::resolver_outputs::ResolverGlobalCtxt { feedable no_hash desc { "getting the resolver outputs" } } - query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { + query resolver_for_lowering(_: ()) -> &'tcx Steal<(crate::resolver_outputs::ResolverAstLowering, Lrc)> { eval_always no_hash desc { "getting the resolver for lowering" } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 220118ae5ccb8..4d9f583ff16f9 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -28,6 +28,8 @@ use std::collections::hash_map::Entry; use std::io; use std::mem; +use crate::cache::CReaderCacheKey; + const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; // A normal span encoded with both location information and a `SyntaxContext` @@ -551,7 +553,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> { { let tcx = self.tcx; - let cache_key = ty::CReaderCacheKey { cnum: None, pos: shorthand }; + let cache_key = CReaderCacheKey { cnum: None, pos: shorthand }; if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) { return ty; diff --git a/compiler/rustc_middle/src/resolver_outputs.rs b/compiler/rustc_middle/src/resolver_outputs.rs new file mode 100644 index 0000000000000..1cb7a259d97f3 --- /dev/null +++ b/compiler/rustc_middle/src/resolver_outputs.rs @@ -0,0 +1,92 @@ +use rustc_ast as ast; +use rustc_ast::node_id::NodeMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::steal::Steal; +use rustc_hir as hir; +use rustc_hir::def::{DefKind, DocLinkResMap, LifetimeRes, Res}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; +use rustc_index::IndexVec; +use rustc_session::lint::LintBuffer; +use rustc_span::hygiene::MacroKind; +use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::{ExpnId, Span}; + +use crate::metadata::ModChild; +use crate::middle::privacy::EffectiveVisibilities; +use crate::ty::Visibility; + +pub struct ResolverOutputs { + pub global_ctxt: ResolverGlobalCtxt, + pub ast_lowering: ResolverAstLowering, +} + +#[derive(Debug)] +pub struct ResolverGlobalCtxt { + pub visibilities: FxHashMap, + /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. + pub has_pub_restricted: bool, + /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. + pub expn_that_defined: FxHashMap, + pub effective_visibilities: EffectiveVisibilities, + pub extern_crate_map: FxHashMap, + pub maybe_unused_trait_imports: FxIndexSet, + pub module_children: LocalDefIdMap>, + pub glob_map: FxHashMap>, + pub main_def: Option, + pub trait_impls: FxIndexMap>, + /// A list of proc macro LocalDefIds, written out in the order in which + /// they are declared in the static array generated by proc_macro_harness. + pub proc_macros: Vec, + /// Mapping from ident span to path span for paths that don't exist as written, but that + /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. + pub confused_type_with_std_module: FxHashMap, + pub doc_link_resolutions: FxHashMap, + pub doc_link_traits_in_scope: FxHashMap>, + pub all_macro_rules: FxHashMap>, +} + +/// Resolutions that should only be used for lowering. +/// This struct is meant to be consumed by lowering. +#[derive(Debug)] +pub struct ResolverAstLowering { + pub legacy_const_generic_args: FxHashMap>>, + + /// Resolutions for nodes that have a single resolution. + pub partial_res_map: NodeMap, + /// Resolutions for import nodes, which have multiple resolutions in different namespaces. + pub import_res_map: NodeMap>>>, + /// Resolutions for labels (node IDs of their corresponding blocks or loops). + pub label_res_map: NodeMap, + /// Resolutions for lifetimes. + pub lifetimes_res_map: NodeMap, + /// Lifetime parameters that lowering will have to introduce. + pub extra_lifetime_params_map: NodeMap>, + + pub next_node_id: ast::NodeId, + + pub node_id_to_def_id: FxHashMap, + pub def_id_to_node_id: IndexVec, + + pub trait_map: NodeMap>, + /// A small map keeping true kinds of built-in macros that appear to be fn-like on + /// the surface (`macro` items in libcore), but are actually attributes or derives. + pub builtin_macro_kinds: FxHashMap, + /// List functions and methods for which lifetime elision was successful. + pub lifetime_elision_allowed: FxHashSet, + + /// Lints that were emitted by the resolver and early lints. + pub lint_buffer: Steal, +} + +#[derive(Clone, Copy, Debug)] +pub struct MainDefinition { + pub res: Res, + pub is_import: bool, + pub span: Span, +} + +impl MainDefinition { + pub fn opt_fn_def_id(self) -> Option { + if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } + } +} diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index ad9891a5dca68..97950f2a11ae1 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -1,56 +1,30 @@ -use crate::mir::interpret::ErrorHandled; -use crate::ty; -use crate::ty::util::{Discr, IntTypeExt}; +use std::cell::RefCell; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; +use std::ops::Range; +use std::str; + use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; -use rustc_data_structures::stable_hasher::HashingControls; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::{IndexSlice, IndexVec}; use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; -use rustc_span::symbol::sym; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT}; -use std::cell::RefCell; -use std::cmp::Ordering; -use std::hash::{Hash, Hasher}; -use std::ops::Range; -use std::str; - -use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr}; +use crate::mir::interpret::ErrorHandled; +use crate::ty::util::{Discr, IntTypeExt}; +use crate::ty::{self, Destructor, FieldIdx, GenericPredicates, SubstsRef, Ty, TyCtxt, Visibility}; -bitflags! { - #[derive(HashStable, TyEncodable, TyDecodable)] - pub struct AdtFlags: u16 { - const NO_ADT_FLAGS = 0; - /// Indicates whether the ADT is an enum. - const IS_ENUM = 1 << 0; - /// Indicates whether the ADT is a union. - const IS_UNION = 1 << 1; - /// Indicates whether the ADT is a struct. - const IS_STRUCT = 1 << 2; - /// Indicates whether the ADT is a struct and has a constructor. - const HAS_CTOR = 1 << 3; - /// Indicates whether the type is `PhantomData`. - const IS_PHANTOM_DATA = 1 << 4; - /// Indicates whether the type has a `#[fundamental]` attribute. - const IS_FUNDAMENTAL = 1 << 5; - /// Indicates whether the type is `Box`. - const IS_BOX = 1 << 6; - /// Indicates whether the type is `ManuallyDrop`. - const IS_MANUALLY_DROP = 1 << 7; - /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`. - /// (i.e., this flag is never set unless this ADT is an enum). - const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8; - /// Indicates whether the type is `UnsafeCell`. - const IS_UNSAFE_CELL = 1 << 9; - } -} +#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] +#[rustc_pass_by_value] +pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>); /// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`. /// @@ -97,69 +71,98 @@ pub struct AdtDefData { repr: ReprOptions, } -impl PartialOrd for AdtDefData { - fn partial_cmp(&self, other: &AdtDefData) -> Option { - Some(self.cmp(&other)) +bitflags! { + #[derive(HashStable, TyEncodable, TyDecodable)] + pub struct AdtFlags: u16 { + const NO_ADT_FLAGS = 0; + /// Indicates whether the ADT is an enum. + const IS_ENUM = 1 << 0; + /// Indicates whether the ADT is a union. + const IS_UNION = 1 << 1; + /// Indicates whether the ADT is a struct. + const IS_STRUCT = 1 << 2; + /// Indicates whether the ADT is a struct and has a constructor. + const HAS_CTOR = 1 << 3; + /// Indicates whether the type is `PhantomData`. + const IS_PHANTOM_DATA = 1 << 4; + /// Indicates whether the type has a `#[fundamental]` attribute. + const IS_FUNDAMENTAL = 1 << 5; + /// Indicates whether the type is `Box`. + const IS_BOX = 1 << 6; + /// Indicates whether the type is `ManuallyDrop`. + const IS_MANUALLY_DROP = 1 << 7; + /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`. + /// (i.e., this flag is never set unless this ADT is an enum). + const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8; + /// Indicates whether the type is `UnsafeCell`. + const IS_UNSAFE_CELL = 1 << 9; } } -/// There should be only one AdtDef for each `did`, therefore -/// it is fine to implement `Ord` only based on `did`. -impl Ord for AdtDefData { - fn cmp(&self, other: &AdtDefData) -> Ordering { - self.did.cmp(&other.did) - } +#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)] +pub enum AdtKind { + Struct, + Union, + Enum, } -/// There should be only one AdtDef for each `did`, therefore -/// it is fine to implement `PartialEq` only based on `did`. -impl PartialEq for AdtDefData { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.did == other.did - } +/// Definition of a variant -- a struct's fields or an enum variant. +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] +pub struct VariantDef { + /// `DefId` that identifies the variant itself. + /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. + pub def_id: DefId, + /// `DefId` that identifies the variant's constructor. + /// If this variant is a struct variant, then this is `None`. + pub ctor: Option<(CtorKind, DefId)>, + /// Variant or struct name. + pub name: Symbol, + /// Discriminant of this variant. + pub discr: VariantDiscr, + /// Fields of this variant. + pub fields: IndexVec, + /// Flags of the variant (e.g. is field list non-exhaustive)? + flags: VariantFlags, } -impl Eq for AdtDefData {} - -/// There should be only one AdtDef for each `did`, therefore -/// it is fine to implement `Hash` only based on `did`. -impl Hash for AdtDefData { - #[inline] - fn hash(&self, s: &mut H) { - self.did.hash(s) +bitflags! { + #[derive(HashStable, TyEncodable, TyDecodable)] + pub struct VariantFlags: u8 { + const NO_VARIANT_FLAGS = 0; + /// Indicates whether the field list of this variant is `#[non_exhaustive]`. + const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; + /// Indicates whether this variant was obtained as part of recovering from + /// a syntactic error. May be incomplete or bogus. + const IS_RECOVERED = 1 << 1; } } -impl<'a> HashStable> for AdtDefData { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - thread_local! { - static CACHE: RefCell> = Default::default(); - } - - let hash: Fingerprint = CACHE.with(|cache| { - let addr = self as *const AdtDefData as usize; - let hashing_controls = hcx.hashing_controls(); - *cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| { - let ty::AdtDefData { did, ref variants, ref flags, ref repr } = *self; - - let mut hasher = StableHasher::new(); - did.hash_stable(hcx, &mut hasher); - variants.hash_stable(hcx, &mut hasher); - flags.hash_stable(hcx, &mut hasher); - repr.hash_stable(hcx, &mut hasher); - - hasher.finish() - }) - }); +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] +pub enum VariantDiscr { + /// Explicit value for this variant, i.e., `X = 123`. + /// The `DefId` corresponds to the embedded constant. + Explicit(DefId), + + /// The previous variant's discriminant plus one. + /// For efficiency reasons, the distance from the + /// last `Explicit` discriminant is being stored, + /// or `0` for the first variant, if it has none. + Relative(u32), +} - hash.hash_stable(hcx, hasher); - } +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] +pub struct FieldDef { + pub did: DefId, + pub name: Symbol, + pub vis: Visibility, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] -#[rustc_pass_by_value] -pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>); +#[derive(Clone, Copy, Debug)] +#[derive(HashStable)] +pub enum Representability { + Representable, + Infinite, +} impl<'tcx> AdtDef<'tcx> { #[inline] @@ -186,73 +189,7 @@ impl<'tcx> AdtDef<'tcx> { pub fn repr(self) -> ReprOptions { self.0.0.repr } -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)] -pub enum AdtKind { - Struct, - Union, - Enum, -} - -impl Into for AdtKind { - fn into(self) -> DataTypeKind { - match self { - AdtKind::Struct => DataTypeKind::Struct, - AdtKind::Union => DataTypeKind::Union, - AdtKind::Enum => DataTypeKind::Enum, - } - } -} - -impl AdtDefData { - /// Creates a new `AdtDefData`. - pub(super) fn new( - tcx: TyCtxt<'_>, - did: DefId, - kind: AdtKind, - variants: IndexVec, - repr: ReprOptions, - ) -> Self { - debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); - let mut flags = AdtFlags::NO_ADT_FLAGS; - - if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { - debug!("found non-exhaustive variant list for {:?}", did); - flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; - } - - flags |= match kind { - AdtKind::Enum => AdtFlags::IS_ENUM, - AdtKind::Union => AdtFlags::IS_UNION, - AdtKind::Struct => AdtFlags::IS_STRUCT, - }; - - if kind == AdtKind::Struct && variants[FIRST_VARIANT].ctor.is_some() { - flags |= AdtFlags::HAS_CTOR; - } - - if tcx.has_attr(did, sym::fundamental) { - flags |= AdtFlags::IS_FUNDAMENTAL; - } - if Some(did) == tcx.lang_items().phantom_data() { - flags |= AdtFlags::IS_PHANTOM_DATA; - } - if Some(did) == tcx.lang_items().owned_box() { - flags |= AdtFlags::IS_BOX; - } - if Some(did) == tcx.lang_items().manually_drop() { - flags |= AdtFlags::IS_MANUALLY_DROP; - } - if Some(did) == tcx.lang_items().unsafe_cell_type() { - flags |= AdtFlags::IS_UNSAFE_CELL; - } - - AdtDefData { did, variants, flags, repr } - } -} -impl<'tcx> AdtDef<'tcx> { /// Returns `true` if this is a struct. #[inline] pub fn is_struct(self) -> bool { @@ -559,9 +496,287 @@ impl<'tcx> AdtDef<'tcx> { } } -#[derive(Clone, Copy, Debug)] -#[derive(HashStable)] -pub enum Representability { - Representable, - Infinite, +impl AdtDefData { + /// Creates a new `AdtDefData`. + pub(super) fn new( + tcx: TyCtxt<'_>, + did: DefId, + kind: AdtKind, + variants: IndexVec, + repr: ReprOptions, + ) -> Self { + debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); + let mut flags = AdtFlags::NO_ADT_FLAGS; + + if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { + debug!("found non-exhaustive variant list for {:?}", did); + flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; + } + + flags |= match kind { + AdtKind::Enum => AdtFlags::IS_ENUM, + AdtKind::Union => AdtFlags::IS_UNION, + AdtKind::Struct => AdtFlags::IS_STRUCT, + }; + + if kind == AdtKind::Struct && variants[FIRST_VARIANT].ctor.is_some() { + flags |= AdtFlags::HAS_CTOR; + } + + if tcx.has_attr(did, sym::fundamental) { + flags |= AdtFlags::IS_FUNDAMENTAL; + } + if Some(did) == tcx.lang_items().phantom_data() { + flags |= AdtFlags::IS_PHANTOM_DATA; + } + if Some(did) == tcx.lang_items().owned_box() { + flags |= AdtFlags::IS_BOX; + } + if Some(did) == tcx.lang_items().manually_drop() { + flags |= AdtFlags::IS_MANUALLY_DROP; + } + if Some(did) == tcx.lang_items().unsafe_cell_type() { + flags |= AdtFlags::IS_UNSAFE_CELL; + } + + AdtDefData { did, variants, flags, repr } + } +} + +impl PartialOrd for AdtDefData { + fn partial_cmp(&self, other: &AdtDefData) -> Option { + Some(self.cmp(&other)) + } +} + +/// There should be only one AdtDef for each `did`, therefore +/// it is fine to implement `Ord` only based on `did`. +impl Ord for AdtDefData { + fn cmp(&self, other: &AdtDefData) -> Ordering { + self.did.cmp(&other.did) + } +} + +/// There should be only one AdtDef for each `did`, therefore +/// it is fine to implement `PartialEq` only based on `did`. +impl PartialEq for AdtDefData { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.did == other.did + } +} + +impl Eq for AdtDefData {} + +/// There should be only one AdtDef for each `did`, therefore +/// it is fine to implement `Hash` only based on `did`. +impl Hash for AdtDefData { + #[inline] + fn hash(&self, s: &mut H) { + self.did.hash(s) + } +} + +impl<'a> HashStable> for AdtDefData { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + thread_local! { + static CACHE: RefCell> = Default::default(); + } + + let hash: Fingerprint = CACHE.with(|cache| { + let addr = self as *const AdtDefData as usize; + let hashing_controls = hcx.hashing_controls(); + *cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| { + let ty::AdtDefData { did, ref variants, ref flags, ref repr } = *self; + + let mut hasher = StableHasher::new(); + did.hash_stable(hcx, &mut hasher); + variants.hash_stable(hcx, &mut hasher); + flags.hash_stable(hcx, &mut hasher); + repr.hash_stable(hcx, &mut hasher); + + hasher.finish() + }) + }); + + hash.hash_stable(hcx, hasher); + } +} + +impl Into for AdtKind { + fn into(self) -> DataTypeKind { + match self { + AdtKind::Struct => DataTypeKind::Struct, + AdtKind::Union => DataTypeKind::Union, + AdtKind::Enum => DataTypeKind::Enum, + } + } +} + +impl VariantDef { + /// Creates a new `VariantDef`. + /// + /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` + /// represents an enum variant). + /// + /// `ctor_did` is the `DefId` that identifies the constructor of unit or + /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`. + /// + /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that + /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having + /// to go through the redirect of checking the ctor's attributes - but compiling a small crate + /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any + /// built-in trait), and we do not want to load attributes twice. + /// + /// If someone speeds up attribute loading to not be a performance concern, they can + /// remove this hack and use the constructor `DefId` everywhere. + pub fn new( + name: Symbol, + variant_did: Option, + ctor: Option<(CtorKind, DefId)>, + discr: VariantDiscr, + fields: IndexVec, + adt_kind: AdtKind, + parent_did: DefId, + recovered: bool, + is_field_list_non_exhaustive: bool, + ) -> Self { + debug!( + "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, + fields = {:?}, adt_kind = {:?}, parent_did = {:?})", + name, variant_did, ctor, discr, fields, adt_kind, parent_did, + ); + + let mut flags = VariantFlags::NO_VARIANT_FLAGS; + if is_field_list_non_exhaustive { + flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; + } + + if recovered { + flags |= VariantFlags::IS_RECOVERED; + } + + VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags } + } + + /// Is this field list non-exhaustive? + #[inline] + pub fn is_field_list_non_exhaustive(&self) -> bool { + self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) + } + + /// Was this variant obtained as part of recovering from a syntactic error? + #[inline] + pub fn is_recovered(&self) -> bool { + self.flags.intersects(VariantFlags::IS_RECOVERED) + } + + /// Computes the `Ident` of this variant by looking up the `Span` + pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { + Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) + } + + #[inline] + pub fn ctor_kind(&self) -> Option { + self.ctor.map(|(kind, _)| kind) + } + + #[inline] + pub fn ctor_def_id(&self) -> Option { + self.ctor.map(|(_, def_id)| def_id) + } + + /// Returns the one field in this variant. + /// + /// `panic!`s if there are no fields or multiple fields. + #[inline] + pub fn single_field(&self) -> &FieldDef { + assert!(self.fields.len() == 1); + + &self.fields[FieldIdx::from_u32(0)] + } +} + +impl PartialEq for VariantDef { + #[inline] + fn eq(&self, other: &Self) -> bool { + // There should be only one `VariantDef` for each `def_id`, therefore + // it is fine to implement `PartialEq` only based on `def_id`. + // + // Below, we exhaustively destructure `self` and `other` so that if the + // definition of `VariantDef` changes, a compile-error will be produced, + // reminding us to revisit this assumption. + + let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; + let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other; + lhs_def_id == rhs_def_id + } +} + +impl Eq for VariantDef {} + +impl Hash for VariantDef { + #[inline] + fn hash(&self, s: &mut H) { + // There should be only one `VariantDef` for each `def_id`, therefore + // it is fine to implement `Hash` only based on `def_id`. + // + // Below, we exhaustively destructure `self` so that if the definition + // of `VariantDef` changes, a compile-error will be produced, reminding + // us to revisit this assumption. + + let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; + def_id.hash(s) + } +} + +impl<'tcx> FieldDef { + /// Returns the type of this field. The resulting type is not normalized. The `subst` is + /// typically obtained via the second field of [`TyKind::Adt`]. + /// + /// [`TyKind::Adt`]: crate::ty::TyKind::Adt + pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { + tcx.type_of(self.did).subst(tcx, subst) + } + + /// Computes the `Ident` of this variant by looking up the `Span` + pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { + Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) + } +} + +impl PartialEq for FieldDef { + #[inline] + fn eq(&self, other: &Self) -> bool { + // There should be only one `FieldDef` for each `did`, therefore it is + // fine to implement `PartialEq` only based on `did`. + // + // Below, we exhaustively destructure `self` so that if the definition + // of `FieldDef` changes, a compile-error will be produced, reminding + // us to revisit this assumption. + + let Self { did: lhs_did, name: _, vis: _ } = &self; + + let Self { did: rhs_did, name: _, vis: _ } = other; + + lhs_did == rhs_did + } +} + +impl Eq for FieldDef {} + +impl Hash for FieldDef { + #[inline] + fn hash(&self, s: &mut H) { + // There should be only one `FieldDef` for each `did`, therefore it is + // fine to implement `Hash` only based on `did`. + // + // Below, we exhaustively destructure `self` so that if the definition + // of `FieldDef` changes, a compile-error will be produced, reminding + // us to revisit this assumption. + + let Self { did, name: _, vis: _ } = &self; + + did.hash(s) + } } diff --git a/compiler/rustc_middle/src/ty/closure_size_profile_data.rs b/compiler/rustc_middle/src/ty/closure_size_profile_data.rs new file mode 100644 index 0000000000000..c2d7e93d31112 --- /dev/null +++ b/compiler/rustc_middle/src/ty/closure_size_profile_data.rs @@ -0,0 +1,10 @@ +use crate::ty::Ty; + +#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct ClosureSizeProfileData<'tcx> { + /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` + pub before_feature_tys: Ty<'tcx>, + /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields` + pub after_feature_tys: Ty<'tcx>, +} diff --git a/compiler/rustc_middle/src/ty/coherence.rs b/compiler/rustc_middle/src/ty/coherence.rs new file mode 100644 index 0000000000000..fe37ff602764b --- /dev/null +++ b/compiler/rustc_middle/src/ty/coherence.rs @@ -0,0 +1,111 @@ +use std::fmt; + +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; + +use crate::ty::{Predicate, SimplifiedType, TraitRef, Ty}; + +/// A map for the local crate mapping each type to a vector of its +/// inherent impls. This is not meant to be used outside of coherence; +/// rather, you should request the vector for a specific type via +/// `tcx.inherent_impls(def_id)` so as to minimize your dependencies +/// (constructing this map requires touching the entire crate). +#[derive(Clone, Debug, Default, HashStable)] +pub struct CrateInherentImpls { + pub inherent_impls: LocalDefIdMap>, + pub incoherent_impls: FxHashMap>, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum ImplOverlapKind { + /// These impls are always allowed to overlap. + Permitted { + /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait + marker: bool, + }, + /// These impls are allowed to overlap, but that raises + /// an issue #33140 future-compatibility warning. + /// + /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's + /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different. + /// + /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied + /// that difference, making what reduces to the following set of impls: + /// + /// ```compile_fail,(E0119) + /// trait Trait {} + /// impl Trait for dyn Send + Sync {} + /// impl Trait for dyn Sync + Send {} + /// ``` + /// + /// Obviously, once we made these types be identical, that code causes a coherence + /// error and a fairly big headache for us. However, luckily for us, the trait + /// `Trait` used in this case is basically a marker trait, and therefore having + /// overlapping impls for it is sound. + /// + /// To handle this, we basically regard the trait as a marker trait, with an additional + /// future-compatibility warning. To avoid accidentally "stabilizing" this feature, + /// it has the following restrictions: + /// + /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be + /// positive impls. + /// 2. The trait-ref of both impls must be equal. + /// 3. The trait-ref of both impls must be a trait object type consisting only of + /// marker traits. + /// 4. Neither of the impls can have any where-clauses. + /// + /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed. + Issue33140, +} + +/// The "header" of an impl is everything outside the body: a Self type, a trait +/// ref (in the case of a trait impl), and a set of predicates (from the +/// bounds / where-clauses). +#[derive(Clone, Debug, TypeFoldable, TypeVisitable)] +pub struct ImplHeader<'tcx> { + pub impl_def_id: DefId, + pub self_ty: Ty<'tcx>, + pub trait_ref: Option>, + pub predicates: Vec>, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] +pub enum ImplSubject<'tcx> { + Trait(TraitRef<'tcx>), + Inherent(Ty<'tcx>), +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum ImplPolarity { + /// `impl Trait for Type` + Positive, + /// `impl !Trait for Type` + Negative, + /// `#[rustc_reservation_impl] impl Trait for Type` + /// + /// This is a "stability hack", not a real Rust feature. + /// See #64631 for details. + Reservation, +} + +impl ImplPolarity { + /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`. + pub fn flip(&self) -> Option { + match self { + ImplPolarity::Positive => Some(ImplPolarity::Negative), + ImplPolarity::Negative => Some(ImplPolarity::Positive), + ImplPolarity::Reservation => None, + } + } +} + +impl fmt::Display for ImplPolarity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Positive => f.write_str("positive"), + Self::Negative => f.write_str("negative"), + Self::Reservation => f.write_str("reservation"), + } + } +} diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index e7107c28bf407..5804a7ea70291 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,12 +1,14 @@ -use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::LitToConstInput; -use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use std::fmt; + use rustc_data_structures::intern::Interned; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; -use std::fmt; + +use crate::middle::resolve_bound_vars as rbv; +use crate::mir::interpret::LitToConstInput; +use crate::ty::{self, BoundVar, InternalSubsts, ParamEnv, ParamEnvAnd, Placeholder, Ty, TyCtxt}; mod int; mod kind; @@ -37,6 +39,8 @@ pub struct ConstData<'tcx> { pub kind: ConstKind<'tcx>, } +pub type PlaceholderConst<'tcx> = Placeholder; + #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstData<'_>, 40); diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 1ac2cd13982b9..c39ae6d57c9de 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,17 +1,14 @@ -use super::Const; -use crate::mir; -use crate::mir::interpret::{AllocId, ConstValue, Scalar}; -use crate::ty::abstract_const::CastKind; -use crate::ty::subst::{InternalSubsts, SubstsRef}; -use crate::ty::ParamEnv; -use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_target::abi::Size; -use super::ScalarInt; +use crate::mir; +use crate::mir::interpret::{AllocId, ConstValue, Scalar}; +use crate::ty::abstract_const::CastKind; +use crate::ty::subst::{InternalSubsts, SubstsRef}; +use crate::ty::{self, BoundVar, Const, List, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; /// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] @@ -74,6 +71,13 @@ pub enum ConstKind<'tcx> { Expr(Expr<'tcx>), } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)] +pub struct BoundConst<'tcx> { + pub var: BoundVar, + pub ty: Ty<'tcx>, +} + impl<'tcx> From> for ConstKind<'tcx> { fn from(const_vid: ty::ConstVid<'tcx>) -> Self { InferConst::Var(const_vid).into() diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8aea2d8aedf98..118e8592e25bc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -5,6 +5,7 @@ pub mod tls; use crate::arena::Arena; +use crate::cache::CReaderCacheKey; use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::infer::canonical::CanonicalVarInfo; use crate::lint::struct_lint_level; @@ -517,8 +518,8 @@ pub struct GlobalCtxt<'tcx> { pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>], // Internal caches for metadata decoding. No need to track deps on this. - pub ty_rcache: Lock>>, - pub pred_rcache: Lock>>, + pub ty_rcache: Lock>>, + pub pred_rcache: Lock>>, /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. diff --git a/compiler/rustc_middle/src/ty/crate_variances_map.rs b/compiler/rustc_middle/src/ty/crate_variances_map.rs new file mode 100644 index 0000000000000..4c7ca77dd8656 --- /dev/null +++ b/compiler/rustc_middle/src/ty/crate_variances_map.rs @@ -0,0 +1,17 @@ +use rustc_hir::def_id::DefIdMap; + +use crate::ty; + +/// The crate variances map is computed during typeck and contains the +/// variance of every item in the local crate. You should not use it +/// directly, because to do so will make your pass dependent on the +/// HIR of every item in the local crate. Instead, use +/// `tcx.variances_of()` to get the variance for a *particular* +/// item. +#[derive(HashStable, Debug)] +pub struct CrateVariancesMap<'tcx> { + /// For each item with generics, maps to a vector of the variance + /// of its generics. If an item has no generics, it will have no + /// entry. + pub variances: DefIdMap<&'tcx [ty::Variance]>, +} diff --git a/compiler/rustc_middle/src/ty/destructor.rs b/compiler/rustc_middle/src/ty/destructor.rs new file mode 100644 index 0000000000000..308c5eef93319 --- /dev/null +++ b/compiler/rustc_middle/src/ty/destructor.rs @@ -0,0 +1,10 @@ +use rustc_hir as hir; +use rustc_hir::def_id::DefId; + +#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] +pub struct Destructor { + /// The `DefId` of the destructor method + pub did: DefId, + /// The constness of the destructor method + pub constness: hir::Constness, +} diff --git a/compiler/rustc_middle/src/ty/destructured_const.rs b/compiler/rustc_middle/src/ty/destructured_const.rs new file mode 100644 index 0000000000000..a59c02e11f305 --- /dev/null +++ b/compiler/rustc_middle/src/ty/destructured_const.rs @@ -0,0 +1,8 @@ +use crate::ty::{self, VariantIdx}; + +/// The constituent parts of a type level constant of kind ADT or array. +#[derive(Copy, Clone, Debug, HashStable)] +pub struct DestructuredConst<'tcx> { + pub variant: Option, + pub fields: &'tcx [ty::Const<'tcx>], +} diff --git a/compiler/rustc_middle/src/ty/impl_trait_in_trait_data.rs b/compiler/rustc_middle/src/ty/impl_trait_in_trait_data.rs new file mode 100644 index 0000000000000..39375ade298cd --- /dev/null +++ b/compiler/rustc_middle/src/ty/impl_trait_in_trait_data.rs @@ -0,0 +1,9 @@ +use rustc_hir::def_id::DefId; + +/// Useful source information about where a desugared associated type for an +/// RPITIT originated from. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)] +pub enum ImplTraitInTraitData { + Trait { fn_def_id: DefId, opaque_def_id: DefId }, + Impl { fn_def_id: DefId }, +} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f882f54d62811..73dbc729f332b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -11,1999 +11,222 @@ #![allow(rustc::usage_of_ty_tykind)] -pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; -pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -pub use self::AssocItemContainer::*; -pub use self::BorrowKind::*; -pub use self::IntVarValue::*; -pub use self::Variance::*; -use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; -use crate::metadata::ModChild; -use crate::middle::privacy::EffectiveVisibilities; -use crate::mir::{Body, GeneratorLayout}; -use crate::traits::{self, Reveal}; -use crate::ty; -use crate::ty::fast_reject::SimplifiedType; -use crate::ty::util::Discr; -pub use adt::*; -pub use assoc::*; -pub use generics::*; -use rustc_ast as ast; -use rustc_ast::node_id::NodeMap; -use rustc_attr as attr; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::intern::Interned; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::steal::Steal; -use rustc_data_structures::tagged_ptr::CopyTaggedPtr; -use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; -use rustc_hir::Node; -use rustc_index::IndexVec; -use rustc_macros::HashStable; -use rustc_query_system::ich::StableHashingContext; -use rustc_serialize::{Decodable, Encodable}; -use rustc_session::lint::LintBuffer; -pub use rustc_session::lint::RegisteredTools; -use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{ExpnId, ExpnKind, Span}; -use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; -pub use rustc_target::abi::{ReprFlags, ReprOptions}; -use rustc_type_ir::WithCachedTypeInfo; -pub use subst::*; -pub use vtable::*; - -use std::fmt::Debug; -use std::hash::{Hash, Hasher}; -use std::marker::PhantomData; -use std::mem; -use std::num::NonZeroUsize; -use std::ops::ControlFlow; -use std::{fmt, str}; - -pub use crate::ty::diagnostics::*; -pub use rustc_type_ir::AliasKind::*; -pub use rustc_type_ir::DynKind::*; -pub use rustc_type_ir::InferTy::*; -pub use rustc_type_ir::RegionKind::*; -pub use rustc_type_ir::TyKind::*; -pub use rustc_type_ir::*; - -pub use self::binding::BindingMode; -pub use self::binding::BindingMode::*; -pub use self::closure::{ - is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, - CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, - RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath, - CAPTURE_STRUCT_LOCAL, -}; -pub use self::consts::{ - Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, -}; -pub use self::context::{ - tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, -}; -pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; -pub use self::list::List; -pub use self::parameterized::ParameterizedOverTcx; -pub use self::rvalue_scopes::RvalueScopes; -pub use self::sty::BoundRegionKind::*; -pub use self::sty::{ - AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, - BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, - EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, - InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, - PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, - Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, -}; -pub use self::trait_def::TraitDef; -pub use self::typeck_results::{ - CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, - GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType, - UserTypeAnnotationIndex, -}; - -pub mod _match; -pub mod abstract_const; -pub mod adjustment; -pub mod binding; -pub mod cast; -pub mod codec; -pub mod error; -pub mod fast_reject; -pub mod flags; -pub mod fold; -pub mod inhabitedness; -pub mod layout; -pub mod normalize_erasing_regions; -pub mod print; -pub mod query; -pub mod relate; -pub mod subst; -pub mod trait_def; -pub mod util; -pub mod visit; -pub mod vtable; -pub mod walk; - -mod adt; -mod assoc; -mod closure; -mod consts; -mod context; -mod diagnostics; -mod erase_regions; -mod generics; -mod impls_ty; -mod instance; -mod list; -mod opaque_types; -mod parameterized; -mod rvalue_scopes; -mod structural_impls; -mod sty; -mod typeck_results; - -// Data types - -pub struct ResolverOutputs { - pub global_ctxt: ResolverGlobalCtxt, - pub ast_lowering: ResolverAstLowering, -} - -#[derive(Debug)] -pub struct ResolverGlobalCtxt { - pub visibilities: FxHashMap, - /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. - pub has_pub_restricted: bool, - /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. - pub expn_that_defined: FxHashMap, - pub effective_visibilities: EffectiveVisibilities, - pub extern_crate_map: FxHashMap, - pub maybe_unused_trait_imports: FxIndexSet, - pub module_children: LocalDefIdMap>, - pub glob_map: FxHashMap>, - pub main_def: Option, - pub trait_impls: FxIndexMap>, - /// A list of proc macro LocalDefIds, written out in the order in which - /// they are declared in the static array generated by proc_macro_harness. - pub proc_macros: Vec, - /// Mapping from ident span to path span for paths that don't exist as written, but that - /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. - pub confused_type_with_std_module: FxHashMap, - pub doc_link_resolutions: FxHashMap, - pub doc_link_traits_in_scope: FxHashMap>, - pub all_macro_rules: FxHashMap>, -} - -/// Resolutions that should only be used for lowering. -/// This struct is meant to be consumed by lowering. -#[derive(Debug)] -pub struct ResolverAstLowering { - pub legacy_const_generic_args: FxHashMap>>, - - /// Resolutions for nodes that have a single resolution. - pub partial_res_map: NodeMap, - /// Resolutions for import nodes, which have multiple resolutions in different namespaces. - pub import_res_map: NodeMap>>>, - /// Resolutions for labels (node IDs of their corresponding blocks or loops). - pub label_res_map: NodeMap, - /// Resolutions for lifetimes. - pub lifetimes_res_map: NodeMap, - /// Lifetime parameters that lowering will have to introduce. - pub extra_lifetime_params_map: NodeMap>, - - pub next_node_id: ast::NodeId, - - pub node_id_to_def_id: FxHashMap, - pub def_id_to_node_id: IndexVec, - - pub trait_map: NodeMap>, - /// A small map keeping true kinds of built-in macros that appear to be fn-like on - /// the surface (`macro` items in libcore), but are actually attributes or derives. - pub builtin_macro_kinds: FxHashMap, - /// List functions and methods for which lifetime elision was successful. - pub lifetime_elision_allowed: FxHashSet, - - /// Lints that were emitted by the resolver and early lints. - pub lint_buffer: Steal, -} - -#[derive(Clone, Copy, Debug)] -pub struct MainDefinition { - pub res: Res, - pub is_import: bool, - pub span: Span, -} - -impl MainDefinition { - pub fn opt_fn_def_id(self) -> Option { - if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } - } -} - -/// The "header" of an impl is everything outside the body: a Self type, a trait -/// ref (in the case of a trait impl), and a set of predicates (from the -/// bounds / where-clauses). -#[derive(Clone, Debug, TypeFoldable, TypeVisitable)] -pub struct ImplHeader<'tcx> { - pub impl_def_id: DefId, - pub self_ty: Ty<'tcx>, - pub trait_ref: Option>, - pub predicates: Vec>, -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] -pub enum ImplSubject<'tcx> { - Trait(TraitRef<'tcx>), - Inherent(Ty<'tcx>), -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] -#[derive(TypeFoldable, TypeVisitable)] -pub enum ImplPolarity { - /// `impl Trait for Type` - Positive, - /// `impl !Trait for Type` - Negative, - /// `#[rustc_reservation_impl] impl Trait for Type` - /// - /// This is a "stability hack", not a real Rust feature. - /// See #64631 for details. - Reservation, -} - -impl ImplPolarity { - /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`. - pub fn flip(&self) -> Option { - match self { - ImplPolarity::Positive => Some(ImplPolarity::Negative), - ImplPolarity::Negative => Some(ImplPolarity::Positive), - ImplPolarity::Reservation => None, - } - } -} - -impl fmt::Display for ImplPolarity { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Positive => f.write_str("positive"), - Self::Negative => f.write_str("negative"), - Self::Reservation => f.write_str("reservation"), - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)] -pub enum Visibility { - /// Visible everywhere (including in other crates). - Public, - /// Visible only in the given crate-local module. - Restricted(Id), -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] -pub enum BoundConstness { - /// `T: Trait` - NotConst, - /// `T: ~const Trait` - /// - /// Requires resolving to const only when we are in a const context. - ConstIfConst, -} - -impl BoundConstness { - /// Reduce `self` and `constness` to two possible combined states instead of four. - pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { - match (constness, self) { - (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, - (_, this) => { - *this = BoundConstness::NotConst; - hir::Constness::NotConst - } - } - } -} - -impl fmt::Display for BoundConstness { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::NotConst => f.write_str("normal"), - Self::ConstIfConst => f.write_str("`~const`"), - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ClosureSizeProfileData<'tcx> { - /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` - pub before_feature_tys: Ty<'tcx>, - /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields` - pub after_feature_tys: Ty<'tcx>, -} - -impl TyCtxt<'_> { - #[inline] - pub fn opt_parent(self, id: DefId) -> Option { - self.def_key(id).parent.map(|index| DefId { index, ..id }) - } - - #[inline] - #[track_caller] - pub fn parent(self, id: DefId) -> DefId { - match self.opt_parent(id) { - Some(id) => id, - // not `unwrap_or_else` to avoid breaking caller tracking - None => bug!("{id:?} doesn't have a parent"), - } - } - - #[inline] - #[track_caller] - pub fn opt_local_parent(self, id: LocalDefId) -> Option { - self.opt_parent(id.to_def_id()).map(DefId::expect_local) - } - - #[inline] - #[track_caller] - pub fn local_parent(self, id: LocalDefId) -> LocalDefId { - self.parent(id.to_def_id()).expect_local() - } - - pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { - if descendant.krate != ancestor.krate { - return false; - } - - while descendant != ancestor { - match self.opt_parent(descendant) { - Some(parent) => descendant = parent, - None => return false, - } - } - true - } -} - -impl Visibility { - pub fn is_public(self) -> bool { - matches!(self, Visibility::Public) - } - - pub fn map_id(self, f: impl FnOnce(Id) -> OutId) -> Visibility { - match self { - Visibility::Public => Visibility::Public, - Visibility::Restricted(id) => Visibility::Restricted(f(id)), - } - } -} - -impl> Visibility { - pub fn to_def_id(self) -> Visibility { - self.map_id(Into::into) - } - - /// Returns `true` if an item with this visibility is accessible from the given module. - pub fn is_accessible_from(self, module: impl Into, tcx: TyCtxt<'_>) -> bool { - match self { - // Public items are visible everywhere. - Visibility::Public => true, - Visibility::Restricted(id) => tcx.is_descendant_of(module.into(), id.into()), - } - } - - /// Returns `true` if this visibility is at least as accessible as the given visibility - pub fn is_at_least(self, vis: Visibility>, tcx: TyCtxt<'_>) -> bool { - match vis { - Visibility::Public => self.is_public(), - Visibility::Restricted(id) => self.is_accessible_from(id, tcx), - } - } -} - -impl Visibility { - pub fn expect_local(self) -> Visibility { - self.map_id(|id| id.expect_local()) - } - - /// Returns `true` if this item is visible anywhere in the local crate. - pub fn is_visible_locally(self) -> bool { - match self { - Visibility::Public => true, - Visibility::Restricted(def_id) => def_id.is_local(), - } - } -} - -/// The crate variances map is computed during typeck and contains the -/// variance of every item in the local crate. You should not use it -/// directly, because to do so will make your pass dependent on the -/// HIR of every item in the local crate. Instead, use -/// `tcx.variances_of()` to get the variance for a *particular* -/// item. -#[derive(HashStable, Debug)] -pub struct CrateVariancesMap<'tcx> { - /// For each item with generics, maps to a vector of the variance - /// of its generics. If an item has no generics, it will have no - /// entry. - pub variances: DefIdMap<&'tcx [ty::Variance]>, -} - -// Contains information needed to resolve types and (in the future) look up -// the types of AST nodes. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct CReaderCacheKey { - pub cnum: Option, - pub pos: usize, -} - -/// Use this rather than `TyKind`, whenever possible. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] -#[rustc_diagnostic_item = "Ty"] -#[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); - -impl ty::EarlyBoundRegion { - /// Does this early bound region have a name? Early bound regions normally - /// always have names except when using anonymous lifetimes (`'_`). - pub fn has_name(&self) -> bool { - self.name != kw::UnderscoreLifetime && self.name != kw::Empty - } -} - -/// Use this rather than `PredicateKind`, whenever possible. -#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] -#[rustc_pass_by_value] -pub struct Predicate<'tcx>( - Interned<'tcx, WithCachedTypeInfo>>>, -); - -impl<'tcx> Predicate<'tcx> { - /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. - #[inline] - pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { - self.0.internee - } - - #[inline(always)] - pub fn flags(self) -> TypeFlags { - self.0.flags - } - - #[inline(always)] - pub fn outer_exclusive_binder(self) -> DebruijnIndex { - self.0.outer_exclusive_binder - } - - /// Flips the polarity of a Predicate. - /// - /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. - pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option> { - let kind = self - .kind() - .map_bound(|kind| match kind { - PredicateKind::Clause(Clause::Trait(TraitPredicate { - trait_ref, - constness, - polarity, - })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate { - trait_ref, - constness, - polarity: polarity.flip()?, - }))), - - _ => None, - }) - .transpose()?; - - Some(tcx.mk_predicate(kind)) - } - - pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { - if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() - && constness != BoundConstness::NotConst - { - self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate { - trait_ref, - constness: BoundConstness::NotConst, - polarity, - })))); - } - self - } - - #[instrument(level = "debug", skip(tcx), ret)] - pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { - tcx.trait_is_coinductive(data.def_id()) - } - ty::PredicateKind::WellFormed(_) => true, - _ => false, - } - } - - /// Whether this projection can be soundly normalized. - /// - /// Wf predicates must not be normalized, as normalization - /// can remove required bounds which would cause us to - /// unsoundly accept some programs. See #91068. - #[inline] - pub fn allow_normalization(self) -> bool { - match self.kind().skip_binder() { - PredicateKind::WellFormed(_) => false, - PredicateKind::Clause(Clause::Trait(_)) - | PredicateKind::Clause(Clause::RegionOutlives(_)) - | PredicateKind::Clause(Clause::TypeOutlives(_)) - | PredicateKind::Clause(Clause::Projection(_)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::ObjectSafe(_) - | PredicateKind::ClosureKind(_, _, _) - | PredicateKind::Subtype(_) - | PredicateKind::Coerce(_) - | PredicateKind::ConstEvaluatable(_) - | PredicateKind::ConstEquate(_, _) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(_) => true, - } - } -} - -impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { - rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -/// A clause is something that can appear in where bounds or be inferred -/// by implied bounds. -pub enum Clause<'tcx> { - /// Corresponds to `where Foo: Bar`. `Foo` here would be - /// the `Self` type of the trait reference and `A`, `B`, and `C` - /// would be the type parameters. - Trait(TraitPredicate<'tcx>), - - /// `where 'a: 'b` - RegionOutlives(RegionOutlivesPredicate<'tcx>), - - /// `where T: 'a` - TypeOutlives(TypeOutlivesPredicate<'tcx>), - - /// `where ::Name == X`, approximately. - /// See the `ProjectionPredicate` struct for details. - Projection(ProjectionPredicate<'tcx>), - - /// Ensures that a const generic argument to a parameter `const N: u8` - /// is of type `u8`. - ConstArgHasType(Const<'tcx>, Ty<'tcx>), -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub enum PredicateKind<'tcx> { - /// Prove a clause - Clause(Clause<'tcx>), - - /// No syntax: `T` well-formed. - WellFormed(GenericArg<'tcx>), - - /// Trait must be object-safe. - ObjectSafe(DefId), - - /// No direct syntax. May be thought of as `where T: FnFoo<...>` - /// for some substitutions `...` and `T` being a closure type. - /// Satisfied (or refuted) once we know the closure's kind. - ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind), - - /// `T1 <: T2` - /// - /// This obligation is created most often when we have two - /// unresolved type variables and hence don't have enough - /// information to process the subtyping obligation yet. - Subtype(SubtypePredicate<'tcx>), - - /// `T1` coerced to `T2` - /// - /// Like a subtyping obligation, this is created most often - /// when we have two unresolved type variables and hence - /// don't have enough information to process the coercion - /// obligation yet. At the moment, we actually process coercions - /// very much like subtyping and don't handle the full coercion - /// logic. - Coerce(CoercePredicate<'tcx>), - - /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Const<'tcx>), - - /// Constants must be equal. The first component is the const that is expected. - ConstEquate(Const<'tcx>, Const<'tcx>), - - /// Represents a type found in the environment that we can use for implied bounds. - /// - /// Only used for Chalk. - TypeWellFormedFromEnv(Ty<'tcx>), - - /// A marker predicate that is always ambiguous. - /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. - Ambiguous, - - /// Separate from `Clause::Projection` which is used for normalization in new solver. - /// This predicate requires two terms to be equal to eachother. - /// - /// Only used for new solver - AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection), -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, Debug)] -pub enum AliasRelationDirection { - Equate, - Subtype, -} - -impl std::fmt::Display for AliasRelationDirection { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - AliasRelationDirection::Equate => write!(f, "=="), - AliasRelationDirection::Subtype => write!(f, "<:"), - } - } -} - -/// The crate outlives map is computed during typeck and contains the -/// outlives of every item in the local crate. You should not use it -/// directly, because to do so will make your pass dependent on the -/// HIR of every item in the local crate. Instead, use -/// `tcx.inferred_outlives_of()` to get the outlives for a *particular* -/// item. -#[derive(HashStable, Debug)] -pub struct CratePredicatesMap<'tcx> { - /// For each struct with outlive bounds, maps to a vector of the - /// predicate of its outlive bounds. If an item has no outlives - /// bounds, it will have no entry. - pub predicates: FxHashMap, Span)]>, -} - -impl<'tcx> Predicate<'tcx> { - /// Performs a substitution suitable for going from a - /// poly-trait-ref to supertraits that must hold if that - /// poly-trait-ref holds. This is slightly different from a normal - /// substitution in terms of what happens with bound regions. See - /// lengthy comment below for details. - pub fn subst_supertrait( - self, - tcx: TyCtxt<'tcx>, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> Predicate<'tcx> { - // The interaction between HRTB and supertraits is not entirely - // obvious. Let me walk you (and myself) through an example. - // - // Let's start with an easy case. Consider two traits: - // - // trait Foo<'a>: Bar<'a,'a> { } - // trait Bar<'b,'c> { } - // - // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then - // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we - // knew that `Foo<'x>` (for any 'x) then we also know that - // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from - // normal substitution. - // - // In terms of why this is sound, the idea is that whenever there - // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` - // holds. So if there is an impl of `T:Foo<'a>` that applies to - // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all - // `'a`. - // - // Another example to be careful of is this: - // - // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } - // trait Bar1<'b,'c> { } - // - // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? - // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The - // reason is similar to the previous example: any impl of - // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So - // basically we would want to collapse the bound lifetimes from - // the input (`trait_ref`) and the supertraits. - // - // To achieve this in practice is fairly straightforward. Let's - // consider the more complicated scenario: - // - // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` - // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, - // where both `'x` and `'b` would have a DB index of 1. - // The substitution from the input trait-ref is therefore going to be - // `'a => 'x` (where `'x` has a DB index of 1). - // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an - // early-bound parameter and `'b` is a late-bound parameter with a - // DB index of 1. - // - If we replace `'a` with `'x` from the input, it too will have - // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` - // just as we wanted. - // - // There is only one catch. If we just apply the substitution `'a - // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will - // adjust the DB index because we substituting into a binder (it - // tries to be so smart...) resulting in `for<'x> for<'b> - // Bar1<'x,'b>` (we have no syntax for this, so use your - // imagination). Basically the 'x will have DB index of 2 and 'b - // will have DB index of 1. Not quite what we want. So we apply - // the substitution to the *contents* of the trait reference, - // rather than the trait reference itself (put another way, the - // substitution code expects equal binding levels in the values - // from the substitution and the value being substituted into, and - // this trick achieves that). - - // Working through the second example: - // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] - // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] - // We want to end up with: - // for<'x, 'b> T: Bar1<'^0.0, '^0.1> - // To do this: - // 1) We must shift all bound vars in predicate by the length - // of trait ref's bound vars. So, we would end up with predicate like - // Self: Bar1<'a, '^0.1> - // 2) We can then apply the trait substs to this, ending up with - // T: Bar1<'^0.0, '^0.1> - // 3) Finally, to create the final bound vars, we concatenate the bound - // vars of the trait ref with those of the predicate: - // ['x, 'b] - let bound_pred = self.kind(); - let pred_bound_vars = bound_pred.bound_vars(); - let trait_bound_vars = trait_ref.bound_vars(); - // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> - let shifted_pred = - tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); - // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> - let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs); - // 3) ['x] + ['b] -> ['x, 'b] - let bound_vars = - tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); - tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct TraitPredicate<'tcx> { - pub trait_ref: TraitRef<'tcx>, - - pub constness: BoundConstness, - - /// If polarity is Positive: we are proving that the trait is implemented. - /// - /// If polarity is Negative: we are proving that a negative impl of this trait - /// exists. (Note that coherence also checks whether negative impls of supertraits - /// exist via a series of predicates.) - /// - /// If polarity is Reserved: that's a bug. - pub polarity: ImplPolarity, -} - -pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; - -impl<'tcx> TraitPredicate<'tcx> { - pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) { - *param_env = param_env.with_constness(self.constness.and(param_env.constness())) - } - - /// Remap the constness of this predicate before emitting it for diagnostics. - pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { - // this is different to `remap_constness` that callees want to print this predicate - // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the - // param_env is not const because it is always satisfied in non-const contexts. - if let hir::Constness::NotConst = param_env.constness() { - self.constness = ty::BoundConstness::NotConst; - } - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } - } - - pub fn def_id(self) -> DefId { - self.trait_ref.def_id - } - - pub fn self_ty(self) -> Ty<'tcx> { - self.trait_ref.self_ty() - } - - #[inline] - pub fn is_const_if_const(self) -> bool { - self.constness == BoundConstness::ConstIfConst - } - - pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool { - match (self.constness, constness) { - (BoundConstness::NotConst, _) - | (BoundConstness::ConstIfConst, hir::Constness::Const) => true, - (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false, - } - } - - pub fn without_const(mut self) -> Self { - self.constness = BoundConstness::NotConst; - self - } -} - -impl<'tcx> PolyTraitPredicate<'tcx> { - pub fn def_id(self) -> DefId { - // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().def_id() - } - - pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { - self.map_bound(|trait_ref| trait_ref.self_ty()) - } - - /// Remap the constness of this predicate before emitting it for diagnostics. - pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { - *self = self.map_bound(|mut p| { - p.remap_constness_diag(param_env); - p - }); - } - - #[inline] - pub fn is_const_if_const(self) -> bool { - self.skip_binder().is_const_if_const() - } - - #[inline] - pub fn polarity(self) -> ImplPolarity { - self.skip_binder().polarity - } -} - -/// `A: B` -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct OutlivesPredicate(pub A, pub B); -pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; -pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; - -/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates -/// whether the `a` type is the type that we should label as "expected" when -/// presenting user diagnostics. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct SubtypePredicate<'tcx> { - pub a_is_expected: bool, - pub a: Ty<'tcx>, - pub b: Ty<'tcx>, -} -pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; - -/// Encodes that we have to coerce *from* the `a` type to the `b` type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct CoercePredicate<'tcx> { - pub a: Ty<'tcx>, - pub b: Ty<'tcx>, -} -pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Term<'tcx> { - ptr: NonZeroUsize, - marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, -} - -impl Debug for Term<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let data = if let Some(ty) = self.ty() { - format!("Term::Ty({:?})", ty) - } else if let Some(ct) = self.ct() { - format!("Term::Ct({:?})", ct) - } else { - unreachable!() - }; - f.write_str(&data) - } -} - -impl<'tcx> From> for Term<'tcx> { - fn from(ty: Ty<'tcx>) -> Self { - TermKind::Ty(ty).pack() - } -} - -impl<'tcx> From> for Term<'tcx> { - fn from(c: Const<'tcx>) -> Self { - TermKind::Const(c).pack() - } -} - -impl<'a, 'tcx> HashStable> for Term<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.unpack().hash_stable(hcx, hasher); - } -} - -impl<'tcx> TypeFoldable> for Term<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(self.unpack().try_fold_with(folder)?.pack()) - } -} - -impl<'tcx> TypeVisitable> for Term<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.unpack().visit_with(visitor) - } -} - -impl<'tcx, E: TyEncoder>> Encodable for Term<'tcx> { - fn encode(&self, e: &mut E) { - self.unpack().encode(e) - } -} - -impl<'tcx, D: TyDecoder>> Decodable for Term<'tcx> { - fn decode(d: &mut D) -> Self { - let res: TermKind<'tcx> = Decodable::decode(d); - res.pack() - } -} - -impl<'tcx> Term<'tcx> { - #[inline] - pub fn unpack(self) -> TermKind<'tcx> { - let ptr = self.ptr.get(); - // SAFETY: use of `Interned::new_unchecked` here is ok because these - // pointers were originally created from `Interned` types in `pack()`, - // and this is just going in the other direction. - unsafe { - match ptr & TAG_MASK { - TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), - ))), - CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), - ))), - _ => core::intrinsics::unreachable(), - } - } - } - - pub fn ty(&self) -> Option> { - if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None } - } - - pub fn ct(&self) -> Option> { - if let TermKind::Const(c) = self.unpack() { Some(c) } else { None } - } - - pub fn into_arg(self) -> GenericArg<'tcx> { - match self.unpack() { - TermKind::Ty(ty) => ty.into(), - TermKind::Const(c) => c.into(), - } - } - - /// This function returns the inner `AliasTy` if this term is a projection. - /// - /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly - /// deal with constants. - pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option> { - match self.unpack() { - TermKind::Ty(ty) => match ty.kind() { - ty::Alias(kind, alias_ty) => match kind { - AliasKind::Projection | AliasKind::Inherent => Some(*alias_ty), - AliasKind::Opaque => None, - }, - _ => None, - }, - TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)), - _ => None, - }, - } - } - - pub fn is_infer(&self) -> bool { - match self.unpack() { - TermKind::Ty(ty) => ty.is_ty_var(), - TermKind::Const(ct) => ct.is_ct_infer(), - } - } -} - -const TAG_MASK: usize = 0b11; -const TYPE_TAG: usize = 0b00; -const CONST_TAG: usize = 0b01; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable)] -pub enum TermKind<'tcx> { - Ty(Ty<'tcx>), - Const(Const<'tcx>), -} - -impl<'tcx> TermKind<'tcx> { - #[inline] - fn pack(self) -> Term<'tcx> { - let (tag, ptr) = match self { - TermKind::Ty(ty) => { - // Ensure we can use the tag bits. - assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) - } - TermKind::Const(ct) => { - // Ensure we can use the tag bits. - assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) - } - }; - - Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum ParamTerm { - Ty(ParamTy), - Const(ParamConst), -} - -impl ParamTerm { - pub fn index(self) -> usize { - match self { - ParamTerm::Ty(ty) => ty.index as usize, - ParamTerm::Const(ct) => ct.index as usize, - } - } -} - -/// This kind of predicate has no *direct* correspondent in the -/// syntax, but it roughly corresponds to the syntactic forms: -/// -/// 1. `T: TraitRef<..., Item = Type>` -/// 2. `>::Item == Type` (NYI) -/// -/// In particular, form #1 is "desugared" to the combination of a -/// normal trait predicate (`T: TraitRef<...>`) and one of these -/// predicates. Form #2 is a broader form in that it also permits -/// equality between arbitrary types. Processing an instance of -/// Form #2 eventually yields one of these `ProjectionPredicate` -/// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ProjectionPredicate<'tcx> { - pub projection_ty: AliasTy<'tcx>, - pub term: Term<'tcx>, -} - -impl<'tcx> ProjectionPredicate<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.projection_ty.self_ty() - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { - Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - self.projection_ty.trait_def_id(tcx) - } - - pub fn def_id(self) -> DefId { - self.projection_ty.def_id - } -} - -pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; - -impl<'tcx> PolyProjectionPredicate<'tcx> { - /// Returns the `DefId` of the trait of the associated item being projected. - #[inline] - pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - self.skip_binder().projection_ty.trait_def_id(tcx) - } - - /// Get the [PolyTraitRef] required for this projection to be well formed. - /// Note that for generic associated types the predicates of the associated - /// type also need to be checked. - #[inline] - pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { - // Note: unlike with `TraitRef::to_poly_trait_ref()`, - // `self.0.trait_ref` is permitted to have escaping regions. - // This is because here `self` has a `Binder` and so does our - // return value, so we are preserving the number of binding - // levels. - self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) - } - - pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { - self.map_bound(|predicate| predicate.term) - } - - /// The `DefId` of the `TraitItem` for the associated type. - /// - /// Note that this is not the `DefId` of the `TraitRef` containing this - /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. - pub fn projection_def_id(&self) -> DefId { - // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().projection_ty.def_id - } -} - -pub trait ToPolyTraitRef<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; -} - -impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - self.map_bound_ref(|trait_pred| trait_pred.trait_ref) - } -} - -pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; -} - -impl<'tcx, T> ToPredicate<'tcx, T> for T { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { - self - } -} - -impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self) - } -} - -impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) - } -} - -impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); - pred.to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }) - } -} - -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitRef<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx> { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - ty::Binder::dummy(self) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx) - } -} - -impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_pred(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(Clause::Projection(..)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) - | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) - | PredicateKind::Clause(Clause::TypeOutlives(..)) - | PredicateKind::ConstEvaluatable(..) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, - } - } - - pub fn to_opt_poly_projection_pred(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(Clause::Trait(..)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) - | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) - | PredicateKind::Clause(Clause::TypeOutlives(..)) - | PredicateKind::ConstEvaluatable(..) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, - } - } - - pub fn to_opt_type_outlives(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)), - PredicateKind::Clause(Clause::Trait(..)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::Clause(Clause::Projection(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) - | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) - | PredicateKind::ConstEvaluatable(..) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, - } - } -} - -/// Represents the bounds declared on a particular set of type -/// parameters. Should eventually be generalized into a flag list of -/// where-clauses. You can obtain an `InstantiatedPredicates` list from a -/// `GenericPredicates` by using the `instantiate` method. Note that this method -/// reflects an important semantic invariant of `InstantiatedPredicates`: while -/// the `GenericPredicates` are expressed in terms of the bound type -/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance -/// represented a set of bounds for some particular instantiation, -/// meaning that the generic parameters have been substituted with -/// their values. -/// -/// Example: -/// ```ignore (illustrative) -/// struct Foo> { ... } -/// ``` -/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like -/// `[[], [U:Bar]]`. Now if there were some particular reference -/// like `Foo`, then the `InstantiatedPredicates` would be `[[], -/// [usize:Bar]]`. -#[derive(Clone, Debug, TypeFoldable, TypeVisitable)] -pub struct InstantiatedPredicates<'tcx> { - pub predicates: Vec>, - pub spans: Vec, -} - -impl<'tcx> InstantiatedPredicates<'tcx> { - pub fn empty() -> InstantiatedPredicates<'tcx> { - InstantiatedPredicates { predicates: vec![], spans: vec![] } - } - - pub fn is_empty(&self) -> bool { - self.predicates.is_empty() - } - - pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { - (&self).into_iter() - } -} - -impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); - - type IntoIter = std::iter::Zip>, std::vec::IntoIter>; - - fn into_iter(self) -> Self::IntoIter { - debug_assert_eq!(self.predicates.len(), self.spans.len()); - std::iter::zip(self.predicates, self.spans) - } -} - -impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); - - type IntoIter = std::iter::Zip< - std::iter::Copied>>, - std::iter::Copied>, - >; - - fn into_iter(self) -> Self::IntoIter { - debug_assert_eq!(self.predicates.len(), self.spans.len()); - std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied()) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct OpaqueTypeKey<'tcx> { - pub def_id: LocalDefId, - pub substs: SubstsRef<'tcx>, -} - -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] -pub struct OpaqueHiddenType<'tcx> { - /// The span of this particular definition of the opaque type. So - /// for example: - /// - /// ```ignore (incomplete snippet) - /// type Foo = impl Baz; - /// fn bar() -> Foo { - /// // ^^^ This is the span we are looking for! - /// } - /// ``` - /// - /// In cases where the fn returns `(impl Trait, impl Trait)` or - /// other such combinations, the result is currently - /// over-approximated, but better than nothing. - pub span: Span, - - /// The type variable that represents the value of the opaque type - /// that we require. In other words, after we compile this function, - /// we will be created a constraint like: - /// ```ignore (pseudo-rust) - /// Foo<'a, T> = ?C - /// ``` - /// where `?C` is the value of this type variable. =) It may - /// naturally refer to the type and lifetime parameters in scope - /// in this function, though ultimately it should only reference - /// those that are arguments to `Foo` in the constraint above. (In - /// other words, `?C` should not include `'b`, even though it's a - /// lifetime parameter on `foo`.) - pub ty: Ty<'tcx>, -} - -impl<'tcx> OpaqueHiddenType<'tcx> { - pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed { - // Found different concrete types for the opaque type. - let sub_diag = if self.span == other.span { - TypeMismatchReason::ConflictType { span: self.span } - } else { - TypeMismatchReason::PreviousUse { span: self.span } - }; - tcx.sess.emit_err(OpaqueHiddenTypeMismatch { - self_ty: self.ty, - other_ty: other.ty, - other_span: other.span, - sub: sub_diag, - }) - } - - #[instrument(level = "debug", skip(tcx), ret)] - pub fn remap_generic_params_to_declaration_params( - self, - opaque_type_key: OpaqueTypeKey<'tcx>, - tcx: TyCtxt<'tcx>, - // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. - ignore_errors: bool, - ) -> Self { - let OpaqueTypeKey { def_id, substs } = opaque_type_key; - - // Use substs to build up a reverse map from regions to their - // identity mappings. This is necessary because of `impl - // Trait` lifetimes are computed by replacing existing - // lifetimes with 'static and remapping only those used in the - // `impl Trait` return type, resulting in the parameters - // shifting. - let id_substs = InternalSubsts::identity_for_item(tcx, def_id); - debug!(?id_substs); - - // This zip may have several times the same lifetime in `substs` paired with a different - // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour: - // it will pick the last one, which is the one we introduced in the impl-trait desugaring. - let map = substs.iter().zip(id_substs).collect(); - debug!("map = {:#?}", map); - - // Convert the type from the function into a type valid outside - // the function, by replacing invalid regions with 'static, - // after producing an error for each of them. - self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors)) - } -} - -/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are -/// identified by both a universe, as well as a name residing within that universe. Distinct bound -/// regions/types/consts within the same universe simply have an unknown relationship to one -/// another. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[derive(HashStable, TyEncodable, TyDecodable)] -pub struct Placeholder { - pub universe: UniverseIndex, - pub bound: T, -} - -pub type PlaceholderRegion = Placeholder; - -pub type PlaceholderType = Placeholder; - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] -#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)] -pub struct BoundConst<'tcx> { - pub var: BoundVar, - pub ty: Ty<'tcx>, -} - -pub type PlaceholderConst<'tcx> = Placeholder; - -/// When type checking, we use the `ParamEnv` to track -/// details about the set of where-clauses that are in scope at this -/// particular point. -#[derive(Copy, Clone, Hash, PartialEq, Eq)] -pub struct ParamEnv<'tcx> { - /// This packs both caller bounds and the reveal enum into one pointer. - /// - /// Caller bounds are `Obligation`s that the caller must satisfy. This is - /// basically the set of bounds on the in-scope type parameters, translated - /// into `Obligation`s, and elaborated and normalized. - /// - /// Use the `caller_bounds()` method to access. - /// - /// Typically, this is `Reveal::UserFacing`, but during codegen we - /// want `Reveal::All`. - /// - /// Note: This is packed, use the reveal() method to access it. - packed: CopyTaggedPtr<&'tcx List>, ParamTag, true>, -} - -#[derive(Copy, Clone)] -struct ParamTag { - reveal: traits::Reveal, - constness: hir::Constness, -} - -impl_tag! { - impl Tag for ParamTag; - ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, - ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, - ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, - ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const }, -} - -impl<'tcx> fmt::Debug for ParamEnv<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ParamEnv") - .field("caller_bounds", &self.caller_bounds()) - .field("reveal", &self.reveal()) - .field("constness", &self.constness()) - .finish() - } -} - -impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.caller_bounds().hash_stable(hcx, hasher); - self.reveal().hash_stable(hcx, hasher); - self.constness().hash_stable(hcx, hasher); - } -} - -impl<'tcx> TypeFoldable> for ParamEnv<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(ParamEnv::new( - self.caller_bounds().try_fold_with(folder)?, - self.reveal().try_fold_with(folder)?, - self.constness(), - )) - } -} - -impl<'tcx> TypeVisitable> for ParamEnv<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.caller_bounds().visit_with(visitor)?; - self.reveal().visit_with(visitor) - } -} - -impl<'tcx> ParamEnv<'tcx> { - /// Construct a trait environment suitable for contexts where - /// there are no where-clauses in scope. Hidden types (like `impl - /// Trait`) are left hidden, so this is suitable for ordinary - /// type-checking. - #[inline] - pub fn empty() -> Self { - Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst) - } - - #[inline] - pub fn caller_bounds(self) -> &'tcx List> { - self.packed.pointer() - } - - #[inline] - pub fn reveal(self) -> traits::Reveal { - self.packed.tag().reveal - } - - #[inline] - pub fn constness(self) -> hir::Constness { - self.packed.tag().constness - } - - #[inline] - pub fn is_const(self) -> bool { - self.packed.tag().constness == hir::Constness::Const - } - - /// Construct a trait environment with no where-clauses in scope - /// where the values of all `impl Trait` and other hidden types - /// are revealed. This is suitable for monomorphized, post-typeck - /// environments like codegen or doing optimizations. - /// - /// N.B., if you want to have predicates in scope, use `ParamEnv::new`, - /// or invoke `param_env.with_reveal_all()`. - #[inline] - pub fn reveal_all() -> Self { - Self::new(List::empty(), Reveal::All, hir::Constness::NotConst) - } +use rustc_ast as ast; +use rustc_attr as attr; +use rustc_data_structures::intern::Interned; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir as hir; +use rustc_hir::def::{CtorOf, DefKind, Res}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::Node; +use rustc_serialize::{Decodable, Encodable}; +use rustc_span::hygiene::MacroKind; +use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::{ExpnKind, Span}; +use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; +use rustc_type_ir::WithCachedTypeInfo; - /// Construct a trait environment with the given set of predicates. - #[inline] - pub fn new( - caller_bounds: &'tcx List>, - reveal: Reveal, - constness: hir::Constness, - ) -> Self { - ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } - } +use self::fast_reject::SimplifiedType; +use self::util::Discr; +use crate::error::TypeMismatchReason; +use crate::mir::{Body, GeneratorLayout}; +use crate::ty; - pub fn with_user_facing(mut self) -> Self { - self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); - self - } +pub mod _match; +pub mod abstract_const; +pub mod adjustment; +pub mod binding; +pub mod cast; +pub mod codec; +pub mod error; +pub mod fast_reject; +pub mod flags; +pub mod fold; +pub mod inhabitedness; +pub mod layout; +pub mod normalize_erasing_regions; +pub mod print; +pub mod query; +pub mod relate; +pub mod subst; +pub mod trait_def; +pub mod util; +pub mod visit; +pub mod vtable; +pub mod walk; - #[inline] - pub fn with_constness(mut self, constness: hir::Constness) -> Self { - self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); - self - } +mod adt; +mod assoc; +mod closure; +mod closure_size_profile_data; +mod coherence; +mod consts; +mod context; +mod crate_variances_map; +mod destructor; +mod destructured_const; +mod diagnostics; +mod erase_regions; +mod generics; +mod impl_trait_in_trait_data; +mod impls_ty; +mod instance; +mod list; +mod opaque; +mod param_env; +mod parameterized; +mod placeholder; +mod predicate; +mod region; +mod rvalue_scopes; +mod structural_impls; +mod sty; +mod symbol_name; +mod term; +mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here +mod typeck_results; +mod visibility; - #[inline] - pub fn with_const(mut self) -> Self { - self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); - self - } +pub use rustc_session::lint::RegisteredTools; +pub use rustc_target::abi::{ReprFlags, ReprOptions}; +pub use rustc_type_ir::AliasKind::*; +pub use rustc_type_ir::DynKind::*; +pub use rustc_type_ir::InferTy::*; +pub use rustc_type_ir::RegionKind::*; +pub use rustc_type_ir::TyKind::*; +pub use rustc_type_ir::*; - #[inline] - pub fn without_const(mut self) -> Self { - self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() }); - self - } +pub use self::adt::{ + AdtDef, AdtDefData, AdtFlags, AdtKind, FieldDef, Representability, VariantDef, VariantDiscr, + VariantFlags, +}; +pub use self::assoc::*; +pub use self::binding::BindingMode; +pub use self::binding::BindingMode::*; +pub use self::closure::{ + is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, + CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, + RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath, + CAPTURE_STRUCT_LOCAL, +}; +pub use self::closure_size_profile_data::ClosureSizeProfileData; +pub use self::coherence::{ + CrateInherentImpls, ImplHeader, ImplOverlapKind, ImplPolarity, ImplSubject, +}; +pub use self::consts::{ + BoundConst, Const, ConstData, ConstInt, ConstKind, Expr, InferConst, PlaceholderConst, + ScalarInt, UnevaluatedConst, ValTree, +}; +pub use self::context::{ + tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, +}; +pub use self::crate_variances_map::CrateVariancesMap; +pub use self::destructor::Destructor; +pub use self::destructured_const::DestructuredConst; +pub use self::diagnostics::*; +pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +pub use self::generics::*; +pub use self::impl_trait_in_trait_data::ImplTraitInTraitData; +pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; +pub use self::list::List; +pub use self::opaque::{OpaqueHiddenType, OpaqueTypeKey}; +pub use self::param_env::{ParamEnv, ParamEnvAnd}; +pub use self::parameterized::ParameterizedOverTcx; +pub use self::placeholder::Placeholder; +pub use self::predicate::{ + AliasRelationDirection, BoundConstness, Clause, CoercePredicate, CratePredicatesMap, + InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate, PolyProjectionPredicate, + PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, + PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, + RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate, +}; +pub use self::region::PlaceholderRegion; +pub use self::rvalue_scopes::RvalueScopes; +pub use self::sty::BoundRegionKind::*; +pub use self::sty::{ + AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, + BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, + EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, + FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, + InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, + PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, + Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, +}; +pub use self::subst::*; +pub use self::symbol_name::SymbolName; +pub use self::term::{ParamTerm, Term, TermKind}; +pub use self::trait_def::TraitDef; +pub use self::ty_::{InferVarInfo, PlaceholderType, Ty}; +pub use self::typeck_results::{ + CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, + GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType, + UserTypeAnnotationIndex, +}; +pub use self::visibility::Visibility; +pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +pub use self::vtable::*; +pub use self::AssocItemContainer::*; +pub use self::BorrowKind::*; +pub use self::IntVarValue::*; +pub use self::Variance::*; +impl TyCtxt<'_> { #[inline] - pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) { - *self = self.with_constness(constness.and(self.constness())) - } - - /// Returns a new parameter environment with the same clauses, but - /// which "reveals" the true results of projections in all cases - /// (even for associated types that are specializable). This is - /// the desired behavior during codegen and certain other special - /// contexts; normally though we want to use `Reveal::UserFacing`, - /// which is the default. - /// All opaque types in the caller_bounds of the `ParamEnv` - /// will be normalized to their underlying types. - /// See PR #65989 and issue #65918 for more details - pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { - if self.packed.tag().reveal == traits::Reveal::All { - return self; - } - - ParamEnv::new( - tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), - Reveal::All, - self.constness(), - ) + pub fn opt_parent(self, id: DefId) -> Option { + self.def_key(id).parent.map(|index| DefId { index, ..id }) } - /// Returns this same environment but with no caller bounds. #[inline] - pub fn without_caller_bounds(self) -> Self { - Self::new(List::empty(), self.reveal(), self.constness()) - } - - /// Creates a suitable environment in which to perform trait - /// queries on the given value. When type-checking, this is simply - /// the pair of the environment plus value. But when reveal is set to - /// All, then if `value` does not reference any type parameters, we will - /// pair it with the empty environment. This improves caching and is generally - /// invisible. - /// - /// N.B., we preserve the environment when type-checking because it - /// is possible for the user to have wacky where-clauses like - /// `where Box: Copy`, which are clearly never - /// satisfiable. We generally want to behave as if they were true, - /// although the surrounding function is never reachable. - pub fn and>>(self, value: T) -> ParamEnvAnd<'tcx, T> { - match self.reveal() { - Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, - - Reveal::All => { - if value.is_global() { - ParamEnvAnd { param_env: self.without_caller_bounds(), value } - } else { - ParamEnvAnd { param_env: self, value } - } - } + #[track_caller] + pub fn parent(self, id: DefId) -> DefId { + match self.opt_parent(id) { + Some(id) => id, + // not `unwrap_or_else` to avoid breaking caller tracking + None => bug!("{id:?} doesn't have a parent"), } } -} -// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that -// the constness of trait bounds is being propagated correctly. -impl<'tcx> PolyTraitRef<'tcx> { #[inline] - pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| ty::TraitPredicate { - trait_ref, - constness, - polarity: ty::ImplPolarity::Positive, - }) + #[track_caller] + pub fn opt_local_parent(self, id: LocalDefId) -> Option { + self.opt_parent(id.to_def_id()).map(DefId::expect_local) } #[inline] - pub fn without_const(self) -> PolyTraitPredicate<'tcx> { - self.with_constness(BoundConstness::NotConst) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] -#[derive(HashStable, Lift)] -pub struct ParamEnvAnd<'tcx, T> { - pub param_env: ParamEnv<'tcx>, - pub value: T, -} - -impl<'tcx, T> ParamEnvAnd<'tcx, T> { - pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { - (self.param_env, self.value) - } -} - -#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] -pub struct Destructor { - /// The `DefId` of the destructor method - pub did: DefId, - /// The constness of the destructor method - pub constness: hir::Constness, -} - -bitflags! { - #[derive(HashStable, TyEncodable, TyDecodable)] - pub struct VariantFlags: u8 { - const NO_VARIANT_FLAGS = 0; - /// Indicates whether the field list of this variant is `#[non_exhaustive]`. - const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; - /// Indicates whether this variant was obtained as part of recovering from - /// a syntactic error. May be incomplete or bogus. - const IS_RECOVERED = 1 << 1; + #[track_caller] + pub fn local_parent(self, id: LocalDefId) -> LocalDefId { + self.parent(id.to_def_id()).expect_local() } -} - -/// Definition of a variant -- a struct's fields or an enum variant. -#[derive(Debug, HashStable, TyEncodable, TyDecodable)] -pub struct VariantDef { - /// `DefId` that identifies the variant itself. - /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. - pub def_id: DefId, - /// `DefId` that identifies the variant's constructor. - /// If this variant is a struct variant, then this is `None`. - pub ctor: Option<(CtorKind, DefId)>, - /// Variant or struct name. - pub name: Symbol, - /// Discriminant of this variant. - pub discr: VariantDiscr, - /// Fields of this variant. - pub fields: IndexVec, - /// Flags of the variant (e.g. is field list non-exhaustive)? - flags: VariantFlags, -} -impl VariantDef { - /// Creates a new `VariantDef`. - /// - /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` - /// represents an enum variant). - /// - /// `ctor_did` is the `DefId` that identifies the constructor of unit or - /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`. - /// - /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that - /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having - /// to go through the redirect of checking the ctor's attributes - but compiling a small crate - /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any - /// built-in trait), and we do not want to load attributes twice. - /// - /// If someone speeds up attribute loading to not be a performance concern, they can - /// remove this hack and use the constructor `DefId` everywhere. - pub fn new( - name: Symbol, - variant_did: Option, - ctor: Option<(CtorKind, DefId)>, - discr: VariantDiscr, - fields: IndexVec, - adt_kind: AdtKind, - parent_did: DefId, - recovered: bool, - is_field_list_non_exhaustive: bool, - ) -> Self { - debug!( - "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, - fields = {:?}, adt_kind = {:?}, parent_did = {:?})", - name, variant_did, ctor, discr, fields, adt_kind, parent_did, - ); - - let mut flags = VariantFlags::NO_VARIANT_FLAGS; - if is_field_list_non_exhaustive { - flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; + pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { + if descendant.krate != ancestor.krate { + return false; } - if recovered { - flags |= VariantFlags::IS_RECOVERED; + while descendant != ancestor { + match self.opt_parent(descendant) { + Some(parent) => descendant = parent, + None => return false, + } } - - VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags } - } - - /// Is this field list non-exhaustive? - #[inline] - pub fn is_field_list_non_exhaustive(&self) -> bool { - self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) - } - - /// Was this variant obtained as part of recovering from a syntactic error? - #[inline] - pub fn is_recovered(&self) -> bool { - self.flags.intersects(VariantFlags::IS_RECOVERED) - } - - /// Computes the `Ident` of this variant by looking up the `Span` - pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { - Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) - } - - #[inline] - pub fn ctor_kind(&self) -> Option { - self.ctor.map(|(kind, _)| kind) - } - - #[inline] - pub fn ctor_def_id(&self) -> Option { - self.ctor.map(|(_, def_id)| def_id) - } - - /// Returns the one field in this variant. - /// - /// `panic!`s if there are no fields or multiple fields. - #[inline] - pub fn single_field(&self) -> &FieldDef { - assert!(self.fields.len() == 1); - - &self.fields[FieldIdx::from_u32(0)] - } -} - -impl PartialEq for VariantDef { - #[inline] - fn eq(&self, other: &Self) -> bool { - // There should be only one `VariantDef` for each `def_id`, therefore - // it is fine to implement `PartialEq` only based on `def_id`. - // - // Below, we exhaustively destructure `self` and `other` so that if the - // definition of `VariantDef` changes, a compile-error will be produced, - // reminding us to revisit this assumption. - - let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; - let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other; - lhs_def_id == rhs_def_id - } -} - -impl Eq for VariantDef {} - -impl Hash for VariantDef { - #[inline] - fn hash(&self, s: &mut H) { - // There should be only one `VariantDef` for each `def_id`, therefore - // it is fine to implement `Hash` only based on `def_id`. - // - // Below, we exhaustively destructure `self` so that if the definition - // of `VariantDef` changes, a compile-error will be produced, reminding - // us to revisit this assumption. - - let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; - def_id.hash(s) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] -pub enum VariantDiscr { - /// Explicit value for this variant, i.e., `X = 123`. - /// The `DefId` corresponds to the embedded constant. - Explicit(DefId), - - /// The previous variant's discriminant plus one. - /// For efficiency reasons, the distance from the - /// last `Explicit` discriminant is being stored, - /// or `0` for the first variant, if it has none. - Relative(u32), -} - -#[derive(Debug, HashStable, TyEncodable, TyDecodable)] -pub struct FieldDef { - pub did: DefId, - pub name: Symbol, - pub vis: Visibility, -} - -impl PartialEq for FieldDef { - #[inline] - fn eq(&self, other: &Self) -> bool { - // There should be only one `FieldDef` for each `did`, therefore it is - // fine to implement `PartialEq` only based on `did`. - // - // Below, we exhaustively destructure `self` so that if the definition - // of `FieldDef` changes, a compile-error will be produced, reminding - // us to revisit this assumption. - - let Self { did: lhs_did, name: _, vis: _ } = &self; - - let Self { did: rhs_did, name: _, vis: _ } = other; - - lhs_did == rhs_did + true } } -impl Eq for FieldDef {} - -impl Hash for FieldDef { - #[inline] - fn hash(&self, s: &mut H) { - // There should be only one `FieldDef` for each `did`, therefore it is - // fine to implement `Hash` only based on `did`. - // - // Below, we exhaustively destructure `self` so that if the definition - // of `FieldDef` changes, a compile-error will be produced, reminding - // us to revisit this assumption. - - let Self { did, name: _, vis: _ } = &self; +const TAG_MASK: usize = 0b11; +const TYPE_TAG: usize = 0b00; +const CONST_TAG: usize = 0b01; - did.hash(s) - } +pub trait ToPolyTraitRef<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; } -impl<'tcx> FieldDef { - /// Returns the type of this field. The resulting type is not normalized. The `subst` is - /// typically obtained via the second field of [`TyKind::Adt`]. - pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { - tcx.type_of(self.did).subst(tcx, subst) - } - - /// Computes the `Ident` of this variant by looking up the `Span` - pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { - Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) +impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { + self.map_bound_ref(|trait_pred| trait_pred.trait_ref) } } -#[derive(Debug, PartialEq, Eq)] -pub enum ImplOverlapKind { - /// These impls are always allowed to overlap. - Permitted { - /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait - marker: bool, - }, - /// These impls are allowed to overlap, but that raises - /// an issue #33140 future-compatibility warning. - /// - /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's - /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different. - /// - /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied - /// that difference, making what reduces to the following set of impls: - /// - /// ```compile_fail,(E0119) - /// trait Trait {} - /// impl Trait for dyn Send + Sync {} - /// impl Trait for dyn Sync + Send {} - /// ``` - /// - /// Obviously, once we made these types be identical, that code causes a coherence - /// error and a fairly big headache for us. However, luckily for us, the trait - /// `Trait` used in this case is basically a marker trait, and therefore having - /// overlapping impls for it is sound. - /// - /// To handle this, we basically regard the trait as a marker trait, with an additional - /// future-compatibility warning. To avoid accidentally "stabilizing" this feature, - /// it has the following restrictions: - /// - /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be - /// positive impls. - /// 2. The trait-ref of both impls must be equal. - /// 3. The trait-ref of both impls must be a trait object type consisting only of - /// marker traits. - /// 4. Neither of the impls can have any where-clauses. - /// - /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed. - Issue33140, -} - -/// Useful source information about where a desugared associated type for an -/// RPITIT originated from. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)] -pub enum ImplTraitInTraitData { - Trait { fn_def_id: DefId, opaque_def_id: DefId }, - Impl { fn_def_id: DefId }, -} - impl<'tcx> TyCtxt<'tcx> { pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> { self.typeck(self.hir().body_owner_def_id(body)) @@ -2596,63 +819,6 @@ pub fn provide(providers: &mut ty::query::Providers) { }; } -/// A map for the local crate mapping each type to a vector of its -/// inherent impls. This is not meant to be used outside of coherence; -/// rather, you should request the vector for a specific type via -/// `tcx.inherent_impls(def_id)` so as to minimize your dependencies -/// (constructing this map requires touching the entire crate). -#[derive(Clone, Debug, Default, HashStable)] -pub struct CrateInherentImpls { - pub inherent_impls: LocalDefIdMap>, - pub incoherent_impls: FxHashMap>, -} - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] -pub struct SymbolName<'tcx> { - /// `&str` gives a consistent ordering, which ensures reproducible builds. - pub name: &'tcx str, -} - -impl<'tcx> SymbolName<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> { - SymbolName { - name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) }, - } - } -} - -impl<'tcx> fmt::Display for SymbolName<'tcx> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.name, fmt) - } -} - -impl<'tcx> fmt::Debug for SymbolName<'tcx> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.name, fmt) - } -} - -#[derive(Debug, Default, Copy, Clone)] -pub struct InferVarInfo { - /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo` - /// obligation, where: - /// - /// * `Foo` is not `Sized` - /// * `(): Foo` may be satisfied - pub self_in_trait: bool, - /// This is true if we identified that this Ty (`?T`) is found in a `<_ as - /// _>::AssocType = ?T` - pub output: bool, -} - -/// The constituent parts of a type level constant of kind ADT or array. -#[derive(Copy, Clone, Debug, HashStable)] -pub struct DestructuredConst<'tcx> { - pub variant: Option, - pub fields: &'tcx [ty::Const<'tcx>], -} - // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque.rs similarity index 69% rename from compiler/rustc_middle/src/ty/opaque_types.rs rename to compiler/rustc_middle/src/ty/opaque.rs index 72710b78c9373..97dab93ecb74c 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque.rs @@ -1,15 +1,57 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::ErrorGuaranteed; +use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::Span; + use crate::error::ConstNotUsedTraitAlias; +use crate::error::OpaqueHiddenTypeMismatch; use crate::ty::fold::{TypeFolder, TypeSuperFoldable}; use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc_data_structures::fx::FxHashMap; -use rustc_span::def_id::DefId; -use rustc_span::Span; +use crate::ty::{self, InternalSubsts, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeMismatchReason}; + +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] +pub struct OpaqueHiddenType<'tcx> { + /// The span of this particular definition of the opaque type. So + /// for example: + /// + /// ```ignore (incomplete snippet) + /// type Foo = impl Baz; + /// fn bar() -> Foo { + /// // ^^^ This is the span we are looking for! + /// } + /// ``` + /// + /// In cases where the fn returns `(impl Trait, impl Trait)` or + /// other such combinations, the result is currently + /// over-approximated, but better than nothing. + pub span: Span, + + /// The type variable that represents the value of the opaque type + /// that we require. In other words, after we compile this function, + /// we will be created a constraint like: + /// ```ignore (pseudo-rust) + /// Foo<'a, T> = ?C + /// ``` + /// where `?C` is the value of this type variable. =) It may + /// naturally refer to the type and lifetime parameters in scope + /// in this function, though ultimately it should only reference + /// those that are arguments to `Foo` in the constraint above. (In + /// other words, `?C` should not include `'b`, even though it's a + /// lifetime parameter on `foo`.) + pub ty: Ty<'tcx>, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct OpaqueTypeKey<'tcx> { + pub def_id: LocalDefId, + pub substs: SubstsRef<'tcx>, +} /// Converts generic params of a TypeFoldable from one /// item's generics to another. Usually from a function's generics /// list to the opaque type's own generics. -pub(super) struct ReverseMapper<'tcx> { +struct ReverseMapper<'tcx> { tcx: TyCtxt<'tcx>, map: FxHashMap, GenericArg<'tcx>>, /// see call sites to fold_kind_no_missing_regions_error @@ -26,6 +68,54 @@ pub(super) struct ReverseMapper<'tcx> { span: Span, } +impl<'tcx> OpaqueHiddenType<'tcx> { + pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed { + // Found different concrete types for the opaque type. + let sub_diag = if self.span == other.span { + TypeMismatchReason::ConflictType { span: self.span } + } else { + TypeMismatchReason::PreviousUse { span: self.span } + }; + tcx.sess.emit_err(OpaqueHiddenTypeMismatch { + self_ty: self.ty, + other_ty: other.ty, + other_span: other.span, + sub: sub_diag, + }) + } + + #[instrument(level = "debug", skip(tcx), ret)] + pub fn remap_generic_params_to_declaration_params( + self, + opaque_type_key: OpaqueTypeKey<'tcx>, + tcx: TyCtxt<'tcx>, + // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. + ignore_errors: bool, + ) -> Self { + let OpaqueTypeKey { def_id, substs } = opaque_type_key; + + // Use substs to build up a reverse map from regions to their + // identity mappings. This is necessary because of `impl + // Trait` lifetimes are computed by replacing existing + // lifetimes with 'static and remapping only those used in the + // `impl Trait` return type, resulting in the parameters + // shifting. + let id_substs = InternalSubsts::identity_for_item(tcx, def_id); + debug!(?id_substs); + + // This zip may have several times the same lifetime in `substs` paired with a different + // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour: + // it will pick the last one, which is the one we introduced in the impl-trait desugaring. + let map = substs.iter().zip(id_substs).collect(); + debug!("map = {:#?}", map); + + // Convert the type from the function into a type valid outside + // the function, by replacing invalid regions with 'static, + // after producing an error for each of them. + self.fold_with(&mut ReverseMapper::new(tcx, map, self.span, ignore_errors)) + } +} + impl<'tcx> ReverseMapper<'tcx> { pub(super) fn new( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/param_env.rs b/compiler/rustc_middle/src/ty/param_env.rs new file mode 100644 index 0000000000000..2a41105c7ecab --- /dev/null +++ b/compiler/rustc_middle/src/ty/param_env.rs @@ -0,0 +1,231 @@ +use std::fmt; +use std::ops::ControlFlow; + +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::tagged_ptr::CopyTaggedPtr; +use rustc_hir as hir; +use rustc_query_system::ich::StableHashingContext; + +use crate::traits; +use crate::ty::{ + self, list::List, Predicate, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, +}; + +/// When type checking, we use the `ParamEnv` to track +/// details about the set of where-clauses that are in scope at this +/// particular point. +#[derive(Copy, Clone, Hash, PartialEq, Eq)] +pub struct ParamEnv<'tcx> { + /// This packs both caller bounds and the reveal enum into one pointer. + /// + /// Caller bounds are `Obligation`s that the caller must satisfy. This is + /// basically the set of bounds on the in-scope type parameters, translated + /// into `Obligation`s, and elaborated and normalized. + /// + /// Use the `caller_bounds()` method to access. + /// + /// Typically, this is `Reveal::UserFacing`, but during codegen we + /// want `Reveal::All`. + /// + /// Note: This is packed, use the reveal() method to access it. + packed: CopyTaggedPtr<&'tcx List>, ParamTag, true>, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] +#[derive(HashStable, Lift)] +pub struct ParamEnvAnd<'tcx, T> { + pub param_env: ParamEnv<'tcx>, + pub value: T, +} + +#[derive(Copy, Clone)] +struct ParamTag { + reveal: traits::Reveal, + constness: hir::Constness, +} + +impl<'tcx> ParamEnv<'tcx> { + /// Construct a trait environment suitable for contexts where + /// there are no where-clauses in scope. Hidden types (like `impl + /// Trait`) are left hidden, so this is suitable for ordinary + /// type-checking. + #[inline] + pub fn empty() -> Self { + Self::new(List::empty(), traits::Reveal::UserFacing, hir::Constness::NotConst) + } + + #[inline] + pub fn caller_bounds(self) -> &'tcx List> { + self.packed.pointer() + } + + #[inline] + pub fn reveal(self) -> traits::Reveal { + self.packed.tag().reveal + } + + #[inline] + pub fn constness(self) -> hir::Constness { + self.packed.tag().constness + } + + #[inline] + pub fn is_const(self) -> bool { + self.packed.tag().constness == hir::Constness::Const + } + + /// Construct a trait environment with no where-clauses in scope + /// where the values of all `impl Trait` and other hidden types + /// are revealed. This is suitable for monomorphized, post-typeck + /// environments like codegen or doing optimizations. + /// + /// N.B., if you want to have predicates in scope, use `ParamEnv::new`, + /// or invoke `param_env.with_reveal_all()`. + #[inline] + pub fn reveal_all() -> Self { + Self::new(List::empty(), traits::Reveal::All, hir::Constness::NotConst) + } + + /// Construct a trait environment with the given set of predicates. + #[inline] + pub fn new( + caller_bounds: &'tcx List>, + reveal: traits::Reveal, + constness: hir::Constness, + ) -> Self { + ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } + } + + pub fn with_user_facing(mut self) -> Self { + self.packed.set_tag(ParamTag { reveal: traits::Reveal::UserFacing, ..self.packed.tag() }); + self + } + + #[inline] + pub fn with_constness(mut self, constness: hir::Constness) -> Self { + self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); + self + } + + #[inline] + pub fn with_const(mut self) -> Self { + self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); + self + } + + #[inline] + pub fn without_const(mut self) -> Self { + self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() }); + self + } + + #[inline] + pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) { + *self = self.with_constness(constness.and(self.constness())) + } + + /// Returns a new parameter environment with the same clauses, but + /// which "reveals" the true results of projections in all cases + /// (even for associated types that are specializable). This is + /// the desired behavior during codegen and certain other special + /// contexts; normally though we want to use `Reveal::UserFacing`, + /// which is the default. + /// All opaque types in the caller_bounds of the `ParamEnv` + /// will be normalized to their underlying types. + /// See PR #65989 and issue #65918 for more details + pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { + if self.packed.tag().reveal == traits::Reveal::All { + return self; + } + + ParamEnv::new( + tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), + traits::Reveal::All, + self.constness(), + ) + } + + /// Returns this same environment but with no caller bounds. + #[inline] + pub fn without_caller_bounds(self) -> Self { + Self::new(List::empty(), self.reveal(), self.constness()) + } + + /// Creates a suitable environment in which to perform trait + /// queries on the given value. When type-checking, this is simply + /// the pair of the environment plus value. But when reveal is set to + /// All, then if `value` does not reference any type parameters, we will + /// pair it with the empty environment. This improves caching and is generally + /// invisible. + /// + /// N.B., we preserve the environment when type-checking because it + /// is possible for the user to have wacky where-clauses like + /// `where Box: Copy`, which are clearly never + /// satisfiable. We generally want to behave as if they were true, + /// although the surrounding function is never reachable. + pub fn and>>(self, value: T) -> ParamEnvAnd<'tcx, T> { + match self.reveal() { + traits::Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, + + traits::Reveal::All => { + if value.is_global() { + ParamEnvAnd { param_env: self.without_caller_bounds(), value } + } else { + ParamEnvAnd { param_env: self, value } + } + } + } + } +} + +impl<'tcx, T> ParamEnvAnd<'tcx, T> { + pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { + (self.param_env, self.value) + } +} + +impl<'tcx> fmt::Debug for ParamEnv<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ParamEnv") + .field("caller_bounds", &self.caller_bounds()) + .field("reveal", &self.reveal()) + .field("constness", &self.constness()) + .finish() + } +} + +impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.caller_bounds().hash_stable(hcx, hasher); + self.reveal().hash_stable(hcx, hasher); + self.constness().hash_stable(hcx, hasher); + } +} + +impl<'tcx> TypeFoldable> for ParamEnv<'tcx> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + Ok(ParamEnv::new( + self.caller_bounds().try_fold_with(folder)?, + self.reveal().try_fold_with(folder)?, + self.constness(), + )) + } +} + +impl<'tcx> TypeVisitable> for ParamEnv<'tcx> { + fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + self.caller_bounds().visit_with(visitor)?; + self.reveal().visit_with(visitor) + } +} + +impl_tag! { + impl Tag for ParamTag; + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const }, +} diff --git a/compiler/rustc_middle/src/ty/placeholder.rs b/compiler/rustc_middle/src/ty/placeholder.rs new file mode 100644 index 0000000000000..eb7e72f79fca7 --- /dev/null +++ b/compiler/rustc_middle/src/ty/placeholder.rs @@ -0,0 +1,12 @@ +use crate::ty::UniverseIndex; + +/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are +/// identified by both a universe, as well as a name residing within that universe. Distinct bound +/// regions/types/consts within the same universe simply have an unknown relationship to one +/// another. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(HashStable, TyEncodable, TyDecodable)] +pub struct Placeholder { + pub universe: UniverseIndex, + pub bound: T, +} diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs new file mode 100644 index 0000000000000..48a7f7b4698dc --- /dev/null +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -0,0 +1,614 @@ +use std::fmt; + +use rustc_data_structures::intern::Interned; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_type_ir::WithCachedTypeInfo; + +use crate::ty::{ + self, AliasTy, Binder, ClosureKind, Const, DebruijnIndex, EarlyBinder, GenericArg, + ImplPolarity, ParamEnv, PolyTraitRef, SubstsRef, Term, TraitRef, Ty, TyCtxt, TypeFlags, +}; + +mod crate_predicates_map; +mod instantiated_predicates; +mod to_predicate; + +pub use crate_predicates_map::CratePredicatesMap; +pub use instantiated_predicates::InstantiatedPredicates; +pub use to_predicate::ToPredicate; + +/// Use this rather than `PredicateKind`, whenever possible. +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Predicate<'tcx>( + pub(super) Interned<'tcx, WithCachedTypeInfo>>>, +); + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub enum PredicateKind<'tcx> { + /// Prove a clause + Clause(Clause<'tcx>), + + /// No syntax: `T` well-formed. + WellFormed(GenericArg<'tcx>), + + /// Trait must be object-safe. + ObjectSafe(DefId), + + /// No direct syntax. May be thought of as `where T: FnFoo<...>` + /// for some substitutions `...` and `T` being a closure type. + /// Satisfied (or refuted) once we know the closure's kind. + ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind), + + /// `T1 <: T2` + /// + /// This obligation is created most often when we have two + /// unresolved type variables and hence don't have enough + /// information to process the subtyping obligation yet. + Subtype(SubtypePredicate<'tcx>), + + /// `T1` coerced to `T2` + /// + /// Like a subtyping obligation, this is created most often + /// when we have two unresolved type variables and hence + /// don't have enough information to process the coercion + /// obligation yet. At the moment, we actually process coercions + /// very much like subtyping and don't handle the full coercion + /// logic. + Coerce(CoercePredicate<'tcx>), + + /// Constant initializer must evaluate successfully. + ConstEvaluatable(ty::Const<'tcx>), + + /// Constants must be equal. The first component is the const that is expected. + ConstEquate(Const<'tcx>, Const<'tcx>), + + /// Represents a type found in the environment that we can use for implied bounds. + /// + /// Only used for Chalk. + TypeWellFormedFromEnv(Ty<'tcx>), + + /// A marker predicate that is always ambiguous. + /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. + Ambiguous, + + /// Separate from `Clause::Projection` which is used for normalization in new solver. + /// This predicate requires two terms to be equal to eachother. + /// + /// Only used for new solver + AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection), +} + +/// A clause is something that can appear in where bounds or be inferred +/// by implied bounds. +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub enum Clause<'tcx> { + /// Corresponds to `where Foo: Bar`. `Foo` here would be + /// the `Self` type of the trait reference and `A`, `B`, and `C` + /// would be the type parameters. + Trait(TraitPredicate<'tcx>), + + /// `where 'a: 'b` + RegionOutlives(RegionOutlivesPredicate<'tcx>), + + /// `where T: 'a` + TypeOutlives(TypeOutlivesPredicate<'tcx>), + + /// `where ::Name == X`, approximately. + /// See the `ProjectionPredicate` struct for details. + Projection(ProjectionPredicate<'tcx>), + + /// Ensures that a const generic argument to a parameter `const N: u8` + /// is of type `u8`. + ConstArgHasType(Const<'tcx>, Ty<'tcx>), +} + +pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; + +/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates +/// whether the `a` type is the type that we should label as "expected" when +/// presenting user diagnostics. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct SubtypePredicate<'tcx> { + pub a_is_expected: bool, + pub a: Ty<'tcx>, + pub b: Ty<'tcx>, +} + +pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; + +/// Encodes that we have to coerce *from* the `a` type to the `b` type. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct CoercePredicate<'tcx> { + pub a: Ty<'tcx>, + pub b: Ty<'tcx>, +} + +pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct TraitPredicate<'tcx> { + pub trait_ref: TraitRef<'tcx>, + + pub constness: BoundConstness, + + /// If polarity is Positive: we are proving that the trait is implemented. + /// + /// If polarity is Negative: we are proving that a negative impl of this trait + /// exists. (Note that coherence also checks whether negative impls of supertraits + /// exist via a series of predicates.) + /// + /// If polarity is Reserved: that's a bug. + pub polarity: ImplPolarity, +} + +pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; +pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; +pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; +pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; + +/// `A: B` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct OutlivesPredicate(pub A, pub B); + +pub type PolyProjectionPredicate<'tcx> = ty::Binder<'tcx, ProjectionPredicate<'tcx>>; + +/// This kind of predicate has no *direct* correspondent in the +/// syntax, but it roughly corresponds to the syntactic forms: +/// +/// 1. `T: TraitRef<..., Item = Type>` +/// 2. `>::Item == Type` (NYI) +/// +/// In particular, form #1 is "desugared" to the combination of a +/// normal trait predicate (`T: TraitRef<...>`) and one of these +/// predicates. Form #2 is a broader form in that it also permits +/// equality between arbitrary types. Processing an instance of +/// Form #2 eventually yields one of these `ProjectionPredicate` +/// instances to normalize the LHS. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct ProjectionPredicate<'tcx> { + pub projection_ty: AliasTy<'tcx>, + pub term: Term<'tcx>, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] +pub enum BoundConstness { + /// `T: Trait` + NotConst, + /// `T: ~const Trait` + /// + /// Requires resolving to const only when we are in a const context. + ConstIfConst, +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, Debug)] +pub enum AliasRelationDirection { + Equate, + Subtype, +} + +impl<'tcx> Predicate<'tcx> { + /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. + #[inline] + pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { + self.0.internee + } + + #[inline(always)] + pub fn flags(self) -> TypeFlags { + self.0.flags + } + + #[inline(always)] + pub fn outer_exclusive_binder(self) -> DebruijnIndex { + self.0.outer_exclusive_binder + } + + /// Flips the polarity of a Predicate. + /// + /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. + pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option> { + let kind = self + .kind() + .map_bound(|kind| match kind { + PredicateKind::Clause(Clause::Trait(TraitPredicate { + trait_ref, + constness, + polarity, + })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate { + trait_ref, + constness, + polarity: polarity.flip()?, + }))), + + _ => None, + }) + .transpose()?; + + Some(tcx.mk_predicate(kind)) + } + + pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { + if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() + && constness != BoundConstness::NotConst + { + self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate { + trait_ref, + constness: BoundConstness::NotConst, + polarity, + })))); + } + self + } + + #[instrument(level = "debug", skip(tcx), ret)] + pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { + match self.kind().skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { + tcx.trait_is_coinductive(data.def_id()) + } + ty::PredicateKind::WellFormed(_) => true, + _ => false, + } + } + + /// Whether this projection can be soundly normalized. + /// + /// Wf predicates must not be normalized, as normalization + /// can remove required bounds which would cause us to + /// unsoundly accept some programs. See #91068. + #[inline] + pub fn allow_normalization(self) -> bool { + match self.kind().skip_binder() { + PredicateKind::WellFormed(_) => false, + PredicateKind::Clause(Clause::Trait(_)) + | PredicateKind::Clause(Clause::RegionOutlives(_)) + | PredicateKind::Clause(Clause::TypeOutlives(_)) + | PredicateKind::Clause(Clause::Projection(_)) + | PredicateKind::Clause(Clause::ConstArgHasType(..)) + | PredicateKind::AliasRelate(..) + | PredicateKind::ObjectSafe(_) + | PredicateKind::ClosureKind(_, _, _) + | PredicateKind::Subtype(_) + | PredicateKind::Coerce(_) + | PredicateKind::ConstEvaluatable(_) + | PredicateKind::ConstEquate(_, _) + | PredicateKind::Ambiguous + | PredicateKind::TypeWellFormedFromEnv(_) => true, + } + } + + /// Performs a substitution suitable for going from a + /// poly-trait-ref to supertraits that must hold if that + /// poly-trait-ref holds. This is slightly different from a normal + /// substitution in terms of what happens with bound regions. See + /// lengthy comment below for details. + pub fn subst_supertrait( + self, + tcx: TyCtxt<'tcx>, + trait_ref: &PolyTraitRef<'tcx>, + ) -> Predicate<'tcx> { + // The interaction between HRTB and supertraits is not entirely + // obvious. Let me walk you (and myself) through an example. + // + // Let's start with an easy case. Consider two traits: + // + // trait Foo<'a>: Bar<'a,'a> { } + // trait Bar<'b,'c> { } + // + // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then + // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we + // knew that `Foo<'x>` (for any 'x) then we also know that + // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from + // normal substitution. + // + // In terms of why this is sound, the idea is that whenever there + // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` + // holds. So if there is an impl of `T:Foo<'a>` that applies to + // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all + // `'a`. + // + // Another example to be careful of is this: + // + // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } + // trait Bar1<'b,'c> { } + // + // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? + // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The + // reason is similar to the previous example: any impl of + // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So + // basically we would want to collapse the bound lifetimes from + // the input (`trait_ref`) and the supertraits. + // + // To achieve this in practice is fairly straightforward. Let's + // consider the more complicated scenario: + // + // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` + // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, + // where both `'x` and `'b` would have a DB index of 1. + // The substitution from the input trait-ref is therefore going to be + // `'a => 'x` (where `'x` has a DB index of 1). + // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an + // early-bound parameter and `'b` is a late-bound parameter with a + // DB index of 1. + // - If we replace `'a` with `'x` from the input, it too will have + // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` + // just as we wanted. + // + // There is only one catch. If we just apply the substitution `'a + // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will + // adjust the DB index because we substituting into a binder (it + // tries to be so smart...) resulting in `for<'x> for<'b> + // Bar1<'x,'b>` (we have no syntax for this, so use your + // imagination). Basically the 'x will have DB index of 2 and 'b + // will have DB index of 1. Not quite what we want. So we apply + // the substitution to the *contents* of the trait reference, + // rather than the trait reference itself (put another way, the + // substitution code expects equal binding levels in the values + // from the substitution and the value being substituted into, and + // this trick achieves that). + + // Working through the second example: + // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] + // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] + // We want to end up with: + // for<'x, 'b> T: Bar1<'^0.0, '^0.1> + // To do this: + // 1) We must shift all bound vars in predicate by the length + // of trait ref's bound vars. So, we would end up with predicate like + // Self: Bar1<'a, '^0.1> + // 2) We can then apply the trait substs to this, ending up with + // T: Bar1<'^0.0, '^0.1> + // 3) Finally, to create the final bound vars, we concatenate the bound + // vars of the trait ref with those of the predicate: + // ['x, 'b] + let bound_pred = self.kind(); + let pred_bound_vars = bound_pred.bound_vars(); + let trait_bound_vars = trait_ref.bound_vars(); + // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> + let shifted_pred = + tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); + // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> + let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs); + // 3) ['x] + ['b] -> ['x, 'b] + let bound_vars = + tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); + tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) + } + + pub fn to_opt_poly_trait_pred(self) -> Option> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(Clause::Projection(..)) + | PredicateKind::Clause(Clause::ConstArgHasType(..)) + | PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::Clause(Clause::RegionOutlives(..)) + | PredicateKind::WellFormed(..) + | PredicateKind::ObjectSafe(..) + | PredicateKind::ClosureKind(..) + | PredicateKind::Clause(Clause::TypeOutlives(..)) + | PredicateKind::ConstEvaluatable(..) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous + | PredicateKind::TypeWellFormedFromEnv(..) => None, + } + } + + pub fn to_opt_poly_projection_pred(self) -> Option> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(Clause::Trait(..)) + | PredicateKind::Clause(Clause::ConstArgHasType(..)) + | PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::Clause(Clause::RegionOutlives(..)) + | PredicateKind::WellFormed(..) + | PredicateKind::ObjectSafe(..) + | PredicateKind::ClosureKind(..) + | PredicateKind::Clause(Clause::TypeOutlives(..)) + | PredicateKind::ConstEvaluatable(..) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous + | PredicateKind::TypeWellFormedFromEnv(..) => None, + } + } + + pub fn to_opt_type_outlives(self) -> Option> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)), + PredicateKind::Clause(Clause::Trait(..)) + | PredicateKind::Clause(Clause::ConstArgHasType(..)) + | PredicateKind::Clause(Clause::Projection(..)) + | PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::Clause(Clause::RegionOutlives(..)) + | PredicateKind::WellFormed(..) + | PredicateKind::ObjectSafe(..) + | PredicateKind::ClosureKind(..) + | PredicateKind::ConstEvaluatable(..) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous + | PredicateKind::TypeWellFormedFromEnv(..) => None, + } + } +} + +impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + +impl<'tcx> TraitPredicate<'tcx> { + pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) { + *param_env = param_env.with_constness(self.constness.and(param_env.constness())) + } + + /// Remap the constness of this predicate before emitting it for diagnostics. + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { + // this is different to `remap_constness` that callees want to print this predicate + // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the + // param_env is not const because it is always satisfied in non-const contexts. + if let hir::Constness::NotConst = param_env.constness() { + self.constness = ty::BoundConstness::NotConst; + } + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } + } + + pub fn def_id(self) -> DefId { + self.trait_ref.def_id + } + + pub fn self_ty(self) -> Ty<'tcx> { + self.trait_ref.self_ty() + } + + #[inline] + pub fn is_const_if_const(self) -> bool { + self.constness == BoundConstness::ConstIfConst + } + + pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool { + match (self.constness, constness) { + (BoundConstness::NotConst, _) + | (BoundConstness::ConstIfConst, hir::Constness::Const) => true, + (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false, + } + } + + pub fn without_const(mut self) -> Self { + self.constness = BoundConstness::NotConst; + self + } +} + +impl<'tcx> PolyTraitPredicate<'tcx> { + pub fn def_id(self) -> DefId { + // Ok to skip binder since trait `DefId` does not care about regions. + self.skip_binder().def_id() + } + + pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { + self.map_bound(|trait_ref| trait_ref.self_ty()) + } + + /// Remap the constness of this predicate before emitting it for diagnostics. + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { + *self = self.map_bound(|mut p| { + p.remap_constness_diag(param_env); + p + }); + } + + #[inline] + pub fn is_const_if_const(self) -> bool { + self.skip_binder().is_const_if_const() + } + + #[inline] + pub fn polarity(self) -> ImplPolarity { + self.skip_binder().polarity + } +} + +impl<'tcx> ProjectionPredicate<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.projection_ty.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { + Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.projection_ty.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.projection_ty.def_id + } +} + +impl<'tcx> PolyProjectionPredicate<'tcx> { + /// Returns the `DefId` of the trait of the associated item being projected. + #[inline] + pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { + self.skip_binder().projection_ty.trait_def_id(tcx) + } + + /// Get the [PolyTraitRef] required for this projection to be well formed. + /// Note that for generic associated types the predicates of the associated + /// type also need to be checked. + #[inline] + pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { + // Note: unlike with `TraitRef::to_poly_trait_ref()`, + // `self.0.trait_ref` is permitted to have escaping regions. + // This is because here `self` has a `Binder` and so does our + // return value, so we are preserving the number of binding + // levels. + self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) + } + + pub fn term(&self) -> ty::Binder<'tcx, Term<'tcx>> { + self.map_bound(|predicate| predicate.term) + } + + /// The `DefId` of the `TraitItem` for the associated type. + /// + /// Note that this is not the `DefId` of the `TraitRef` containing this + /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. + pub fn projection_def_id(&self) -> DefId { + // Ok to skip binder since trait `DefId` does not care about regions. + self.skip_binder().projection_ty.def_id + } +} + +impl BoundConstness { + /// Reduce `self` and `constness` to two possible combined states instead of four. + pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { + match (constness, self) { + (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, + (_, this) => { + *this = BoundConstness::NotConst; + hir::Constness::NotConst + } + } + } +} + +impl fmt::Display for BoundConstness { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::NotConst => f.write_str("normal"), + Self::ConstIfConst => f.write_str("`~const`"), + } + } +} + +impl fmt::Display for AliasRelationDirection { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AliasRelationDirection::Equate => write!(f, "=="), + AliasRelationDirection::Subtype => write!(f, "<:"), + } + } +} diff --git a/compiler/rustc_middle/src/ty/predicate/crate_predicates_map.rs b/compiler/rustc_middle/src/ty/predicate/crate_predicates_map.rs new file mode 100644 index 0000000000000..28a411fba679b --- /dev/null +++ b/compiler/rustc_middle/src/ty/predicate/crate_predicates_map.rs @@ -0,0 +1,19 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::DefId; +use rustc_span::Span; + +use crate::ty::Clause; + +/// The crate outlives map is computed during typeck and contains the +/// outlives of every item in the local crate. You should not use it +/// directly, because to do so will make your pass dependent on the +/// HIR of every item in the local crate. Instead, use +/// `tcx.inferred_outlives_of()` to get the outlives for a *particular* +/// item. +#[derive(HashStable, Debug)] +pub struct CratePredicatesMap<'tcx> { + /// For each struct with outlive bounds, maps to a vector of the + /// predicate of its outlive bounds. If an item has no outlives + /// bounds, it will have no entry. + pub predicates: FxHashMap, Span)]>, +} diff --git a/compiler/rustc_middle/src/ty/predicate/instantiated_predicates.rs b/compiler/rustc_middle/src/ty/predicate/instantiated_predicates.rs new file mode 100644 index 0000000000000..d0153c44ab40b --- /dev/null +++ b/compiler/rustc_middle/src/ty/predicate/instantiated_predicates.rs @@ -0,0 +1,67 @@ +use rustc_span::Span; + +use crate::ty::Predicate; + +/// Represents the bounds declared on a particular set of type +/// parameters. Should eventually be generalized into a flag list of +/// where-clauses. You can obtain an `InstantiatedPredicates` list from a +/// `GenericPredicates` by using the `instantiate` method. Note that this method +/// reflects an important semantic invariant of `InstantiatedPredicates`: while +/// the `GenericPredicates` are expressed in terms of the bound type +/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance +/// represented a set of bounds for some particular instantiation, +/// meaning that the generic parameters have been substituted with +/// their values. +/// +/// Example: +/// ```ignore (illustrative) +/// struct Foo> { ... } +/// ``` +/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like +/// `[[], [U:Bar]]`. Now if there were some particular reference +/// like `Foo`, then the `InstantiatedPredicates` would be `[[], +/// [usize:Bar]]`. +#[derive(Clone, Debug, TypeFoldable, TypeVisitable)] +pub struct InstantiatedPredicates<'tcx> { + pub predicates: Vec>, + pub spans: Vec, +} + +impl<'tcx> InstantiatedPredicates<'tcx> { + pub fn empty() -> InstantiatedPredicates<'tcx> { + InstantiatedPredicates { predicates: vec![], spans: vec![] } + } + + pub fn is_empty(&self) -> bool { + self.predicates.is_empty() + } + + pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { + (&self).into_iter() + } +} + +impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { + type Item = (Predicate<'tcx>, Span); + + type IntoIter = std::iter::Zip>, std::vec::IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + debug_assert_eq!(self.predicates.len(), self.spans.len()); + std::iter::zip(self.predicates, self.spans) + } +} + +impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { + type Item = (Predicate<'tcx>, Span); + + type IntoIter = std::iter::Zip< + std::iter::Copied>>, + std::iter::Copied>, + >; + + fn into_iter(self) -> Self::IntoIter { + debug_assert_eq!(self.predicates.len(), self.spans.len()); + std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied()) + } +} diff --git a/compiler/rustc_middle/src/ty/predicate/to_predicate.rs b/compiler/rustc_middle/src/ty/predicate/to_predicate.rs new file mode 100644 index 0000000000000..7d2eb5270697a --- /dev/null +++ b/compiler/rustc_middle/src/ty/predicate/to_predicate.rs @@ -0,0 +1,103 @@ +use crate::ty::{ + self, Clause, PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolyTraitPredicate, + PolyTypeOutlivesPredicate, Predicate, PredicateKind, TraitPredicate, TraitRef, TyCtxt, +}; + +pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; +} + +impl<'tcx, T> ToPredicate<'tcx, T> for T { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { + self + } +} + +impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for ty::Binder<'tcx, PredicateKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(self) + } +} + +impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) + } +} + +impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for ty::Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for ty::Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| TraitPredicate { + trait_ref, + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, + }) + } +} + +impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitRef<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { + ty::Binder::dummy(self) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx) + } +} diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs new file mode 100644 index 0000000000000..a9d25fd181850 --- /dev/null +++ b/compiler/rustc_middle/src/ty/region.rs @@ -0,0 +1,3 @@ +use crate::ty::{BoundRegion, Placeholder}; + +pub type PlaceholderRegion = Placeholder; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 488d83b5f671b..972dc9a87a0fa 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,11 +5,11 @@ use crate::infer::canonical::Canonical; use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; -use crate::ty::InferTy::*; use crate::ty::{ self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use crate::ty::{BoundConstness, InferTy::*, PolyTraitPredicate}; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; use polonius_engine::Atom; @@ -895,6 +895,22 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn def_id(&self) -> DefId { self.skip_binder().def_id } + + #[inline] + pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| ty::TraitPredicate { + trait_ref, + constness, + polarity: ty::ImplPolarity::Positive, + }) + } + + // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that + // the constness of trait bounds is being propagated correctly. + #[inline] + pub fn without_const(self) -> PolyTraitPredicate<'tcx> { + self.with_constness(BoundConstness::NotConst) + } } impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { @@ -1482,6 +1498,14 @@ pub struct EarlyBoundRegion { pub name: Symbol, } +impl EarlyBoundRegion { + /// Does this early bound region have a name? Early bound regions normally + /// always have names except when using anonymous lifetimes (`'_`). + pub fn has_name(&self) -> bool { + self.name != kw::UnderscoreLifetime && self.name != kw::Empty + } +} + impl fmt::Debug for EarlyBoundRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}, {}", self.index, self.name) diff --git a/compiler/rustc_middle/src/ty/symbol_name.rs b/compiler/rustc_middle/src/ty/symbol_name.rs new file mode 100644 index 0000000000000..4024f283d6c0c --- /dev/null +++ b/compiler/rustc_middle/src/ty/symbol_name.rs @@ -0,0 +1,29 @@ +use std::{fmt, str}; + +use crate::ty::TyCtxt; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] +pub struct SymbolName<'tcx> { + /// `&str` gives a consistent ordering, which ensures reproducible builds. + pub name: &'tcx str, +} + +impl<'tcx> SymbolName<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> { + SymbolName { + name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) }, + } + } +} + +impl<'tcx> fmt::Display for SymbolName<'tcx> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.name, fmt) + } +} + +impl<'tcx> fmt::Debug for SymbolName<'tcx> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.name, fmt) + } +} diff --git a/compiler/rustc_middle/src/ty/term.rs b/compiler/rustc_middle/src/ty/term.rs new file mode 100644 index 0000000000000..b1957d91374c6 --- /dev/null +++ b/compiler/rustc_middle/src/ty/term.rs @@ -0,0 +1,184 @@ +use std::fmt; +use std::marker::PhantomData; +use std::mem; +use std::num::NonZeroUsize; +use std::ops::ControlFlow; + +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_query_system::ich::StableHashingContext; + +use crate::ty::{ + self, AliasKind, AliasTy, Const, ConstKind, Decodable, Encodable, FallibleTypeFolder, + GenericArg, Interned, ParamConst, ParamTy, Ty, TyCtxt, TyDecoder, TyEncoder, TypeFoldable, + TypeVisitable, TypeVisitor, WithCachedTypeInfo, CONST_TAG, TAG_MASK, TYPE_TAG, +}; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Term<'tcx> { + ptr: NonZeroUsize, + marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] +pub enum TermKind<'tcx> { + Ty(Ty<'tcx>), + Const(Const<'tcx>), +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum ParamTerm { + Ty(ParamTy), + Const(ParamConst), +} + +impl<'tcx> Term<'tcx> { + #[inline] + pub fn unpack(self) -> TermKind<'tcx> { + let ptr = self.ptr.get(); + // SAFETY: use of `Interned::new_unchecked` here is ok because these + // pointers were originally created from `Interned` types in `pack()`, + // and this is just going in the other direction. + unsafe { + match ptr & TAG_MASK { + TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + ))), + CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( + &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), + ))), + _ => core::intrinsics::unreachable(), + } + } + } + + pub fn ty(&self) -> Option> { + if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None } + } + + pub fn ct(&self) -> Option> { + if let TermKind::Const(c) = self.unpack() { Some(c) } else { None } + } + + pub fn into_arg(self) -> GenericArg<'tcx> { + match self.unpack() { + TermKind::Ty(ty) => ty.into(), + TermKind::Const(c) => c.into(), + } + } + + /// This function returns the inner `AliasTy` if this term is a projection. + /// + /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly + /// deal with constants. + pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option> { + match self.unpack() { + TermKind::Ty(ty) => match ty.kind() { + ty::Alias(kind, alias_ty) => match kind { + AliasKind::Projection | AliasKind::Inherent => Some(*alias_ty), + AliasKind::Opaque => None, + }, + _ => None, + }, + TermKind::Const(ct) => match ct.kind() { + ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)), + _ => None, + }, + } + } + + pub fn is_infer(&self) -> bool { + match self.unpack() { + TermKind::Ty(ty) => ty.is_ty_var(), + TermKind::Const(ct) => ct.is_ct_infer(), + } + } +} + +impl fmt::Debug for Term<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let data = if let Some(ty) = self.ty() { + format!("Term::Ty({:?})", ty) + } else if let Some(ct) = self.ct() { + format!("Term::Ct({:?})", ct) + } else { + unreachable!() + }; + f.write_str(&data) + } +} + +impl<'tcx> From> for Term<'tcx> { + fn from(ty: Ty<'tcx>) -> Self { + TermKind::Ty(ty).pack() + } +} + +impl<'tcx> From> for Term<'tcx> { + fn from(c: Const<'tcx>) -> Self { + TermKind::Const(c).pack() + } +} + +impl<'a, 'tcx> HashStable> for Term<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.unpack().hash_stable(hcx, hasher); + } +} + +impl<'tcx> TypeFoldable> for Term<'tcx> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + Ok(self.unpack().try_fold_with(folder)?.pack()) + } +} + +impl<'tcx> TypeVisitable> for Term<'tcx> { + fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + self.unpack().visit_with(visitor) + } +} + +impl<'tcx, E: TyEncoder>> Encodable for Term<'tcx> { + fn encode(&self, e: &mut E) { + self.unpack().encode(e) + } +} + +impl<'tcx, D: TyDecoder>> Decodable for Term<'tcx> { + fn decode(d: &mut D) -> Self { + let res: TermKind<'tcx> = Decodable::decode(d); + res.pack() + } +} + +impl<'tcx> TermKind<'tcx> { + #[inline] + pub(super) fn pack(self) -> Term<'tcx> { + let (tag, ptr) = match self { + TermKind::Ty(ty) => { + // Ensure we can use the tag bits. + assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + } + TermKind::Const(ct) => { + // Ensure we can use the tag bits. + assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); + (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) + } + }; + + Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } + } +} + +impl ParamTerm { + pub fn index(self) -> usize { + match self { + ParamTerm::Ty(ty) => ty.index as usize, + ParamTerm::Const(ct) => ct.index as usize, + } + } +} diff --git a/compiler/rustc_middle/src/ty/ty_.rs b/compiler/rustc_middle/src/ty/ty_.rs new file mode 100644 index 0000000000000..de9d2495c3ef8 --- /dev/null +++ b/compiler/rustc_middle/src/ty/ty_.rs @@ -0,0 +1,24 @@ +use crate::ty::{BoundTy, Interned, Placeholder, TyKind, WithCachedTypeInfo}; + +/// Use this rather than `TyKind`, whenever possible. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[rustc_diagnostic_item = "Ty"] +#[rustc_pass_by_value] +pub struct Ty<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo>>); + +pub type PlaceholderType = Placeholder; + +#[derive(Debug, Default, Copy, Clone)] +pub struct InferVarInfo { + /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo` + /// obligation, where: + /// + /// * `Foo` is not `Sized` + /// * `(): Foo` may be satisfied + pub self_in_trait: bool, + /// This is true if we identified that this Ty (`?T`) is found in a `<_ as + /// _>::AssocType = ?T` + pub output: bool, +} + +// FIXME: move `Ty` inherent impls here (and possibly change structure wrt `sty` mod) diff --git a/compiler/rustc_middle/src/ty/visibility.rs b/compiler/rustc_middle/src/ty/visibility.rs new file mode 100644 index 0000000000000..c6778d0c5e9bd --- /dev/null +++ b/compiler/rustc_middle/src/ty/visibility.rs @@ -0,0 +1,61 @@ +use rustc_hir::def_id::{DefId, LocalDefId}; + +use crate::ty::TyCtxt; + +#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)] +pub enum Visibility { + /// Visible everywhere (including in other crates). + Public, + /// Visible only in the given crate-local module. + Restricted(Id), +} + +impl Visibility { + pub fn is_public(self) -> bool { + matches!(self, Visibility::Public) + } + + pub fn map_id(self, f: impl FnOnce(Id) -> OutId) -> Visibility { + match self { + Visibility::Public => Visibility::Public, + Visibility::Restricted(id) => Visibility::Restricted(f(id)), + } + } +} + +impl> Visibility { + pub fn to_def_id(self) -> Visibility { + self.map_id(Into::into) + } + + /// Returns `true` if an item with this visibility is accessible from the given module. + pub fn is_accessible_from(self, module: impl Into, tcx: TyCtxt<'_>) -> bool { + match self { + // Public items are visible everywhere. + Visibility::Public => true, + Visibility::Restricted(id) => tcx.is_descendant_of(module.into(), id.into()), + } + } + + /// Returns `true` if this visibility is at least as accessible as the given visibility + pub fn is_at_least(self, vis: Visibility>, tcx: TyCtxt<'_>) -> bool { + match vis { + Visibility::Public => self.is_public(), + Visibility::Restricted(id) => self.is_accessible_from(id, tcx), + } + } +} + +impl Visibility { + pub fn expect_local(self) -> Visibility { + self.map_id(|id| id.expect_local()) + } + + /// Returns `true` if this item is visible anywhere in the local crate. + pub fn is_visible_locally(self) -> bool { + match self { + Visibility::Public => true, + Visibility::Restricted(def_id) => def_id.is_local(), + } + } +} diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 99fc69d1bec7b..4e70bc488bdfe 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -11,7 +11,8 @@ use rustc_errors::{ }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{MainDefinition, Ty}; +use rustc_middle::resolver_outputs::MainDefinition; +use rustc_middle::ty::Ty; use rustc_span::{Span, Symbol, DUMMY_SP}; use crate::check_attr::ProcMacroKind; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c12dc2f5d92a5..0472138d3c82b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -47,9 +47,11 @@ use rustc_index::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; +use rustc_middle::resolver_outputs::{ + MainDefinition, ResolverAstLowering, ResolverGlobalCtxt, ResolverOutputs, +}; use rustc_middle::span_bug; -use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt}; -use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; +use rustc_middle::ty::{self, RegisteredTools, TyCtxt}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::LintBuffer; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -1417,7 +1419,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { doc_link_traits_in_scope: self.doc_link_traits_in_scope, all_macro_rules: self.all_macro_rules, }; - let ast_lowering = ty::ResolverAstLowering { + let ast_lowering = ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args, partial_res_map: self.partial_res_map, import_res_map: self.import_res_map,