Uplift RegionVid
This commit is contained in:
parent
75cb5c51cd
commit
569fb43aa0
@ -15,8 +15,31 @@ use std::path::Path;
|
|||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct RustcFacts;
|
pub struct RustcFacts;
|
||||||
|
|
||||||
|
rustc_index::newtype_index! {
|
||||||
|
/// A (kinda) newtype of `RegionVid` so we can implement `Atom` on it.
|
||||||
|
#[orderable]
|
||||||
|
#[debug_format = "'?{}"]
|
||||||
|
pub struct PoloniusRegionVid {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl polonius_engine::Atom for PoloniusRegionVid {
|
||||||
|
fn index(self) -> usize {
|
||||||
|
self.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<RegionVid> for PoloniusRegionVid {
|
||||||
|
fn from(value: RegionVid) -> Self {
|
||||||
|
Self::from_usize(value.as_usize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<PoloniusRegionVid> for RegionVid {
|
||||||
|
fn from(value: PoloniusRegionVid) -> Self {
|
||||||
|
Self::from_usize(value.as_usize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl polonius_engine::FactTypes for RustcFacts {
|
impl polonius_engine::FactTypes for RustcFacts {
|
||||||
type Origin = RegionVid;
|
type Origin = PoloniusRegionVid;
|
||||||
type Loan = BorrowIndex;
|
type Loan = BorrowIndex;
|
||||||
type Point = LocationIndex;
|
type Point = LocationIndex;
|
||||||
type Variable = Local;
|
type Variable = Local;
|
||||||
@ -119,7 +142,7 @@ trait FactRow {
|
|||||||
) -> Result<(), Box<dyn Error>>;
|
) -> Result<(), Box<dyn Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FactRow for RegionVid {
|
impl FactRow for PoloniusRegionVid {
|
||||||
fn write(
|
fn write(
|
||||||
&self,
|
&self,
|
||||||
out: &mut dyn Write,
|
out: &mut dyn Write,
|
||||||
|
@ -8,7 +8,7 @@ use rustc_middle::ty::TyCtxt;
|
|||||||
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
||||||
|
|
||||||
use crate::borrow_set::BorrowSet;
|
use crate::borrow_set::BorrowSet;
|
||||||
use crate::facts::AllFacts;
|
use crate::facts::{AllFacts, PoloniusRegionVid};
|
||||||
use crate::location::LocationTable;
|
use crate::location::LocationTable;
|
||||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||||
use crate::universal_regions::UniversalRegions;
|
use crate::universal_regions::UniversalRegions;
|
||||||
@ -137,7 +137,9 @@ fn emit_universal_region_facts(
|
|||||||
// the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
|
// the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
|
||||||
// added to the existing number of loans, as if they succeeded them in the set.
|
// added to the existing number of loans, as if they succeeded them in the set.
|
||||||
//
|
//
|
||||||
all_facts.universal_region.extend(universal_regions.universal_regions());
|
all_facts
|
||||||
|
.universal_region
|
||||||
|
.extend(universal_regions.universal_regions().map(PoloniusRegionVid::from));
|
||||||
let borrow_count = borrow_set.len();
|
let borrow_count = borrow_set.len();
|
||||||
debug!(
|
debug!(
|
||||||
"emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
|
"emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
|
||||||
@ -148,7 +150,7 @@ fn emit_universal_region_facts(
|
|||||||
for universal_region in universal_regions.universal_regions() {
|
for universal_region in universal_regions.universal_regions() {
|
||||||
let universal_region_idx = universal_region.index();
|
let universal_region_idx = universal_region.index();
|
||||||
let placeholder_loan_idx = borrow_count + universal_region_idx;
|
let placeholder_loan_idx = borrow_count + universal_region_idx;
|
||||||
all_facts.placeholder.push((universal_region, placeholder_loan_idx.into()));
|
all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2: the universal region relations `outlives` constraints are emitted as
|
// 2: the universal region relations `outlives` constraints are emitted as
|
||||||
@ -160,7 +162,7 @@ fn emit_universal_region_facts(
|
|||||||
fr1={:?}, fr2={:?}",
|
fr1={:?}, fr2={:?}",
|
||||||
fr1, fr2
|
fr1, fr2
|
||||||
);
|
);
|
||||||
all_facts.known_placeholder_subset.push((fr1, fr2));
|
all_facts.known_placeholder_subset.push((fr1.into(), fr2.into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1506,7 +1506,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||||||
subset_errors.sort();
|
subset_errors.sort();
|
||||||
subset_errors.dedup();
|
subset_errors.dedup();
|
||||||
|
|
||||||
for (longer_fr, shorter_fr) in subset_errors.into_iter() {
|
for &(longer_fr, shorter_fr) in subset_errors.into_iter() {
|
||||||
debug!(
|
debug!(
|
||||||
"check_polonius_subset_errors: subset_error longer_fr={:?},\
|
"check_polonius_subset_errors: subset_error longer_fr={:?},\
|
||||||
shorter_fr={:?}",
|
shorter_fr={:?}",
|
||||||
@ -1514,14 +1514,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let propagated = self.try_propagate_universal_region_error(
|
let propagated = self.try_propagate_universal_region_error(
|
||||||
*longer_fr,
|
longer_fr.into(),
|
||||||
*shorter_fr,
|
shorter_fr.into(),
|
||||||
&mut propagated_outlives_requirements,
|
&mut propagated_outlives_requirements,
|
||||||
);
|
);
|
||||||
if propagated == RegionRelationCheckResult::Error {
|
if propagated == RegionRelationCheckResult::Error {
|
||||||
errors_buffer.push(RegionErrorKind::RegionError {
|
errors_buffer.push(RegionErrorKind::RegionError {
|
||||||
longer_fr: *longer_fr,
|
longer_fr: longer_fr.into(),
|
||||||
shorter_fr: *shorter_fr,
|
shorter_fr: shorter_fr.into(),
|
||||||
fr_origin: NllRegionVariableOrigin::FreeRegion,
|
fr_origin: NllRegionVariableOrigin::FreeRegion,
|
||||||
is_reported: true,
|
is_reported: true,
|
||||||
});
|
});
|
||||||
|
@ -117,7 +117,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
|
|||||||
let universal_regions = &typeck.borrowck_context.universal_regions;
|
let universal_regions = &typeck.borrowck_context.universal_regions;
|
||||||
typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
|
typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
|
||||||
let region_vid = universal_regions.to_region_vid(region);
|
let region_vid = universal_regions.to_region_vid(region);
|
||||||
facts.use_of_var_derefs_origin.push((local, region_vid));
|
facts.use_of_var_derefs_origin.push((local, region_vid.into()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
|
|||||||
let universal_regions = &typeck.borrowck_context.universal_regions;
|
let universal_regions = &typeck.borrowck_context.universal_regions;
|
||||||
typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
|
typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
|
||||||
let region_vid = universal_regions.to_region_vid(drop_live_region);
|
let region_vid = universal_regions.to_region_vid(drop_live_region);
|
||||||
facts.drop_of_var_derefs_origin.push((local, region_vid));
|
facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,16 +260,14 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
|
|||||||
|constraint: &OutlivesConstraint<'_>| {
|
|constraint: &OutlivesConstraint<'_>| {
|
||||||
if let Some(from_location) = constraint.locations.from_location() {
|
if let Some(from_location) = constraint.locations.from_location() {
|
||||||
Either::Left(iter::once((
|
Either::Left(iter::once((
|
||||||
constraint.sup,
|
constraint.sup.into(),
|
||||||
constraint.sub,
|
constraint.sub.into(),
|
||||||
location_table.mid_index(from_location),
|
location_table.mid_index(from_location),
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
Either::Right(
|
Either::Right(location_table.all_points().map(move |location| {
|
||||||
location_table
|
(constraint.sup.into(), constraint.sub.into(), location)
|
||||||
.all_points()
|
}))
|
||||||
.map(move |location| (constraint.sup, constraint.sub, location)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@ -2547,7 +2545,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
if let Some(borrow_index) = borrow_set.get_index_of(&location) {
|
if let Some(borrow_index) = borrow_set.get_index_of(&location) {
|
||||||
let region_vid = borrow_region.as_var();
|
let region_vid = borrow_region.as_var();
|
||||||
all_facts.loan_issued_at.push((
|
all_facts.loan_issued_at.push((
|
||||||
region_vid,
|
region_vid.into(),
|
||||||
borrow_index,
|
borrow_index,
|
||||||
location_table.mid_index(location),
|
location_table.mid_index(location),
|
||||||
));
|
));
|
||||||
|
@ -134,7 +134,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||||||
type EarlyParamRegion = ty::EarlyParamRegion;
|
type EarlyParamRegion = ty::EarlyParamRegion;
|
||||||
type LateParamRegion = ty::LateParamRegion;
|
type LateParamRegion = ty::LateParamRegion;
|
||||||
type BoundRegion = ty::BoundRegion;
|
type BoundRegion = ty::BoundRegion;
|
||||||
type InferRegion = ty::RegionVid;
|
|
||||||
type PlaceholderRegion = ty::PlaceholderRegion;
|
type PlaceholderRegion = ty::PlaceholderRegion;
|
||||||
|
|
||||||
type ParamEnv = ty::ParamEnv<'tcx>;
|
type ParamEnv = ty::ParamEnv<'tcx>;
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use polonius_engine::Atom;
|
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_errors::MultiSpan;
|
use rustc_errors::MultiSpan;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_index::Idx;
|
|
||||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::symbol::{kw, Symbol};
|
use rustc_span::symbol::{kw, Symbol};
|
||||||
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
|
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
|
||||||
use rustc_type_ir::RegionKind as IrRegionKind;
|
use rustc_type_ir::RegionKind as IrRegionKind;
|
||||||
|
pub use rustc_type_ir::RegionVid;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use crate::ty::{self, BoundVar, TyCtxt, TypeFlags};
|
use crate::ty::{self, BoundVar, TyCtxt, TypeFlags};
|
||||||
@ -348,21 +347,6 @@ impl std::fmt::Debug for EarlyParamRegion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
|
||||||
/// A **region** (lifetime) **v**ariable **ID**.
|
|
||||||
#[derive(HashStable)]
|
|
||||||
#[encodable]
|
|
||||||
#[orderable]
|
|
||||||
#[debug_format = "'?{}"]
|
|
||||||
pub struct RegionVid {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Atom for RegionVid {
|
|
||||||
fn index(self) -> usize {
|
|
||||||
Idx::index(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
|
#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
|
||||||
#[derive(HashStable)]
|
#[derive(HashStable)]
|
||||||
/// The parameter representation of late-bound function parameters, "some region
|
/// The parameter representation of late-bound function parameters, "some region
|
||||||
|
@ -259,18 +259,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Region<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::RegionVid {
|
|
||||||
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
|
||||||
this: WithInfcx<'_, Infcx, &Self>,
|
|
||||||
f: &mut core::fmt::Formatter<'_>,
|
|
||||||
) -> core::fmt::Result {
|
|
||||||
match this.infcx.universe_of_lt(*this.data) {
|
|
||||||
Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
|
|
||||||
None => write!(f, "{:?}", this.data),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
||||||
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
||||||
this: WithInfcx<'_, Infcx, &Self>,
|
this: WithInfcx<'_, Infcx, &Self>,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex};
|
use crate::{ConstVid, InferCtxtLike, Interner, RegionVid, TyVid, UniverseIndex};
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
@ -16,7 +16,7 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn universe_of_lt(&self, _lt: I::InferRegion) -> Option<UniverseIndex> {
|
fn universe_of_lt(&self, _lt: RegionVid) -> Option<UniverseIndex> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opportunistic_resolve_lt_var(&self, _vid: I::InferRegion) -> Option<I::Region> {
|
fn opportunistic_resolve_lt_var(&self, _vid: RegionVid) -> Option<I::Region> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{ConstVid, Interner, TyVid, UniverseIndex};
|
use crate::{ConstVid, Interner, RegionVid, TyVid, UniverseIndex};
|
||||||
|
|
||||||
pub trait InferCtxtLike {
|
pub trait InferCtxtLike {
|
||||||
type Interner: Interner;
|
type Interner: Interner;
|
||||||
@ -13,10 +13,7 @@ pub trait InferCtxtLike {
|
|||||||
/// Resolve `TyVid` to its inferred type, if it has been equated with a non-infer type.
|
/// Resolve `TyVid` to its inferred type, if it has been equated with a non-infer type.
|
||||||
fn probe_ty_var(&self, vid: TyVid) -> Option<<Self::Interner as Interner>::Ty>;
|
fn probe_ty_var(&self, vid: TyVid) -> Option<<Self::Interner as Interner>::Ty>;
|
||||||
|
|
||||||
fn universe_of_lt(
|
fn universe_of_lt(&self, lt: RegionVid) -> Option<UniverseIndex>;
|
||||||
&self,
|
|
||||||
lt: <Self::Interner as Interner>::InferRegion,
|
|
||||||
) -> Option<UniverseIndex>;
|
|
||||||
|
|
||||||
/// Resolve `InferRegion` to its inferred region, if it has been equated with
|
/// Resolve `InferRegion` to its inferred region, if it has been equated with
|
||||||
/// a non-infer region.
|
/// a non-infer region.
|
||||||
@ -27,7 +24,7 @@ pub trait InferCtxtLike {
|
|||||||
/// var we're trying to resolve. That's why it's called *opportunistic*.
|
/// var we're trying to resolve. That's why it's called *opportunistic*.
|
||||||
fn opportunistic_resolve_lt_var(
|
fn opportunistic_resolve_lt_var(
|
||||||
&self,
|
&self,
|
||||||
vid: <Self::Interner as Interner>::InferRegion,
|
vid: RegionVid,
|
||||||
) -> Option<<Self::Interner as Interner>::Region>;
|
) -> Option<<Self::Interner as Interner>::Region>;
|
||||||
|
|
||||||
fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
|
fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
|
||||||
|
@ -79,7 +79,6 @@ pub trait Interner:
|
|||||||
type EarlyParamRegion: Copy + Debug + Hash + Eq;
|
type EarlyParamRegion: Copy + Debug + Hash + Eq;
|
||||||
type LateParamRegion: Copy + Debug + Hash + Eq;
|
type LateParamRegion: Copy + Debug + Hash + Eq;
|
||||||
type BoundRegion: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
|
type BoundRegion: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
|
||||||
type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Eq;
|
|
||||||
type PlaceholderRegion: PlaceholderLike;
|
type PlaceholderRegion: PlaceholderLike;
|
||||||
|
|
||||||
// Predicates
|
// Predicates
|
||||||
|
@ -1,13 +1,35 @@
|
|||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use rustc_macros::{TyDecodable, TyEncodable};
|
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
|
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
|
||||||
|
|
||||||
use self::RegionKind::*;
|
use self::RegionKind::*;
|
||||||
|
|
||||||
|
rustc_index::newtype_index! {
|
||||||
|
/// A **region** **v**ariable **ID**.
|
||||||
|
#[encodable]
|
||||||
|
#[orderable]
|
||||||
|
#[debug_format = "'?{}"]
|
||||||
|
#[gate_rustc_only]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||||
|
pub struct RegionVid {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> DebugWithInfcx<I> for RegionVid {
|
||||||
|
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
|
||||||
|
this: WithInfcx<'_, Infcx, &Self>,
|
||||||
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
|
) -> core::fmt::Result {
|
||||||
|
match this.infcx.universe_of_lt(*this.data) {
|
||||||
|
Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
|
||||||
|
None => write!(f, "{:?}", this.data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Representation of regions. Note that the NLL checker uses a distinct
|
/// Representation of regions. Note that the NLL checker uses a distinct
|
||||||
/// representation of regions. For this reason, it internally replaces all the
|
/// representation of regions. For this reason, it internally replaces all the
|
||||||
/// regions with inference variables -- the index of the variable is then used
|
/// regions with inference variables -- the index of the variable is then used
|
||||||
@ -152,7 +174,7 @@ pub enum RegionKind<I: Interner> {
|
|||||||
ReStatic,
|
ReStatic,
|
||||||
|
|
||||||
/// A region variable. Should not exist outside of type inference.
|
/// A region variable. Should not exist outside of type inference.
|
||||||
ReVar(I::InferRegion),
|
ReVar(RegionVid),
|
||||||
|
|
||||||
/// A placeholder region -- the higher-ranked version of `ReLateParam`.
|
/// A placeholder region -- the higher-ranked version of `ReLateParam`.
|
||||||
/// Should not exist outside of type inference.
|
/// Should not exist outside of type inference.
|
||||||
@ -251,7 +273,6 @@ where
|
|||||||
I::EarlyParamRegion: HashStable<CTX>,
|
I::EarlyParamRegion: HashStable<CTX>,
|
||||||
I::BoundRegion: HashStable<CTX>,
|
I::BoundRegion: HashStable<CTX>,
|
||||||
I::LateParamRegion: HashStable<CTX>,
|
I::LateParamRegion: HashStable<CTX>,
|
||||||
I::InferRegion: HashStable<CTX>,
|
|
||||||
I::PlaceholderRegion: HashStable<CTX>,
|
I::PlaceholderRegion: HashStable<CTX>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user