Merge ref '44e34e1ac6' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.
Upstream ref: rust-lang/rust@44e34e1ac6
Filtered ref: rust-lang/rustc-dev-guide@e740092d12
Upstream diff: 370143facf...44e34e1ac6
This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
commit
678328aa94
175 changed files with 2629 additions and 1546 deletions
16
Cargo.lock
16
Cargo.lock
|
|
@ -184,9 +184,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
|||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
version = "0.15.3"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a800c6f7c005e5bcb76ff0b9e61c9e54ad379ce4e83a88ed14ff487a73776d"
|
||||
checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57"
|
||||
dependencies = [
|
||||
"askama_macros",
|
||||
"itoa",
|
||||
|
|
@ -197,9 +197,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "askama_derive"
|
||||
version = "0.15.3"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cb7657165bac49b5c533850e7cd67c1c60059aefc31088f89aa431c8a90d5d9"
|
||||
checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37"
|
||||
dependencies = [
|
||||
"askama_parser",
|
||||
"basic-toml",
|
||||
|
|
@ -214,18 +214,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "askama_macros"
|
||||
version = "0.15.3"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e55eacd3e54d32483cd10d0a881a0f28a40f3a763704ac9b8693edc39d7321c7"
|
||||
checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b"
|
||||
dependencies = [
|
||||
"askama_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_parser"
|
||||
version = "0.15.3"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20c3df8886ab5acdcd76eee93b3e2df1ef734251438b5b942b5fea22c50d2a0f"
|
||||
checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c"
|
||||
dependencies = [
|
||||
"rustc-hash 2.1.1",
|
||||
"serde",
|
||||
|
|
|
|||
|
|
@ -172,8 +172,22 @@ impl<T> TypedArena<T> {
|
|||
available_bytes >= additional_bytes
|
||||
}
|
||||
|
||||
/// Allocates storage for `len >= 1` values in this arena, and returns a
|
||||
/// raw pointer to the first value's storage.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Caller must initialize each of the `len` slots to a droppable value
|
||||
/// before the arena is dropped.
|
||||
///
|
||||
/// In practice, this typically means that the caller must be able to
|
||||
/// raw-copy `len` already-initialized values into the slice without any
|
||||
/// possibility of panicking.
|
||||
///
|
||||
/// FIXME(Zalathar): This is *very* fragile; perhaps we need a different
|
||||
/// approach to arena-allocating slices of droppable values.
|
||||
#[inline]
|
||||
fn alloc_raw_slice(&self, len: usize) -> *mut T {
|
||||
unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T {
|
||||
assert!(size_of::<T>() != 0);
|
||||
assert!(len != 0);
|
||||
|
||||
|
|
@ -208,7 +222,7 @@ impl<T> TypedArena<T> {
|
|||
&self,
|
||||
iter: impl IntoIterator<Item = Result<T, E>>,
|
||||
) -> Result<&mut [T], E> {
|
||||
// Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason
|
||||
// Despite the similarity with `DroplessArena`, we cannot reuse their fast case. The reason
|
||||
// is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a
|
||||
// reference to `self` and adding elements to the arena during iteration.
|
||||
//
|
||||
|
|
@ -229,9 +243,15 @@ impl<T> TypedArena<T> {
|
|||
}
|
||||
// Move the content to the arena by copying and then forgetting it.
|
||||
let len = vec.len();
|
||||
let start_ptr = self.alloc_raw_slice(len);
|
||||
|
||||
// SAFETY: After allocating raw storage for exactly `len` values, we
|
||||
// must fully initialize the storage without panicking, and we must
|
||||
// also prevent the stale values in the vec from being dropped.
|
||||
Ok(unsafe {
|
||||
let start_ptr = self.alloc_raw_slice(len);
|
||||
// Initialize the newly-allocated storage without panicking.
|
||||
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
||||
// Prevent the stale values in the vec from being dropped.
|
||||
vec.set_len(0);
|
||||
slice::from_raw_parts_mut(start_ptr, len)
|
||||
})
|
||||
|
|
@ -584,7 +604,7 @@ impl DroplessArena {
|
|||
&self,
|
||||
iter: impl IntoIterator<Item = Result<T, E>>,
|
||||
) -> Result<&mut [T], E> {
|
||||
// Despite the similarlty with `alloc_from_iter`, we cannot reuse their fast case, as we
|
||||
// Despite the similarity with `alloc_from_iter`, we cannot reuse their fast case, as we
|
||||
// cannot know the minimum length of the iterator in this case.
|
||||
assert!(size_of::<T>() != 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1961,7 +1961,8 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
|
||||
self.print_name(lifetime.ident.name)
|
||||
self.word(lifetime.ident.name.to_string());
|
||||
self.ann_post(lifetime.ident)
|
||||
}
|
||||
|
||||
fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];
|
||||
type Item = Symbol;
|
||||
const CONVERT: ConvertFn<Self::Item> =
|
||||
|items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span);
|
||||
|items, first_span| AttributeKind::RustcAllowConstFnUnstable(items, first_span);
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ impl<S: Stage> SingleAttributeParser<S> for ObjcClassParser {
|
|||
cx.emit_err(NullOnObjcClass { span: nv.value_span });
|
||||
return None;
|
||||
}
|
||||
Some(AttributeKind::ObjcClass { classname, span: cx.attr_span })
|
||||
Some(AttributeKind::RustcObjcClass { classname, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +213,7 @@ impl<S: Stage> SingleAttributeParser<S> for ObjcSelectorParser {
|
|||
cx.emit_err(NullOnObjcSelector { span: nv.value_span });
|
||||
return None;
|
||||
}
|
||||
Some(AttributeKind::ObjcSelector { methname, span: cx.attr_span })
|
||||
Some(AttributeKind::RustcObjcSelector { methname, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(AttributeKind::Confusables {
|
||||
Some(AttributeKind::RustcConfusables {
|
||||
symbols: self.confusables,
|
||||
first_span: self.first_span.unwrap(),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ impl<S: Stage> SingleAttributeParser<S> for DummyParser {
|
|||
const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really
|
||||
|
||||
fn convert(_: &mut AcceptContext<'_, '_, S>, _: &ArgParser) -> Option<AttributeKind> {
|
||||
Some(AttributeKind::Dummy)
|
||||
Some(AttributeKind::RustcDummy)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser {
|
|||
Allow(Target::Static),
|
||||
Allow(Target::ForeignStatic),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStdInternalSymbol;
|
||||
}
|
||||
|
||||
pub(crate) struct LinkOrdinalParser;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser {
|
|||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::AsPtr;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAsPtr;
|
||||
}
|
||||
|
||||
pub(crate) struct PubTransparentParser;
|
||||
|
|
@ -23,7 +23,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser {
|
|||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent;
|
||||
}
|
||||
|
||||
pub(crate) struct PassByValueParser;
|
||||
|
|
@ -35,7 +35,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser {
|
|||
Allow(Target::Enum),
|
||||
Allow(Target::TyAlias),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassByValue;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcShouldNotBeCalledOnConstItems;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
|
||||
use rustc_hir::attrs::RustcLayoutType;
|
||||
use rustc_session::errors;
|
||||
|
||||
use super::prelude::*;
|
||||
|
|
@ -329,3 +330,73 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcOffloadKernelParser {
|
|||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLayoutParser;
|
||||
|
||||
impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_layout];
|
||||
|
||||
type Item = RustcLayoutType;
|
||||
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcLayout(items);
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
Allow(Target::TyAlias),
|
||||
]);
|
||||
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]);
|
||||
|
||||
fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let ArgParser::List(items) = args else {
|
||||
cx.expected_list(cx.attr_span, args);
|
||||
return vec![];
|
||||
};
|
||||
|
||||
let mut result = Vec::new();
|
||||
for item in items.mixed() {
|
||||
let Some(arg) = item.meta_item() else {
|
||||
cx.unexpected_literal(item.span());
|
||||
continue;
|
||||
};
|
||||
let Some(ident) = arg.ident() else {
|
||||
cx.expected_identifier(arg.span());
|
||||
return vec![];
|
||||
};
|
||||
let ty = match ident.name {
|
||||
sym::abi => RustcLayoutType::Abi,
|
||||
sym::align => RustcLayoutType::Align,
|
||||
sym::size => RustcLayoutType::Size,
|
||||
sym::homogeneous_aggregate => RustcLayoutType::HomogenousAggregate,
|
||||
sym::debug => RustcLayoutType::Debug,
|
||||
_ => {
|
||||
cx.expected_specific_argument(
|
||||
ident.span,
|
||||
&[sym::abi, sym::align, sym::size, sym::homogeneous_aggregate, sym::debug],
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
result.push(ty);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcNonConstTraitMethodParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNonConstTraitMethodParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_non_const_trait_method];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ impl<S: Stage> AttributeParser<S> for BodyStabilityParser {
|
|||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
let (stability, span) = self.stability?;
|
||||
|
||||
Some(AttributeKind::BodyStability { stability, span })
|
||||
Some(AttributeKind::RustcBodyStability { stability, span })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for ConstStabilityIndirectParser {
|
|||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ConstStabilityIndirect;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConstStabilityIndirect;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -258,7 +258,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
|
|||
|
||||
let (stability, span) = self.stability?;
|
||||
|
||||
Some(AttributeKind::ConstStability { stability, span })
|
||||
Some(AttributeKind::RustcConstStability { stability, span })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,11 @@ impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
|
|||
cx.duplicate_key(arg.span(), key);
|
||||
}
|
||||
}
|
||||
Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
|
||||
Some(AttributeKind::RustcSkipDuringMethodDispatch {
|
||||
array,
|
||||
boxed_slice,
|
||||
span: cx.attr_span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +63,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar;
|
||||
}
|
||||
|
||||
pub(crate) struct TypeConstParser;
|
||||
|
|
@ -91,7 +95,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDenyExplicitImpl;
|
||||
}
|
||||
|
||||
pub(crate) struct DynIncompatibleTraitParser;
|
||||
|
|
@ -99,7 +103,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for DynIncompatibleTraitParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DynIncompatibleTrait;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDynIncompatibleTrait;
|
||||
}
|
||||
|
||||
// Specialization
|
||||
|
|
@ -109,7 +113,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcSpecializationTrait;
|
||||
}
|
||||
|
||||
pub(crate) struct UnsafeSpecializationMarkerParser;
|
||||
|
|
@ -117,7 +121,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcUnsafeSpecializationMarker;
|
||||
}
|
||||
|
||||
// Coherence
|
||||
|
|
@ -127,7 +131,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_coinductive];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoinductive;
|
||||
}
|
||||
|
||||
pub(crate) struct AllowIncoherentImplParser;
|
||||
|
|
@ -136,7 +140,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl;
|
||||
}
|
||||
|
||||
pub(crate) struct FundamentalParser;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,6 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
|
|||
}
|
||||
None => None,
|
||||
}
|
||||
.map(AttributeKind::MacroTransparency)
|
||||
.map(AttributeKind::RustcMacroTransparency)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,13 +75,13 @@ use crate::attributes::rustc_dump::{
|
|||
RustcDumpVtable,
|
||||
};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser,
|
||||
RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser,
|
||||
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
|
||||
RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser,
|
||||
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
|
||||
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, RustcNounwindParser,
|
||||
RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser,
|
||||
RustcSimdMonomorphizeLaneLimitParser,
|
||||
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser,
|
||||
RustcNonConstTraitMethodParser, RustcNounwindParser, RustcObjectLifetimeDefaultParser,
|
||||
RustcOffloadKernelParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser,
|
||||
};
|
||||
use crate::attributes::semantics::MayDangleParser;
|
||||
use crate::attributes::stability::{
|
||||
|
|
@ -198,6 +198,7 @@ attribute_parsers!(
|
|||
Combine<ForceTargetFeatureParser>,
|
||||
Combine<LinkParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<RustcLayoutParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
Combine<UnstableFeatureBoundParser>,
|
||||
// tidy-alphabetical-end
|
||||
|
|
@ -304,6 +305,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<RustcMainParser>>,
|
||||
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
|
||||
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
|
||||
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
|
||||
Single<WithoutArgs<RustcNounwindParser>>,
|
||||
Single<WithoutArgs<RustcOffloadKernelParser>>,
|
||||
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ pub(crate) fn allowed_targets_applied(
|
|||
];
|
||||
const IMPL_LIKE: &[Target] =
|
||||
&[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }];
|
||||
const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum];
|
||||
const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum, Target::Union];
|
||||
|
||||
let mut added_fake_targets = Vec::new();
|
||||
filter_targets(
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ pub(crate) trait TypeOpInfo<'tcx> {
|
|||
|
||||
let placeholder_region = ty::Region::new_placeholder(
|
||||
tcx,
|
||||
ty::Placeholder::new(adjusted_universe.into(), placeholder.bound),
|
||||
ty::PlaceholderRegion::new(adjusted_universe.into(), placeholder.bound),
|
||||
);
|
||||
|
||||
let error_region =
|
||||
|
|
@ -179,7 +179,7 @@ pub(crate) trait TypeOpInfo<'tcx> {
|
|||
adjusted_universe.map(|adjusted| {
|
||||
ty::Region::new_placeholder(
|
||||
tcx,
|
||||
ty::Placeholder::new(adjusted.into(), error_placeholder.bound),
|
||||
ty::PlaceholderRegion::new(adjusted.into(), error_placeholder.bound),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ fn render_region_vid<'tcx>(
|
|||
format!(" (for<{}>)", tcx.item_name(def_id))
|
||||
}
|
||||
ty::BoundRegionKind::ClosureEnv | ty::BoundRegionKind::Anon => " (for<'_>)".to_string(),
|
||||
ty::BoundRegionKind::NamedAnon(_) => {
|
||||
ty::BoundRegionKind::NamedForPrinting(_) => {
|
||||
bug!("only used for pretty printing")
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_middle::ty::{self, RegionVid};
|
|||
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::BorrowIndex;
|
||||
use crate::polonius::LiveLoans;
|
||||
use crate::{BorrowIndex, TyCtxt};
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// A single integer representing a `ty::Placeholder`.
|
||||
|
|
@ -420,18 +420,18 @@ impl ToElementIndex<'_> for RegionVid {
|
|||
impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> {
|
||||
fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool
|
||||
where
|
||||
Self: Into<ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion>>,
|
||||
Self: Into<ty::PlaceholderRegion<'tcx>>,
|
||||
{
|
||||
let placeholder: ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion> = self.into();
|
||||
let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
|
||||
let index = values.placeholder_indices.lookup_index(placeholder);
|
||||
values.placeholders.insert(row, index)
|
||||
}
|
||||
|
||||
fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool
|
||||
where
|
||||
Self: Into<ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion>>,
|
||||
Self: Into<ty::PlaceholderRegion<'tcx>>,
|
||||
{
|
||||
let placeholder: ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion> = self.into();
|
||||
let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
|
||||
let index = values.placeholder_indices.lookup_index(placeholder);
|
||||
values.placeholders.contains(row, index)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -775,7 +775,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
ty::BoundRegionKind::Anon => sym::anon,
|
||||
ty::BoundRegionKind::Named(def_id) => tcx.item_name(def_id),
|
||||
ty::BoundRegionKind::ClosureEnv => sym::env,
|
||||
ty::BoundRegionKind::NamedAnon(_) => {
|
||||
ty::BoundRegionKind::NamedForPrinting(_) => {
|
||||
bug!("only used for pretty printing")
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||
let infcx = self.type_checker.infcx;
|
||||
let mut lazy_universe = None;
|
||||
let delegate = FnMutDelegate {
|
||||
regions: &mut |br: ty::BoundRegion| {
|
||||
regions: &mut |br: ty::BoundRegion<'tcx>| {
|
||||
// The first time this closure is called, create a
|
||||
// new universe for the placeholders we will make
|
||||
// from here out.
|
||||
|
|
@ -191,10 +191,10 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||
|
||||
placeholder_reg
|
||||
},
|
||||
types: &mut |_bound_ty: ty::BoundTy| {
|
||||
types: &mut |_bound_ty: ty::BoundTy<'tcx>| {
|
||||
unreachable!("we only replace regions in nll_relate, not types")
|
||||
},
|
||||
consts: &mut |_bound_const: ty::BoundConst| {
|
||||
consts: &mut |_bound_const: ty::BoundConst<'tcx>| {
|
||||
unreachable!("we only replace regions in nll_relate, not consts")
|
||||
},
|
||||
};
|
||||
|
|
@ -218,7 +218,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||
let infcx = self.type_checker.infcx;
|
||||
let mut reg_map = FxHashMap::default();
|
||||
let delegate = FnMutDelegate {
|
||||
regions: &mut |br: ty::BoundRegion| {
|
||||
regions: &mut |br: ty::BoundRegion<'tcx>| {
|
||||
if let Some(ex_reg_var) = reg_map.get(&br) {
|
||||
*ex_reg_var
|
||||
} else {
|
||||
|
|
@ -230,10 +230,10 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||
ex_reg_var
|
||||
}
|
||||
},
|
||||
types: &mut |_bound_ty: ty::BoundTy| {
|
||||
types: &mut |_bound_ty: ty::BoundTy<'tcx>| {
|
||||
unreachable!("we only replace regions in nll_relate, not types")
|
||||
},
|
||||
consts: &mut |_bound_const: ty::BoundConst| {
|
||||
consts: &mut |_bound_const: ty::BoundConst<'tcx>| {
|
||||
unreachable!("we only replace regions in nll_relate, not consts")
|
||||
},
|
||||
};
|
||||
|
|
@ -268,7 +268,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||
ty::BoundRegionKind::Anon => sym::anon,
|
||||
ty::BoundRegionKind::Named(def_id) => self.type_checker.tcx().item_name(def_id),
|
||||
ty::BoundRegionKind::ClosureEnv => sym::env,
|
||||
ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
|
||||
ty::BoundRegionKind::NamedForPrinting(_) => bug!("only used for pretty printing"),
|
||||
};
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ fn process_builtin_attrs(
|
|||
},
|
||||
AttributeKind::FfiConst(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST,
|
||||
AttributeKind::FfiPure(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE,
|
||||
AttributeKind::StdInternalSymbol(_) => {
|
||||
AttributeKind::RustcStdInternalSymbol(_) => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
|
||||
}
|
||||
AttributeKind::Linkage(linkage, span) => {
|
||||
|
|
@ -217,10 +217,10 @@ fn process_builtin_attrs(
|
|||
AttributeKind::Sanitize { span, .. } => {
|
||||
interesting_spans.sanitize = Some(*span);
|
||||
}
|
||||
AttributeKind::ObjcClass { classname, .. } => {
|
||||
AttributeKind::RustcObjcClass { classname, .. } => {
|
||||
codegen_fn_attrs.objc_class = Some(*classname);
|
||||
}
|
||||
AttributeKind::ObjcSelector { methname, .. } => {
|
||||
AttributeKind::RustcObjcSelector { methname, .. } => {
|
||||
codegen_fn_attrs.objc_selector = Some(*methname);
|
||||
}
|
||||
AttributeKind::EiiForeignItem => {
|
||||
|
|
|
|||
|
|
@ -774,16 +774,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
|
||||
// Attempting to call a trait method?
|
||||
if let Some(trait_did) = tcx.trait_of_assoc(callee) {
|
||||
// We can't determine the actual callee here, so we have to do different checks
|
||||
// than usual.
|
||||
// We can't determine the actual callee (the underlying impl of the trait) here, so we have
|
||||
// to do different checks than usual.
|
||||
|
||||
trace!("attempting to call a trait method");
|
||||
let trait_is_const = tcx.is_const_trait(trait_did);
|
||||
let is_const = tcx.constness(callee) == hir::Constness::Const;
|
||||
|
||||
// Only consider a trait to be const if the const conditions hold.
|
||||
// Otherwise, it's really misleading to call something "conditionally"
|
||||
// const when it's very obviously not conditionally const.
|
||||
if trait_is_const && has_const_conditions == Some(ConstConditionsHold::Yes) {
|
||||
if is_const && has_const_conditions == Some(ConstConditionsHold::Yes) {
|
||||
// Trait calls are always conditionally-const.
|
||||
self.check_op(ops::ConditionallyConstCall {
|
||||
callee,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ pub fn rustc_allow_const_fn_unstable(
|
|||
) -> bool {
|
||||
let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
|
||||
|
||||
find_attr!(attrs, AttributeKind::AllowConstFnUnstable(syms, _) if syms.contains(&feature_gate))
|
||||
find_attr!(attrs, AttributeKind::RustcAllowConstFnUnstable(syms, _) if syms.contains(&feature_gate))
|
||||
}
|
||||
|
||||
/// Returns `true` if the given `def_id` (trait or function) is "safe to expose on stable".
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{
|
||||
Constness, ExprKind, ForeignItemKind, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind,
|
||||
Node, TraitItem, TraitItemKind, VariantData,
|
||||
Node, TraitItem, TraitItemKind, VariantData, find_attr,
|
||||
};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
|
@ -36,7 +37,13 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness {
|
|||
Constness::NotConst => tcx.constness(tcx.local_parent(def_id)),
|
||||
}
|
||||
}
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. }) => tcx.trait_def(tcx.local_parent(def_id)).constness,
|
||||
Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => {
|
||||
if find_attr!(tcx.hir_attrs(ti.hir_id()), AttributeKind::RustcNonConstTraitMethod) {
|
||||
Constness::NotConst
|
||||
} else {
|
||||
tcx.trait_def(tcx.local_parent(def_id)).constness
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.dcx().span_bug(
|
||||
tcx.def_span(def_id),
|
||||
|
|
|
|||
|
|
@ -963,13 +963,16 @@ impl SyntaxExtension {
|
|||
let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability);
|
||||
|
||||
// FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
|
||||
if let Some(sp) = find_attr!(attrs, AttributeKind::ConstStability { span, .. } => *span) {
|
||||
if let Some(sp) =
|
||||
find_attr!(attrs, AttributeKind::RustcConstStability { span, .. } => *span)
|
||||
{
|
||||
sess.dcx().emit_err(errors::MacroConstStability {
|
||||
span: sp,
|
||||
head_span: sess.source_map().guess_head_span(span),
|
||||
});
|
||||
}
|
||||
if let Some(sp) = find_attr!(attrs, AttributeKind::BodyStability{ span, .. } => *span) {
|
||||
if let Some(sp) = find_attr!(attrs, AttributeKind::RustcBodyStability{ span, .. } => *span)
|
||||
{
|
||||
sess.dcx().emit_err(errors::MacroBodyStability {
|
||||
span: sp,
|
||||
head_span: sess.source_map().guess_head_span(span),
|
||||
|
|
|
|||
|
|
@ -819,7 +819,7 @@ pub fn compile_declarative_macro(
|
|||
}
|
||||
assert!(!kinds.is_empty());
|
||||
|
||||
let transparency = find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
|
||||
let transparency = find_attr!(attrs, AttributeKind::RustcMacroTransparency(x) => *x)
|
||||
.unwrap_or(Transparency::fallback(macro_rules));
|
||||
|
||||
if let Some(guar) = guar {
|
||||
|
|
|
|||
|
|
@ -1329,6 +1329,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
"`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \
|
||||
the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_non_const_trait_method, AttributeType::Normal, template!(Word),
|
||||
ErrorFollowing, EncodeCrossCrate::No,
|
||||
"`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \
|
||||
as non-const to allow large traits an easier transition to const"
|
||||
),
|
||||
|
||||
BuiltinAttribute {
|
||||
name: sym::rustc_diagnostic_item,
|
||||
|
|
|
|||
|
|
@ -690,6 +690,15 @@ impl IntoDiagArg for CrateType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
|
||||
pub enum RustcLayoutType {
|
||||
Abi,
|
||||
Align,
|
||||
Size,
|
||||
HomogenousAggregate,
|
||||
Debug,
|
||||
}
|
||||
|
||||
/// Represents parsed *built-in* inert attributes.
|
||||
///
|
||||
/// ## Overview
|
||||
|
|
@ -746,31 +755,15 @@ pub enum AttributeKind {
|
|||
// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
|
||||
Align { align: Align, span: Span },
|
||||
|
||||
/// Represents `#[rustc_allow_const_fn_unstable]`.
|
||||
AllowConstFnUnstable(ThinVec<Symbol>, Span),
|
||||
|
||||
/// Represents `#[rustc_allow_incoherent_impl]`.
|
||||
AllowIncoherentImpl(Span),
|
||||
|
||||
/// Represents `#[allow_internal_unsafe]`.
|
||||
AllowInternalUnsafe(Span),
|
||||
|
||||
/// Represents `#[allow_internal_unstable]`.
|
||||
AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
|
||||
|
||||
/// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
|
||||
AsPtr(Span),
|
||||
|
||||
/// Represents `#[automatically_derived]`
|
||||
AutomaticallyDerived(Span),
|
||||
|
||||
/// Represents `#[rustc_default_body_unstable]`.
|
||||
BodyStability {
|
||||
stability: DefaultBodyStability,
|
||||
/// Span of the `#[rustc_default_body_unstable(...)]` attribute
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents the trace attribute of `#[cfg_attr]`
|
||||
CfgAttrTrace,
|
||||
|
||||
|
|
@ -780,9 +773,6 @@ pub enum AttributeKind {
|
|||
/// Represents `#[cfi_encoding]`
|
||||
CfiEncoding { encoding: Symbol },
|
||||
|
||||
/// Represents `#[rustc_coinductive]`.
|
||||
Coinductive(Span),
|
||||
|
||||
/// Represents `#[cold]`.
|
||||
Cold(Span),
|
||||
|
||||
|
|
@ -792,26 +782,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[compiler_builtins]`.
|
||||
CompilerBuiltins,
|
||||
|
||||
/// Represents `#[rustc_confusables]`.
|
||||
Confusables {
|
||||
symbols: ThinVec<Symbol>,
|
||||
// FIXME(jdonszelmann): remove when target validation code is moved
|
||||
first_span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[const_continue]`.
|
||||
ConstContinue(Span),
|
||||
|
||||
/// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
|
||||
ConstStability {
|
||||
stability: PartialConstStability,
|
||||
/// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_const_stable_indirect]`.
|
||||
ConstStabilityIndirect,
|
||||
|
||||
/// Represents `#[coroutine]`.
|
||||
Coroutine(Span),
|
||||
|
||||
|
|
@ -830,9 +803,6 @@ pub enum AttributeKind {
|
|||
/// Represents `#[debugger_visualizer]`.
|
||||
DebuggerVisualizer(ThinVec<DebugVisualizer>),
|
||||
|
||||
/// Represents `#[rustc_deny_explicit_impl]`.
|
||||
DenyExplicitImpl(Span),
|
||||
|
||||
/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
|
||||
Deprecation { deprecation: Deprecation, span: Span },
|
||||
|
||||
|
|
@ -848,12 +818,6 @@ pub enum AttributeKind {
|
|||
/// i.e. doc comments.
|
||||
DocComment { style: AttrStyle, kind: DocFragmentKind, span: Span, comment: Symbol },
|
||||
|
||||
/// Represents `#[rustc_dummy]`.
|
||||
Dummy,
|
||||
|
||||
/// Represents `#[rustc_dyn_incompatible_trait]`.
|
||||
DynIncompatibleTrait(Span),
|
||||
|
||||
/// Implementation detail of `#[eii]`
|
||||
EiiDeclaration(EiiDecl),
|
||||
|
||||
|
|
@ -920,9 +884,6 @@ pub enum AttributeKind {
|
|||
/// Represents [`#[macro_export]`](https://doc.rust-lang.org/reference/macros-by-example.html#r-macro.decl.scope.path).
|
||||
MacroExport { span: Span, local_inner_macros: bool },
|
||||
|
||||
/// Represents `#[rustc_macro_transparency]`.
|
||||
MacroTransparency(Transparency),
|
||||
|
||||
/// Represents `#[macro_use]`.
|
||||
MacroUse { span: Span, arguments: MacroUseArgs },
|
||||
|
||||
|
|
@ -978,24 +939,12 @@ pub enum AttributeKind {
|
|||
/// Represents `#[non_exhaustive]`
|
||||
NonExhaustive(Span),
|
||||
|
||||
/// Represents `#[rustc_objc_class]`
|
||||
ObjcClass { classname: Symbol, span: Span },
|
||||
|
||||
/// Represents `#[rustc_objc_selector]`
|
||||
ObjcSelector { methname: Symbol, span: Span },
|
||||
|
||||
/// Represents `#[optimize(size|speed)]`
|
||||
Optimize(OptimizeAttr, Span),
|
||||
|
||||
/// Represents `#[panic_runtime]`
|
||||
PanicRuntime,
|
||||
|
||||
/// Represents `#[rustc_paren_sugar]`.
|
||||
ParenSugar(Span),
|
||||
|
||||
/// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
|
||||
PassByValue(Span),
|
||||
|
||||
/// Represents `#[patchable_function_entry]`
|
||||
PatchableFunctionEntry { prefix: u8, entry: u8 },
|
||||
|
||||
|
|
@ -1023,9 +972,6 @@ pub enum AttributeKind {
|
|||
/// Represents `#[profiler_runtime]`
|
||||
ProfilerRuntime,
|
||||
|
||||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
PubTransparent(Span),
|
||||
|
||||
/// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute)
|
||||
RecursionLimit { attr_span: Span, limit_span: Span, limit: Limit },
|
||||
|
||||
|
|
@ -1041,15 +987,55 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_allocator_zeroed_variant]`
|
||||
RustcAllocatorZeroedVariant { name: Symbol },
|
||||
|
||||
/// Represents `#[rustc_allow_const_fn_unstable]`.
|
||||
RustcAllowConstFnUnstable(ThinVec<Symbol>, Span),
|
||||
|
||||
/// Represents `#[rustc_allow_incoherent_impl]`.
|
||||
RustcAllowIncoherentImpl(Span),
|
||||
|
||||
/// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
|
||||
RustcAsPtr(Span),
|
||||
|
||||
/// Represents `#[rustc_default_body_unstable]`.
|
||||
RustcBodyStability {
|
||||
stability: DefaultBodyStability,
|
||||
/// Span of the `#[rustc_default_body_unstable(...)]` attribute
|
||||
span: Span,
|
||||
},
|
||||
/// Represents `#[rustc_builtin_macro]`.
|
||||
RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
|
||||
|
||||
/// Represents `#[rustc_coherence_is_core]`
|
||||
RustcCoherenceIsCore(Span),
|
||||
|
||||
/// Represents `#[rustc_coinductive]`.
|
||||
RustcCoinductive(Span),
|
||||
|
||||
/// Represents `#[rustc_confusables]`.
|
||||
RustcConfusables {
|
||||
symbols: ThinVec<Symbol>,
|
||||
// FIXME(jdonszelmann): remove when target validation code is moved
|
||||
first_span: Span,
|
||||
},
|
||||
/// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
|
||||
RustcConstStability {
|
||||
stability: PartialConstStability,
|
||||
/// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_const_stable_indirect]`.
|
||||
RustcConstStabilityIndirect,
|
||||
|
||||
/// Represents `#[rustc_deallocator]`
|
||||
RustcDeallocator,
|
||||
|
||||
/// Represents `#[rustc_deny_explicit_impl]`.
|
||||
RustcDenyExplicitImpl(Span),
|
||||
|
||||
/// Represents `#[rustc_dummy]`.
|
||||
RustcDummy,
|
||||
|
||||
/// Represents `#[rustc_dump_def_parents]`
|
||||
RustcDumpDefParents,
|
||||
|
||||
|
|
@ -1065,9 +1051,15 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_dump_vtable]`
|
||||
RustcDumpVtable(Span),
|
||||
|
||||
/// Represents `#[rustc_dyn_incompatible_trait]`.
|
||||
RustcDynIncompatibleTrait(Span),
|
||||
|
||||
/// Represents `#[rustc_has_incoherent_inherent_impls]`
|
||||
RustcHasIncoherentInherentImpls,
|
||||
|
||||
/// Represents `#[rustc_layout]`
|
||||
RustcLayout(ThinVec<RustcLayoutType>),
|
||||
|
||||
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
|
||||
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
|
||||
|
||||
|
|
@ -1089,6 +1081,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_lint_untracked_query_information]`
|
||||
RustcLintUntrackedQueryInformation,
|
||||
|
||||
/// Represents `#[rustc_macro_transparency]`.
|
||||
RustcMacroTransparency(Transparency),
|
||||
|
||||
/// Represents `#[rustc_main]`.
|
||||
RustcMain,
|
||||
|
||||
|
|
@ -1101,18 +1096,36 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_no_implicit_autorefs]`
|
||||
RustcNoImplicitAutorefs,
|
||||
|
||||
/// Represents `#[rustc_non_const_trait_method]`.
|
||||
RustcNonConstTraitMethod,
|
||||
|
||||
/// Represents `#[rustc_nounwind]`
|
||||
RustcNounwind,
|
||||
|
||||
/// Represents `#[rustc_objc_class]`
|
||||
RustcObjcClass { classname: Symbol, span: Span },
|
||||
|
||||
/// Represents `#[rustc_objc_selector]`
|
||||
RustcObjcSelector { methname: Symbol, span: Span },
|
||||
|
||||
/// Represents `#[rustc_object_lifetime_default]`.
|
||||
RustcObjectLifetimeDefault,
|
||||
|
||||
/// Represents `#[rustc_offload_kernel]`
|
||||
RustcOffloadKernel,
|
||||
|
||||
/// Represents `#[rustc_paren_sugar]`.
|
||||
RustcParenSugar(Span),
|
||||
|
||||
/// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
|
||||
RustcPassByValue(Span),
|
||||
|
||||
/// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]`
|
||||
RustcPassIndirectlyInNonRusticAbis(Span),
|
||||
|
||||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
RustcPubTransparent(Span),
|
||||
|
||||
/// Represents `#[rustc_reallocator]`
|
||||
RustcReallocator,
|
||||
|
||||
|
|
@ -1130,6 +1143,18 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`.
|
||||
RustcSimdMonomorphizeLaneLimit(Limit),
|
||||
|
||||
/// Represents `#[rustc_skip_during_method_dispatch]`.
|
||||
RustcSkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
|
||||
|
||||
/// Represents `#[rustc_specialization_trait]`.
|
||||
RustcSpecializationTrait(Span),
|
||||
|
||||
/// Represents `#[rustc_std_internal_symbol]`.
|
||||
RustcStdInternalSymbol(Span),
|
||||
|
||||
/// Represents `#[rustc_unsafe_specialization_marker]`.
|
||||
RustcUnsafeSpecializationMarker(Span),
|
||||
|
||||
/// Represents `#[rustc_variance]`
|
||||
RustcVariance,
|
||||
|
||||
|
|
@ -1151,22 +1176,12 @@ pub enum AttributeKind {
|
|||
/// Represents `#[should_panic]`
|
||||
ShouldPanic { reason: Option<Symbol>, span: Span },
|
||||
|
||||
/// Represents `#[rustc_skip_during_method_dispatch]`.
|
||||
SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
|
||||
|
||||
/// Represents `#[rustc_specialization_trait]`.
|
||||
SpecializationTrait(Span),
|
||||
|
||||
/// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
|
||||
Stability {
|
||||
stability: Stability,
|
||||
/// Span of the attribute.
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_std_internal_symbol]`.
|
||||
StdInternalSymbol(Span),
|
||||
|
||||
/// Represents `#[target_feature(enable = "...")]` and
|
||||
/// `#[unsafe(force_target_feature(enable = "...")]`.
|
||||
TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool },
|
||||
|
|
@ -1183,9 +1198,6 @@ pub enum AttributeKind {
|
|||
/// Represents `#[type_length_limit]`
|
||||
TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit },
|
||||
|
||||
/// Represents `#[rustc_unsafe_specialization_marker]`.
|
||||
UnsafeSpecializationMarker(Span),
|
||||
|
||||
/// Represents `#[unstable_feature_bound]`.
|
||||
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
|
||||
|
||||
|
|
|
|||
|
|
@ -19,37 +19,26 @@ impl AttributeKind {
|
|||
match self {
|
||||
// tidy-alphabetical-start
|
||||
Align { .. } => No,
|
||||
AllowConstFnUnstable(..) => No,
|
||||
AllowIncoherentImpl(..) => No,
|
||||
AllowInternalUnsafe(..) => Yes,
|
||||
AllowInternalUnstable(..) => Yes,
|
||||
AsPtr(..) => Yes,
|
||||
AutomaticallyDerived(..) => Yes,
|
||||
BodyStability { .. } => No,
|
||||
CfgAttrTrace => Yes,
|
||||
CfgTrace(..) => Yes,
|
||||
CfiEncoding { .. } => Yes,
|
||||
Coinductive(..) => No,
|
||||
Cold(..) => No,
|
||||
CollapseDebugInfo(..) => Yes,
|
||||
CompilerBuiltins => No,
|
||||
Confusables { .. } => Yes,
|
||||
ConstContinue(..) => No,
|
||||
ConstStability { .. } => Yes,
|
||||
ConstStabilityIndirect => No,
|
||||
Coroutine(..) => No,
|
||||
Coverage(..) => No,
|
||||
CrateName { .. } => No,
|
||||
CrateType(_) => No,
|
||||
CustomMir(_, _, _) => Yes,
|
||||
DebuggerVisualizer(..) => No,
|
||||
DenyExplicitImpl(..) => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DoNotRecommend { .. } => Yes,
|
||||
Doc(_) => Yes,
|
||||
DocComment { .. } => Yes,
|
||||
Dummy => No,
|
||||
DynIncompatibleTrait(..) => No,
|
||||
EiiDeclaration(_) => Yes,
|
||||
EiiForeignItem => No,
|
||||
EiiImpls(..) => No,
|
||||
|
|
@ -69,7 +58,6 @@ impl AttributeKind {
|
|||
LoopMatch(..) => No,
|
||||
MacroEscape(..) => No,
|
||||
MacroExport { .. } => Yes,
|
||||
MacroTransparency(..) => Yes,
|
||||
MacroUse { .. } => No,
|
||||
Marker(..) => No,
|
||||
MayDangle(..) => No,
|
||||
|
|
@ -87,12 +75,8 @@ impl AttributeKind {
|
|||
NoMangle(..) => Yes, // Needed for rustdoc
|
||||
NoStd(..) => No,
|
||||
NonExhaustive(..) => Yes, // Needed for rustdoc
|
||||
ObjcClass { .. } => No,
|
||||
ObjcSelector { .. } => No,
|
||||
Optimize(..) => No,
|
||||
PanicRuntime => No,
|
||||
ParenSugar(..) => No,
|
||||
PassByValue(..) => Yes,
|
||||
PatchableFunctionEntry { .. } => Yes,
|
||||
Path(..) => No,
|
||||
PatternComplexityLimit { .. } => No,
|
||||
|
|
@ -102,21 +86,32 @@ impl AttributeKind {
|
|||
ProcMacroAttribute(..) => No,
|
||||
ProcMacroDerive { .. } => No,
|
||||
ProfilerRuntime => No,
|
||||
PubTransparent(..) => Yes,
|
||||
RecursionLimit { .. } => No,
|
||||
Repr { .. } => No,
|
||||
RustcAllocator => No,
|
||||
RustcAllocatorZeroed => No,
|
||||
RustcAllocatorZeroedVariant { .. } => Yes,
|
||||
RustcAllowConstFnUnstable(..) => No,
|
||||
RustcAllowIncoherentImpl(..) => No,
|
||||
RustcAsPtr(..) => Yes,
|
||||
RustcBodyStability { .. } => No,
|
||||
RustcBuiltinMacro { .. } => Yes,
|
||||
RustcCoherenceIsCore(..) => No,
|
||||
RustcCoinductive(..) => No,
|
||||
RustcConfusables { .. } => Yes,
|
||||
RustcConstStability { .. } => Yes,
|
||||
RustcConstStabilityIndirect => No,
|
||||
RustcDeallocator => No,
|
||||
RustcDenyExplicitImpl(..) => No,
|
||||
RustcDummy => No,
|
||||
RustcDumpDefParents => No,
|
||||
RustcDumpItemBounds => No,
|
||||
RustcDumpPredicates => No,
|
||||
RustcDumpUserArgs => No,
|
||||
RustcDumpVtable(..) => No,
|
||||
RustcDynIncompatibleTrait(..) => No,
|
||||
RustcHasIncoherentInherentImpls => Yes,
|
||||
RustcLayout(..) => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcLegacyConstGenerics { .. } => Yes,
|
||||
|
|
@ -124,32 +119,39 @@ impl AttributeKind {
|
|||
RustcLintOptTy => Yes,
|
||||
RustcLintQueryInstability => Yes,
|
||||
RustcLintUntrackedQueryInformation => Yes,
|
||||
RustcMacroTransparency(..) => Yes,
|
||||
RustcMain => No,
|
||||
RustcMustImplementOneOf { .. } => No,
|
||||
RustcNeverReturnsNullPointer => Yes,
|
||||
RustcNoImplicitAutorefs => Yes,
|
||||
RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
|
||||
RustcNounwind => No,
|
||||
RustcObjcClass { .. } => No,
|
||||
RustcObjcSelector { .. } => No,
|
||||
RustcObjectLifetimeDefault => No,
|
||||
RustcOffloadKernel => Yes,
|
||||
RustcParenSugar(..) => No,
|
||||
RustcPassByValue(..) => Yes,
|
||||
RustcPassIndirectlyInNonRusticAbis(..) => No,
|
||||
RustcPubTransparent(..) => Yes,
|
||||
RustcReallocator => No,
|
||||
RustcScalableVector { .. } => Yes,
|
||||
RustcShouldNotBeCalledOnConstItems(..) => Yes,
|
||||
RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate
|
||||
RustcSkipDuringMethodDispatch { .. } => No,
|
||||
RustcSpecializationTrait(..) => No,
|
||||
RustcStdInternalSymbol(..) => No,
|
||||
RustcUnsafeSpecializationMarker(..) => No,
|
||||
RustcVariance => No,
|
||||
RustcVarianceOfOpaques => No,
|
||||
Sanitize { .. } => No,
|
||||
ShouldPanic { .. } => No,
|
||||
SkipDuringMethodDispatch { .. } => No,
|
||||
SpecializationTrait(..) => No,
|
||||
Stability { .. } => Yes,
|
||||
StdInternalSymbol(..) => No,
|
||||
TargetFeature { .. } => No,
|
||||
ThreadLocal => No,
|
||||
TrackCaller(..) => Yes,
|
||||
TypeConst(..) => Yes,
|
||||
TypeLengthLimit { .. } => No,
|
||||
UnsafeSpecializationMarker(..) => No,
|
||||
UnstableFeatureBound(..) => No,
|
||||
Used { .. } => No,
|
||||
WindowsSubsystem(..) => No,
|
||||
|
|
|
|||
|
|
@ -1701,7 +1701,10 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
|||
ty::Array(ty, _) => check_unsuited(tcx, typing_env, *ty),
|
||||
ty::Adt(def, args) => {
|
||||
if !def.did().is_local()
|
||||
&& !find_attr!(tcx.get_all_attrs(def.did()), AttributeKind::PubTransparent(_))
|
||||
&& !find_attr!(
|
||||
tcx.get_all_attrs(def.did()),
|
||||
AttributeKind::RustcPubTransparent(_)
|
||||
)
|
||||
{
|
||||
let non_exhaustive = def.is_variant_list_non_exhaustive()
|
||||
|| def.variants().iter().any(ty::VariantDef::is_field_list_non_exhaustive);
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate),
|
||||
);
|
||||
|
||||
let is_conditionally_const = tcx.is_conditionally_const(impl_def_id);
|
||||
let is_conditionally_const = tcx.is_conditionally_const(impl_m.def_id);
|
||||
if is_conditionally_const {
|
||||
// Augment the hybrid param-env with the const conditions
|
||||
// of the impl header and the trait method.
|
||||
|
|
@ -592,7 +592,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
ty,
|
||||
Ty::new_placeholder(
|
||||
tcx,
|
||||
ty::Placeholder::new(
|
||||
ty::PlaceholderType::new(
|
||||
universe,
|
||||
ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon },
|
||||
),
|
||||
|
|
@ -2551,7 +2551,7 @@ fn param_env_with_gat_bounds<'tcx>(
|
|||
}
|
||||
};
|
||||
|
||||
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
|
||||
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind<'tcx>; 8]> =
|
||||
smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).own_params.len());
|
||||
// Extend the impl's identity args with late-bound GAT vars
|
||||
let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id)
|
||||
|
|
@ -2587,7 +2587,7 @@ fn param_env_with_gat_bounds<'tcx>(
|
|||
ty::Const::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundConst { var: ty::BoundVar::from_usize(bound_vars.len() - 1) },
|
||||
ty::BoundConst::new(ty::BoundVar::from_usize(bound_vars.len() - 1)),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ impl<'tcx> InherentCollect<'tcx> {
|
|||
for &impl_item in items {
|
||||
if !find_attr!(
|
||||
self.tcx.get_all_attrs(impl_item),
|
||||
AttributeKind::AllowIncoherentImpl(_)
|
||||
AttributeKind::RustcAllowIncoherentImpl(_)
|
||||
) {
|
||||
let impl_span = self.tcx.def_span(impl_def_id);
|
||||
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant {
|
||||
|
|
@ -125,7 +125,7 @@ impl<'tcx> InherentCollect<'tcx> {
|
|||
for &impl_item in items {
|
||||
if !find_attr!(
|
||||
self.tcx.get_all_attrs(impl_item),
|
||||
AttributeKind::AllowIncoherentImpl(_)
|
||||
AttributeKind::RustcAllowIncoherentImpl(_)
|
||||
) {
|
||||
let span = self.tcx.def_span(impl_def_id);
|
||||
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive {
|
||||
|
|
|
|||
|
|
@ -889,7 +889,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
|||
|
||||
let attrs = tcx.get_all_attrs(def_id);
|
||||
|
||||
let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_));
|
||||
let paren_sugar = find_attr!(attrs, AttributeKind::RustcParenSugar(_));
|
||||
if paren_sugar && !tcx.features().unboxed_closures() {
|
||||
tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
|
||||
}
|
||||
|
|
@ -897,22 +897,23 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
|||
// Only regular traits can be marker.
|
||||
let is_marker = !is_alias && find_attr!(attrs, AttributeKind::Marker(_));
|
||||
|
||||
let rustc_coinductive = find_attr!(attrs, AttributeKind::Coinductive(_));
|
||||
let rustc_coinductive = find_attr!(attrs, AttributeKind::RustcCoinductive(_));
|
||||
let is_fundamental = find_attr!(attrs, AttributeKind::Fundamental);
|
||||
|
||||
let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
|
||||
attrs,
|
||||
AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
|
||||
AttributeKind::RustcSkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
|
||||
)
|
||||
.unwrap_or([false; 2]);
|
||||
|
||||
let specialization_kind = if find_attr!(attrs, AttributeKind::UnsafeSpecializationMarker(_)) {
|
||||
ty::trait_def::TraitSpecializationKind::Marker
|
||||
} else if find_attr!(attrs, AttributeKind::SpecializationTrait(_)) {
|
||||
ty::trait_def::TraitSpecializationKind::AlwaysApplicable
|
||||
} else {
|
||||
ty::trait_def::TraitSpecializationKind::None
|
||||
};
|
||||
let specialization_kind =
|
||||
if find_attr!(attrs, AttributeKind::RustcUnsafeSpecializationMarker(_)) {
|
||||
ty::trait_def::TraitSpecializationKind::Marker
|
||||
} else if find_attr!(attrs, AttributeKind::RustcSpecializationTrait(_)) {
|
||||
ty::trait_def::TraitSpecializationKind::AlwaysApplicable
|
||||
} else {
|
||||
ty::trait_def::TraitSpecializationKind::None
|
||||
};
|
||||
|
||||
let must_implement_one_of = find_attr!(
|
||||
attrs,
|
||||
|
|
@ -923,9 +924,9 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
|||
.collect::<Box<[_]>>()
|
||||
);
|
||||
|
||||
let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_));
|
||||
let deny_explicit_impl = find_attr!(attrs, AttributeKind::RustcDenyExplicitImpl(_));
|
||||
let force_dyn_incompatible =
|
||||
find_attr!(attrs, AttributeKind::DynIncompatibleTrait(span) => *span);
|
||||
find_attr!(attrs, AttributeKind::RustcDynIncompatibleTrait(span) => *span);
|
||||
|
||||
ty::TraitDef {
|
||||
def_id: def_id.to_def_id(),
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ struct MapAndCompressBoundVars<'tcx> {
|
|||
binder: ty::DebruijnIndex,
|
||||
/// List of bound vars that remain unsubstituted because they were not
|
||||
/// mentioned in the GAT's args.
|
||||
still_bound_vars: Vec<ty::BoundVariableKind>,
|
||||
still_bound_vars: Vec<ty::BoundVariableKind<'tcx>>,
|
||||
/// Subtle invariant: If the `GenericArg` is bound, then it should be
|
||||
/// stored with the debruijn index of `INNERMOST` so it can be shifted
|
||||
/// correctly during substitution.
|
||||
|
|
@ -330,7 +330,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MapAndCompressBoundVars<'tcx> {
|
|||
} else {
|
||||
let var = ty::BoundVar::from_usize(self.still_bound_vars.len());
|
||||
self.still_bound_vars.push(ty::BoundVariableKind::Const);
|
||||
let mapped = ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst { var });
|
||||
let mapped =
|
||||
ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst::new(var));
|
||||
self.mapping.insert(old_bound.var, mapped.into());
|
||||
mapped
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,9 +63,9 @@ impl ResolvedArg {
|
|||
|
||||
struct BoundVarContext<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
rbv: &'a mut ResolveBoundVars,
|
||||
rbv: &'a mut ResolveBoundVars<'tcx>,
|
||||
disambiguator: &'a mut DisambiguatorState,
|
||||
scope: ScopeRef<'a>,
|
||||
scope: ScopeRef<'a, 'tcx>,
|
||||
opaque_capture_errors: RefCell<Option<OpaqueHigherRankedLifetimeCaptureErrors>>,
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ struct OpaqueHigherRankedLifetimeCaptureErrors {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Scope<'a> {
|
||||
enum Scope<'a, 'tcx> {
|
||||
/// Declares lifetimes, and each can be early-bound or late-bound.
|
||||
/// The `DebruijnIndex` of late-bound lifetimes starts at `1` and
|
||||
/// it should be shifted by the number of `Binder`s in between the
|
||||
|
|
@ -94,7 +94,7 @@ enum Scope<'a> {
|
|||
/// to append to.
|
||||
hir_id: HirId,
|
||||
|
||||
s: ScopeRef<'a>,
|
||||
s: ScopeRef<'a, 'tcx>,
|
||||
|
||||
/// If this binder comes from a where clause, specify how it was created.
|
||||
/// This is used to diagnose inaccessible lifetimes in APIT:
|
||||
|
|
@ -110,7 +110,7 @@ enum Scope<'a> {
|
|||
/// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`.
|
||||
Body {
|
||||
id: hir::BodyId,
|
||||
s: ScopeRef<'a>,
|
||||
s: ScopeRef<'a, 'tcx>,
|
||||
},
|
||||
|
||||
/// Use a specific lifetime (if `Some`) or leave it unset (to be
|
||||
|
|
@ -118,7 +118,7 @@ enum Scope<'a> {
|
|||
/// for the default choice of lifetime in a trait object type.
|
||||
ObjectLifetimeDefault {
|
||||
lifetime: Option<ResolvedArg>,
|
||||
s: ScopeRef<'a>,
|
||||
s: ScopeRef<'a, 'tcx>,
|
||||
},
|
||||
|
||||
/// When we have nested trait refs, we concatenate late bound vars for inner
|
||||
|
|
@ -126,12 +126,12 @@ enum Scope<'a> {
|
|||
/// lifetimes encountered when identifying the trait that an associated type
|
||||
/// is declared on.
|
||||
Supertrait {
|
||||
bound_vars: Vec<ty::BoundVariableKind>,
|
||||
s: ScopeRef<'a>,
|
||||
bound_vars: Vec<ty::BoundVariableKind<'tcx>>,
|
||||
s: ScopeRef<'a, 'tcx>,
|
||||
},
|
||||
|
||||
TraitRefBoundary {
|
||||
s: ScopeRef<'a>,
|
||||
s: ScopeRef<'a, 'tcx>,
|
||||
},
|
||||
|
||||
/// Remap lifetimes that appear in opaque types to fresh lifetime parameters. Given:
|
||||
|
|
@ -148,7 +148,7 @@ enum Scope<'a> {
|
|||
/// Mapping from each captured lifetime `'a` to the duplicate generic parameter `'b`.
|
||||
captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
|
||||
|
||||
s: ScopeRef<'a>,
|
||||
s: ScopeRef<'a, 'tcx>,
|
||||
},
|
||||
|
||||
/// Disallows capturing late-bound vars from parent scopes.
|
||||
|
|
@ -157,7 +157,7 @@ enum Scope<'a> {
|
|||
/// since we don't do something more correct like replacing any captured
|
||||
/// late-bound vars with early-bound params in the const's own generics.
|
||||
LateBoundary {
|
||||
s: ScopeRef<'a>,
|
||||
s: ScopeRef<'a, 'tcx>,
|
||||
what: &'static str,
|
||||
deny_late_regions: bool,
|
||||
},
|
||||
|
|
@ -167,7 +167,7 @@ enum Scope<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
impl<'a> Scope<'a> {
|
||||
impl<'a, 'tcx> Scope<'a, 'tcx> {
|
||||
// A helper for debugging scopes without printing parent scopes
|
||||
fn debug_truncated(&self) -> impl fmt::Debug {
|
||||
fmt::from_fn(move |f| match self {
|
||||
|
|
@ -227,7 +227,7 @@ enum BinderScopeType {
|
|||
Concatenating,
|
||||
}
|
||||
|
||||
type ScopeRef<'a> = &'a Scope<'a>;
|
||||
type ScopeRef<'a, 'tcx> = &'a Scope<'a, 'tcx>;
|
||||
|
||||
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
|
|
@ -253,7 +253,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
/// You should not read the result of this query directly, but rather use
|
||||
/// `named_variable_map`, `late_bound_vars_map`, etc.
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
|
||||
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars<'_> {
|
||||
let mut rbv = ResolveBoundVars::default();
|
||||
let mut visitor = BoundVarContext {
|
||||
tcx,
|
||||
|
|
@ -287,7 +287,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
|
|||
rbv
|
||||
}
|
||||
|
||||
fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind {
|
||||
fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind<'tcx> {
|
||||
let def_id = param.def_id.to_def_id();
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
|
|
@ -301,7 +301,9 @@ fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableK
|
|||
/// Turn a [`ty::GenericParamDef`] into a bound arg. Generally, this should only
|
||||
/// be used when turning early-bound vars into late-bound vars when lowering
|
||||
/// return type notation.
|
||||
fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind {
|
||||
fn generic_param_def_as_bound_arg<'tcx>(
|
||||
param: &ty::GenericParamDef,
|
||||
) -> ty::BoundVariableKind<'tcx> {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id))
|
||||
|
|
@ -329,7 +331,9 @@ fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx
|
|||
|
||||
impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
/// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
|
||||
fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
|
||||
fn poly_trait_ref_binder_info(
|
||||
&mut self,
|
||||
) -> (Vec<ty::BoundVariableKind<'tcx>>, BinderScopeType) {
|
||||
let mut scope = self.scope;
|
||||
let mut supertrait_bound_vars = vec![];
|
||||
loop {
|
||||
|
|
@ -364,7 +368,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
|
||||
Scope::Binder { hir_id, .. } => {
|
||||
// Nested poly trait refs have the binders concatenated
|
||||
let mut full_binders =
|
||||
let mut full_binders: Vec<ty::BoundVariableKind<'tcx>> =
|
||||
self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
|
||||
full_binders.extend(supertrait_bound_vars);
|
||||
break (full_binders, BinderScopeType::Concatenating);
|
||||
|
|
@ -1094,7 +1098,7 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
|
||||
fn with<F>(&mut self, wrap_scope: Scope<'_, 'tcx>, f: F)
|
||||
where
|
||||
F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
|
||||
{
|
||||
|
|
@ -1115,7 +1119,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
*self.opaque_capture_errors.borrow_mut() = this.opaque_capture_errors.into_inner();
|
||||
}
|
||||
|
||||
fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
|
||||
fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind<'tcx>>) {
|
||||
if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
|
||||
bug!(
|
||||
"overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
|
||||
|
|
@ -1931,7 +1935,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
def_id: DefId,
|
||||
assoc_ident: Ident,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
|
||||
) -> Option<(Vec<ty::BoundVariableKind<'tcx>>, &'tcx ty::AssocItem)> {
|
||||
let trait_defines_associated_item_named = |trait_def_id: DefId| {
|
||||
tcx.associated_items(trait_def_id).find_by_ident_and_kind(
|
||||
tcx,
|
||||
|
|
@ -1942,7 +1946,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
};
|
||||
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
|
||||
let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind<'tcx>; 8]>); 8]> =
|
||||
smallvec![(def_id, smallvec![])];
|
||||
let mut visited: FxHashSet<DefId> = FxHashSet::default();
|
||||
loop {
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
param_ty: Ty<'tcx>,
|
||||
hir_bounds: I,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
|
||||
predicate_filter: PredicateFilter,
|
||||
overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
|
||||
) where
|
||||
|
|
@ -1000,7 +1000,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 't
|
|||
.delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
|
||||
return ControlFlow::Break(guar);
|
||||
}
|
||||
ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
|
||||
ty::BoundRegionKind::NamedForPrinting(_) => {
|
||||
bug!("only used for pretty printing")
|
||||
}
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -2310,7 +2310,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => ty::Const::new_bound(
|
||||
tcx,
|
||||
debruijn,
|
||||
ty::BoundConst { var: ty::BoundVar::from_u32(index) },
|
||||
ty::BoundConst::new(ty::BoundVar::from_u32(index)),
|
||||
),
|
||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id),
|
||||
|
|
@ -3196,8 +3196,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
#[instrument(level = "trace", skip(self, generate_err))]
|
||||
fn validate_late_bound_regions<'cx>(
|
||||
&'cx self,
|
||||
constrained_regions: FxIndexSet<ty::BoundRegionKind>,
|
||||
referenced_regions: FxIndexSet<ty::BoundRegionKind>,
|
||||
constrained_regions: FxIndexSet<ty::BoundRegionKind<'tcx>>,
|
||||
referenced_regions: FxIndexSet<ty::BoundRegionKind<'tcx>>,
|
||||
generate_err: impl Fn(&str) -> Diag<'cx>,
|
||||
) {
|
||||
for br in referenced_regions.difference(&constrained_regions) {
|
||||
|
|
|
|||
|
|
@ -1365,6 +1365,7 @@ pub fn can_coerce<'tcx>(
|
|||
/// - WARNING: I don't believe this final type is guaranteed to be
|
||||
/// related to your initial `expected_ty` in any particular way,
|
||||
/// although it will typically be a subtype, so you should check it.
|
||||
/// Check the note below for more details.
|
||||
/// - Invoking `complete()` may cause us to go and adjust the "adjustments" on
|
||||
/// previously coerced expressions.
|
||||
///
|
||||
|
|
@ -1378,6 +1379,28 @@ pub fn can_coerce<'tcx>(
|
|||
/// }
|
||||
/// let final_ty = coerce.complete(fcx);
|
||||
/// ```
|
||||
///
|
||||
/// NOTE: Why does the `expected_ty` participate in the LUB?
|
||||
/// When coercing, each branch should use the following expectations for type inference:
|
||||
/// - The branch can be coerced to the expected type of the match/if/whatever.
|
||||
/// - The branch can be coercion lub'd with the types of the previous branches.
|
||||
/// Ideally we'd have some sort of `Expectation::ParticipatesInCoerceLub(ongoing_lub_ty, final_ty)`,
|
||||
/// but adding and using this feels very challenging.
|
||||
/// What we instead do is to use the expected type of the match/if/whatever as
|
||||
/// the initial coercion lub. This allows us to use the lub of "expected type of match" with
|
||||
/// "types from previous branches" as the coercion target, which can contains both expectations.
|
||||
///
|
||||
/// Two concerns with this approach:
|
||||
/// - We may have incompatible `final_ty` if that lub is different from the expected
|
||||
/// type of the match. However, in this case coercing the final type of the
|
||||
/// `CoerceMany` to its expected type would have error'd anyways, so we don't care.
|
||||
/// - We may constrain the `expected_ty` too early. For some branches with
|
||||
/// type `a` and `b`, we end up with `(a lub expected_ty) lub b` instead of
|
||||
/// `(a lub b) lub expected_ty`. They should be the same type. However,
|
||||
/// `a lub expected_ty` may constrain inference variables in `expected_ty`.
|
||||
/// In this case the difference does matter and we get actually incorrect results.
|
||||
/// FIXME: Ideally we'd compute the final type without unnecessarily constraining
|
||||
/// the expected type of the match when computing the types of its branches.
|
||||
pub(crate) struct CoerceMany<'tcx> {
|
||||
expected_ty: Ty<'tcx>,
|
||||
final_ty: Option<Ty<'tcx>>,
|
||||
|
|
|
|||
|
|
@ -605,6 +605,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
parent_id = self.tcx.parent_hir_id(*hir_id);
|
||||
parent
|
||||
}
|
||||
hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Let(_), .. }) => {
|
||||
parent_id = self.tcx.parent_hir_id(*hir_id);
|
||||
parent
|
||||
}
|
||||
hir::Node::LetStmt(hir::LetStmt { hir_id, .. }) => {
|
||||
parent_id = self.tcx.parent_hir_id(*hir_id);
|
||||
parent
|
||||
}
|
||||
hir::Node::Block(_) => {
|
||||
parent_id = self.tcx.parent_hir_id(parent_id);
|
||||
parent
|
||||
|
|
|
|||
|
|
@ -1670,11 +1670,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let coerce_to = expected
|
||||
.to_option(self)
|
||||
.and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index())
|
||||
.and_then(|uty| {
|
||||
self.try_structurally_resolve_type(expr.span, uty)
|
||||
.builtin_index()
|
||||
// Avoid using the original type variable as the coerce_to type, as it may resolve
|
||||
// during the first coercion instead of being the LUB type.
|
||||
.filter(|t| !self.try_structurally_resolve_type(expr.span, *t).is_ty_var())
|
||||
})
|
||||
.unwrap_or_else(|| self.next_ty_var(expr.span));
|
||||
let mut coerce = CoerceMany::with_capacity(coerce_to, args.len());
|
||||
|
||||
for e in args {
|
||||
// FIXME: the element expectation should use
|
||||
// `try_structurally_resolve_and_adjust_for_branches` just like in `if` and `match`.
|
||||
// While that fixes nested coercion, it will break [some
|
||||
// code like this](https://github.com/rust-lang/rust/pull/140283#issuecomment-2958776528).
|
||||
// If we find a way to support recursive tuple coercion, this break can be avoided.
|
||||
let e_ty = self.check_expr_with_hint(e, coerce_to);
|
||||
let cause = self.misc(e.span);
|
||||
coerce.coerce(self, &cause, e, e_ty);
|
||||
|
|
|
|||
|
|
@ -2242,7 +2242,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
for inherent_method in
|
||||
self.tcx.associated_items(inherent_impl_did).in_definition_order()
|
||||
{
|
||||
if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::Confusables{symbols, ..} => symbols)
|
||||
if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::RustcConfusables{symbols, ..} => symbols)
|
||||
&& candidates.contains(&item_name.name)
|
||||
&& inherent_method.is_fn()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -684,19 +684,19 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
|||
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
|
||||
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderTy(ty::Placeholder::new(
|
||||
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType::new(
|
||||
reverse_universe_map[&placeholder.universe],
|
||||
placeholder.bound,
|
||||
))
|
||||
}
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderRegion(ty::Placeholder::new(
|
||||
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new(
|
||||
reverse_universe_map[&placeholder.universe],
|
||||
placeholder.bound,
|
||||
))
|
||||
}
|
||||
CanonicalVarKind::PlaceholderConst(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderConst(ty::Placeholder::new(
|
||||
CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst::new(
|
||||
reverse_universe_map[&placeholder.universe],
|
||||
placeholder.bound,
|
||||
))
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ pub enum RegionVariableOrigin<'tcx> {
|
|||
|
||||
/// Region variables created when instantiating a binder with
|
||||
/// existential variables, e.g. when calling a function or method.
|
||||
BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime),
|
||||
BoundRegion(Span, ty::BoundRegionKind<'tcx>, BoundRegionConversionTime),
|
||||
|
||||
UpvarRegion(ty::UpvarId, Span),
|
||||
|
||||
|
|
@ -1300,13 +1300,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> {
|
||||
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
|
||||
fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> {
|
||||
self.args[br.var.index()].expect_region()
|
||||
}
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> {
|
||||
self.args[bt.var.index()].expect_ty()
|
||||
}
|
||||
fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> {
|
||||
fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> {
|
||||
self.args[bc.var.index()].expect_const()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ pub(super) fn can_match_erased_ty<'tcx>(
|
|||
struct MatchAgainstHigherRankedOutlives<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
pattern_depth: ty::DebruijnIndex,
|
||||
map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
|
||||
map: FxHashMap<ty::BoundRegion<'tcx>, ty::Region<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
|
||||
|
|
@ -115,7 +115,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
|
|||
#[instrument(level = "trace", skip(self))]
|
||||
fn bind(
|
||||
&mut self,
|
||||
br: ty::BoundRegion,
|
||||
br: ty::BoundRegion<'tcx>,
|
||||
value: ty::Region<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::Region<'tcx>> {
|
||||
match self.map.entry(br) {
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let next_universe = self.create_next_universe();
|
||||
|
||||
let delegate = FnMutDelegate {
|
||||
regions: &mut |br: ty::BoundRegion| {
|
||||
regions: &mut |br: ty::BoundRegion<'tcx>| {
|
||||
ty::Region::new_placeholder(self.tcx, ty::PlaceholderRegion::new(next_universe, br))
|
||||
},
|
||||
types: &mut |bound_ty: ty::BoundTy| {
|
||||
types: &mut |bound_ty: ty::BoundTy<'tcx>| {
|
||||
Ty::new_placeholder(self.tcx, ty::PlaceholderType::new(next_universe, bound_ty))
|
||||
},
|
||||
consts: &mut |bound_const: ty::BoundConst| {
|
||||
consts: &mut |bound_const: ty::BoundConst<'tcx>| {
|
||||
ty::Const::new_placeholder(
|
||||
self.tcx,
|
||||
ty::PlaceholderConst::new(next_universe, bound_const),
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
&& let ty = cx.typeck_results().expr_ty(receiver)
|
||||
&& owns_allocation(cx.tcx, ty)
|
||||
&& let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
&& find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::AsPtr(_))
|
||||
&& find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::RustcAsPtr(_))
|
||||
{
|
||||
// FIXME: use `emit_node_lint` when `#[primary_span]` is added.
|
||||
cx.tcx.emit_node_span_lint(
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ where
|
|||
// When we get into a binder, we need to add its own bound vars to the scope.
|
||||
let mut added = vec![];
|
||||
for arg in t.bound_vars() {
|
||||
let arg: ty::BoundVariableKind = arg;
|
||||
let arg: ty::BoundVariableKind<'tcx> = arg;
|
||||
match arg {
|
||||
ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id))
|
||||
| ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
|
|||
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
|
||||
match path.res {
|
||||
Res::Def(_, def_id)
|
||||
if find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::PassByValue(_)) =>
|
||||
if find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::RustcPassByValue(_)) =>
|
||||
{
|
||||
let name = cx.tcx.item_ident(def_id);
|
||||
let path_segment = path.segments.last().unwrap();
|
||||
|
|
@ -52,7 +52,10 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
|
|||
}
|
||||
Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
|
||||
if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() {
|
||||
if find_attr!(cx.tcx.get_all_attrs(adt.did()), AttributeKind::PassByValue(_)) {
|
||||
if find_attr!(
|
||||
cx.tcx.get_all_attrs(adt.did()),
|
||||
AttributeKind::RustcPassByValue(_)
|
||||
) {
|
||||
return Some(cx.tcx.def_path_str_with_args(adt.did(), args));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -539,10 +539,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
);
|
||||
}
|
||||
MustUsePath::Def(span, def_id, reason) => {
|
||||
let span = span.find_ancestor_not_from_macro().unwrap_or(*span);
|
||||
let ancenstor_span = span.find_ancestor_not_from_macro().unwrap_or(*span);
|
||||
let is_redundant_let_ignore = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.span_to_prev_source(ancenstor_span)
|
||||
.ok()
|
||||
.map(|prev| prev.trim_end().ends_with("let _ ="))
|
||||
.unwrap_or(false);
|
||||
let suggestion_span =
|
||||
if is_redundant_let_ignore { *span } else { ancenstor_span };
|
||||
cx.emit_span_lint(
|
||||
UNUSED_MUST_USE,
|
||||
span,
|
||||
ancenstor_span,
|
||||
UnusedDef {
|
||||
pre: descr_pre,
|
||||
post: descr_post,
|
||||
|
|
@ -551,11 +560,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
note: *reason,
|
||||
suggestion: (!is_inner).then_some(if expr_is_from_block {
|
||||
UnusedDefSuggestion::BlockTailExpr {
|
||||
before_span: span.shrink_to_lo(),
|
||||
after_span: span.shrink_to_hi(),
|
||||
before_span: suggestion_span.shrink_to_lo(),
|
||||
after_span: suggestion_span.shrink_to_hi(),
|
||||
}
|
||||
} else {
|
||||
UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() }
|
||||
UnusedDefSuggestion::NormalExpr {
|
||||
span: suggestion_span.shrink_to_lo(),
|
||||
}
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
|
@ -794,7 +805,10 @@ trait UnusedDelimLint {
|
|||
|
||||
ExprKind::Break(_label, None) => return false,
|
||||
ExprKind::Break(_label, Some(break_expr)) => {
|
||||
return matches!(break_expr.kind, ExprKind::Block(..));
|
||||
// `if (break 'label i) { ... }` removing parens would make `i { ... }`
|
||||
// be parsed as a struct literal, so keep parentheses if the break value
|
||||
// ends with a path (which could be mistaken for a struct name).
|
||||
return matches!(break_expr.kind, ExprKind::Block(..) | ExprKind::Path(..));
|
||||
}
|
||||
|
||||
ExprKind::Range(_lhs, Some(rhs), _limits) => {
|
||||
|
|
|
|||
|
|
@ -280,31 +280,21 @@ fn add_query_desc_cached_impl(
|
|||
let crate::query::Providers { #name: _, .. };
|
||||
};
|
||||
|
||||
// Find out if we should cache the query on disk
|
||||
let cache = if let Some((args, expr)) = modifiers.cache.as_ref() {
|
||||
// Generate a function to check whether we should cache the query to disk, for some key.
|
||||
if let Some((args, expr)) = modifiers.cache.as_ref() {
|
||||
let tcx = args.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ });
|
||||
// expr is a `Block`, meaning that `{ #expr }` gets expanded
|
||||
// to `{ { stmts... } }`, which triggers the `unused_braces` lint.
|
||||
// we're taking `key` by reference, but some rustc types usually prefer being passed by value
|
||||
quote! {
|
||||
cached.extend(quote! {
|
||||
#[allow(unused_variables, unused_braces, rustc::pass_by_value)]
|
||||
#[inline]
|
||||
pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool {
|
||||
#ra_hint
|
||||
#expr
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
// we're taking `key` by reference, but some rustc types usually prefer being passed by value
|
||||
#[allow(rustc::pass_by_value)]
|
||||
#[inline]
|
||||
pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::queries::#name::Key<'tcx>) -> bool {
|
||||
#ra_hint
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
let (tcx, desc) = &modifiers.desc;
|
||||
let tcx = tcx.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t });
|
||||
|
|
@ -322,10 +312,6 @@ fn add_query_desc_cached_impl(
|
|||
descs.extend(quote! {
|
||||
#desc
|
||||
});
|
||||
|
||||
cached.extend(quote! {
|
||||
#cache
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
|
|
|
|||
|
|
@ -365,6 +365,33 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn hir_owner_parent_impl(self, owner_id: OwnerId) -> HirId {
|
||||
self.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| {
|
||||
let parent_owner_id = self.local_def_id_to_hir_id(parent_def_id).owner;
|
||||
HirId {
|
||||
owner: parent_owner_id,
|
||||
local_id: self.hir_crate(()).owners[parent_owner_id.def_id]
|
||||
.unwrap()
|
||||
.parenting
|
||||
.get(&owner_id.def_id)
|
||||
.copied()
|
||||
.unwrap_or(ItemLocalId::ZERO),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Optimization of `hir_owner_parent` query as an inlined function
|
||||
/// in case of non-incremental build. The query itself renamed to `hir_owner_parent_q`.
|
||||
#[inline]
|
||||
pub fn hir_owner_parent(self, owner_id: OwnerId) -> HirId {
|
||||
if self.dep_graph.is_fully_enabled() {
|
||||
self.hir_owner_parent_q(owner_id)
|
||||
} else {
|
||||
self.hir_owner_parent_impl(owner_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Hashes computed by [`TyCtxt::hash_owner_nodes`] if necessary.
|
||||
|
|
@ -386,20 +413,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
};
|
||||
providers.opt_hir_owner_nodes =
|
||||
|tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes);
|
||||
providers.hir_owner_parent = |tcx, owner_id| {
|
||||
tcx.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| {
|
||||
let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner;
|
||||
HirId {
|
||||
owner: parent_owner_id,
|
||||
local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id]
|
||||
.unwrap()
|
||||
.parenting
|
||||
.get(&owner_id.def_id)
|
||||
.copied()
|
||||
.unwrap_or(ItemLocalId::ZERO),
|
||||
}
|
||||
})
|
||||
};
|
||||
providers.hir_owner_parent_q = |tcx, owner_id| tcx.hir_owner_parent_impl(owner_id);
|
||||
providers.hir_attr_map = |tcx, id| {
|
||||
tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ pub enum ObjectLifetimeDefault {
|
|||
/// Maps the id of each bound variable reference to the variable decl
|
||||
/// that it corresponds to.
|
||||
#[derive(Debug, Default, HashStable)]
|
||||
pub struct ResolveBoundVars {
|
||||
pub struct ResolveBoundVars<'tcx> {
|
||||
// Maps from every use of a named (not anonymous) bound var to a
|
||||
// `ResolvedArg` describing how that variable is bound.
|
||||
pub defs: SortedMap<ItemLocalId, ResolvedArg>,
|
||||
|
|
@ -59,7 +59,7 @@ pub struct ResolveBoundVars {
|
|||
// - closures
|
||||
// - trait refs
|
||||
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
|
||||
pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
|
||||
pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind<'tcx>>>,
|
||||
|
||||
// List captured variables for each opaque type.
|
||||
pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
//! To improve compile times and code size for the compiler itself, query
|
||||
//! values are "erased" in some contexts (e.g. inside in-memory cache types),
|
||||
//! to reduce the number of generic instantiations created during codegen.
|
||||
//!
|
||||
//! See <https://github.com/rust-lang/rust/pull/151715> for some bootstrap-time
|
||||
//! and performance benchmarks.
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::intrinsics::transmute_unchecked;
|
||||
use std::mem::MaybeUninit;
|
||||
|
|
@ -14,138 +21,169 @@ use crate::ty::adjustment::CoerceUnsizedInfo;
|
|||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::{mir, traits};
|
||||
|
||||
/// Internal implementation detail of [`Erased`].
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Erased<T: Copy> {
|
||||
// We use `MaybeUninit` here so we can store any value
|
||||
// in `data` since we aren't actually storing a `T`.
|
||||
data: MaybeUninit<T>,
|
||||
pub struct ErasedData<Storage: Copy> {
|
||||
/// We use `MaybeUninit` here to make sure it's legal to store a transmuted
|
||||
/// value that isn't actually of type `Storage`.
|
||||
data: MaybeUninit<Storage>,
|
||||
}
|
||||
|
||||
pub trait EraseType: Copy {
|
||||
type Result: Copy;
|
||||
/// Trait for types that can be erased into [`Erased<Self>`].
|
||||
///
|
||||
/// Erasing and unerasing values is performed by [`erase_val`] and [`restore_val`].
|
||||
///
|
||||
/// FIXME: This whole trait could potentially be replaced by `T: Copy` and the
|
||||
/// storage type `[u8; size_of::<T>()]` when support for that is more mature.
|
||||
pub trait Erasable: Copy {
|
||||
/// Storage type to used for erased values of this type.
|
||||
/// Should be `[u8; N]`, where N is equal to `size_of::<Self>`.
|
||||
///
|
||||
/// [`ErasedData`] wraps this storage type in `MaybeUninit` to ensure that
|
||||
/// transmutes to/from erased storage are well-defined.
|
||||
type Storage: Copy;
|
||||
}
|
||||
|
||||
// Allow `type_alias_bounds` since compilation will fail without `EraseType`.
|
||||
#[allow(type_alias_bounds)]
|
||||
pub type Erase<T: EraseType> = Erased<impl Copy>;
|
||||
/// A value of `T` that has been "erased" into some opaque storage type.
|
||||
///
|
||||
/// This is helpful for reducing the number of concrete instantiations needed
|
||||
/// during codegen when building the compiler.
|
||||
///
|
||||
/// Using an opaque type alias allows the type checker to enforce that
|
||||
/// `Erased<T>` and `Erased<U>` are still distinct types, while allowing
|
||||
/// monomorphization to see that they might actually use the same storage type.
|
||||
pub type Erased<T: Erasable> = ErasedData<impl Copy>;
|
||||
|
||||
/// Erases a value of type `T` into `Erased<T>`.
|
||||
///
|
||||
/// `Erased<T>` and `Erased<U>` are type-checked as distinct types, but codegen
|
||||
/// can see whether they actually have the same storage type.
|
||||
///
|
||||
/// FIXME: This might have soundness issues with erasable types that don't
|
||||
/// implement the same auto-traits as `[u8; _]`; see
|
||||
/// <https://github.com/rust-lang/rust/pull/151715#discussion_r2740113250>
|
||||
#[inline(always)]
|
||||
#[define_opaque(Erase)]
|
||||
pub fn erase<T: EraseType>(src: T) -> Erase<T> {
|
||||
#[define_opaque(Erased)]
|
||||
pub fn erase_val<T: Erasable>(value: T) -> Erased<T> {
|
||||
// Ensure the sizes match
|
||||
const {
|
||||
if size_of::<T>() != size_of::<T::Result>() {
|
||||
panic!("size of T must match erased type T::Result")
|
||||
if size_of::<T>() != size_of::<T::Storage>() {
|
||||
panic!("size of T must match erased type <T as Erasable>::Storage")
|
||||
}
|
||||
};
|
||||
|
||||
Erased::<<T as EraseType>::Result> {
|
||||
ErasedData::<<T as Erasable>::Storage> {
|
||||
// `transmute_unchecked` is needed here because it does not have `transmute`'s size check
|
||||
// (and thus allows to transmute between `T` and `MaybeUninit<T::Result>`) (we do the size
|
||||
// (and thus allows to transmute between `T` and `MaybeUninit<T::Storage>`) (we do the size
|
||||
// check ourselves in the `const` block above).
|
||||
//
|
||||
// `transmute_copy` is also commonly used for this (and it would work here since
|
||||
// `EraseType: Copy`), but `transmute_unchecked` better explains the intent.
|
||||
// `Erasable: Copy`), but `transmute_unchecked` better explains the intent.
|
||||
//
|
||||
// SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
|
||||
data: unsafe { transmute_unchecked::<T, MaybeUninit<T::Result>>(src) },
|
||||
data: unsafe { transmute_unchecked::<T, MaybeUninit<T::Storage>>(value) },
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores an erased value.
|
||||
/// Restores an erased value to its real type.
|
||||
///
|
||||
/// This relies on the fact that `Erased<T>` and `Erased<U>` are type-checked
|
||||
/// as distinct types, even if they use the same storage type.
|
||||
#[inline(always)]
|
||||
#[define_opaque(Erase)]
|
||||
pub fn restore<T: EraseType>(value: Erase<T>) -> T {
|
||||
let value: Erased<<T as EraseType>::Result> = value;
|
||||
// See comment in `erase` for why we use `transmute_unchecked`.
|
||||
#[define_opaque(Erased)]
|
||||
pub fn restore_val<T: Erasable>(erased_value: Erased<T>) -> T {
|
||||
let ErasedData { data }: ErasedData<<T as Erasable>::Storage> = erased_value;
|
||||
// See comment in `erase_val` for why we use `transmute_unchecked`.
|
||||
//
|
||||
// SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance
|
||||
// of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
|
||||
// the right size.
|
||||
unsafe { transmute_unchecked::<MaybeUninit<T::Result>, T>(value.data) }
|
||||
// SAFETY: Due to the use of impl Trait in `Erased` the only way to safely create an instance
|
||||
// of `Erased` is to call `erase_val`, so we know that `erased_value.data` is a valid instance
|
||||
// of `T` of the right size.
|
||||
unsafe { transmute_unchecked::<MaybeUninit<T::Storage>, T>(data) }
|
||||
}
|
||||
|
||||
impl<T> EraseType for &'_ T {
|
||||
type Result = [u8; size_of::<&'static ()>()];
|
||||
// FIXME(#151565): Using `T: ?Sized` here should let us remove the separate
|
||||
// impls for fat reference types.
|
||||
impl<T> Erasable for &'_ T {
|
||||
type Storage = [u8; size_of::<&'static ()>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for &'_ [T] {
|
||||
type Result = [u8; size_of::<&'static [()]>()];
|
||||
impl<T> Erasable for &'_ [T] {
|
||||
type Storage = [u8; size_of::<&'static [()]>()];
|
||||
}
|
||||
|
||||
impl EraseType for &'_ OsStr {
|
||||
type Result = [u8; size_of::<&'static OsStr>()];
|
||||
impl Erasable for &'_ OsStr {
|
||||
type Storage = [u8; size_of::<&'static OsStr>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for &'_ ty::List<T> {
|
||||
type Result = [u8; size_of::<&'static ty::List<()>>()];
|
||||
impl<T> Erasable for &'_ ty::List<T> {
|
||||
type Storage = [u8; size_of::<&'static ty::List<()>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for &'_ ty::ListWithCachedTypeInfo<T> {
|
||||
type Result = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()];
|
||||
impl<T> Erasable for &'_ ty::ListWithCachedTypeInfo<T> {
|
||||
type Storage = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()];
|
||||
}
|
||||
|
||||
impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> {
|
||||
type Result = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()];
|
||||
impl<I: rustc_index::Idx, T> Erasable for &'_ rustc_index::IndexSlice<I, T> {
|
||||
type Storage = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> {
|
||||
type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
|
||||
impl<T> Erasable for Result<&'_ T, traits::query::NoSolution> {
|
||||
type Storage = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Result<&'_ [T], traits::query::NoSolution> {
|
||||
type Result = [u8; size_of::<Result<&'static [()], traits::query::NoSolution>>()];
|
||||
impl<T> Erasable for Result<&'_ [T], traits::query::NoSolution> {
|
||||
type Storage = [u8; size_of::<Result<&'static [()], traits::query::NoSolution>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
|
||||
type Result = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
|
||||
impl<T> Erasable for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
|
||||
type Storage = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> {
|
||||
type Result = [u8; size_of::<Result<&'static [()], rustc_errors::ErrorGuaranteed>>()];
|
||||
impl<T> Erasable for Result<&'_ [T], rustc_errors::ErrorGuaranteed> {
|
||||
type Storage = [u8; size_of::<Result<&'static [()], rustc_errors::ErrorGuaranteed>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
|
||||
type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
|
||||
impl<T> Erasable for Result<&'_ T, traits::CodegenObligationError> {
|
||||
type Storage = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> {
|
||||
type Result = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()];
|
||||
impl<T> Erasable for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> {
|
||||
type Storage = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> {
|
||||
type Result = [u8; size_of::<
|
||||
impl<T> Erasable for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> {
|
||||
type Storage = [u8; size_of::<
|
||||
Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>,
|
||||
>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<Option<ty::Instance<'_>>, rustc_errors::ErrorGuaranteed> {
|
||||
type Result =
|
||||
impl Erasable for Result<Option<ty::Instance<'_>>, rustc_errors::ErrorGuaranteed> {
|
||||
type Storage =
|
||||
[u8; size_of::<Result<Option<ty::Instance<'static>>, rustc_errors::ErrorGuaranteed>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed> {
|
||||
type Result = [u8; size_of::<Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed>>()];
|
||||
impl Erasable for Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed> {
|
||||
type Storage = [u8; size_of::<Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed>>()];
|
||||
}
|
||||
|
||||
impl EraseType
|
||||
impl Erasable
|
||||
for Result<Option<ty::EarlyBinder<'_, ty::Const<'_>>>, rustc_errors::ErrorGuaranteed>
|
||||
{
|
||||
type Result = [u8; size_of::<
|
||||
type Storage = [u8; size_of::<
|
||||
Result<Option<ty::EarlyBinder<'static, ty::Const<'static>>>, rustc_errors::ErrorGuaranteed>,
|
||||
>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
|
||||
type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
|
||||
impl Erasable for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
|
||||
type Storage = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<bool, &ty::layout::LayoutError<'_>> {
|
||||
type Result = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()];
|
||||
impl Erasable for Result<bool, &ty::layout::LayoutError<'_>> {
|
||||
type Storage = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<rustc_abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>> {
|
||||
type Result = [u8; size_of::<
|
||||
impl Erasable for Result<rustc_abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>> {
|
||||
type Storage = [u8; size_of::<
|
||||
Result<
|
||||
rustc_abi::TyAndLayout<'static, Ty<'static>>,
|
||||
&'static ty::layout::LayoutError<'static>,
|
||||
|
|
@ -153,35 +191,36 @@ impl EraseType for Result<rustc_abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::Layou
|
|||
>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
|
||||
type Result = [u8; size_of::<Result<mir::ConstAlloc<'static>, mir::interpret::ErrorHandled>>()];
|
||||
impl Erasable for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
|
||||
type Storage =
|
||||
[u8; size_of::<Result<mir::ConstAlloc<'static>, mir::interpret::ErrorHandled>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<mir::ConstValue, mir::interpret::ErrorHandled> {
|
||||
type Result = [u8; size_of::<Result<mir::ConstValue, mir::interpret::ErrorHandled>>()];
|
||||
impl Erasable for Result<mir::ConstValue, mir::interpret::ErrorHandled> {
|
||||
type Storage = [u8; size_of::<Result<mir::ConstValue, mir::interpret::ErrorHandled>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Option<(mir::ConstValue, Ty<'_>)> {
|
||||
type Result = [u8; size_of::<Option<(mir::ConstValue, Ty<'_>)>>()];
|
||||
impl Erasable for Option<(mir::ConstValue, Ty<'_>)> {
|
||||
type Storage = [u8; size_of::<Option<(mir::ConstValue, Ty<'_>)>>()];
|
||||
}
|
||||
|
||||
impl EraseType for EvalToValTreeResult<'_> {
|
||||
type Result = [u8; size_of::<EvalToValTreeResult<'static>>()];
|
||||
impl Erasable for EvalToValTreeResult<'_> {
|
||||
type Storage = [u8; size_of::<EvalToValTreeResult<'static>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
|
||||
type Result =
|
||||
impl Erasable for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
|
||||
type Storage =
|
||||
[u8; size_of::<Result<&'static ty::List<Ty<'static>>, ty::util::AlwaysRequiresDrop>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
|
||||
type Result = [u8; size_of::<Result<ty::EarlyBinder<'static, Ty<'_>>, CyclePlaceholder>>()];
|
||||
impl Erasable for Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
|
||||
type Storage = [u8; size_of::<Result<ty::EarlyBinder<'static, Ty<'_>>, CyclePlaceholder>>()];
|
||||
}
|
||||
|
||||
impl EraseType
|
||||
impl Erasable
|
||||
for Result<(&'_ [Spanned<MonoItem<'_>>], &'_ [Spanned<MonoItem<'_>>]), NormalizationErrorInMono>
|
||||
{
|
||||
type Result = [u8; size_of::<
|
||||
type Storage = [u8; size_of::<
|
||||
Result<
|
||||
(&'static [Spanned<MonoItem<'static>>], &'static [Spanned<MonoItem<'static>>]),
|
||||
NormalizationErrorInMono,
|
||||
|
|
@ -189,86 +228,89 @@ impl EraseType
|
|||
>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<&'_ TokenStream, ()> {
|
||||
type Result = [u8; size_of::<Result<&'static TokenStream, ()>>()];
|
||||
impl Erasable for Result<&'_ TokenStream, ()> {
|
||||
type Storage = [u8; size_of::<Result<&'static TokenStream, ()>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Option<&'_ T> {
|
||||
type Result = [u8; size_of::<Option<&'static ()>>()];
|
||||
impl<T> Erasable for Option<&'_ T> {
|
||||
type Storage = [u8; size_of::<Option<&'static ()>>()];
|
||||
}
|
||||
|
||||
impl<T> EraseType for Option<&'_ [T]> {
|
||||
type Result = [u8; size_of::<Option<&'static [()]>>()];
|
||||
impl<T> Erasable for Option<&'_ [T]> {
|
||||
type Storage = [u8; size_of::<Option<&'static [()]>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Option<&'_ OsStr> {
|
||||
type Result = [u8; size_of::<Option<&'static OsStr>>()];
|
||||
impl Erasable for Option<&'_ OsStr> {
|
||||
type Storage = [u8; size_of::<Option<&'static OsStr>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Option<mir::DestructuredConstant<'_>> {
|
||||
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
|
||||
impl Erasable for Option<mir::DestructuredConstant<'_>> {
|
||||
type Storage = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
|
||||
}
|
||||
|
||||
impl EraseType for ty::ImplTraitHeader<'_> {
|
||||
type Result = [u8; size_of::<ty::ImplTraitHeader<'static>>()];
|
||||
impl Erasable for ty::ImplTraitHeader<'_> {
|
||||
type Storage = [u8; size_of::<ty::ImplTraitHeader<'static>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Option<ty::EarlyBinder<'_, Ty<'_>>> {
|
||||
type Result = [u8; size_of::<Option<ty::EarlyBinder<'static, Ty<'static>>>>()];
|
||||
impl Erasable for Option<ty::EarlyBinder<'_, Ty<'_>>> {
|
||||
type Storage = [u8; size_of::<Option<ty::EarlyBinder<'static, Ty<'static>>>>()];
|
||||
}
|
||||
|
||||
impl EraseType for rustc_hir::MaybeOwner<'_> {
|
||||
type Result = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
|
||||
impl Erasable for rustc_hir::MaybeOwner<'_> {
|
||||
type Storage = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
|
||||
}
|
||||
|
||||
impl<T: EraseType> EraseType for ty::EarlyBinder<'_, T> {
|
||||
type Result = T::Result;
|
||||
impl<T: Erasable> Erasable for ty::EarlyBinder<'_, T> {
|
||||
type Storage = T::Storage;
|
||||
}
|
||||
|
||||
impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
|
||||
type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
|
||||
impl Erasable for ty::Binder<'_, ty::FnSig<'_>> {
|
||||
type Storage = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
|
||||
}
|
||||
|
||||
impl EraseType for ty::Binder<'_, ty::CoroutineWitnessTypes<TyCtxt<'_>>> {
|
||||
type Result =
|
||||
impl Erasable for ty::Binder<'_, ty::CoroutineWitnessTypes<TyCtxt<'_>>> {
|
||||
type Storage =
|
||||
[u8; size_of::<ty::Binder<'static, ty::CoroutineWitnessTypes<TyCtxt<'static>>>>()];
|
||||
}
|
||||
|
||||
impl EraseType for ty::Binder<'_, &'_ ty::List<Ty<'_>>> {
|
||||
type Result = [u8; size_of::<ty::Binder<'static, &'static ty::List<Ty<'static>>>>()];
|
||||
impl Erasable for ty::Binder<'_, &'_ ty::List<Ty<'_>>> {
|
||||
type Storage = [u8; size_of::<ty::Binder<'static, &'static ty::List<Ty<'static>>>>()];
|
||||
}
|
||||
|
||||
impl<T0, T1> EraseType for (&'_ T0, &'_ T1) {
|
||||
type Result = [u8; size_of::<(&'static (), &'static ())>()];
|
||||
impl<T0, T1> Erasable for (&'_ T0, &'_ T1) {
|
||||
type Storage = [u8; size_of::<(&'static (), &'static ())>()];
|
||||
}
|
||||
|
||||
impl<T0> EraseType for (solve::QueryResult<'_>, &'_ T0) {
|
||||
type Result = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()];
|
||||
impl<T0> Erasable for (solve::QueryResult<'_>, &'_ T0) {
|
||||
type Storage = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()];
|
||||
}
|
||||
|
||||
impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
|
||||
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
|
||||
impl<T0, T1> Erasable for (&'_ T0, &'_ [T1]) {
|
||||
type Storage = [u8; size_of::<(&'static (), &'static [()])>()];
|
||||
}
|
||||
|
||||
impl<T0, T1> EraseType for (&'_ [T0], &'_ [T1]) {
|
||||
type Result = [u8; size_of::<(&'static [()], &'static [()])>()];
|
||||
impl<T0, T1> Erasable for (&'_ [T0], &'_ [T1]) {
|
||||
type Storage = [u8; size_of::<(&'static [()], &'static [()])>()];
|
||||
}
|
||||
|
||||
impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
|
||||
type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
|
||||
impl<T0> Erasable for (&'_ T0, Result<(), ErrorGuaranteed>) {
|
||||
type Storage = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
|
||||
}
|
||||
|
||||
macro_rules! trivial {
|
||||
macro_rules! impl_erasable_for_simple_types {
|
||||
($($ty:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl EraseType for $ty {
|
||||
type Result = [u8; size_of::<$ty>()];
|
||||
impl Erasable for $ty {
|
||||
type Storage = [u8; size_of::<$ty>()];
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
trivial! {
|
||||
// For concrete types with no lifetimes, the erased storage for `Foo` is
|
||||
// `[u8; size_of::<Foo>()]`.
|
||||
impl_erasable_for_simple_types! {
|
||||
// FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this.
|
||||
(),
|
||||
bool,
|
||||
Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>,
|
||||
|
|
@ -346,7 +388,6 @@ trivial! {
|
|||
rustc_middle::ty::AssocContainer,
|
||||
rustc_middle::ty::Asyncness,
|
||||
rustc_middle::ty::AsyncDestructor,
|
||||
rustc_middle::ty::BoundVariableKind,
|
||||
rustc_middle::ty::AnonConstKind,
|
||||
rustc_middle::ty::Destructor,
|
||||
rustc_middle::ty::fast_reject::SimplifiedType,
|
||||
|
|
@ -378,17 +419,23 @@ trivial! {
|
|||
usize,
|
||||
}
|
||||
|
||||
macro_rules! tcx_lifetime {
|
||||
macro_rules! impl_erasable_for_single_lifetime_types {
|
||||
($($($fake_path:ident)::+),+ $(,)?) => {
|
||||
$(
|
||||
impl<'tcx> EraseType for $($fake_path)::+<'tcx> {
|
||||
type Result = [u8; size_of::<$($fake_path)::+<'static>>()];
|
||||
impl<'tcx> Erasable for $($fake_path)::+<'tcx> {
|
||||
type Storage = [u8; size_of::<$($fake_path)::+<'static>>()];
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
tcx_lifetime! {
|
||||
// For types containing a single lifetime and no other generics, e.g.
|
||||
// `Foo<'tcx>`, the erased storage is `[u8; size_of::<Foo<'static>>()]`.
|
||||
//
|
||||
// FIXME(#151565): Some of the hand-written impls above that only use one
|
||||
// lifetime can probably be migrated here.
|
||||
impl_erasable_for_single_lifetime_types! {
|
||||
// FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this.
|
||||
rustc_middle::middle::exported_symbols::ExportedSymbol,
|
||||
rustc_middle::mir::Const,
|
||||
rustc_middle::mir::DestructuredConstant,
|
||||
|
|
@ -415,6 +462,7 @@ tcx_lifetime! {
|
|||
rustc_middle::ty::ConstConditions,
|
||||
rustc_middle::ty::inhabitedness::InhabitedPredicate,
|
||||
rustc_middle::ty::Instance,
|
||||
rustc_middle::ty::BoundVariableKind,
|
||||
rustc_middle::ty::InstanceKind,
|
||||
rustc_middle::ty::layout::FnAbiError,
|
||||
rustc_middle::ty::layout::LayoutError,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached};
|
|||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
|
||||
use crate::dep_graph;
|
||||
use crate::query::IntoQueryParam;
|
||||
use crate::query::erase::{self, Erase, EraseType};
|
||||
use crate::query::erase::{self, Erasable, Erased};
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
/// Shared implementation of `tcx.$query(..)` and `tcx.at(span).$query(..)`
|
||||
|
|
@ -27,7 +26,6 @@ pub(crate) fn query_get_at<'tcx, Cache>(
|
|||
where
|
||||
Cache: QueryCache,
|
||||
{
|
||||
let key = key.into_query_param();
|
||||
match try_get_cached(tcx, query_cache, &key) {
|
||||
Some(value) => value,
|
||||
None => execute_query(tcx, span, key, QueryMode::Get).unwrap(),
|
||||
|
|
@ -46,7 +44,6 @@ pub(crate) fn query_ensure<'tcx, Cache>(
|
|||
) where
|
||||
Cache: QueryCache,
|
||||
{
|
||||
let key = key.into_query_param();
|
||||
if try_get_cached(tcx, query_cache, &key).is_none() {
|
||||
execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache });
|
||||
}
|
||||
|
|
@ -63,15 +60,14 @@ pub(crate) fn query_ensure_error_guaranteed<'tcx, Cache, T>(
|
|||
check_cache: bool,
|
||||
) -> Result<(), ErrorGuaranteed>
|
||||
where
|
||||
Cache: QueryCache<Value = Erase<Result<T, ErrorGuaranteed>>>,
|
||||
Result<T, ErrorGuaranteed>: EraseType,
|
||||
Cache: QueryCache<Value = Erased<Result<T, ErrorGuaranteed>>>,
|
||||
Result<T, ErrorGuaranteed>: Erasable,
|
||||
{
|
||||
let key = key.into_query_param();
|
||||
if let Some(res) = try_get_cached(tcx, query_cache, &key) {
|
||||
erase::restore(res).map(drop)
|
||||
erase::restore_val(res).map(drop)
|
||||
} else {
|
||||
execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache })
|
||||
.map(erase::restore)
|
||||
.map(erase::restore_val)
|
||||
.map(|res| res.map(drop))
|
||||
// Either we actually executed the query, which means we got a full `Result`,
|
||||
// or we can just assume the query succeeded, because it was green in the
|
||||
|
|
@ -90,17 +86,17 @@ pub(crate) fn query_feed<'tcx, Cache, Value>(
|
|||
hasher: Option<fn(&mut StableHashingContext<'_>, &Value) -> Fingerprint>,
|
||||
cache: &Cache,
|
||||
key: Cache::Key,
|
||||
erased: Erase<Value>,
|
||||
erased: Erased<Value>,
|
||||
) where
|
||||
Cache: QueryCache<Value = Erase<Value>>,
|
||||
Cache: QueryCache<Value = Erased<Value>>,
|
||||
Cache::Key: DepNodeParams<TyCtxt<'tcx>>,
|
||||
Value: EraseType + Debug,
|
||||
Value: Erasable + Debug,
|
||||
{
|
||||
let value = erase::restore::<Value>(erased);
|
||||
let value = erase::restore_val::<Value>(erased);
|
||||
|
||||
match try_get_cached(tcx, cache, &key) {
|
||||
Some(old) => {
|
||||
let old = erase::restore::<Value>(old);
|
||||
let old = erase::restore_val::<Value>(old);
|
||||
if let Some(hasher) = hasher {
|
||||
let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx
|
||||
.with_stable_hashing_context(|mut hcx| {
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ use rustc_index::IndexVec;
|
|||
use rustc_lint_defs::LintId;
|
||||
use rustc_macros::rustc_queries;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_query_system::query::{QueryMode, QueryStackDeferred, QueryState};
|
||||
use rustc_query_system::query::{QueryMode, QueryState};
|
||||
use rustc_session::Limits;
|
||||
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
||||
use rustc_session::cstore::{
|
||||
|
|
@ -121,7 +121,6 @@ use crate::mir::interpret::{
|
|||
use crate::mir::mono::{
|
||||
CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono,
|
||||
};
|
||||
use crate::query::erase::{Erase, erase, restore};
|
||||
use crate::query::plumbing::CyclePlaceholder;
|
||||
use crate::traits::query::{
|
||||
CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal,
|
||||
|
|
@ -266,7 +265,7 @@ rustc_queries! {
|
|||
///
|
||||
/// This can be conveniently accessed by `tcx.hir_*` methods.
|
||||
/// Avoid calling this query directly.
|
||||
query hir_owner_parent(key: hir::OwnerId) -> hir::HirId {
|
||||
query hir_owner_parent_q(key: hir::OwnerId) -> hir::HirId {
|
||||
desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
|
|
@ -2116,7 +2115,7 @@ rustc_queries! {
|
|||
/// Does lifetime resolution on items. Importantly, we can't resolve
|
||||
/// lifetimes directly on things like trait methods, because of trait params.
|
||||
/// See `rustc_resolve::late::lifetimes` for details.
|
||||
query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars {
|
||||
query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars<'tcx> {
|
||||
arena_cache
|
||||
desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) }
|
||||
}
|
||||
|
|
@ -2145,7 +2144,7 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
query late_bound_vars_map(owner_id: hir::OwnerId)
|
||||
-> &'tcx SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>> {
|
||||
-> &'tcx SortedMap<ItemLocalId, Vec<ty::BoundVariableKind<'tcx>>> {
|
||||
desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) }
|
||||
}
|
||||
/// For an opaque type, return the list of (captured lifetime, inner generic param).
|
||||
|
|
|
|||
|
|
@ -18,6 +18,18 @@ use crate::query::{
|
|||
};
|
||||
use crate::ty::TyCtxt;
|
||||
|
||||
pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool;
|
||||
|
||||
pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: &Key,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
index: DepNodeIndex,
|
||||
) -> Option<Value>;
|
||||
|
||||
pub type IsLoadableFromDiskFn<'tcx, Key> =
|
||||
fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool;
|
||||
|
||||
/// Stores function pointers and other metadata for a particular query.
|
||||
///
|
||||
/// Used indirectly by query plumbing in `rustc_query_system`, via a trait.
|
||||
|
|
@ -31,18 +43,11 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
|
|||
pub query_state: usize,
|
||||
// Offset of this query's cache field in the QueryCaches struct
|
||||
pub query_cache: usize,
|
||||
pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool,
|
||||
pub will_cache_on_disk_for_key_fn: Option<WillCacheOnDiskForKeyFn<'tcx, C::Key>>,
|
||||
pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value,
|
||||
pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
|
||||
pub can_load_from_disk: bool,
|
||||
pub try_load_from_disk: fn(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: &C::Key,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
index: DepNodeIndex,
|
||||
) -> Option<C::Value>,
|
||||
pub loadable_from_disk:
|
||||
fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool,
|
||||
pub try_load_from_disk_fn: Option<TryLoadFromDiskFn<'tcx, C::Key, C::Value>>,
|
||||
pub is_loadable_from_disk_fn: Option<IsLoadableFromDiskFn<'tcx, C::Key>>,
|
||||
pub hash_result: HashResult<C::Value>,
|
||||
pub value_from_cycle_error:
|
||||
fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value,
|
||||
|
|
@ -266,6 +271,7 @@ macro_rules! define_callbacks {
|
|||
pub mod queries {
|
||||
$(pub mod $name {
|
||||
use super::super::*;
|
||||
use $crate::query::erase::{self, Erased};
|
||||
|
||||
pub type Key<'tcx> = $($K)*;
|
||||
pub type Value<'tcx> = $V;
|
||||
|
|
@ -288,29 +294,33 @@ macro_rules! define_callbacks {
|
|||
#[inline(always)]
|
||||
pub fn provided_to_erased<'tcx>(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
value: ProvidedValue<'tcx>,
|
||||
) -> Erase<Value<'tcx>> {
|
||||
erase(query_if_arena!([$($modifiers)*]
|
||||
provided_value: ProvidedValue<'tcx>,
|
||||
) -> Erased<Value<'tcx>> {
|
||||
// Store the provided value in an arena and get a reference
|
||||
// to it, for queries with `arena_cache`.
|
||||
let value: Value<'tcx> = query_if_arena!([$($modifiers)*]
|
||||
{
|
||||
use $crate::query::arena_cached::ArenaCached;
|
||||
|
||||
if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() {
|
||||
<$V as ArenaCached>::alloc_in_arena(
|
||||
|v| _tcx.query_system.arenas.$name.alloc(v),
|
||||
value,
|
||||
provided_value,
|
||||
)
|
||||
} else {
|
||||
<$V as ArenaCached>::alloc_in_arena(
|
||||
|v| _tcx.arena.dropless.alloc(v),
|
||||
value,
|
||||
provided_value,
|
||||
)
|
||||
}
|
||||
}
|
||||
(value)
|
||||
))
|
||||
// Otherwise, the provided value is the value.
|
||||
(provided_value)
|
||||
);
|
||||
erase::erase_val(value)
|
||||
}
|
||||
|
||||
pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>;
|
||||
pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erased<$V>>;
|
||||
|
||||
// Ensure that keys grow no larger than 88 bytes by accident.
|
||||
// Increase this limit if necessary, but do try to keep the size low if possible
|
||||
|
|
@ -411,7 +421,9 @@ macro_rules! define_callbacks {
|
|||
#[inline(always)]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
|
||||
{
|
||||
restore::<$V>(crate::query::inner::query_get_at(
|
||||
use $crate::query::{erase, inner};
|
||||
|
||||
erase::restore_val::<$V>(inner::query_get_at(
|
||||
self.tcx,
|
||||
self.tcx.query_system.fns.engine.$name,
|
||||
&self.tcx.query_system.caches.$name,
|
||||
|
|
@ -433,7 +445,7 @@ macro_rules! define_callbacks {
|
|||
#[derive(Default)]
|
||||
pub struct QueryStates<'tcx> {
|
||||
$(
|
||||
pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>,
|
||||
pub $name: QueryState<'tcx, $($K)*>,
|
||||
)*
|
||||
}
|
||||
|
||||
|
|
@ -480,7 +492,7 @@ macro_rules! define_callbacks {
|
|||
Span,
|
||||
queries::$name::Key<'tcx>,
|
||||
QueryMode,
|
||||
) -> Option<Erase<$V>>,)*
|
||||
) -> Option<$crate::query::erase::Erased<$V>>,)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -427,11 +427,11 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [Spanned<MonoItem<'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind> {
|
||||
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind<'tcx>> {
|
||||
fn decode(decoder: &mut D) -> &'tcx Self {
|
||||
let len = decoder.read_usize();
|
||||
decoder.interner().mk_bound_variable_kinds_from_iter(
|
||||
(0..len).map::<ty::BoundVariableKind, _>(|_| Decodable::decode(decoder)),
|
||||
(0..len).map::<ty::BoundVariableKind<'tcx>, _>(|_| Decodable::decode(decoder)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -495,7 +495,7 @@ impl_decodable_via_ref! {
|
|||
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
&'tcx traits::ImplSource<'tcx, ()>,
|
||||
&'tcx mir::Body<'tcx>,
|
||||
&'tcx ty::List<ty::BoundVariableKind>,
|
||||
&'tcx ty::List<ty::BoundVariableKind<'tcx>>,
|
||||
&'tcx ty::List<ty::Pattern<'tcx>>,
|
||||
&'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ impl<'tcx> Const<'tcx> {
|
|||
pub fn new_bound(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
debruijn: ty::DebruijnIndex,
|
||||
bound_const: ty::BoundConst,
|
||||
bound_const: ty::BoundConst<'tcx>,
|
||||
) -> Const<'tcx> {
|
||||
Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const))
|
||||
}
|
||||
|
|
@ -103,7 +103,7 @@ impl<'tcx> Const<'tcx> {
|
|||
pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> {
|
||||
Const::new(
|
||||
tcx,
|
||||
ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst { var }),
|
||||
ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst::new(var)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -183,13 +183,13 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
|||
fn new_bound(
|
||||
interner: TyCtxt<'tcx>,
|
||||
debruijn: ty::DebruijnIndex,
|
||||
bound_const: ty::BoundConst,
|
||||
bound_const: ty::BoundConst<'tcx>,
|
||||
) -> Self {
|
||||
Const::new_bound(interner, debruijn, bound_const)
|
||||
}
|
||||
|
||||
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
|
||||
Const::new_bound(tcx, debruijn, ty::BoundConst { var })
|
||||
Const::new_bound(tcx, debruijn, ty::BoundConst::new(var))
|
||||
}
|
||||
|
||||
fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self {
|
||||
|
|
|
|||
|
|
@ -108,9 +108,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>];
|
||||
type GenericArg = ty::GenericArg<'tcx>;
|
||||
type Term = ty::Term<'tcx>;
|
||||
type BoundVarKinds = &'tcx List<ty::BoundVariableKind>;
|
||||
type BoundVarKinds = &'tcx List<ty::BoundVariableKind<'tcx>>;
|
||||
|
||||
type BoundVarKind = ty::BoundVariableKind;
|
||||
type PredefinedOpaques = solve::PredefinedOpaques<'tcx>;
|
||||
|
||||
fn mk_predefined_opaques_in_body(
|
||||
|
|
@ -144,10 +143,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
|
||||
type FnInputTys = &'tcx [Ty<'tcx>];
|
||||
type ParamTy = ParamTy;
|
||||
type BoundTy = ty::BoundTy;
|
||||
type Symbol = Symbol;
|
||||
|
||||
type PlaceholderTy = ty::PlaceholderType<'tcx>;
|
||||
type ErrorGuaranteed = ErrorGuaranteed;
|
||||
type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
|
||||
|
||||
|
|
@ -157,10 +154,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
type Safety = hir::Safety;
|
||||
type Abi = ExternAbi;
|
||||
type Const = ty::Const<'tcx>;
|
||||
type PlaceholderConst = ty::PlaceholderConst<'tcx>;
|
||||
|
||||
type ParamConst = ty::ParamConst;
|
||||
type BoundConst = ty::BoundConst;
|
||||
type ValueConst = ty::Value<'tcx>;
|
||||
type ExprConst = ty::Expr<'tcx>;
|
||||
type ValTree = ty::ValTree<'tcx>;
|
||||
|
|
@ -169,8 +164,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
type Region = Region<'tcx>;
|
||||
type EarlyParamRegion = ty::EarlyParamRegion;
|
||||
type LateParamRegion = ty::LateParamRegion;
|
||||
type BoundRegion = ty::BoundRegion;
|
||||
type PlaceholderRegion = ty::PlaceholderRegion<'tcx>;
|
||||
|
||||
type RegionAssumptions = &'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>>;
|
||||
|
||||
|
|
@ -776,6 +769,13 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
) -> (QueryResult<'tcx>, &'tcx inspect::Probe<TyCtxt<'tcx>>) {
|
||||
self.evaluate_root_goal_for_proof_tree_raw(canonical_goal)
|
||||
}
|
||||
|
||||
fn item_name(self, id: DefId) -> Symbol {
|
||||
let id = id.into_query_param();
|
||||
self.opt_item_name(id).unwrap_or_else(|| {
|
||||
bug!("item_name: no name for {:?}", self.def_path(id));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! bidirectional_lang_item_map {
|
||||
|
|
@ -938,7 +938,7 @@ pub struct CtxtInterners<'tcx> {
|
|||
const_: InternedSet<'tcx, WithCachedTypeInfo<ty::ConstKind<'tcx>>>,
|
||||
pat: InternedSet<'tcx, PatternKind<'tcx>>,
|
||||
const_allocation: InternedSet<'tcx, Allocation>,
|
||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind<'tcx>>>,
|
||||
layout: InternedSet<'tcx, LayoutData<FieldIdx, VariantIdx>>,
|
||||
adt_def: InternedSet<'tcx, AdtDefData>,
|
||||
external_constraints: InternedSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>,
|
||||
|
|
@ -2530,7 +2530,7 @@ nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> }
|
|||
nop_list_lift! {
|
||||
poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>
|
||||
}
|
||||
nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind }
|
||||
nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind<'a> => ty::BoundVariableKind<'tcx> }
|
||||
|
||||
// This is the impl for `&'a GenericArgs<'a>`.
|
||||
nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> }
|
||||
|
|
@ -2817,7 +2817,7 @@ slice_interners!(
|
|||
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
|
||||
projs: pub mk_projs(ProjectionKind),
|
||||
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
|
||||
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
|
||||
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind<'tcx>),
|
||||
fields: pub mk_fields(FieldIdx),
|
||||
local_def_ids: intern_local_def_ids(LocalDefId),
|
||||
captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>),
|
||||
|
|
@ -3242,7 +3242,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
|
||||
T: CollectAndApply<ty::BoundVariableKind<'tcx>, &'tcx List<ty::BoundVariableKind<'tcx>>>,
|
||||
{
|
||||
T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
|
||||
}
|
||||
|
|
@ -3362,7 +3362,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id))
|
||||
}
|
||||
|
||||
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
|
||||
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind<'tcx>> {
|
||||
self.mk_bound_variable_kinds(
|
||||
&self
|
||||
.late_bound_vars_map(id.owner)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_type_ir::data_structures::DelayedMap;
|
||||
|
||||
use crate::ty::{
|
||||
self, Binder, BoundConst, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
};
|
||||
|
||||
|
|
@ -58,28 +58,28 @@ where
|
|||
/// gets mapped to the same result. `BoundVarReplacer` caches by using
|
||||
/// a `DelayedMap` which does not cache the first few types it encounters.
|
||||
pub trait BoundVarReplacerDelegate<'tcx> {
|
||||
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>;
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>;
|
||||
fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx>;
|
||||
fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx>;
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx>;
|
||||
fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx>;
|
||||
}
|
||||
|
||||
/// A simple delegate taking 3 mutable functions. The used functions must
|
||||
/// always return the same result for each bound variable, no matter how
|
||||
/// frequently they are called.
|
||||
pub struct FnMutDelegate<'a, 'tcx> {
|
||||
pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
|
||||
pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
|
||||
pub consts: &'a mut (dyn FnMut(ty::BoundConst) -> ty::Const<'tcx> + 'a),
|
||||
pub regions: &'a mut (dyn FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx> + 'a),
|
||||
pub types: &'a mut (dyn FnMut(ty::BoundTy<'tcx>) -> Ty<'tcx> + 'a),
|
||||
pub consts: &'a mut (dyn FnMut(ty::BoundConst<'tcx>) -> ty::Const<'tcx> + 'a),
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> {
|
||||
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
|
||||
fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> {
|
||||
(self.regions)(br)
|
||||
}
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> {
|
||||
(self.types)(bt)
|
||||
}
|
||||
fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> {
|
||||
fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> {
|
||||
(self.consts)(bc)
|
||||
}
|
||||
}
|
||||
|
|
@ -207,13 +207,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self,
|
||||
value: Binder<'tcx, T>,
|
||||
mut fld_r: F,
|
||||
) -> (T, FxIndexMap<ty::BoundRegion, ty::Region<'tcx>>)
|
||||
) -> (T, FxIndexMap<ty::BoundRegion<'tcx>, ty::Region<'tcx>>)
|
||||
where
|
||||
F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
|
||||
F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>,
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let mut region_map = FxIndexMap::default();
|
||||
let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
|
||||
let real_fld_r =
|
||||
|br: ty::BoundRegion<'tcx>| *region_map.entry(br).or_insert_with(|| fld_r(br));
|
||||
let value = self.instantiate_bound_regions_uncached(value, real_fld_r);
|
||||
(value, region_map)
|
||||
}
|
||||
|
|
@ -224,7 +225,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
mut replace_regions: F,
|
||||
) -> T
|
||||
where
|
||||
F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
|
||||
F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>,
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let value = value.skip_binder();
|
||||
|
|
@ -292,14 +293,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.replace_escaping_bound_vars_uncached(
|
||||
value,
|
||||
FnMutDelegate {
|
||||
regions: &mut |r: ty::BoundRegion| {
|
||||
regions: &mut |r: ty::BoundRegion<'tcx>| {
|
||||
ty::Region::new_bound(
|
||||
self,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
|
||||
)
|
||||
},
|
||||
types: &mut |t: ty::BoundTy| {
|
||||
types: &mut |t: ty::BoundTy<'tcx>| {
|
||||
Ty::new_bound(
|
||||
self,
|
||||
ty::INNERMOST,
|
||||
|
|
@ -307,11 +308,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
)
|
||||
},
|
||||
consts: &mut |c| {
|
||||
ty::Const::new_bound(
|
||||
self,
|
||||
ty::INNERMOST,
|
||||
ty::BoundConst { var: shift_bv(c.var) },
|
||||
)
|
||||
ty::Const::new_bound(self, ty::INNERMOST, ty::BoundConst::new(shift_bv(c.var)))
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
@ -333,10 +330,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
{
|
||||
struct Anonymize<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
map: &'a mut FxIndexMap<ty::BoundVar, ty::BoundVariableKind>,
|
||||
map: &'a mut FxIndexMap<ty::BoundVar, ty::BoundVariableKind<'tcx>>,
|
||||
}
|
||||
impl<'tcx> BoundVarReplacerDelegate<'tcx> for Anonymize<'_, 'tcx> {
|
||||
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
|
||||
fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> {
|
||||
let entry = self.map.entry(br.var);
|
||||
let index = entry.index();
|
||||
let var = ty::BoundVar::from_usize(index);
|
||||
|
|
@ -346,7 +343,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let br = ty::BoundRegion { var, kind };
|
||||
ty::Region::new_bound(self.tcx, ty::INNERMOST, br)
|
||||
}
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
|
||||
fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> {
|
||||
let entry = self.map.entry(bt.var);
|
||||
let index = entry.index();
|
||||
let var = ty::BoundVar::from_usize(index);
|
||||
|
|
@ -355,12 +352,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
.expect_ty();
|
||||
Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind })
|
||||
}
|
||||
fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> {
|
||||
fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> {
|
||||
let entry = self.map.entry(bc.var);
|
||||
let index = entry.index();
|
||||
let var = ty::BoundVar::from_usize(index);
|
||||
let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const();
|
||||
ty::Const::new_bound(self.tcx, ty::INNERMOST, BoundConst { var })
|
||||
ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst::new(var))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,13 +97,13 @@ pub use self::predicate::{
|
|||
RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate,
|
||||
};
|
||||
pub use self::region::{
|
||||
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region,
|
||||
RegionKind, RegionVid,
|
||||
EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionKind, RegionVid,
|
||||
};
|
||||
pub use self::sty::{
|
||||
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
|
||||
CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
|
||||
ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs,
|
||||
AliasTy, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind,
|
||||
BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs,
|
||||
InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst, PlaceholderRegion,
|
||||
PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
pub use self::typeck_results::{
|
||||
|
|
@ -914,100 +914,6 @@ impl<'tcx> DefinitionSiteHiddenType<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderRegion<'tcx> = ty::Placeholder<TyCtxt<'tcx>, BoundRegion>;
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::PlaceholderLike<TyCtxt<'tcx>> for PlaceholderRegion<'tcx> {
|
||||
type Bound = BoundRegion;
|
||||
|
||||
fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(self) -> BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
ty::Placeholder::new(ui, self.bound)
|
||||
}
|
||||
|
||||
fn new(ui: UniverseIndex, bound: BoundRegion) -> Self {
|
||||
ty::Placeholder::new(ui, bound)
|
||||
}
|
||||
|
||||
fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||
ty::Placeholder::new(ui, BoundRegion { var, kind: BoundRegionKind::Anon })
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderType<'tcx> = ty::Placeholder<TyCtxt<'tcx>, BoundTy>;
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::PlaceholderLike<TyCtxt<'tcx>> for PlaceholderType<'tcx> {
|
||||
type Bound = BoundTy;
|
||||
|
||||
fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(self) -> BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
ty::Placeholder::new(ui, self.bound)
|
||||
}
|
||||
|
||||
fn new(ui: UniverseIndex, bound: BoundTy) -> Self {
|
||||
ty::Placeholder::new(ui, bound)
|
||||
}
|
||||
|
||||
fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||
ty::Placeholder::new(ui, BoundTy { var, kind: BoundTyKind::Anon })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
pub struct BoundConst {
|
||||
pub var: BoundVar,
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundConst {
|
||||
fn var(self) -> BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
fn assert_eq(self, var: ty::BoundVariableKind) {
|
||||
var.expect_const()
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderConst<'tcx> = ty::Placeholder<TyCtxt<'tcx>, BoundConst>;
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::PlaceholderLike<TyCtxt<'tcx>> for PlaceholderConst<'tcx> {
|
||||
type Bound = BoundConst;
|
||||
|
||||
fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(self) -> BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
ty::Placeholder::new(ui, self.bound)
|
||||
}
|
||||
|
||||
fn new(ui: UniverseIndex, bound: BoundConst) -> Self {
|
||||
ty::Placeholder::new(ui, bound)
|
||||
}
|
||||
|
||||
fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||
ty::Placeholder::new(ui, BoundConst { var })
|
||||
}
|
||||
}
|
||||
|
||||
pub type Clauses<'tcx> = &'tcx ListWithCachedTypeInfo<Clause<'tcx>>;
|
||||
|
||||
impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> {
|
||||
|
|
@ -2180,8 +2086,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
DefKind::Impl { of_trait: false } => {
|
||||
self.constness(def_id) == hir::Constness::Const
|
||||
}
|
||||
DefKind::Impl { of_trait: true } | DefKind::Trait => {
|
||||
self.is_conditionally_const(parent_def_id)
|
||||
DefKind::Impl { of_trait: true } => {
|
||||
let Some(trait_method_did) = self.trait_item_of(def_id) else {
|
||||
return false;
|
||||
};
|
||||
self.constness(trait_method_did) == hir::Constness::Const
|
||||
&& self.is_conditionally_const(parent_def_id)
|
||||
}
|
||||
DefKind::Trait => {
|
||||
self.constness(def_id) == hir::Constness::Const
|
||||
&& self.is_conditionally_const(parent_def_id)
|
||||
}
|
||||
_ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ pub struct RegionHighlightMode<'tcx> {
|
|||
/// This is used when you have a signature like `fn foo(x: &u32,
|
||||
/// y: &'a u32)` and we want to give a name to the region of the
|
||||
/// reference `x`.
|
||||
highlight_bound_region: Option<(ty::BoundRegionKind, usize)>,
|
||||
highlight_bound_region: Option<(ty::BoundRegionKind<'tcx>, usize)>,
|
||||
}
|
||||
|
||||
impl<'tcx> RegionHighlightMode<'tcx> {
|
||||
|
|
@ -246,7 +246,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
|
|||
/// Highlight the given bound region.
|
||||
/// We can only highlight one bound region at a time. See
|
||||
/// the field `highlight_bound_region` for more detailed notes.
|
||||
pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind, number: usize) {
|
||||
pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind<'tcx>, number: usize) {
|
||||
assert!(self.highlight_bound_region.is_none());
|
||||
self.highlight_bound_region = Some((br, number));
|
||||
}
|
||||
|
|
@ -2639,12 +2639,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
struct RegionFolder<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
current_index: ty::DebruijnIndex,
|
||||
region_map: UnordMap<ty::BoundRegion, ty::Region<'tcx>>,
|
||||
region_map: UnordMap<ty::BoundRegion<'tcx>, ty::Region<'tcx>>,
|
||||
name: &'a mut (
|
||||
dyn FnMut(
|
||||
Option<ty::DebruijnIndex>, // Debruijn index of the folded late-bound region
|
||||
ty::DebruijnIndex, // Index corresponding to binder level
|
||||
ty::BoundRegion,
|
||||
ty::BoundRegion<'tcx>,
|
||||
) -> ty::Region<'tcx>
|
||||
+ 'a
|
||||
),
|
||||
|
|
@ -2717,7 +2717,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
&mut self,
|
||||
value: &ty::Binder<'tcx, T>,
|
||||
mode: WrapBinderMode,
|
||||
) -> Result<(T, UnordMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
|
||||
) -> Result<(T, UnordMap<ty::BoundRegion<'tcx>, ty::Region<'tcx>>), fmt::Error>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -2810,12 +2810,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
// see issue #102392.
|
||||
let mut name = |lifetime_idx: Option<ty::DebruijnIndex>,
|
||||
binder_level_idx: ty::DebruijnIndex,
|
||||
br: ty::BoundRegion| {
|
||||
br: ty::BoundRegion<'tcx>| {
|
||||
let (name, kind) = if let Some(name) = br.kind.get_name(tcx) {
|
||||
(name, br.kind)
|
||||
} else {
|
||||
let name = next_name(self);
|
||||
(name, ty::BoundRegionKind::NamedAnon(name))
|
||||
(name, ty::BoundRegionKind::NamedForPrinting(name))
|
||||
};
|
||||
|
||||
if let Some(lt_idx) = lifetime_idx {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ impl<'tcx> Region<'tcx> {
|
|||
pub fn new_bound(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
debruijn: ty::DebruijnIndex,
|
||||
bound_region: ty::BoundRegion,
|
||||
bound_region: ty::BoundRegion<'tcx>,
|
||||
) -> Region<'tcx> {
|
||||
// Use a pre-interned one when possible.
|
||||
if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region
|
||||
|
|
@ -160,7 +160,7 @@ impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> {
|
|||
fn new_bound(
|
||||
interner: TyCtxt<'tcx>,
|
||||
debruijn: ty::DebruijnIndex,
|
||||
var: ty::BoundRegion,
|
||||
var: ty::BoundRegion<'tcx>,
|
||||
) -> Self {
|
||||
Region::new_bound(interner, debruijn, var)
|
||||
}
|
||||
|
|
@ -388,7 +388,7 @@ pub struct LateParamRegion {
|
|||
pub kind: LateParamRegionKind,
|
||||
}
|
||||
|
||||
/// When liberating bound regions, we map their [`BoundRegionKind`]
|
||||
/// When liberating bound regions, we map their [`ty::BoundRegionKind`]
|
||||
/// to this as we need to track the index of anonymous regions. We
|
||||
/// otherwise end up liberating multiple bound regions to the same
|
||||
/// late-bound region.
|
||||
|
|
@ -397,7 +397,7 @@ pub struct LateParamRegion {
|
|||
pub enum LateParamRegionKind {
|
||||
/// An anonymous region parameter for a given fn (&T)
|
||||
///
|
||||
/// Unlike [`BoundRegionKind::Anon`], this tracks the index of the
|
||||
/// Unlike [`ty::BoundRegionKind::Anon`], this tracks the index of the
|
||||
/// liberated bound region.
|
||||
///
|
||||
/// We should ideally never liberate anonymous regions, but do so for the
|
||||
|
|
@ -418,12 +418,14 @@ pub enum LateParamRegionKind {
|
|||
}
|
||||
|
||||
impl LateParamRegionKind {
|
||||
pub fn from_bound(var: BoundVar, br: BoundRegionKind) -> LateParamRegionKind {
|
||||
pub fn from_bound(var: BoundVar, br: ty::BoundRegionKind<'_>) -> LateParamRegionKind {
|
||||
match br {
|
||||
BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()),
|
||||
BoundRegionKind::Named(def_id) => LateParamRegionKind::Named(def_id),
|
||||
BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv,
|
||||
BoundRegionKind::NamedAnon(name) => LateParamRegionKind::NamedAnon(var.as_u32(), name),
|
||||
ty::BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()),
|
||||
ty::BoundRegionKind::Named(def_id) => LateParamRegionKind::Named(def_id),
|
||||
ty::BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv,
|
||||
ty::BoundRegionKind::NamedForPrinting(name) => {
|
||||
LateParamRegionKind::NamedAnon(var.as_u32(), name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -450,81 +452,6 @@ impl LateParamRegionKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundRegionKind {
|
||||
/// An anonymous region parameter for a given fn (&T)
|
||||
Anon,
|
||||
|
||||
/// An anonymous region parameter with a `Symbol` name.
|
||||
///
|
||||
/// Used to give late-bound regions names for things like pretty printing.
|
||||
NamedAnon(Symbol),
|
||||
|
||||
/// Late-bound regions that appear in the AST.
|
||||
Named(DefId),
|
||||
|
||||
/// Anonymous region for the implicit env pointer parameter
|
||||
/// to a closure
|
||||
ClosureEnv,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub struct BoundRegion {
|
||||
pub var: BoundVar,
|
||||
pub kind: BoundRegionKind,
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion {
|
||||
fn var(self) -> BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
fn assert_eq(self, var: ty::BoundVariableKind) {
|
||||
assert_eq!(self.kind, var.expect_region())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for BoundRegion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.kind {
|
||||
BoundRegionKind::Anon => write!(f, "{:?}", self.var),
|
||||
BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var),
|
||||
BoundRegionKind::Named(def) => {
|
||||
write!(f, "{:?}.Named({:?})", self.var, def)
|
||||
}
|
||||
BoundRegionKind::NamedAnon(symbol) => {
|
||||
write!(f, "{:?}.NamedAnon({:?})", self.var, symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BoundRegionKind {
|
||||
pub fn is_named(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
self.get_name(tcx).is_some()
|
||||
}
|
||||
|
||||
pub fn get_name(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
|
||||
match *self {
|
||||
BoundRegionKind::Named(def_id) => {
|
||||
let name = tcx.item_name(def_id);
|
||||
if name != kw::UnderscoreLifetime { Some(name) } else { None }
|
||||
}
|
||||
BoundRegionKind::NamedAnon(name) => Some(name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> Option<DefId> {
|
||||
match *self {
|
||||
BoundRegionKind::Named(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some types are used a lot. Make sure they don't unintentionally get bigger.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod size_asserts {
|
||||
|
|
|
|||
|
|
@ -65,21 +65,6 @@ impl<'tcx> fmt::Debug for ty::adjustment::PatAdjustment<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ty::BoundRegionKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ty::BoundRegionKind::Anon => write!(f, "BrAnon"),
|
||||
ty::BoundRegionKind::NamedAnon(name) => {
|
||||
write!(f, "BrNamedAnon({name})")
|
||||
}
|
||||
ty::BoundRegionKind::Named(did) => {
|
||||
write!(f, "BrNamed({did:?})")
|
||||
}
|
||||
ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ty::LateParamRegion {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ReLateParam({:?}, {:?})", self.scope, self.kind)
|
||||
|
|
@ -175,15 +160,6 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ty::BoundTy {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.kind {
|
||||
ty::BoundTyKind::Anon => write!(f, "{:?}", self.var),
|
||||
ty::BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for GenericArg<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.kind() {
|
||||
|
|
@ -255,7 +231,8 @@ TrivialTypeTraversalImpls! {
|
|||
crate::ty::AdtKind,
|
||||
crate::ty::AssocItem,
|
||||
crate::ty::AssocKind,
|
||||
crate::ty::BoundRegion,
|
||||
crate::ty::BoundRegion<'tcx>,
|
||||
crate::ty::BoundTy<'tcx>,
|
||||
crate::ty::ScalarInt,
|
||||
crate::ty::UserTypeAnnotationIndex,
|
||||
crate::ty::abstract_const::NotConstEvaluatable,
|
||||
|
|
@ -284,7 +261,6 @@ TrivialTypeTraversalImpls! {
|
|||
TrivialTypeTraversalAndLiftImpls! {
|
||||
// tidy-alphabetical-start
|
||||
crate::mir::RuntimeChecks,
|
||||
crate::ty::BoundTy,
|
||||
crate::ty::ParamTy,
|
||||
crate::ty::instance::ReifyReason,
|
||||
rustc_hir::def_id::DefId,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, kw, sym};
|
||||
use rustc_type_ir::TyKind::*;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::walk::TypeWalker;
|
||||
|
|
@ -26,8 +26,8 @@ use crate::infer::canonical::Canonical;
|
|||
use crate::traits::ObligationCause;
|
||||
use crate::ty::InferTy::*;
|
||||
use crate::ty::{
|
||||
self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
|
||||
Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
|
||||
self, AdtDef, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, Region, Ty,
|
||||
TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
|
||||
};
|
||||
|
||||
// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
|
||||
|
|
@ -40,6 +40,15 @@ pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
|
|||
pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
|
||||
pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
|
||||
pub type Placeholder<'tcx, T> = ir::Placeholder<TyCtxt<'tcx>, T>;
|
||||
pub type PlaceholderRegion<'tcx> = ir::PlaceholderRegion<TyCtxt<'tcx>>;
|
||||
pub type PlaceholderType<'tcx> = ir::PlaceholderType<TyCtxt<'tcx>>;
|
||||
pub type PlaceholderConst<'tcx> = ir::PlaceholderConst<TyCtxt<'tcx>>;
|
||||
pub type BoundTy<'tcx> = ir::BoundTy<TyCtxt<'tcx>>;
|
||||
pub type BoundConst<'tcx> = ir::BoundConst<TyCtxt<'tcx>>;
|
||||
pub type BoundRegion<'tcx> = ir::BoundRegion<TyCtxt<'tcx>>;
|
||||
pub type BoundVariableKind<'tcx> = ir::BoundVariableKind<TyCtxt<'tcx>>;
|
||||
pub type BoundRegionKind<'tcx> = ir::BoundRegionKind<TyCtxt<'tcx>>;
|
||||
pub type BoundTyKind<'tcx> = ir::BoundTyKind<TyCtxt<'tcx>>;
|
||||
|
||||
pub trait Article {
|
||||
fn article(&self) -> &'static str;
|
||||
|
|
@ -257,37 +266,6 @@ impl<'tcx> InlineConstArgs<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundVariableKind {
|
||||
Ty(BoundTyKind),
|
||||
Region(BoundRegionKind),
|
||||
Const,
|
||||
}
|
||||
|
||||
impl BoundVariableKind {
|
||||
pub fn expect_region(self) -> BoundRegionKind {
|
||||
match self {
|
||||
BoundVariableKind::Region(lt) => lt,
|
||||
_ => bug!("expected a region, but found another kind"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_ty(self) -> BoundTyKind {
|
||||
match self {
|
||||
BoundVariableKind::Ty(ty) => ty,
|
||||
_ => bug!("expected a type, but found another kind"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_const(self) {
|
||||
match self {
|
||||
BoundVariableKind::Const => (),
|
||||
_ => bug!("expected a const, but found another kind"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
|
||||
pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
|
||||
|
||||
|
|
@ -381,30 +359,6 @@ impl ParamConst {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub struct BoundTy {
|
||||
pub var: BoundVar,
|
||||
pub kind: BoundTyKind,
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundTy {
|
||||
fn var(self) -> BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
fn assert_eq(self, var: ty::BoundVariableKind) {
|
||||
assert_eq!(self.kind, var.expect_ty())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundTyKind {
|
||||
Anon,
|
||||
Param(DefId),
|
||||
}
|
||||
|
||||
/// Constructors for `Ty`
|
||||
impl<'tcx> Ty<'tcx> {
|
||||
/// Avoid using this in favour of more specific `new_*` methods, where possible.
|
||||
|
|
@ -479,7 +433,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
pub fn new_bound(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
index: ty::DebruijnIndex,
|
||||
bound_ty: ty::BoundTy,
|
||||
bound_ty: ty::BoundTy<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
// Use a pre-interned one when possible.
|
||||
if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty
|
||||
|
|
@ -961,7 +915,11 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
|||
Ty::new_placeholder(tcx, placeholder)
|
||||
}
|
||||
|
||||
fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self {
|
||||
fn new_bound(
|
||||
interner: TyCtxt<'tcx>,
|
||||
debruijn: ty::DebruijnIndex,
|
||||
var: ty::BoundTy<'tcx>,
|
||||
) -> Self {
|
||||
Ty::new_bound(interner, debruijn, var)
|
||||
}
|
||||
|
||||
|
|
@ -2135,6 +2093,12 @@ impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Symbol<TyCtxt<'tcx>> for Symbol {
|
||||
fn is_kw_underscore_lifetime(self) -> bool {
|
||||
self == kw::UnderscoreLifetime
|
||||
}
|
||||
}
|
||||
|
||||
// Some types are used a lot. Make sure they don't unintentionally get bigger.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod size_asserts {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
pub fn collect_constrained_late_bound_regions<T>(
|
||||
self,
|
||||
value: Binder<'tcx, T>,
|
||||
) -> FxIndexSet<ty::BoundRegionKind>
|
||||
) -> FxIndexSet<ty::BoundRegionKind<'tcx>>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -124,7 +124,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
pub fn collect_referenced_late_bound_regions<T>(
|
||||
self,
|
||||
value: Binder<'tcx, T>,
|
||||
) -> FxIndexSet<ty::BoundRegionKind>
|
||||
) -> FxIndexSet<ty::BoundRegionKind<'tcx>>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -135,7 +135,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self,
|
||||
value: Binder<'tcx, T>,
|
||||
just_constrained: bool,
|
||||
) -> FxIndexSet<ty::BoundRegionKind>
|
||||
) -> FxIndexSet<ty::BoundRegionKind<'tcx>>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -149,9 +149,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Collects all the late-bound regions at the innermost binding level
|
||||
/// into a hash set.
|
||||
struct LateBoundRegionsCollector {
|
||||
struct LateBoundRegionsCollector<'tcx> {
|
||||
current_index: ty::DebruijnIndex,
|
||||
regions: FxIndexSet<ty::BoundRegionKind>,
|
||||
regions: FxIndexSet<ty::BoundRegionKind<'tcx>>,
|
||||
|
||||
/// `true` if we only want regions that are known to be
|
||||
/// "constrained" when you equate this type with another type. In
|
||||
|
|
@ -163,13 +163,13 @@ struct LateBoundRegionsCollector {
|
|||
just_constrained: bool,
|
||||
}
|
||||
|
||||
impl LateBoundRegionsCollector {
|
||||
impl LateBoundRegionsCollector<'_> {
|
||||
fn new(just_constrained: bool) -> Self {
|
||||
Self { current_index: ty::INNERMOST, regions: Default::default(), just_constrained }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector<'tcx> {
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) {
|
||||
self.current_index.shift_in(1);
|
||||
t.super_visit_with(self);
|
||||
|
|
|
|||
|
|
@ -1086,11 +1086,6 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
|
|||
|
||||
let Some((name, decl_span)) = self.checked_places.names[index] else { continue };
|
||||
|
||||
// By convention, underscore-prefixed bindings are explicitly allowed to be unused.
|
||||
if name.as_str().starts_with('_') {
|
||||
continue;
|
||||
}
|
||||
|
||||
let is_maybe_drop_guard = maybe_drop_guard(
|
||||
tcx,
|
||||
self.typing_env,
|
||||
|
|
@ -1118,6 +1113,11 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
|
|||
continue;
|
||||
};
|
||||
|
||||
// By convention, underscore-prefixed bindings are allowed to be unused explicitly
|
||||
if name.as_str().starts_with('_') {
|
||||
break;
|
||||
}
|
||||
|
||||
match kind {
|
||||
AccessKind::Assign => {
|
||||
let suggestion = annotate_mut_binding_to_immutable_binding(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use rustc_type_ir::inherent::*;
|
|||
use rustc_type_ir::solve::{Goal, QueryInput};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, Flags, InferCtxtLike,
|
||||
Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
Interner, PlaceholderConst, PlaceholderType, TypeFlags, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
|
|
@ -357,13 +358,13 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
},
|
||||
ty::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy(
|
||||
PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
),
|
||||
CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
|
||||
},
|
||||
ty::Param(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy(
|
||||
PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
),
|
||||
CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"),
|
||||
},
|
||||
|
|
@ -513,17 +514,23 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
|
|||
ty::InferConst::Fresh(_) => todo!(),
|
||||
},
|
||||
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst(
|
||||
PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
),
|
||||
CanonicalizeMode::Input { .. } => {
|
||||
CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon(
|
||||
ty::UniverseIndex::ROOT,
|
||||
self.variables.len().into(),
|
||||
))
|
||||
}
|
||||
CanonicalizeMode::Response { .. } => {
|
||||
CanonicalVarKind::PlaceholderConst(placeholder)
|
||||
}
|
||||
},
|
||||
ty::ConstKind::Param(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst(
|
||||
PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
),
|
||||
CanonicalizeMode::Input { .. } => {
|
||||
CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon(
|
||||
ty::UniverseIndex::ROOT,
|
||||
self.variables.len().into(),
|
||||
))
|
||||
}
|
||||
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
|
||||
},
|
||||
// FIXME: See comment above -- we could fold the region separately or something.
|
||||
|
|
|
|||
|
|
@ -177,9 +177,9 @@ where
|
|||
}
|
||||
}
|
||||
ty::GenericArgKind::Const(c) => {
|
||||
if let ty::ConstKind::Bound(index_kind, bv) = c.kind() {
|
||||
if let ty::ConstKind::Bound(index_kind, bc) = c.kind() {
|
||||
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
|
||||
opt_values[bv.var()] = Some(*original_value);
|
||||
opt_values[bc.var()] = Some(*original_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use core::panic;
|
|||
use rustc_type_ir::data_structures::IndexMap;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::{
|
||||
self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
self as ty, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType,
|
||||
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
|
||||
pub struct BoundVarReplacer<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
|
||||
|
|
@ -16,9 +16,9 @@ where
|
|||
// These three maps track the bound variable that were replaced by placeholders. It might be
|
||||
// nice to remove these since we already have the `kind` in the placeholder; we really just need
|
||||
// the `var` (but we *could* bring that into scope if we were to track them as we pass them).
|
||||
mapped_regions: IndexMap<I::PlaceholderRegion, I::BoundRegion>,
|
||||
mapped_types: IndexMap<I::PlaceholderTy, I::BoundTy>,
|
||||
mapped_consts: IndexMap<I::PlaceholderConst, I::BoundConst>,
|
||||
mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
|
||||
mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
|
||||
mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
|
||||
// The current depth relative to *this* folding, *not* the entire normalization. In other words,
|
||||
// the depth of binders we've passed here.
|
||||
current_index: ty::DebruijnIndex,
|
||||
|
|
@ -40,9 +40,9 @@ where
|
|||
value: T,
|
||||
) -> (
|
||||
T,
|
||||
IndexMap<I::PlaceholderRegion, I::BoundRegion>,
|
||||
IndexMap<I::PlaceholderTy, I::BoundTy>,
|
||||
IndexMap<I::PlaceholderConst, I::BoundConst>,
|
||||
IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
|
||||
IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
|
||||
IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
|
||||
) {
|
||||
let mut replacer = BoundVarReplacer {
|
||||
infcx,
|
||||
|
|
@ -103,7 +103,7 @@ where
|
|||
if debruijn >= self.current_index =>
|
||||
{
|
||||
let universe = self.universe_for(debruijn);
|
||||
let p = PlaceholderLike::new(universe, br);
|
||||
let p = PlaceholderRegion::new(universe, br);
|
||||
self.mapped_regions.insert(p, br);
|
||||
Region::new_placeholder(self.cx(), p)
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ where
|
|||
if debruijn >= self.current_index =>
|
||||
{
|
||||
let universe = self.universe_for(debruijn);
|
||||
let p = PlaceholderLike::new(universe, bound_ty);
|
||||
let p = PlaceholderType::new(universe, bound_ty);
|
||||
self.mapped_types.insert(p, bound_ty);
|
||||
Ty::new_placeholder(self.cx(), p)
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ where
|
|||
if debruijn >= self.current_index =>
|
||||
{
|
||||
let universe = self.universe_for(debruijn);
|
||||
let p = PlaceholderLike::new(universe, bound_const);
|
||||
let p = PlaceholderConst::new(universe, bound_const);
|
||||
self.mapped_consts.insert(p, bound_const);
|
||||
Const::new_placeholder(self.cx(), p)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,8 +302,6 @@ passes_layout_align =
|
|||
align: {$align}
|
||||
passes_layout_homogeneous_aggregate =
|
||||
homogeneous_aggregate: {$homogeneous_aggregate}
|
||||
passes_layout_invalid_attribute =
|
||||
`#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
|
||||
passes_layout_of =
|
||||
layout_of({$normalized_ty}) = {$ty_layout}
|
||||
passes_layout_size =
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
span: attr_span,
|
||||
stability: Stability { level, feature },
|
||||
}
|
||||
| AttributeKind::ConstStability {
|
||||
| AttributeKind::RustcConstStability {
|
||||
span: attr_span,
|
||||
stability: PartialConstStability { level, feature, .. },
|
||||
},
|
||||
|
|
@ -168,7 +168,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span) | AttributeKind::AllowInternalUnstable(.., attr_span)) => {
|
||||
self.check_macro_only_attr(*attr_span, span, target, attrs)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::AllowConstFnUnstable(_, first_span)) => {
|
||||
Attribute::Parsed(AttributeKind::RustcAllowConstFnUnstable(_, first_span)) => {
|
||||
self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::Deprecation {span: attr_span, .. }) => {
|
||||
|
|
@ -180,7 +180,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => {
|
||||
self.check_object_lifetime_default(hir_id);
|
||||
}
|
||||
&Attribute::Parsed(AttributeKind::PubTransparent(attr_span)) => {
|
||||
&Attribute::Parsed(AttributeKind::RustcPubTransparent(attr_span)) => {
|
||||
self.check_rustc_pub_transparent(attr_span, span, attrs)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => {
|
||||
|
|
@ -226,29 +226,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)},
|
||||
Attribute::Parsed(
|
||||
// tidy-alphabetical-start
|
||||
AttributeKind::AllowIncoherentImpl(..)
|
||||
| AttributeKind::AsPtr(..)
|
||||
AttributeKind::RustcAllowIncoherentImpl(..)
|
||||
| AttributeKind::AutomaticallyDerived(..)
|
||||
| AttributeKind::BodyStability { .. }
|
||||
| AttributeKind::CfgAttrTrace
|
||||
| AttributeKind::CfgTrace(..)
|
||||
| AttributeKind::CfiEncoding { .. }
|
||||
| AttributeKind::Coinductive(..)
|
||||
| AttributeKind::Cold(..)
|
||||
| AttributeKind::CollapseDebugInfo(..)
|
||||
| AttributeKind::CompilerBuiltins
|
||||
| AttributeKind::Confusables { .. }
|
||||
| AttributeKind::ConstStabilityIndirect
|
||||
| AttributeKind::Coroutine(..)
|
||||
| AttributeKind::Coverage (..)
|
||||
| AttributeKind::CrateName { .. }
|
||||
| AttributeKind::CrateType(..)
|
||||
| AttributeKind::DebuggerVisualizer(..)
|
||||
| AttributeKind::DenyExplicitImpl(..)
|
||||
// `#[doc]` is actually a lot more than just doc comments, so is checked below
|
||||
| AttributeKind::DocComment {..}
|
||||
| AttributeKind::Dummy
|
||||
| AttributeKind::DynIncompatibleTrait(..)
|
||||
| AttributeKind::EiiDeclaration { .. }
|
||||
| AttributeKind::EiiForeignItem
|
||||
| AttributeKind::ExportName { .. }
|
||||
|
|
@ -262,7 +254,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::LinkSection { .. }
|
||||
| AttributeKind::Linkage(..)
|
||||
| AttributeKind::MacroEscape( .. )
|
||||
| AttributeKind::MacroTransparency(_)
|
||||
| AttributeKind::MacroUse { .. }
|
||||
| AttributeKind::Marker(..)
|
||||
| AttributeKind::MoveSizeLimit { .. }
|
||||
|
|
@ -277,12 +268,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::NoMain
|
||||
| AttributeKind::NoMangle(..)
|
||||
| AttributeKind::NoStd { .. }
|
||||
| AttributeKind::ObjcClass { .. }
|
||||
| AttributeKind::ObjcSelector { .. }
|
||||
| AttributeKind::Optimize(..)
|
||||
| AttributeKind::PanicRuntime
|
||||
| AttributeKind::ParenSugar(..)
|
||||
| AttributeKind::PassByValue (..)
|
||||
| AttributeKind::PatchableFunctionEntry { .. }
|
||||
| AttributeKind::Path(..)
|
||||
| AttributeKind::PatternComplexityLimit { .. }
|
||||
|
|
@ -295,46 +282,60 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::RustcAllocator
|
||||
| AttributeKind::RustcAllocatorZeroed
|
||||
| AttributeKind::RustcAllocatorZeroedVariant { .. }
|
||||
| AttributeKind::RustcAsPtr(..)
|
||||
| AttributeKind::RustcBodyStability { .. }
|
||||
| AttributeKind::RustcBuiltinMacro { .. }
|
||||
| AttributeKind::RustcCoherenceIsCore(..)
|
||||
| AttributeKind::RustcCoinductive(..)
|
||||
| AttributeKind::RustcConfusables { .. }
|
||||
| AttributeKind::RustcConstStabilityIndirect
|
||||
| AttributeKind::RustcDeallocator
|
||||
| AttributeKind::RustcDenyExplicitImpl(..)
|
||||
| AttributeKind::RustcDummy
|
||||
| AttributeKind::RustcDumpDefParents
|
||||
| AttributeKind::RustcDumpItemBounds
|
||||
| AttributeKind::RustcDumpPredicates
|
||||
| AttributeKind::RustcDumpUserArgs
|
||||
| AttributeKind::RustcDumpVtable(..)
|
||||
| AttributeKind::RustcDynIncompatibleTrait(..)
|
||||
| AttributeKind::RustcHasIncoherentInherentImpls
|
||||
| AttributeKind::RustcLayout(..)
|
||||
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
|
||||
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
|
||||
| AttributeKind::RustcLintOptDenyFieldAccess { .. }
|
||||
| AttributeKind::RustcLintOptTy
|
||||
| AttributeKind::RustcLintQueryInstability
|
||||
| AttributeKind::RustcLintUntrackedQueryInformation
|
||||
| AttributeKind::RustcMacroTransparency(_)
|
||||
| AttributeKind::RustcMain
|
||||
| AttributeKind::RustcNeverReturnsNullPointer
|
||||
| AttributeKind::RustcNoImplicitAutorefs
|
||||
| AttributeKind::RustcNonConstTraitMethod
|
||||
| AttributeKind::RustcNounwind
|
||||
| AttributeKind::RustcObjcClass { .. }
|
||||
| AttributeKind::RustcObjcSelector { .. }
|
||||
| AttributeKind::RustcOffloadKernel
|
||||
| AttributeKind::RustcParenSugar(..)
|
||||
| AttributeKind::RustcPassByValue (..)
|
||||
| AttributeKind::RustcPassIndirectlyInNonRusticAbis(..)
|
||||
| AttributeKind::RustcReallocator
|
||||
| AttributeKind::RustcScalableVector { .. }
|
||||
| AttributeKind::RustcShouldNotBeCalledOnConstItems(..)
|
||||
| AttributeKind::RustcSimdMonomorphizeLaneLimit(..)
|
||||
| AttributeKind::RustcSkipDuringMethodDispatch { .. }
|
||||
| AttributeKind::RustcSpecializationTrait(..)
|
||||
| AttributeKind::RustcStdInternalSymbol (..)
|
||||
| AttributeKind::RustcUnsafeSpecializationMarker(..)
|
||||
| AttributeKind::RustcVariance
|
||||
| AttributeKind::RustcVarianceOfOpaques
|
||||
| AttributeKind::ShouldPanic { .. }
|
||||
| AttributeKind::SkipDuringMethodDispatch { .. }
|
||||
| AttributeKind::SpecializationTrait(..)
|
||||
| AttributeKind::StdInternalSymbol (..)
|
||||
| AttributeKind::ThreadLocal
|
||||
| AttributeKind::TypeConst{..}
|
||||
| AttributeKind::TypeLengthLimit { .. }
|
||||
| AttributeKind::UnsafeSpecializationMarker(..)
|
||||
| AttributeKind::UnstableFeatureBound(..)
|
||||
| AttributeKind::Used { .. }
|
||||
| AttributeKind::WindowsSubsystem(..)
|
||||
// tidy-alphabetical-end
|
||||
|
||||
) => { /* do nothing */ }
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
|
|
|
|||
|
|
@ -519,13 +519,6 @@ pub(crate) struct LayoutOf<'tcx> {
|
|||
pub ty_layout: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_layout_invalid_attribute)]
|
||||
pub(crate) struct LayoutInvalidAttribute {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_abi_of)]
|
||||
pub(crate) struct AbiOf {
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
use rustc_abi::{HasDataLayout, TargetDataLayout};
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_hir::attrs::{AttributeKind, RustcLayoutType};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::TyCtxtInferExt;
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
use crate::errors::{
|
||||
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
|
||||
LayoutSize, UnrecognizedArgument,
|
||||
};
|
||||
use crate::errors::{LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutOf, LayoutSize};
|
||||
|
||||
pub fn test_layout(tcx: TyCtxt<'_>) {
|
||||
if !tcx.features().rustc_attrs() {
|
||||
|
|
@ -22,14 +20,14 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
|
|||
return;
|
||||
}
|
||||
for id in tcx.hir_crate_items(()).definitions() {
|
||||
for attr in tcx.get_attrs(id, sym::rustc_layout) {
|
||||
match tcx.def_kind(id) {
|
||||
DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union => {
|
||||
dump_layout_of(tcx, id, attr);
|
||||
}
|
||||
_ => {
|
||||
tcx.dcx().emit_err(LayoutInvalidAttribute { span: tcx.def_span(id) });
|
||||
}
|
||||
let attrs = tcx.get_all_attrs(id);
|
||||
if let Some(attrs) = find_attr!(attrs, AttributeKind::RustcLayout(attrs) => attrs) {
|
||||
// Attribute parsing handles error reporting
|
||||
if matches!(
|
||||
tcx.def_kind(id),
|
||||
DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union
|
||||
) {
|
||||
dump_layout_of(tcx, id, attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,7 +64,7 @@ pub fn ensure_wf<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
||||
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attrs: &[RustcLayoutType]) {
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
|
||||
let ty = tcx.type_of(item_def_id).instantiate_identity();
|
||||
let span = tcx.def_span(item_def_id.to_def_id());
|
||||
|
|
@ -75,32 +73,29 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
|||
}
|
||||
match tcx.layout_of(typing_env.as_query_input(ty)) {
|
||||
Ok(ty_layout) => {
|
||||
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
|
||||
// The `..` are the names of fields to dump.
|
||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||
for meta_item in meta_items {
|
||||
match meta_item.name() {
|
||||
for attr in attrs {
|
||||
match attr {
|
||||
// FIXME: this never was about ABI and now this dump arg is confusing
|
||||
Some(sym::abi) => {
|
||||
RustcLayoutType::Abi => {
|
||||
tcx.dcx().emit_err(LayoutAbi {
|
||||
span,
|
||||
abi: format!("{:?}", ty_layout.backend_repr),
|
||||
});
|
||||
}
|
||||
|
||||
Some(sym::align) => {
|
||||
RustcLayoutType::Align => {
|
||||
tcx.dcx().emit_err(LayoutAlign {
|
||||
span,
|
||||
align: format!("{:?}", ty_layout.align),
|
||||
});
|
||||
}
|
||||
|
||||
Some(sym::size) => {
|
||||
RustcLayoutType::Size => {
|
||||
tcx.dcx()
|
||||
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
|
||||
}
|
||||
|
||||
Some(sym::homogeneous_aggregate) => {
|
||||
RustcLayoutType::HomogenousAggregate => {
|
||||
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
|
||||
span,
|
||||
homogeneous_aggregate: format!(
|
||||
|
|
@ -111,16 +106,12 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
|||
});
|
||||
}
|
||||
|
||||
Some(sym::debug) => {
|
||||
RustcLayoutType::Debug => {
|
||||
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
|
||||
// FIXME: using the `Debug` impl here isn't ideal.
|
||||
let ty_layout = format!("{:#?}", *ty_layout);
|
||||
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
|
||||
}
|
||||
|
||||
_ => {
|
||||
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ impl<'tcx> LibFeatureCollector<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::Stability { stability, span }) => {
|
||||
(stability.feature, stability.level, *span)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::ConstStability { stability, span }) => {
|
||||
Attribute::Parsed(AttributeKind::RustcConstStability { stability, span }) => {
|
||||
(stability.feature, stability.level, *span)
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::BodyStability { stability, span }) => {
|
||||
Attribute::Parsed(AttributeKind::RustcBodyStability { stability, span }) => {
|
||||
(stability.feature, stability.level, *span)
|
||||
}
|
||||
_ => return None,
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ fn lookup_default_body_stability(
|
|||
|
||||
let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
|
||||
// FIXME: check that this item can have body stability
|
||||
find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability)
|
||||
find_attr!(attrs, AttributeKind::RustcBodyStability { stability, .. } => *stability)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
|
|
@ -214,7 +214,7 @@ fn lookup_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ConstSt
|
|||
{
|
||||
let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
|
||||
let const_stability_indirect =
|
||||
find_attr!(attrs, AttributeKind::ConstStabilityIndirect);
|
||||
find_attr!(attrs, AttributeKind::RustcConstStabilityIndirect);
|
||||
return Some(ConstStability::unmarked(const_stability_indirect, parent_stab));
|
||||
}
|
||||
}
|
||||
|
|
@ -223,9 +223,9 @@ fn lookup_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ConstSt
|
|||
}
|
||||
|
||||
let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
|
||||
let const_stability_indirect = find_attr!(attrs, AttributeKind::ConstStabilityIndirect);
|
||||
let const_stability_indirect = find_attr!(attrs, AttributeKind::RustcConstStabilityIndirect);
|
||||
let const_stab =
|
||||
find_attr!(attrs, AttributeKind::ConstStability { stability, span: _ } => *stability);
|
||||
find_attr!(attrs, AttributeKind::RustcConstStability { stability, span: _ } => *stability);
|
||||
|
||||
// After checking the immediate attributes, get rid of the span and compute implied
|
||||
// const stability: inherit feature gate from regular stability.
|
||||
|
|
@ -393,7 +393,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
|||
if let Some(fn_sig) = fn_sig
|
||||
&& !fn_sig.header.is_const()
|
||||
&& const_stab.is_some()
|
||||
&& find_attr_span!(ConstStability).is_some()
|
||||
&& find_attr_span!(RustcConstStability).is_some()
|
||||
{
|
||||
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
|
||||
}
|
||||
|
|
@ -403,7 +403,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
|||
&& let Some(fn_sig) = fn_sig
|
||||
&& const_stab.is_const_stable()
|
||||
&& !stab.is_some_and(|s| s.is_stable())
|
||||
&& let Some(const_span) = find_attr_span!(ConstStability)
|
||||
&& let Some(const_span) = find_attr_span!(RustcConstStability)
|
||||
{
|
||||
self.tcx
|
||||
.dcx()
|
||||
|
|
@ -413,7 +413,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
|||
if let Some(stab) = &const_stab
|
||||
&& stab.is_const_stable()
|
||||
&& stab.const_stable_indirect
|
||||
&& let Some(span) = find_attr_span!(ConstStability)
|
||||
&& let Some(span) = find_attr_span!(RustcConstStability)
|
||||
{
|
||||
self.tcx.dcx().emit_err(errors::RustcConstStableIndirectPairing { span });
|
||||
}
|
||||
|
|
@ -602,7 +602,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||
let stab = find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
|
||||
|
||||
// FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
|
||||
let const_stab = find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability);
|
||||
let const_stab = find_attr!(attrs, AttributeKind::RustcConstStability{stability, ..} => *stability);
|
||||
|
||||
let unstable_feature_stab =
|
||||
find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(default_field_values)]
|
||||
#![feature(try_blocks)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
@ -29,8 +30,8 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility,
|
|||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::{
|
||||
self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitor,
|
||||
self, AssocContainer, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitor,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
|
|
@ -311,6 +312,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn assoc_has_type_of(tcx: TyCtxt<'_>, item: &ty::AssocItem) -> bool {
|
||||
if let ty::AssocKind::Type { data: ty::AssocTypeData::Normal(..) } = item.kind
|
||||
&& let hir::Node::TraitItem(item) =
|
||||
tcx.hir_node(tcx.local_def_id_to_hir_id(item.def_id.expect_local()))
|
||||
&& let hir::TraitItemKind::Type(_, None) = item.kind
|
||||
{
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
|
||||
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
|
||||
}
|
||||
|
|
@ -497,7 +510,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
|||
let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
|
||||
let attrs = self.tcx.hir_attrs(hir_id);
|
||||
|
||||
if find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
|
||||
if find_attr!(attrs, AttributeKind::RustcMacroTransparency(x) => *x)
|
||||
.unwrap_or(Transparency::fallback(md.macro_rules))
|
||||
!= Transparency::Opaque
|
||||
{
|
||||
|
|
@ -639,6 +652,19 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> EmbargoVisitor<'tcx> {
|
||||
fn check_assoc_item(&mut self, item: &ty::AssocItem, item_ev: EffectiveVisibility) {
|
||||
let def_id = item.def_id.expect_local();
|
||||
let tcx = self.tcx;
|
||||
let mut reach = self.reach(def_id, item_ev);
|
||||
reach.generics().predicates();
|
||||
if assoc_has_type_of(tcx, item) {
|
||||
reach.ty();
|
||||
}
|
||||
if item.is_type() && item.container == AssocContainer::Trait {
|
||||
reach.bounds();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_def_id(&mut self, owner_id: OwnerId) {
|
||||
// Update levels of nested things and mark all items
|
||||
// in interfaces of reachable items as reachable.
|
||||
|
|
@ -669,22 +695,10 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
|||
self.reach(owner_id.def_id, item_ev).generics().predicates();
|
||||
|
||||
for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
|
||||
if assoc_item.is_impl_trait_in_trait() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let def_id = assoc_item.def_id.expect_local();
|
||||
self.update(def_id, item_ev, Level::Reachable);
|
||||
|
||||
let tcx = self.tcx;
|
||||
let mut reach = self.reach(def_id, item_ev);
|
||||
reach.generics().predicates();
|
||||
|
||||
if assoc_item.is_type() && !assoc_item.defaultness(tcx).has_value() {
|
||||
// No type to visit.
|
||||
} else {
|
||||
reach.ty();
|
||||
}
|
||||
self.check_assoc_item(assoc_item, item_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -722,17 +736,13 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
|||
}
|
||||
|
||||
for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
|
||||
if assoc_item.is_impl_trait_in_trait() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let def_id = assoc_item.def_id.expect_local();
|
||||
let max_vis =
|
||||
if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) };
|
||||
self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
|
||||
|
||||
if let Some(impl_item_ev) = self.get(def_id) {
|
||||
self.reach(def_id, impl_item_ev).generics().predicates().ty();
|
||||
self.check_assoc_item(assoc_item, impl_item_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -824,7 +834,12 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
|
|||
}
|
||||
|
||||
fn predicates(&mut self) -> &mut Self {
|
||||
self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id));
|
||||
self.visit_predicates(self.ev.tcx.explicit_predicates_of(self.item_def_id));
|
||||
self
|
||||
}
|
||||
|
||||
fn bounds(&mut self) -> &mut Self {
|
||||
self.visit_clauses(self.ev.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -1353,26 +1368,20 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
|||
/// The visitor checks that each component type is at least this visible.
|
||||
required_visibility: ty::Visibility,
|
||||
required_effective_vis: Option<EffectiveVisibility>,
|
||||
in_assoc_ty: bool,
|
||||
in_primary_interface: bool,
|
||||
skip_assoc_tys: bool,
|
||||
hard_error: bool = false,
|
||||
in_primary_interface: bool = true,
|
||||
skip_assoc_tys: bool = false,
|
||||
}
|
||||
|
||||
impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
||||
fn generics(&mut self) -> &mut Self {
|
||||
self.in_primary_interface = true;
|
||||
for param in &self.tcx.generics_of(self.item_def_id).own_params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
if has_default {
|
||||
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
|
||||
}
|
||||
}
|
||||
// FIXME(generic_const_exprs): May want to look inside const here
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
|
||||
}
|
||||
if let GenericParamDefKind::Const { .. } = param.kind {
|
||||
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
|
||||
}
|
||||
if let Some(default) = param.default_value(self.tcx) {
|
||||
let _ = self.visit(default.instantiate_identity());
|
||||
}
|
||||
}
|
||||
self
|
||||
|
|
@ -1427,7 +1436,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
|||
};
|
||||
|
||||
let vis = self.tcx.local_visibility(local_def_id);
|
||||
if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) {
|
||||
if self.hard_error && !vis.is_at_least(self.required_visibility, self.tcx) {
|
||||
let vis_descr = match vis {
|
||||
ty::Visibility::Public => "public",
|
||||
ty::Visibility::Restricted(vis_def_id) => {
|
||||
|
|
@ -1544,9 +1553,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
|
|||
item_def_id: def_id,
|
||||
required_visibility,
|
||||
required_effective_vis,
|
||||
in_assoc_ty: false,
|
||||
in_primary_interface: true,
|
||||
skip_assoc_tys: false,
|
||||
..
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1584,16 +1591,17 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
|
|||
) {
|
||||
let mut check = self.check(item.def_id.expect_local(), vis, effective_vis);
|
||||
|
||||
let (check_ty, is_assoc_ty) = match item.kind {
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => (true, false),
|
||||
ty::AssocKind::Type { .. } => (item.defaultness(self.tcx).has_value(), true),
|
||||
};
|
||||
|
||||
check.in_assoc_ty = is_assoc_ty;
|
||||
let is_assoc_ty = item.is_type();
|
||||
check.hard_error = is_assoc_ty && !item.is_impl_trait_in_trait();
|
||||
check.generics().predicates();
|
||||
if check_ty {
|
||||
if assoc_has_type_of(self.tcx, item) {
|
||||
check.hard_error = check.hard_error && item.defaultness(self.tcx).has_value();
|
||||
check.ty();
|
||||
}
|
||||
if is_assoc_ty && item.container == AssocContainer::Trait {
|
||||
check.hard_error = false;
|
||||
check.bounds();
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
|
||||
|
|
@ -1625,20 +1633,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
|
|||
self.check(def_id, item_visibility, effective_vis).generics().predicates();
|
||||
|
||||
for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
|
||||
if assoc_item.is_impl_trait_in_trait() {
|
||||
continue;
|
||||
}
|
||||
|
||||
self.check_assoc_item(assoc_item, item_visibility, effective_vis);
|
||||
|
||||
if assoc_item.is_type() {
|
||||
self.check(
|
||||
assoc_item.def_id.expect_local(),
|
||||
item_visibility,
|
||||
effective_vis,
|
||||
)
|
||||
.bounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
DefKind::TraitAlias => {
|
||||
|
|
@ -1712,10 +1707,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
|
|||
}
|
||||
|
||||
for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
|
||||
if assoc_item.is_impl_trait_in_trait() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let impl_item_vis = if !of_trait {
|
||||
min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ where
|
|||
}
|
||||
|
||||
impl RustcInternal for BoundVariableKind {
|
||||
type T<'tcx> = rustc_ty::BoundVariableKind;
|
||||
type T<'tcx> = rustc_ty::BoundVariableKind<'tcx>;
|
||||
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundTyKind<'tcx> {
|
||||
type T = crate::ty::BoundTyKind;
|
||||
|
||||
fn stable<'cx>(
|
||||
|
|
@ -290,7 +290,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundRegionKind<'tcx> {
|
||||
type T = crate::ty::BoundRegionKind;
|
||||
|
||||
fn stable<'cx>(
|
||||
|
|
@ -307,12 +307,12 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
|
|||
cx.tcx.item_name(*def_id).to_string(),
|
||||
),
|
||||
ty::BoundRegionKind::ClosureEnv => BoundRegionKind::BrEnv,
|
||||
ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
|
||||
ty::BoundRegionKind::NamedForPrinting(_) => bug!("only used for pretty printing"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundVariableKind<'tcx> {
|
||||
type T = crate::ty::BoundVariableKind;
|
||||
|
||||
fn stable<'cx>(
|
||||
|
|
@ -546,7 +546,7 @@ impl<'tcx> Stable<'tcx> for ty::ParamTy {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundTy {
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundTy<'tcx> {
|
||||
type T = crate::ty::BoundTy;
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -78,7 +78,10 @@ impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> {
|
|||
fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
|
||||
T: ty::CollectAndApply<
|
||||
ty::BoundVariableKind<'tcx>,
|
||||
&'tcx List<ty::BoundVariableKind<'tcx>>,
|
||||
>,
|
||||
{
|
||||
TyCtxt::mk_bound_variable_kinds_from_iter(self, iter)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,10 @@ pub trait InternalCx<'tcx>: Copy + Clone {
|
|||
fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>;
|
||||
T: ty::CollectAndApply<
|
||||
ty::BoundVariableKind<'tcx>,
|
||||
&'tcx List<ty::BoundVariableKind<'tcx>>,
|
||||
>;
|
||||
|
||||
fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>>;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use rustc_data_structures::stable_hasher::HashStable;
|
|||
use rustc_data_structures::sync::AtomicU64;
|
||||
use rustc_middle::arena::Arena;
|
||||
use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNodeIndex};
|
||||
use rustc_middle::query::erase::{Erase, erase, restore};
|
||||
use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
|
||||
use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable};
|
||||
use rustc_middle::query::{
|
||||
|
|
@ -22,7 +21,7 @@ use rustc_query_system::dep_graph::SerializedDepNodeIndex;
|
|||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_query_system::query::{
|
||||
CycleError, CycleErrorHandling, HashResult, QueryCache, QueryDispatcher, QueryMap, QueryMode,
|
||||
QueryStackDeferred, QueryState, get_query_incr, get_query_non_incr,
|
||||
QueryState, get_query_incr, get_query_non_incr,
|
||||
};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
|
||||
|
|
@ -67,7 +66,7 @@ impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDA
|
|||
|
||||
// This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`.
|
||||
impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
|
||||
QueryDispatcher for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
|
||||
QueryDispatcher<'tcx> for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
|
||||
where
|
||||
for<'a> C::Key: HashStable<StableHashingContext<'a>>,
|
||||
{
|
||||
|
|
@ -82,15 +81,12 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
|
||||
(self.vtable.cache_on_disk)(tcx, key)
|
||||
fn will_cache_on_disk_for_key(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
|
||||
self.vtable.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn query_state<'a>(
|
||||
self,
|
||||
qcx: QueryCtxt<'tcx>,
|
||||
) -> &'a QueryState<Self::Key, QueryStackDeferred<'tcx>>
|
||||
fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<'tcx, Self::Key>
|
||||
where
|
||||
QueryCtxt<'tcx>: 'a,
|
||||
{
|
||||
|
|
@ -99,7 +95,7 @@ where
|
|||
unsafe {
|
||||
&*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>)
|
||||
.byte_add(self.vtable.query_state)
|
||||
.cast::<QueryState<Self::Key, QueryStackDeferred<'tcx>>>()
|
||||
.cast::<QueryState<'tcx, Self::Key>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,21 +128,18 @@ where
|
|||
prev_index: SerializedDepNodeIndex,
|
||||
index: DepNodeIndex,
|
||||
) -> Option<Self::Value> {
|
||||
if self.vtable.can_load_from_disk {
|
||||
(self.vtable.try_load_from_disk)(qcx.tcx, key, prev_index, index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// `?` will return None immediately for queries that never cache to disk.
|
||||
self.vtable.try_load_from_disk_fn?(qcx.tcx, key, prev_index, index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn loadable_from_disk(
|
||||
fn is_loadable_from_disk(
|
||||
self,
|
||||
qcx: QueryCtxt<'tcx>,
|
||||
key: &Self::Key,
|
||||
index: SerializedDepNodeIndex,
|
||||
) -> bool {
|
||||
(self.vtable.loadable_from_disk)(qcx.tcx, key, index)
|
||||
self.vtable.is_loadable_from_disk_fn.map_or(false, |f| f(qcx.tcx, key, index))
|
||||
}
|
||||
|
||||
fn value_from_cycle_error(
|
||||
|
|
@ -212,13 +205,15 @@ where
|
|||
/// on the type `rustc_query_impl::query_impl::$name::QueryType`.
|
||||
trait QueryDispatcherUnerased<'tcx> {
|
||||
type UnerasedValue;
|
||||
type Dispatcher: QueryDispatcher<Qcx = QueryCtxt<'tcx>>;
|
||||
type Dispatcher: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>;
|
||||
|
||||
const NAME: &'static &'static str;
|
||||
|
||||
fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher;
|
||||
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue;
|
||||
fn restore_val(
|
||||
value: <Self::Dispatcher as QueryDispatcher<'tcx>>::Value,
|
||||
) -> Self::UnerasedValue;
|
||||
}
|
||||
|
||||
pub fn query_system<'a>(
|
||||
|
|
|
|||
|
|
@ -60,9 +60,7 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryContext for QueryCtxt<'tcx> {
|
||||
type QueryInfo = QueryStackDeferred<'tcx>;
|
||||
|
||||
impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> {
|
||||
#[inline]
|
||||
fn jobserver_proxy(&self) -> &Proxy {
|
||||
&self.tcx.jobserver_proxy
|
||||
|
|
@ -93,10 +91,7 @@ impl<'tcx> QueryContext for QueryCtxt<'tcx> {
|
|||
/// Prefer passing `false` to `require_complete` to avoid potential deadlocks,
|
||||
/// especially when called from within a deadlock handler, unless a
|
||||
/// complete map is needed and no deadlock is possible at this call site.
|
||||
fn collect_active_jobs(
|
||||
self,
|
||||
require_complete: bool,
|
||||
) -> Result<QueryMap<QueryStackDeferred<'tcx>>, QueryMap<QueryStackDeferred<'tcx>>> {
|
||||
fn collect_active_jobs(self, require_complete: bool) -> Result<QueryMap<'tcx>, QueryMap<'tcx>> {
|
||||
let mut jobs = QueryMap::default();
|
||||
let mut complete = true;
|
||||
|
||||
|
|
@ -281,7 +276,10 @@ macro_rules! feedable {
|
|||
|
||||
macro_rules! hash_result {
|
||||
([][$V:ty]) => {{
|
||||
Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result)))
|
||||
Some(|hcx, result| {
|
||||
let result = ::rustc_middle::query::erase::restore_val::<$V>(*result);
|
||||
::rustc_query_system::dep_graph::hash_result(hcx, &result)
|
||||
})
|
||||
}};
|
||||
([(no_hash) $($rest:tt)*][$V:ty]) => {{
|
||||
None
|
||||
|
|
@ -319,7 +317,7 @@ macro_rules! should_ever_cache_on_disk {
|
|||
};
|
||||
}
|
||||
|
||||
fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>(
|
||||
fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>(
|
||||
(tcx, key, kind, name, do_describe): (
|
||||
TyCtxt<'tcx>,
|
||||
K,
|
||||
|
|
@ -370,18 +368,16 @@ pub(crate) fn create_query_frame<
|
|||
) -> QueryStackFrame<QueryStackDeferred<'tcx>> {
|
||||
let def_id = key.key_as_def_id();
|
||||
|
||||
let hash = || {
|
||||
tcx.with_stable_hashing_context(|mut hcx| {
|
||||
let mut hasher = StableHasher::new();
|
||||
kind.as_usize().hash_stable(&mut hcx, &mut hasher);
|
||||
key.hash_stable(&mut hcx, &mut hasher);
|
||||
hasher.finish::<Hash64>()
|
||||
})
|
||||
};
|
||||
let hash = tcx.with_stable_hashing_context(|mut hcx| {
|
||||
let mut hasher = StableHasher::new();
|
||||
kind.as_usize().hash_stable(&mut hcx, &mut hasher);
|
||||
key.hash_stable(&mut hcx, &mut hasher);
|
||||
hasher.finish::<Hash64>()
|
||||
});
|
||||
let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();
|
||||
|
||||
let info =
|
||||
QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra);
|
||||
QueryStackDeferred::new((tcx, key, kind, name, do_describe), mk_query_stack_frame_extra);
|
||||
|
||||
QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle)
|
||||
}
|
||||
|
|
@ -400,7 +396,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
|
|||
assert!(query.query_state(qcx).all_inactive());
|
||||
let cache = query.query_cache(qcx);
|
||||
cache.iter(&mut |key, value, dep_node| {
|
||||
if query.cache_on_disk(qcx.tcx, key) {
|
||||
if query.will_cache_on_disk_for_key(qcx.tcx, key) {
|
||||
let dep_node = SerializedDepNodeIndex::new(dep_node.index());
|
||||
|
||||
// Record position of the cache entry.
|
||||
|
|
@ -414,7 +410,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
|
|||
}
|
||||
|
||||
pub(crate) fn query_key_hash_verify<'tcx>(
|
||||
query: impl QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
query: impl QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>,
|
||||
qcx: QueryCtxt<'tcx>,
|
||||
) {
|
||||
let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());
|
||||
|
|
@ -442,14 +438,14 @@ pub(crate) fn query_key_hash_verify<'tcx>(
|
|||
|
||||
fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>,
|
||||
{
|
||||
debug_assert!(tcx.dep_graph.is_green(&dep_node));
|
||||
|
||||
let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
|
||||
panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
|
||||
});
|
||||
if query.cache_on_disk(tcx, &key) {
|
||||
if query.will_cache_on_disk_for_key(tcx, &key) {
|
||||
let _ = query.execute_query(tcx, key);
|
||||
}
|
||||
}
|
||||
|
|
@ -488,7 +484,7 @@ where
|
|||
|
||||
fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
|
||||
where
|
||||
Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>,
|
||||
{
|
||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||
// `DepNode::codegen_unit`:
|
||||
|
|
@ -597,6 +593,7 @@ macro_rules! define_queries {
|
|||
pub(crate) mod query_impl { $(pub(crate) mod $name {
|
||||
use super::super::*;
|
||||
use std::marker::PhantomData;
|
||||
use ::rustc_middle::query::erase::{self, Erased};
|
||||
|
||||
pub(crate) mod get_query_incr {
|
||||
use super::*;
|
||||
|
|
@ -609,7 +606,7 @@ macro_rules! define_queries {
|
|||
span: Span,
|
||||
key: queries::$name::Key<'tcx>,
|
||||
mode: QueryMode,
|
||||
) -> Option<Erase<queries::$name::Value<'tcx>>> {
|
||||
) -> Option<Erased<queries::$name::Value<'tcx>>> {
|
||||
#[cfg(debug_assertions)]
|
||||
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
|
||||
get_query_incr(
|
||||
|
|
@ -631,7 +628,7 @@ macro_rules! define_queries {
|
|||
span: Span,
|
||||
key: queries::$name::Key<'tcx>,
|
||||
__mode: QueryMode,
|
||||
) -> Option<Erase<queries::$name::Value<'tcx>>> {
|
||||
) -> Option<Erased<queries::$name::Value<'tcx>>> {
|
||||
Some(get_query_non_incr(
|
||||
QueryType::query_dispatcher(tcx),
|
||||
QueryCtxt::new(tcx),
|
||||
|
|
@ -651,8 +648,12 @@ macro_rules! define_queries {
|
|||
cycle_error_handling: cycle_error_handling!([$($modifiers)*]),
|
||||
query_state: std::mem::offset_of!(QueryStates<'tcx>, $name),
|
||||
query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name),
|
||||
cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
|
||||
execute_query: |tcx, key| erase(tcx.$name(key)),
|
||||
will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] {
|
||||
Some(::rustc_middle::query::cached::$name)
|
||||
} {
|
||||
None
|
||||
}),
|
||||
execute_query: |tcx, key| erase::erase_val(tcx.$name(key)),
|
||||
compute: |tcx, key| {
|
||||
#[cfg(debug_assertions)]
|
||||
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
|
||||
|
|
@ -669,39 +670,36 @@ macro_rules! define_queries {
|
|||
)
|
||||
)
|
||||
},
|
||||
can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
|
||||
try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
|
||||
|tcx, key, prev_index, index| {
|
||||
if ::rustc_middle::query::cached::$name(tcx, key) {
|
||||
let value = $crate::plumbing::try_load_from_disk::<
|
||||
queries::$name::ProvidedValue<'tcx>
|
||||
>(
|
||||
tcx,
|
||||
prev_index,
|
||||
index,
|
||||
);
|
||||
value.map(|value| queries::$name::provided_to_erased(tcx, value))
|
||||
} else {
|
||||
None
|
||||
try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] {
|
||||
Some(|tcx, key, prev_index, index| {
|
||||
// Check the `cache_on_disk_if` condition for this key.
|
||||
if !::rustc_middle::query::cached::$name(tcx, key) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let value: queries::$name::ProvidedValue<'tcx> =
|
||||
$crate::plumbing::try_load_from_disk(tcx, prev_index, index)?;
|
||||
|
||||
// Arena-alloc the value if appropriate, and erase it.
|
||||
Some(queries::$name::provided_to_erased(tcx, value))
|
||||
})
|
||||
} {
|
||||
|_tcx, _key, _prev_index, _index| None
|
||||
None
|
||||
}),
|
||||
is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] {
|
||||
Some(|tcx, key, index| -> bool {
|
||||
::rustc_middle::query::cached::$name(tcx, key) &&
|
||||
$crate::plumbing::loadable_from_disk(tcx, index)
|
||||
})
|
||||
} {
|
||||
None
|
||||
}),
|
||||
value_from_cycle_error: |tcx, cycle, guar| {
|
||||
let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar);
|
||||
erase(result)
|
||||
},
|
||||
loadable_from_disk: |_tcx, _key, _index| {
|
||||
should_ever_cache_on_disk!([$($modifiers)*] {
|
||||
::rustc_middle::query::cached::$name(_tcx, _key) &&
|
||||
$crate::plumbing::loadable_from_disk(_tcx, _index)
|
||||
} {
|
||||
false
|
||||
})
|
||||
erase::erase_val(result)
|
||||
},
|
||||
hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
|
||||
format_value: |value| format!("{:?}", restore::<queries::$name::Value<'tcx>>(*value)),
|
||||
format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -730,14 +728,14 @@ macro_rules! define_queries {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue {
|
||||
restore::<queries::$name::Value<'tcx>>(value)
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher<'tcx>>::Value) -> Self::UnerasedValue {
|
||||
erase::restore_val::<queries::$name::Value<'tcx>>(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn collect_active_jobs<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
qmap: &mut QueryMap<QueryStackDeferred<'tcx>>,
|
||||
qmap: &mut QueryMap<'tcx>,
|
||||
require_complete: bool,
|
||||
) -> Option<()> {
|
||||
let make_query = |tcx, key| {
|
||||
|
|
@ -821,7 +819,7 @@ macro_rules! define_queries {
|
|||
// These arrays are used for iteration and can't be indexed by `DepKind`.
|
||||
|
||||
const COLLECT_ACTIVE_JOBS: &[
|
||||
for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<QueryStackDeferred<'tcx>>, bool) -> Option<()>
|
||||
for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, bool) -> Option<()>
|
||||
] =
|
||||
&[$(query_impl::$name::collect_active_jobs),*];
|
||||
|
||||
|
|
|
|||
|
|
@ -519,7 +519,11 @@ impl<D: Deps> DepGraph<D> {
|
|||
/// This encodes a diagnostic by creating a node with an unique index and associating
|
||||
/// `diagnostic` with it, for use in the next session.
|
||||
#[inline]
|
||||
pub fn record_diagnostic<Qcx: QueryContext>(&self, qcx: Qcx, diagnostic: &DiagInner) {
|
||||
pub fn record_diagnostic<'tcx, Qcx: QueryContext<'tcx>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
diagnostic: &DiagInner,
|
||||
) {
|
||||
if let Some(ref data) = self.data {
|
||||
D::read_deps(|task_deps| match task_deps {
|
||||
TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return,
|
||||
|
|
@ -532,7 +536,7 @@ impl<D: Deps> DepGraph<D> {
|
|||
/// This forces a diagnostic node green by running its side effect. `prev_index` would
|
||||
/// refer to a node created used `encode_diagnostic` in the previous session.
|
||||
#[inline]
|
||||
pub fn force_diagnostic_node<Qcx: QueryContext>(
|
||||
pub fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
|
|
@ -669,7 +673,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||
/// This encodes a diagnostic by creating a node with an unique index and associating
|
||||
/// `diagnostic` with it, for use in the next session.
|
||||
#[inline]
|
||||
fn encode_diagnostic<Qcx: QueryContext>(
|
||||
fn encode_diagnostic<'tcx, Qcx: QueryContext<'tcx>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
diagnostic: &DiagInner,
|
||||
|
|
@ -693,7 +697,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||
/// This forces a diagnostic node green by running its side effect. `prev_index` would
|
||||
/// refer to a node created used `encode_diagnostic` in the previous session.
|
||||
#[inline]
|
||||
fn force_diagnostic_node<Qcx: QueryContext>(
|
||||
fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
|
|
@ -843,7 +847,7 @@ impl<D: Deps> DepGraph<D> {
|
|||
DepNodeColor::Unknown
|
||||
}
|
||||
|
||||
pub fn try_mark_green<Qcx: QueryContext<Deps = D>>(
|
||||
pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
dep_node: &DepNode,
|
||||
|
|
@ -858,7 +862,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||
/// A node will have an index, when it's already been marked green, or when we can mark it
|
||||
/// green. This function will mark the current task as a reader of the specified node, when
|
||||
/// a node index can be found for that node.
|
||||
pub(crate) fn try_mark_green<Qcx: QueryContext<Deps = D>>(
|
||||
pub(crate) fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
dep_node: &DepNode,
|
||||
|
|
@ -883,7 +887,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||
}
|
||||
|
||||
#[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")]
|
||||
fn try_mark_parent_green<Qcx: QueryContext<Deps = D>>(
|
||||
fn try_mark_parent_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
parent_dep_node_index: SerializedDepNodeIndex,
|
||||
|
|
@ -973,7 +977,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||
|
||||
/// Try to mark a dep-node which existed in the previous compilation session as green.
|
||||
#[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")]
|
||||
fn try_mark_previous_green<Qcx: QueryContext<Deps = D>>(
|
||||
fn try_mark_previous_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
prev_dep_node_index: SerializedDepNodeIndex,
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerp
|
|||
|
||||
/// Unambiguous shorthand for `<This::Qcx as HasDepContext>::DepContext`.
|
||||
#[expect(type_alias_bounds)]
|
||||
type DepContextOf<This: QueryDispatcher> =
|
||||
<<This as QueryDispatcher>::Qcx as HasDepContext>::DepContext;
|
||||
type DepContextOf<'tcx, This: QueryDispatcher<'tcx>> =
|
||||
<<This as QueryDispatcher<'tcx>>::Qcx as HasDepContext>::DepContext;
|
||||
|
||||
/// Trait that can be used as a vtable for a single query, providing operations
|
||||
/// and metadata for that query.
|
||||
|
|
@ -25,15 +25,15 @@ type DepContextOf<This: QueryDispatcher> =
|
|||
/// Those types are not visible from this `rustc_query_system` crate.
|
||||
///
|
||||
/// "Dispatcher" should be understood as a near-synonym of "vtable".
|
||||
pub trait QueryDispatcher: Copy {
|
||||
pub trait QueryDispatcher<'tcx>: Copy {
|
||||
fn name(self) -> &'static str;
|
||||
|
||||
/// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`.
|
||||
type Qcx: QueryContext;
|
||||
type Qcx: QueryContext<'tcx>;
|
||||
|
||||
// `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
|
||||
// but it isn't necessary.
|
||||
type Key: DepNodeParams<DepContextOf<Self>> + Eq + Hash + Copy + Debug;
|
||||
type Key: DepNodeParams<DepContextOf<'tcx, Self>> + Eq + Hash + Copy + Debug;
|
||||
type Value: Copy;
|
||||
|
||||
type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
|
||||
|
|
@ -41,18 +41,15 @@ pub trait QueryDispatcher: Copy {
|
|||
fn format_value(self) -> fn(&Self::Value) -> String;
|
||||
|
||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||
fn query_state<'a>(
|
||||
self,
|
||||
tcx: Self::Qcx,
|
||||
) -> &'a QueryState<Self::Key, <Self::Qcx as QueryContext>::QueryInfo>;
|
||||
fn query_state<'a>(self, tcx: Self::Qcx) -> &'a QueryState<'tcx, Self::Key>;
|
||||
|
||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||
fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache;
|
||||
|
||||
fn cache_on_disk(self, tcx: DepContextOf<Self>, key: &Self::Key) -> bool;
|
||||
fn will_cache_on_disk_for_key(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> bool;
|
||||
|
||||
// Don't use this method to compute query results, instead use the methods on TyCtxt
|
||||
fn execute_query(self, tcx: DepContextOf<Self>, k: Self::Key) -> Self::Value;
|
||||
fn execute_query(self, tcx: DepContextOf<'tcx, Self>, k: Self::Key) -> Self::Value;
|
||||
|
||||
fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value;
|
||||
|
||||
|
|
@ -64,7 +61,7 @@ pub trait QueryDispatcher: Copy {
|
|||
index: DepNodeIndex,
|
||||
) -> Option<Self::Value>;
|
||||
|
||||
fn loadable_from_disk(
|
||||
fn is_loadable_from_disk(
|
||||
self,
|
||||
qcx: Self::Qcx,
|
||||
key: &Self::Key,
|
||||
|
|
@ -74,7 +71,7 @@ pub trait QueryDispatcher: Copy {
|
|||
/// Synthesize an error value to let compilation continue after a cycle.
|
||||
fn value_from_cycle_error(
|
||||
self,
|
||||
tcx: DepContextOf<Self>,
|
||||
tcx: DepContextOf<'tcx, Self>,
|
||||
cycle_error: &CycleError<QueryStackFrameExtra>,
|
||||
guar: ErrorGuaranteed,
|
||||
) -> Self::Value;
|
||||
|
|
@ -89,7 +86,7 @@ pub trait QueryDispatcher: Copy {
|
|||
fn hash_result(self) -> HashResult<Self::Value>;
|
||||
|
||||
// Just here for convenience and checking that the key matches the kind, don't override this.
|
||||
fn construct_dep_node(self, tcx: DepContextOf<Self>, key: &Self::Key) -> DepNode {
|
||||
fn construct_dep_node(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> DepNode {
|
||||
DepNode::construct(tcx, self.dep_kind(), key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_session::Session;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
|
||||
use super::QueryStackFrameExtra;
|
||||
use super::{QueryStackDeferred, QueryStackFrameExtra};
|
||||
use crate::dep_graph::DepContext;
|
||||
use crate::error::CycleStack;
|
||||
use crate::query::plumbing::CycleError;
|
||||
|
|
@ -26,8 +26,8 @@ pub struct QueryInfo<I> {
|
|||
pub query: QueryStackFrame<I>,
|
||||
}
|
||||
|
||||
impl<I> QueryInfo<I> {
|
||||
pub(crate) fn lift<Qcx: QueryContext<QueryInfo = I>>(
|
||||
impl<'tcx> QueryInfo<QueryStackDeferred<'tcx>> {
|
||||
pub(crate) fn lift<Qcx: QueryContext<'tcx>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
) -> QueryInfo<QueryStackFrameExtra> {
|
||||
|
|
@ -35,39 +35,39 @@ impl<I> QueryInfo<I> {
|
|||
}
|
||||
}
|
||||
|
||||
pub type QueryMap<I> = FxHashMap<QueryJobId, QueryJobInfo<I>>;
|
||||
pub type QueryMap<'tcx> = FxHashMap<QueryJobId, QueryJobInfo<'tcx>>;
|
||||
|
||||
/// A value uniquely identifying an active query job.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct QueryJobId(pub NonZero<u64>);
|
||||
|
||||
impl QueryJobId {
|
||||
fn query<I: Clone>(self, map: &QueryMap<I>) -> QueryStackFrame<I> {
|
||||
fn query<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> QueryStackFrame<QueryStackDeferred<'tcx>> {
|
||||
map.get(&self).unwrap().query.clone()
|
||||
}
|
||||
|
||||
fn span<I>(self, map: &QueryMap<I>) -> Span {
|
||||
fn span<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Span {
|
||||
map.get(&self).unwrap().job.span
|
||||
}
|
||||
|
||||
fn parent<I>(self, map: &QueryMap<I>) -> Option<QueryJobId> {
|
||||
fn parent<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option<QueryJobId> {
|
||||
map.get(&self).unwrap().job.parent
|
||||
}
|
||||
|
||||
fn latch<I>(self, map: &QueryMap<I>) -> Option<&QueryLatch<I>> {
|
||||
fn latch<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option<&'a QueryLatch<'tcx>> {
|
||||
map.get(&self).unwrap().job.latch.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct QueryJobInfo<I> {
|
||||
pub query: QueryStackFrame<I>,
|
||||
pub job: QueryJob<I>,
|
||||
pub struct QueryJobInfo<'tcx> {
|
||||
pub query: QueryStackFrame<QueryStackDeferred<'tcx>>,
|
||||
pub job: QueryJob<'tcx>,
|
||||
}
|
||||
|
||||
/// Represents an active query job.
|
||||
#[derive(Debug)]
|
||||
pub struct QueryJob<I> {
|
||||
pub struct QueryJob<'tcx> {
|
||||
pub id: QueryJobId,
|
||||
|
||||
/// The span corresponding to the reason for which this query was required.
|
||||
|
|
@ -77,23 +77,23 @@ pub struct QueryJob<I> {
|
|||
pub parent: Option<QueryJobId>,
|
||||
|
||||
/// The latch that is used to wait on this job.
|
||||
latch: Option<QueryLatch<I>>,
|
||||
latch: Option<QueryLatch<'tcx>>,
|
||||
}
|
||||
|
||||
impl<I> Clone for QueryJob<I> {
|
||||
impl<'tcx> Clone for QueryJob<'tcx> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> QueryJob<I> {
|
||||
impl<'tcx> QueryJob<'tcx> {
|
||||
/// Creates a new query job.
|
||||
#[inline]
|
||||
pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
|
||||
QueryJob { id, span, parent, latch: None }
|
||||
}
|
||||
|
||||
pub(super) fn latch(&mut self) -> QueryLatch<I> {
|
||||
pub(super) fn latch(&mut self) -> QueryLatch<'tcx> {
|
||||
if self.latch.is_none() {
|
||||
self.latch = Some(QueryLatch::new());
|
||||
}
|
||||
|
|
@ -113,12 +113,12 @@ impl<I> QueryJob<I> {
|
|||
}
|
||||
|
||||
impl QueryJobId {
|
||||
pub(super) fn find_cycle_in_stack<I: Clone>(
|
||||
pub(super) fn find_cycle_in_stack<'tcx>(
|
||||
&self,
|
||||
query_map: QueryMap<I>,
|
||||
query_map: QueryMap<'tcx>,
|
||||
current_job: &Option<QueryJobId>,
|
||||
span: Span,
|
||||
) -> CycleError<I> {
|
||||
) -> CycleError<QueryStackDeferred<'tcx>> {
|
||||
// Find the waitee amongst `current_job` parents
|
||||
let mut cycle = Vec::new();
|
||||
let mut current_job = Option::clone(current_job);
|
||||
|
|
@ -152,7 +152,10 @@ impl QueryJobId {
|
|||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
pub fn find_dep_kind_root<I: Clone>(&self, query_map: QueryMap<I>) -> (QueryJobInfo<I>, usize) {
|
||||
pub fn find_dep_kind_root<'tcx>(
|
||||
&self,
|
||||
query_map: QueryMap<'tcx>,
|
||||
) -> (QueryJobInfo<'tcx>, usize) {
|
||||
let mut depth = 1;
|
||||
let info = query_map.get(&self).unwrap();
|
||||
let dep_kind = info.query.dep_kind;
|
||||
|
|
@ -172,31 +175,31 @@ impl QueryJobId {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct QueryWaiter<I> {
|
||||
struct QueryWaiter<'tcx> {
|
||||
query: Option<QueryJobId>,
|
||||
condvar: Condvar,
|
||||
span: Span,
|
||||
cycle: Mutex<Option<CycleError<I>>>,
|
||||
cycle: Mutex<Option<CycleError<QueryStackDeferred<'tcx>>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct QueryLatchInfo<I> {
|
||||
struct QueryLatchInfo<'tcx> {
|
||||
complete: bool,
|
||||
waiters: Vec<Arc<QueryWaiter<I>>>,
|
||||
waiters: Vec<Arc<QueryWaiter<'tcx>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct QueryLatch<I> {
|
||||
info: Arc<Mutex<QueryLatchInfo<I>>>,
|
||||
pub(super) struct QueryLatch<'tcx> {
|
||||
info: Arc<Mutex<QueryLatchInfo<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<I> Clone for QueryLatch<I> {
|
||||
impl<'tcx> Clone for QueryLatch<'tcx> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { info: Arc::clone(&self.info) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> QueryLatch<I> {
|
||||
impl<'tcx> QueryLatch<'tcx> {
|
||||
fn new() -> Self {
|
||||
QueryLatch {
|
||||
info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })),
|
||||
|
|
@ -206,10 +209,10 @@ impl<I> QueryLatch<I> {
|
|||
/// Awaits for the query job to complete.
|
||||
pub(super) fn wait_on(
|
||||
&self,
|
||||
qcx: impl QueryContext,
|
||||
qcx: impl QueryContext<'tcx>,
|
||||
query: Option<QueryJobId>,
|
||||
span: Span,
|
||||
) -> Result<(), CycleError<I>> {
|
||||
) -> Result<(), CycleError<QueryStackDeferred<'tcx>>> {
|
||||
let waiter =
|
||||
Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() });
|
||||
self.wait_on_inner(qcx, &waiter);
|
||||
|
|
@ -224,7 +227,7 @@ impl<I> QueryLatch<I> {
|
|||
}
|
||||
|
||||
/// Awaits the caller on this latch by blocking the current thread.
|
||||
fn wait_on_inner(&self, qcx: impl QueryContext, waiter: &Arc<QueryWaiter<I>>) {
|
||||
fn wait_on_inner(&self, qcx: impl QueryContext<'tcx>, waiter: &Arc<QueryWaiter<'tcx>>) {
|
||||
let mut info = self.info.lock();
|
||||
if !info.complete {
|
||||
// We push the waiter on to the `waiters` list. It can be accessed inside
|
||||
|
|
@ -260,7 +263,7 @@ impl<I> QueryLatch<I> {
|
|||
|
||||
/// Removes a single waiter from the list of waiters.
|
||||
/// This is used to break query cycles.
|
||||
fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter<I>> {
|
||||
fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter<'tcx>> {
|
||||
let mut info = self.info.lock();
|
||||
debug_assert!(!info.complete);
|
||||
// Remove the waiter from the list of waiters
|
||||
|
|
@ -280,8 +283,8 @@ type Waiter = (QueryJobId, usize);
|
|||
/// For visits of resumable waiters it returns Some(Some(Waiter)) which has the
|
||||
/// required information to resume the waiter.
|
||||
/// If all `visit` calls returns None, this function also returns None.
|
||||
fn visit_waiters<I, F>(
|
||||
query_map: &QueryMap<I>,
|
||||
fn visit_waiters<'tcx, F>(
|
||||
query_map: &QueryMap<'tcx>,
|
||||
query: QueryJobId,
|
||||
mut visit: F,
|
||||
) -> Option<Option<Waiter>>
|
||||
|
|
@ -314,8 +317,8 @@ where
|
|||
/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP.
|
||||
/// If a cycle is detected, this initial value is replaced with the span causing
|
||||
/// the cycle.
|
||||
fn cycle_check<I>(
|
||||
query_map: &QueryMap<I>,
|
||||
fn cycle_check<'tcx>(
|
||||
query_map: &QueryMap<'tcx>,
|
||||
query: QueryJobId,
|
||||
span: Span,
|
||||
stack: &mut Vec<(Span, QueryJobId)>,
|
||||
|
|
@ -354,8 +357,8 @@ fn cycle_check<I>(
|
|||
/// Finds out if there's a path to the compiler root (aka. code which isn't in a query)
|
||||
/// from `query` without going through any of the queries in `visited`.
|
||||
/// This is achieved with a depth first search.
|
||||
fn connected_to_root<I>(
|
||||
query_map: &QueryMap<I>,
|
||||
fn connected_to_root<'tcx>(
|
||||
query_map: &QueryMap<'tcx>,
|
||||
query: QueryJobId,
|
||||
visited: &mut FxHashSet<QueryJobId>,
|
||||
) -> bool {
|
||||
|
|
@ -376,7 +379,7 @@ fn connected_to_root<I>(
|
|||
}
|
||||
|
||||
// Deterministically pick an query from a list
|
||||
fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap<I>, queries: &'a [T], f: F) -> &'a T
|
||||
fn pick_query<'a, 'tcx, T, F>(query_map: &QueryMap<'tcx>, queries: &'a [T], f: F) -> &'a T
|
||||
where
|
||||
F: Fn(&T) -> (Span, QueryJobId),
|
||||
{
|
||||
|
|
@ -401,10 +404,10 @@ where
|
|||
/// the function return true.
|
||||
/// If a cycle was not found, the starting query is removed from `jobs` and
|
||||
/// the function returns false.
|
||||
fn remove_cycle<I: Clone>(
|
||||
query_map: &QueryMap<I>,
|
||||
fn remove_cycle<'tcx>(
|
||||
query_map: &QueryMap<'tcx>,
|
||||
jobs: &mut Vec<QueryJobId>,
|
||||
wakelist: &mut Vec<Arc<QueryWaiter<I>>>,
|
||||
wakelist: &mut Vec<Arc<QueryWaiter<'tcx>>>,
|
||||
) -> bool {
|
||||
let mut visited = FxHashSet::default();
|
||||
let mut stack = Vec::new();
|
||||
|
|
@ -505,10 +508,7 @@ fn remove_cycle<I: Clone>(
|
|||
/// uses a query latch and then resuming that waiter.
|
||||
/// There may be multiple cycles involved in a deadlock, so this searches
|
||||
/// all active queries for cycles before finally resuming all the waiters at once.
|
||||
pub fn break_query_cycles<I: Clone + Debug>(
|
||||
query_map: QueryMap<I>,
|
||||
registry: &rustc_thread_pool::Registry,
|
||||
) {
|
||||
pub fn break_query_cycles<'tcx>(query_map: QueryMap<'tcx>, registry: &rustc_thread_pool::Registry) {
|
||||
let mut wakelist = Vec::new();
|
||||
// It is OK per the comments:
|
||||
// - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932
|
||||
|
|
@ -602,7 +602,7 @@ pub fn report_cycle<'a>(
|
|||
sess.dcx().create_err(cycle_diag)
|
||||
}
|
||||
|
||||
pub fn print_query_stack<Qcx: QueryContext>(
|
||||
pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>(
|
||||
qcx: Qcx,
|
||||
mut current_query: Option<QueryJobId>,
|
||||
dcx: DiagCtxtHandle<'_>,
|
||||
|
|
|
|||
|
|
@ -58,22 +58,19 @@ pub struct QueryStackFrame<I> {
|
|||
pub def_id_for_ty_in_cycle: Option<DefId>,
|
||||
}
|
||||
|
||||
impl<I> QueryStackFrame<I> {
|
||||
impl<'tcx> QueryStackFrame<QueryStackDeferred<'tcx>> {
|
||||
#[inline]
|
||||
pub fn new(
|
||||
info: I,
|
||||
info: QueryStackDeferred<'tcx>,
|
||||
dep_kind: DepKind,
|
||||
hash: impl FnOnce() -> Hash64,
|
||||
hash: Hash64,
|
||||
def_id: Option<DefId>,
|
||||
def_id_for_ty_in_cycle: Option<DefId>,
|
||||
) -> Self {
|
||||
Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle }
|
||||
Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle }
|
||||
}
|
||||
|
||||
fn lift<Qcx: QueryContext<QueryInfo = I>>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
) -> QueryStackFrame<QueryStackFrameExtra> {
|
||||
fn lift<Qcx: QueryContext<'tcx>>(&self, qcx: Qcx) -> QueryStackFrame<QueryStackFrameExtra> {
|
||||
QueryStackFrame {
|
||||
info: qcx.lift_query_info(&self.info),
|
||||
dep_kind: self.dep_kind,
|
||||
|
|
@ -159,9 +156,7 @@ pub enum QuerySideEffect {
|
|||
Diagnostic(DiagInner),
|
||||
}
|
||||
|
||||
pub trait QueryContext: HasDepContext {
|
||||
type QueryInfo: Clone;
|
||||
|
||||
pub trait QueryContext<'tcx>: HasDepContext {
|
||||
/// Gets a jobserver reference which is used to release then acquire
|
||||
/// a token while waiting on a query.
|
||||
fn jobserver_proxy(&self) -> &Proxy;
|
||||
|
|
@ -171,12 +166,9 @@ pub trait QueryContext: HasDepContext {
|
|||
/// Get the query information from the TLS context.
|
||||
fn current_query_job(self) -> Option<QueryJobId>;
|
||||
|
||||
fn collect_active_jobs(
|
||||
self,
|
||||
require_complete: bool,
|
||||
) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>;
|
||||
fn collect_active_jobs(self, require_complete: bool) -> Result<QueryMap<'tcx>, QueryMap<'tcx>>;
|
||||
|
||||
fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra;
|
||||
fn lift_query_info(self, info: &QueryStackDeferred<'tcx>) -> QueryStackFrameExtra;
|
||||
|
||||
/// Load a side effect associated to the node in the previous session.
|
||||
fn load_side_effect(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use rustc_errors::{Diag, FatalError, StashKey};
|
|||
use rustc_span::{DUMMY_SP, Span};
|
||||
use tracing::instrument;
|
||||
|
||||
use super::{QueryDispatcher, QueryStackFrameExtra};
|
||||
use super::{QueryDispatcher, QueryStackDeferred, QueryStackFrameExtra};
|
||||
use crate::dep_graph::{
|
||||
DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext,
|
||||
};
|
||||
|
|
@ -34,23 +34,23 @@ fn equivalent_key<K: Eq, V>(k: &K) -> impl Fn(&(K, V)) -> bool + '_ {
|
|||
move |x| x.0 == *k
|
||||
}
|
||||
|
||||
pub struct QueryState<K, I> {
|
||||
active: Sharded<hashbrown::HashTable<(K, QueryResult<I>)>>,
|
||||
pub struct QueryState<'tcx, K> {
|
||||
active: Sharded<hashbrown::HashTable<(K, QueryResult<'tcx>)>>,
|
||||
}
|
||||
|
||||
/// Indicates the state of a query for a given key in a query map.
|
||||
enum QueryResult<I> {
|
||||
enum QueryResult<'tcx> {
|
||||
/// An already executing query. The query job can be used to await for its completion.
|
||||
Started(QueryJob<I>),
|
||||
Started(QueryJob<'tcx>),
|
||||
|
||||
/// The query panicked. Queries trying to wait on this will raise a fatal error which will
|
||||
/// silently panic.
|
||||
Poisoned,
|
||||
}
|
||||
|
||||
impl<I> QueryResult<I> {
|
||||
impl<'tcx> QueryResult<'tcx> {
|
||||
/// Unwraps the query job expecting that it has started.
|
||||
fn expect_job(self) -> QueryJob<I> {
|
||||
fn expect_job(self) -> QueryJob<'tcx> {
|
||||
match self {
|
||||
Self::Started(job) => job,
|
||||
Self::Poisoned => {
|
||||
|
|
@ -60,7 +60,7 @@ impl<I> QueryResult<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<K, I> QueryState<K, I>
|
||||
impl<'tcx, K> QueryState<'tcx, K>
|
||||
where
|
||||
K: Eq + Hash + Copy + Debug,
|
||||
{
|
||||
|
|
@ -71,13 +71,13 @@ where
|
|||
pub fn collect_active_jobs<Qcx: Copy>(
|
||||
&self,
|
||||
qcx: Qcx,
|
||||
make_query: fn(Qcx, K) -> QueryStackFrame<I>,
|
||||
jobs: &mut QueryMap<I>,
|
||||
make_query: fn(Qcx, K) -> QueryStackFrame<QueryStackDeferred<'tcx>>,
|
||||
jobs: &mut QueryMap<'tcx>,
|
||||
require_complete: bool,
|
||||
) -> Option<()> {
|
||||
let mut active = Vec::new();
|
||||
|
||||
let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<I>)>>| {
|
||||
let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<'tcx>)>>| {
|
||||
for (k, v) in iter.iter() {
|
||||
if let QueryResult::Started(ref job) = *v {
|
||||
active.push((*k, job.clone()));
|
||||
|
|
@ -108,40 +108,40 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<K, I> Default for QueryState<K, I> {
|
||||
fn default() -> QueryState<K, I> {
|
||||
impl<'tcx, K> Default for QueryState<'tcx, K> {
|
||||
fn default() -> QueryState<'tcx, K> {
|
||||
QueryState { active: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
/// A type representing the responsibility to execute the job in the `job` field.
|
||||
/// This will poison the relevant query if dropped.
|
||||
struct JobOwner<'tcx, K, I>
|
||||
struct JobOwner<'a, 'tcx, K>
|
||||
where
|
||||
K: Eq + Hash + Copy,
|
||||
{
|
||||
state: &'tcx QueryState<K, I>,
|
||||
state: &'a QueryState<'tcx, K>,
|
||||
key: K,
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn mk_cycle<Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value
|
||||
fn mk_cycle<'tcx, Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
|
||||
handle_cycle_error(query, qcx, &cycle_error, error)
|
||||
}
|
||||
|
||||
fn handle_cycle_error<Q>(
|
||||
fn handle_cycle_error<'tcx, Q>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
cycle_error: &CycleError,
|
||||
error: Diag<'_>,
|
||||
) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
match query.cycle_error_handling() {
|
||||
CycleErrorHandling::Error => {
|
||||
|
|
@ -170,7 +170,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, K, I> JobOwner<'tcx, K, I>
|
||||
impl<'a, 'tcx, K> JobOwner<'a, 'tcx, K>
|
||||
where
|
||||
K: Eq + Hash + Copy,
|
||||
{
|
||||
|
|
@ -207,7 +207,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I>
|
||||
impl<'a, 'tcx, K> Drop for JobOwner<'a, 'tcx, K>
|
||||
where
|
||||
K: Eq + Hash + Copy,
|
||||
{
|
||||
|
|
@ -241,8 +241,8 @@ pub struct CycleError<I = QueryStackFrameExtra> {
|
|||
pub cycle: Vec<QueryInfo<I>>,
|
||||
}
|
||||
|
||||
impl<I> CycleError<I> {
|
||||
fn lift<Qcx: QueryContext<QueryInfo = I>>(&self, qcx: Qcx) -> CycleError<QueryStackFrameExtra> {
|
||||
impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
|
||||
fn lift<Qcx: QueryContext<'tcx>>(&self, qcx: Qcx) -> CycleError<QueryStackFrameExtra> {
|
||||
CycleError {
|
||||
usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))),
|
||||
cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(),
|
||||
|
|
@ -272,14 +272,14 @@ where
|
|||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn cycle_error<Q>(
|
||||
fn cycle_error<'tcx, Q>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
try_execute: QueryJobId,
|
||||
span: Span,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
// Ensure there was no errors collecting all active jobs.
|
||||
// We need the complete map to ensure we find a cycle to break.
|
||||
|
|
@ -290,16 +290,16 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn wait_for_query<Q>(
|
||||
fn wait_for_query<'tcx, Q>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
key: Q::Key,
|
||||
latch: QueryLatch<<Q::Qcx as QueryContext>::QueryInfo>,
|
||||
latch: QueryLatch<'tcx>,
|
||||
current: Option<QueryJobId>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
// For parallel queries, we'll block and wait until the query running
|
||||
// in another thread has completed. Record how long we wait in the
|
||||
|
|
@ -339,7 +339,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn try_execute_query<Q, const INCR: bool>(
|
||||
fn try_execute_query<'tcx, Q, const INCR: bool>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
|
|
@ -347,7 +347,7 @@ fn try_execute_query<Q, const INCR: bool>(
|
|||
dep_node: Option<DepNode>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
let state = query.query_state(qcx);
|
||||
let key_hash = sharded::make_hash(&key);
|
||||
|
|
@ -408,17 +408,17 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn execute_job<Q, const INCR: bool>(
|
||||
fn execute_job<'tcx, Q, const INCR: bool>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
state: &QueryState<Q::Key, <Q::Qcx as QueryContext>::QueryInfo>,
|
||||
state: &QueryState<'tcx, Q::Key>,
|
||||
key: Q::Key,
|
||||
key_hash: u64,
|
||||
id: QueryJobId,
|
||||
dep_node: Option<DepNode>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
// Use `JobOwner` so the query will be poisoned if executing it panics.
|
||||
let job_owner = JobOwner { state, key };
|
||||
|
|
@ -480,14 +480,14 @@ where
|
|||
|
||||
// Fast path for when incr. comp. is off.
|
||||
#[inline(always)]
|
||||
fn execute_job_non_incr<Q>(
|
||||
fn execute_job_non_incr<'tcx, Q>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
key: Q::Key,
|
||||
job_id: QueryJobId,
|
||||
) -> (Q::Value, DepNodeIndex)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
|
|
@ -516,7 +516,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn execute_job_incr<Q>(
|
||||
fn execute_job_incr<'tcx, Q>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
|
||||
|
|
@ -525,7 +525,7 @@ fn execute_job_incr<Q>(
|
|||
job_id: QueryJobId,
|
||||
) -> (Q::Value, DepNodeIndex)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
if !query.anon() && !query.eval_always() {
|
||||
// `to_dep_node` is expensive for some `DepKind`s.
|
||||
|
|
@ -571,7 +571,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn try_load_from_disk_and_cache_in_memory<Q>(
|
||||
fn try_load_from_disk_and_cache_in_memory<'tcx, Q>(
|
||||
query: Q,
|
||||
dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
|
||||
qcx: Q::Qcx,
|
||||
|
|
@ -579,7 +579,7 @@ fn try_load_from_disk_and_cache_in_memory<Q>(
|
|||
dep_node: &DepNode,
|
||||
) -> Option<(Q::Value, DepNodeIndex)>
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
// Note this function can be called concurrently from the same query
|
||||
// We must ensure that this is handled correctly.
|
||||
|
|
@ -623,7 +623,7 @@ where
|
|||
// We always expect to find a cached result for things that
|
||||
// can be forced from `DepNode`.
|
||||
debug_assert!(
|
||||
!query.cache_on_disk(*qcx.dep_context(), key)
|
||||
!query.will_cache_on_disk_for_key(*qcx.dep_context(), key)
|
||||
|| !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
|
||||
"missing on-disk cache entry for {dep_node:?}"
|
||||
);
|
||||
|
|
@ -631,7 +631,7 @@ where
|
|||
// Sanity check for the logic in `ensure`: if the node is green and the result loadable,
|
||||
// we should actually be able to load it.
|
||||
debug_assert!(
|
||||
!query.loadable_from_disk(qcx, key, prev_dep_node_index),
|
||||
!query.is_loadable_from_disk(qcx, key, prev_dep_node_index),
|
||||
"missing on-disk cache entry for loadable {dep_node:?}"
|
||||
);
|
||||
|
||||
|
|
@ -757,14 +757,14 @@ fn incremental_verify_ich_failed<Tcx>(
|
|||
///
|
||||
/// Note: The optimization is only available during incr. comp.
|
||||
#[inline(never)]
|
||||
fn ensure_must_run<Q>(
|
||||
fn ensure_must_run<'tcx, Q>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
key: &Q::Key,
|
||||
check_cache: bool,
|
||||
) -> (bool, Option<DepNode>)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
if query.eval_always() {
|
||||
return (true, None);
|
||||
|
|
@ -798,7 +798,7 @@ where
|
|||
return (false, None);
|
||||
}
|
||||
|
||||
let loadable = query.loadable_from_disk(qcx, key, serialized_dep_node_index);
|
||||
let loadable = query.is_loadable_from_disk(qcx, key, serialized_dep_node_index);
|
||||
(!loadable, Some(dep_node))
|
||||
}
|
||||
|
||||
|
|
@ -809,9 +809,9 @@ pub enum QueryMode {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_query_non_incr<Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value
|
||||
pub fn get_query_non_incr<'tcx, Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
|
|
@ -819,7 +819,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_query_incr<Q>(
|
||||
pub fn get_query_incr<'tcx, Q>(
|
||||
query: Q,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
|
|
@ -827,7 +827,7 @@ pub fn get_query_incr<Q>(
|
|||
mode: QueryMode,
|
||||
) -> Option<Q::Value>
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
|
|
@ -849,9 +849,9 @@ where
|
|||
Some(result)
|
||||
}
|
||||
|
||||
pub fn force_query<Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode)
|
||||
pub fn force_query<'tcx, Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode)
|
||||
where
|
||||
Q: QueryDispatcher,
|
||||
Q: QueryDispatcher<'tcx>,
|
||||
{
|
||||
// We may be concurrently trying both execute and force a query.
|
||||
// Ensure that only one of them runs the query.
|
||||
|
|
|
|||
|
|
@ -1709,7 +1709,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
) else {
|
||||
|
|
@ -2546,7 +2545,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns_to_try),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -2650,7 +2648,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ValueNS),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -350,7 +350,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, module),
|
||||
parent_scope,
|
||||
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
None,
|
||||
)
|
||||
|
|
@ -368,7 +367,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
None,
|
||||
)
|
||||
|
|
@ -396,12 +394,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
scope_set: ScopeSet<'ra>,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
finalize: Option<Finalize>,
|
||||
force: bool,
|
||||
ignore_decl: Option<Decl<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<Decl<'ra>, Determinacy> {
|
||||
assert!(force || finalize.is_none()); // `finalize` implies `force`
|
||||
|
||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
if !matches!(scope_set, ScopeSet::Module(..)) && orig_ident.is_path_segment_keyword() {
|
||||
return Err(Determinacy::Determined);
|
||||
|
|
@ -451,7 +446,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
parent_scope,
|
||||
// Shadowed decls don't need to be marked as used or non-speculatively loaded.
|
||||
if innermost_results.is_empty() { finalize } else { None },
|
||||
force,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
) {
|
||||
|
|
@ -509,7 +503,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// Scope visiting walked all the scopes and maybe found something in one of them.
|
||||
match innermost_results.first() {
|
||||
Some(&(decl, ..)) => Ok(decl),
|
||||
None => Err(Determinacy::determined(determinacy == Determinacy::Determined || force)),
|
||||
None => Err(determinacy),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -523,7 +517,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
scope_set: ScopeSet<'ra>,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
finalize: Option<Finalize>,
|
||||
force: bool,
|
||||
ignore_decl: Option<Decl<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {
|
||||
|
|
@ -546,7 +539,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
match self.reborrow().resolve_derive_macro_path(
|
||||
derive,
|
||||
parent_scope,
|
||||
force,
|
||||
false,
|
||||
ignore_import,
|
||||
) {
|
||||
Ok((Some(ext), _)) => {
|
||||
|
|
@ -617,11 +610,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
Ok(decl)
|
||||
}
|
||||
Err(ControlFlow::Continue(determinacy)) => Err(determinacy),
|
||||
Err(ControlFlow::Break(determinacy)) => {
|
||||
return Err(ControlFlow::Break(Determinacy::determined(
|
||||
determinacy == Determinacy::Determined || force,
|
||||
)));
|
||||
}
|
||||
Err(ControlFlow::Break(..)) => return decl,
|
||||
}
|
||||
}
|
||||
Scope::ModuleGlobs(module, derive_fallback_lint_id) => {
|
||||
|
|
@ -668,11 +657,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
Ok(binding)
|
||||
}
|
||||
Err(ControlFlow::Continue(determinacy)) => Err(determinacy),
|
||||
Err(ControlFlow::Break(determinacy)) => {
|
||||
return Err(ControlFlow::Break(Determinacy::determined(
|
||||
determinacy == Determinacy::Determined || force,
|
||||
)));
|
||||
}
|
||||
Err(ControlFlow::Break(..)) => return binding,
|
||||
}
|
||||
}
|
||||
Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {
|
||||
|
|
@ -715,7 +700,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, prelude),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -951,7 +935,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, module),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
),
|
||||
|
|
@ -960,7 +943,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::ModuleAndExternPrelude(ns, module),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
),
|
||||
|
|
@ -973,7 +955,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::ExternPrelude,
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -996,7 +977,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -1180,7 +1160,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, module),
|
||||
adjusted_parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
);
|
||||
|
|
@ -1881,7 +1860,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -1957,8 +1935,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
Err(Undetermined) => return PathResult::Indeterminate,
|
||||
Err(Determined) => {
|
||||
Err(Undetermined) if finalize.is_none() => return PathResult::Indeterminate,
|
||||
Err(Determined | Undetermined) => {
|
||||
if let Some(ModuleOrUniformRoot::Module(module)) = module
|
||||
&& opt_ns.is_some()
|
||||
&& !module.is_normal()
|
||||
|
|
|
|||
|
|
@ -1498,7 +1498,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
&import.parent_scope,
|
||||
None,
|
||||
false,
|
||||
decls[ns].get().decl(),
|
||||
None,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -799,10 +799,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(kind),
|
||||
parent_scope,
|
||||
None,
|
||||
force,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let binding = binding.map_err(|determinacy| {
|
||||
Determinacy::determined(determinacy == Determinacy::Determined || force)
|
||||
});
|
||||
if let Err(Determinacy::Undetermined) = binding {
|
||||
return Err(Determinacy::Undetermined);
|
||||
}
|
||||
|
|
@ -958,7 +960,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(kind),
|
||||
&parent_scope,
|
||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
) {
|
||||
|
|
@ -1013,7 +1014,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(MacroKind::Attr),
|
||||
&parent_scope,
|
||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
|
@ -1117,7 +1117,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(MacroKind::Bang),
|
||||
&ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1995,6 +1995,7 @@ symbols! {
|
|||
rustc_no_implicit_autorefs,
|
||||
rustc_no_implicit_bounds,
|
||||
rustc_no_mir_inline,
|
||||
rustc_non_const_trait_method,
|
||||
rustc_nonnull_optimization_guaranteed,
|
||||
rustc_nounwind,
|
||||
rustc_objc_class,
|
||||
|
|
|
|||
|
|
@ -34,14 +34,18 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
|||
(Some(self.tcx().def_span(def_id)), Some(self.tcx().item_name(def_id)))
|
||||
}
|
||||
ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None),
|
||||
ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
|
||||
ty::BoundRegionKind::NamedForPrinting(_) => {
|
||||
bug!("only used for pretty printing")
|
||||
}
|
||||
};
|
||||
let (sup_span, sup_symbol) = match *sup_name {
|
||||
ty::BoundRegionKind::Named(def_id) => {
|
||||
(Some(self.tcx().def_span(def_id)), Some(self.tcx().item_name(def_id)))
|
||||
}
|
||||
ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None),
|
||||
ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"),
|
||||
ty::BoundRegionKind::NamedForPrinting(_) => {
|
||||
bug!("only used for pretty printing")
|
||||
}
|
||||
};
|
||||
let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
|
||||
(Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => {
|
||||
|
|
|
|||
|
|
@ -1052,7 +1052,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn report_inference_failure(&self, var_origin: RegionVariableOrigin<'tcx>) -> Diag<'_> {
|
||||
let br_string = |br: ty::BoundRegionKind| {
|
||||
let br_string = |br: ty::BoundRegionKind<'tcx>| {
|
||||
let mut s = match br {
|
||||
ty::BoundRegionKind::Named(def_id) => self.tcx.item_name(def_id).to_string(),
|
||||
_ => String::new(),
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ fn plug_infer_with_placeholders<'tcx>(
|
|||
ty,
|
||||
Ty::new_placeholder(
|
||||
self.infcx.tcx,
|
||||
ty::Placeholder::new(
|
||||
ty::PlaceholderType::new(
|
||||
self.universe,
|
||||
ty::BoundTy { var: self.next_var(), kind: ty::BoundTyKind::Anon },
|
||||
),
|
||||
|
|
@ -592,9 +592,9 @@ fn plug_infer_with_placeholders<'tcx>(
|
|||
ct,
|
||||
ty::Const::new_placeholder(
|
||||
self.infcx.tcx,
|
||||
ty::Placeholder::new(
|
||||
ty::PlaceholderConst::new(
|
||||
self.universe,
|
||||
ty::BoundConst { var: self.next_var() },
|
||||
ty::BoundConst::new(self.next_var()),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -623,7 +623,7 @@ fn plug_infer_with_placeholders<'tcx>(
|
|||
r,
|
||||
ty::Region::new_placeholder(
|
||||
self.infcx.tcx,
|
||||
ty::Placeholder::new(
|
||||
ty::PlaceholderRegion::new(
|
||||
self.universe,
|
||||
ty::BoundRegion {
|
||||
var: self.next_var(),
|
||||
|
|
|
|||
|
|
@ -772,7 +772,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
|
|||
self.idx += 1;
|
||||
ty::Const::new_placeholder(
|
||||
self.tcx,
|
||||
ty::PlaceholderConst::new(ty::UniverseIndex::ROOT, ty::BoundConst { var: idx }),
|
||||
ty::PlaceholderConst::new(ty::UniverseIndex::ROOT, ty::BoundConst::new(idx)),
|
||||
)
|
||||
} else {
|
||||
c.super_fold_with(self)
|
||||
|
|
|
|||
|
|
@ -220,9 +220,9 @@ pub fn with_replaced_escaping_bound_vars<
|
|||
/// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
|
||||
pub struct PlaceholderReplacer<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion>,
|
||||
mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy>,
|
||||
mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst>,
|
||||
mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion<'tcx>>,
|
||||
mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy<'tcx>>,
|
||||
mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst<'tcx>>,
|
||||
universe_indices: &'a [Option<ty::UniverseIndex>],
|
||||
current_index: ty::DebruijnIndex,
|
||||
}
|
||||
|
|
@ -230,9 +230,9 @@ pub struct PlaceholderReplacer<'a, 'tcx> {
|
|||
impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> {
|
||||
pub fn replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion>,
|
||||
mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy>,
|
||||
mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst>,
|
||||
mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion<'tcx>>,
|
||||
mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy<'tcx>>,
|
||||
mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst<'tcx>>,
|
||||
universe_indices: &'a [Option<ty::UniverseIndex>],
|
||||
value: T,
|
||||
) -> T {
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ struct ImplTraitInTraitFinder<'a, 'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
predicates: &'a mut Vec<ty::Clause<'tcx>>,
|
||||
fn_def_id: DefId,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
|
||||
seen: FxHashSet<DefId>,
|
||||
depth: ty::DebruijnIndex,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
|
||||
use derive_where::derive_where;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
|
||||
use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use rustc_type_ir_macros::{
|
||||
GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic,
|
||||
};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::data_structures::SsoHashSet;
|
||||
|
|
@ -23,8 +26,11 @@ use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex};
|
|||
/// for more details.
|
||||
///
|
||||
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
|
||||
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)]
|
||||
// FIXME(derive-where#136): Need to use separate `derive_where` for
|
||||
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
|
||||
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
|
||||
#[derive_where(Copy; I: Interner, T: Copy)]
|
||||
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)]
|
||||
#[derive(GenericTypeVisitable)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub struct Binder<I: Interner, T> {
|
||||
|
|
@ -359,9 +365,12 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
|
|||
/// `instantiate`.
|
||||
///
|
||||
/// See <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html> for more details.
|
||||
#[derive_where(Clone, PartialEq, Ord, Hash, Debug; I: Interner, T)]
|
||||
#[derive_where(PartialOrd; I: Interner, T: Ord)]
|
||||
// FIXME(derive-where#136): Need to use separate `derive_where` for
|
||||
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
|
||||
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
|
||||
#[derive_where(Ord; I: Interner, T: Ord)]
|
||||
#[derive_where(Copy; I: Interner, T: Copy)]
|
||||
#[derive_where(Clone, PartialOrd, PartialEq, Hash, Debug; I: Interner, T)]
|
||||
#[derive(GenericTypeVisitable)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
|
|
@ -955,11 +964,12 @@ pub enum BoundVarIndexKind {
|
|||
/// 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_where(Clone, PartialEq, Ord, Hash; I: Interner, T)]
|
||||
#[derive_where(PartialOrd; I: Interner, T: Ord)]
|
||||
#[derive_where(Copy; I: Interner, T: Copy, T)]
|
||||
#[derive_where(Eq; T)]
|
||||
// FIXME(derive-where#136): Need to use separate `derive_where` for
|
||||
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
|
||||
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
|
||||
#[derive_where(Ord; I: Interner, T: Ord)]
|
||||
#[derive_where(Copy; I: Interner, T: Copy)]
|
||||
#[derive_where(Clone, PartialOrd, PartialEq, Eq, Hash; I: Interner, T)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
|
|
@ -973,12 +983,6 @@ pub struct Placeholder<I: Interner, T> {
|
|||
_tcx: PhantomData<fn() -> I>,
|
||||
}
|
||||
|
||||
impl<I: Interner, T> Placeholder<I, T> {
|
||||
pub fn new(universe: UniverseIndex, bound: T) -> Self {
|
||||
Placeholder { universe, bound, _tcx: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: fmt::Debug> fmt::Debug for ty::Placeholder<I, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.universe == ty::UniverseIndex::ROOT {
|
||||
|
|
@ -1003,3 +1007,321 @@ where
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
|
||||
#[derive(Lift_Generic)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
|
||||
pub enum BoundRegionKind<I: Interner> {
|
||||
/// An anonymous region parameter for a given fn (&T)
|
||||
Anon,
|
||||
|
||||
/// An anonymous region parameter with a `Symbol` name.
|
||||
///
|
||||
/// Used to give late-bound regions names for things like pretty printing.
|
||||
NamedForPrinting(I::Symbol),
|
||||
|
||||
/// Late-bound regions that appear in the AST.
|
||||
Named(I::DefId),
|
||||
|
||||
/// Anonymous region for the implicit env pointer parameter
|
||||
/// to a closure
|
||||
ClosureEnv,
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ty::BoundRegionKind<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ty::BoundRegionKind::Anon => write!(f, "BrAnon"),
|
||||
ty::BoundRegionKind::NamedForPrinting(name) => {
|
||||
write!(f, "BrNamedForPrinting({:?})", name)
|
||||
}
|
||||
ty::BoundRegionKind::Named(did) => {
|
||||
write!(f, "BrNamed({did:?})")
|
||||
}
|
||||
ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> BoundRegionKind<I> {
|
||||
pub fn is_named(&self, tcx: I) -> bool {
|
||||
self.get_name(tcx).is_some()
|
||||
}
|
||||
|
||||
pub fn get_name(&self, tcx: I) -> Option<I::Symbol> {
|
||||
match *self {
|
||||
ty::BoundRegionKind::Named(def_id) => {
|
||||
let name = tcx.item_name(def_id);
|
||||
if name.is_kw_underscore_lifetime() { None } else { Some(name) }
|
||||
}
|
||||
ty::BoundRegionKind::NamedForPrinting(name) => Some(name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> Option<I::DefId> {
|
||||
match *self {
|
||||
ty::BoundRegionKind::Named(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)]
|
||||
#[derive(Lift_Generic)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
pub enum BoundTyKind<I: Interner> {
|
||||
Anon,
|
||||
Param(I::DefId),
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)]
|
||||
#[derive(Lift_Generic)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
pub enum BoundVariableKind<I: Interner> {
|
||||
Ty(BoundTyKind<I>),
|
||||
Region(BoundRegionKind<I>),
|
||||
Const,
|
||||
}
|
||||
|
||||
impl<I: Interner> BoundVariableKind<I> {
|
||||
pub fn expect_region(self) -> BoundRegionKind<I> {
|
||||
match self {
|
||||
BoundVariableKind::Region(lt) => lt,
|
||||
_ => panic!("expected a region, but found another kind"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_ty(self) -> BoundTyKind<I> {
|
||||
match self {
|
||||
BoundVariableKind::Ty(ty) => ty,
|
||||
_ => panic!("expected a type, but found another kind"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_const(self) {
|
||||
match self {
|
||||
BoundVariableKind::Const => (),
|
||||
_ => panic!("expected a const, but found another kind"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, HashStable_NoContext, Decodable_NoContext)
|
||||
)]
|
||||
pub struct BoundRegion<I: Interner> {
|
||||
pub var: ty::BoundVar,
|
||||
pub kind: BoundRegionKind<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner> core::fmt::Debug for BoundRegion<I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.kind {
|
||||
BoundRegionKind::Anon => write!(f, "{:?}", self.var),
|
||||
BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var),
|
||||
BoundRegionKind::Named(def) => {
|
||||
write!(f, "{:?}.Named({:?})", self.var, def)
|
||||
}
|
||||
BoundRegionKind::NamedForPrinting(symbol) => {
|
||||
write!(f, "{:?}.NamedAnon({:?})", self.var, symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> BoundRegion<I> {
|
||||
pub fn var(self) -> ty::BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
pub fn assert_eq(self, var: BoundVariableKind<I>) {
|
||||
assert_eq!(self.kind, var.expect_region())
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderRegion<I> = ty::Placeholder<I, BoundRegion<I>>;
|
||||
|
||||
impl<I: Interner> PlaceholderRegion<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
pub fn var(self) -> ty::BoundVar {
|
||||
self.bound.var()
|
||||
}
|
||||
|
||||
pub fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Self { universe: ui, bound: self.bound, _tcx: PhantomData }
|
||||
}
|
||||
|
||||
pub fn new(ui: UniverseIndex, bound: BoundRegion<I>) -> Self {
|
||||
Self { universe: ui, bound, _tcx: PhantomData }
|
||||
}
|
||||
|
||||
pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self {
|
||||
let bound = BoundRegion { var, kind: BoundRegionKind::Anon };
|
||||
Self { universe: ui, bound, _tcx: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
pub struct BoundTy<I: Interner> {
|
||||
pub var: ty::BoundVar,
|
||||
pub kind: BoundTyKind<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner, U: Interner> Lift<U> for BoundTy<I>
|
||||
where
|
||||
BoundTyKind<I>: Lift<U, Lifted = BoundTyKind<U>>,
|
||||
{
|
||||
type Lifted = BoundTy<U>;
|
||||
|
||||
fn lift_to_interner(self, cx: U) -> Option<Self::Lifted> {
|
||||
Some(BoundTy { var: self.var, kind: self.kind.lift_to_interner(cx)? })
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ty::BoundTy<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.kind {
|
||||
ty::BoundTyKind::Anon => write!(f, "{:?}", self.var),
|
||||
ty::BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> BoundTy<I> {
|
||||
pub fn var(self) -> ty::BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
pub fn assert_eq(self, var: BoundVariableKind<I>) {
|
||||
assert_eq!(self.kind, var.expect_ty())
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderType<I> = ty::Placeholder<I, BoundTy<I>>;
|
||||
|
||||
impl<I: Interner> PlaceholderType<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
pub fn var(self) -> ty::BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
pub fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Self { universe: ui, bound: self.bound, _tcx: PhantomData }
|
||||
}
|
||||
|
||||
pub fn new(ui: UniverseIndex, bound: BoundTy<I>) -> Self {
|
||||
Self { universe: ui, bound, _tcx: PhantomData }
|
||||
}
|
||||
|
||||
pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self {
|
||||
let bound = BoundTy { var, kind: BoundTyKind::Anon };
|
||||
Self { universe: ui, bound, _tcx: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, PartialEq, Debug, Eq, Hash; I: Interner)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
pub struct BoundConst<I: Interner> {
|
||||
pub var: ty::BoundVar,
|
||||
#[derive_where(skip(Debug))]
|
||||
pub _tcx: PhantomData<fn() -> I>,
|
||||
}
|
||||
|
||||
impl<I: Interner> BoundConst<I> {
|
||||
pub fn var(self) -> ty::BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
pub fn assert_eq(self, var: BoundVariableKind<I>) {
|
||||
var.expect_const()
|
||||
}
|
||||
|
||||
pub fn new(var: ty::BoundVar) -> Self {
|
||||
Self { var, _tcx: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderConst<I> = ty::Placeholder<I, BoundConst<I>>;
|
||||
|
||||
impl<I: Interner> PlaceholderConst<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
pub fn var(self) -> ty::BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
pub fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Self { universe: ui, bound: self.bound, _tcx: PhantomData }
|
||||
}
|
||||
|
||||
pub fn new(ui: UniverseIndex, bound: BoundConst<I>) -> Self {
|
||||
Self { universe: ui, bound, _tcx: PhantomData }
|
||||
}
|
||||
|
||||
pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self {
|
||||
let bound = BoundConst::new(var);
|
||||
Self { universe: ui, bound, _tcx: PhantomData }
|
||||
}
|
||||
|
||||
pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty {
|
||||
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
|
||||
// `ConstArgHasType` are never desugared to be higher ranked.
|
||||
match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => {
|
||||
assert!(!(placeholder_ct, ty).has_escaping_bound_vars());
|
||||
|
||||
match placeholder_ct.kind() {
|
||||
ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => {
|
||||
Some(ty)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
|
||||
// N.B. it may be tempting to fix ICEs by making this function return
|
||||
// `Option<Ty<'tcx>>` instead of `Ty<'tcx>`; however, this is generally
|
||||
// considered to be a bandaid solution, since it hides more important
|
||||
// underlying issues with how we construct generics and predicates of
|
||||
// items. It's advised to fix the underlying issue rather than trying
|
||||
// to modify this function.
|
||||
let ty = candidates.next().unwrap_or_else(|| {
|
||||
panic!("cannot find `{self:?}` in param-env: {env:#?}");
|
||||
});
|
||||
assert!(
|
||||
candidates.next().is_none(),
|
||||
"did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}"
|
||||
);
|
||||
ty
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue