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:
The rustc-josh-sync Cronjob Bot 2026-01-31 02:06:15 +00:00
commit 678328aa94
175 changed files with 2629 additions and 1546 deletions

View file

@ -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",

View file

@ -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);

View file

@ -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) {

View file

@ -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)),

View file

@ -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 })
}
}

View file

@ -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(),
})

View file

@ -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)
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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 })
}
}

View file

@ -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;

View file

@ -32,6 +32,6 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
}
None => None,
}
.map(AttributeKind::MacroTransparency)
.map(AttributeKind::RustcMacroTransparency)
}
}

View file

@ -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>>,

View file

@ -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(

View file

@ -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 {

View file

@ -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")
}
},

View file

@ -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)
}

View file

@ -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")
}
};

View file

@ -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) {

View file

@ -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 => {

View file

@ -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,

View file

@ -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".

View file

@ -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),

View file

@ -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),

View file

@ -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 {

View file

@ -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,

View file

@ -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)>),

View file

@ -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,

View file

@ -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);

View file

@ -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()
}

View file

@ -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 {

View file

@ -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(),

View file

@ -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
};

View file

@ -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 {

View file

@ -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")
}
});
}
_ => {}

View file

@ -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) {

View file

@ -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>>,

View file

@ -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

View file

@ -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);

View file

@ -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()
{

View file

@ -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,
))

View file

@ -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()
}
}

View file

@ -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) {

View file

@ -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),

View file

@ -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(

View file

@ -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)) => {

View file

@ -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));
}
}

View file

@ -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) => {

View file

@ -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 {

View file

@ -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)
};

View file

@ -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)>>,

View file

@ -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,

View file

@ -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| {

View file

@ -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).

View file

@ -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>>,)*
}
};
}

View file

@ -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>>,
}

View file

@ -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 {

View file

@ -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)

View file

@ -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))
}
}

View file

@ -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:?}"),
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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,

View file

@ -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 {

View file

@ -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);

View file

@ -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(

View file

@ -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.

View file

@ -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);
}
}
}

View file

@ -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)
}

View file

@ -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 =

View file

@ -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);

View file

@ -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 {

View file

@ -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() });
}
}
}
}

View file

@ -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,

View file

@ -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)

View file

@ -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 {

View file

@ -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,

View file

@ -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,

View file

@ -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)
}

View file

@ -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>>;

View file

@ -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>(

View file

@ -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),*];

View file

@ -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,

View file

@ -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)
}
}

View file

@ -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<'_>,

View file

@ -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(

View file

@ -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.

View file

@ -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,
) {

View file

@ -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()

View file

@ -1498,7 +1498,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ScopeSet::All(ns),
&import.parent_scope,
None,
false,
decls[ns].get().decl(),
None,
) {

View file

@ -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,
);

View file

@ -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,

View file

@ -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)) => {

View file

@ -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(),

View file

@ -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(),

View file

@ -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)

View file

@ -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 {

View file

@ -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,
}

View file

@ -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