Skip to content

Introduce an abstraction for EvaluationCache and SelectionCache #75055

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc_middle/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub enum ErrorHandled {
TooGeneric,
}

CloneTypeFoldableImpls! {
CloneTypeFoldableAndLiftImpls! {
ErrorHandled,
}

Expand Down
35 changes: 17 additions & 18 deletions src/librustc_middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub type ChalkCanonicalGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx

pub use self::ImplSource::*;
pub use self::ObligationCauseCode::*;
pub use self::SelectionError::*;

pub use self::chalk::{
ChalkEnvironmentAndGoal, ChalkEnvironmentClause, RustInterner as ChalkRustInterner,
Expand Down Expand Up @@ -86,7 +85,7 @@ pub enum Reveal {
///
/// We do not want to intern this as there are a lot of obligation causes which
/// only live for a short period of time.
#[derive(Clone, PartialEq, Eq, Hash)]
#[derive(Clone, PartialEq, Eq, Hash, Lift)]
pub struct ObligationCause<'tcx> {
/// `None` for `ObligationCause::dummy`, `Some` otherwise.
data: Option<Rc<ObligationCauseData<'tcx>>>,
Expand All @@ -111,7 +110,7 @@ impl Deref for ObligationCause<'tcx> {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct ObligationCauseData<'tcx> {
pub span: Span,

Expand Down Expand Up @@ -169,14 +168,14 @@ impl<'tcx> ObligationCause<'tcx> {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct UnifyReceiverContext<'tcx> {
pub assoc_item: ty::AssocItem,
pub param_env: ty::ParamEnv<'tcx>,
pub substs: SubstsRef<'tcx>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from the span.
MiscObligation,
Expand Down Expand Up @@ -343,7 +342,7 @@ impl ObligationCauseCode<'_> {
#[cfg(target_arch = "x86_64")]
static_assert_size!(ObligationCauseCode<'_>, 32);

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct MatchExpressionArmCause<'tcx> {
pub arm_span: Span,
pub source: hir::MatchSource,
Expand All @@ -359,7 +358,7 @@ pub struct IfExpressionCause {
pub semicolon: Option<Span>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct DerivedObligationCause<'tcx> {
/// The trait reference of the parent obligation that led to the
/// current obligation. Note that only trait obligations lead to
Expand All @@ -371,7 +370,7 @@ pub struct DerivedObligationCause<'tcx> {
pub parent_code: Rc<ObligationCauseCode<'tcx>>,
}

#[derive(Clone, Debug, TypeFoldable)]
#[derive(Clone, Debug, TypeFoldable, Lift)]
pub enum SelectionError<'tcx> {
Unimplemented,
OutputTypeParameterMismatch(
Expand Down Expand Up @@ -427,7 +426,7 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
/// ### The type parameter `N`
///
/// See explanation on `ImplSourceUserDefinedData`.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub enum ImplSource<'tcx, N> {
/// ImplSource identifying a particular impl.
ImplSourceUserDefined(ImplSourceUserDefinedData<'tcx, N>),
Expand Down Expand Up @@ -558,14 +557,14 @@ impl<'tcx, N> ImplSource<'tcx, N> {
/// is `Obligation`, as one might expect. During codegen, however, this
/// is `()`, because codegen only requires a shallow resolution of an
/// impl, and nested obligations are satisfied later.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceUserDefinedData<'tcx, N> {
pub impl_def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub nested: Vec<N>,
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceGeneratorData<'tcx, N> {
pub generator_def_id: DefId,
pub substs: SubstsRef<'tcx>,
Expand All @@ -574,7 +573,7 @@ pub struct ImplSourceGeneratorData<'tcx, N> {
pub nested: Vec<N>,
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceClosureData<'tcx, N> {
pub closure_def_id: DefId,
pub substs: SubstsRef<'tcx>,
Expand All @@ -583,18 +582,18 @@ pub struct ImplSourceClosureData<'tcx, N> {
pub nested: Vec<N>,
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceAutoImplData<N> {
pub trait_def_id: DefId,
pub nested: Vec<N>,
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceBuiltinData<N> {
pub nested: Vec<N>,
}

#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceObjectData<'tcx, N> {
/// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
Expand All @@ -607,17 +606,17 @@ pub struct ImplSourceObjectData<'tcx, N> {
pub nested: Vec<N>,
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceFnPointerData<'tcx, N> {
pub fn_ty: Ty<'tcx>,
pub nested: Vec<N>,
}

// FIXME(@lcnr): This should be refactored and merged with other builtin vtables.
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
pub struct ImplSourceDiscriminantKindData;

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceTraitAliasData<'tcx, N> {
pub alias_def_id: DefId,
pub substs: SubstsRef<'tcx>,
Expand Down
99 changes: 8 additions & 91 deletions src/librustc_middle/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,18 @@ use self::EvaluationResult::*;

use super::{SelectionError, SelectionResult};

use crate::dep_graph::DepNodeIndex;
use crate::ty::{self, TyCtxt};
use crate::ty;

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
use rustc_hir::def_id::DefId;
use rustc_query_system::cache::Cache;

#[derive(Clone, Default)]
pub struct SelectionCache<'tcx> {
pub hashmap: Lock<
FxHashMap<
ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>,
>,
>,
}
pub type SelectionCache<'tcx> = Cache<
ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
>;

impl<'tcx> SelectionCache<'tcx> {
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
pub fn clear(&self) {
*self.hashmap.borrow_mut() = Default::default();
}
}
pub type EvaluationCache<'tcx> =
Cache<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, EvaluationResult>;

/// The selection process begins by considering all impls, where
/// clauses, and so forth that might resolve an obligation. Sometimes
Expand Down Expand Up @@ -264,75 +253,3 @@ impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
SelectionError::Overflow
}
}

#[derive(Clone, Default)]
pub struct EvaluationCache<'tcx> {
pub hashmap: Lock<
FxHashMap<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, WithDepNode<EvaluationResult>>,
>,
}

impl<'tcx> EvaluationCache<'tcx> {
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
pub fn clear(&self) {
*self.hashmap.borrow_mut() = Default::default();
}
}

#[derive(Clone, Eq, PartialEq)]
pub struct WithDepNode<T> {
dep_node: DepNodeIndex,
cached_value: T,
}

impl<T: Clone> WithDepNode<T> {
pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
WithDepNode { dep_node, cached_value }
}

pub fn get(&self, tcx: TyCtxt<'_>) -> T {
tcx.dep_graph.read_index(self.dep_node);
self.cached_value.clone()
}
}

#[derive(Clone, Debug)]
pub enum IntercrateAmbiguityCause {
DownstreamCrate { trait_desc: String, self_desc: Option<String> },
UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
ReservationImpl { message: String },
}

impl IntercrateAmbiguityCause {
/// Emits notes when the overlap is caused by complex intercrate ambiguities.
/// See #23980 for details.
pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
err.note(&self.intercrate_ambiguity_hint());
}

pub fn intercrate_ambiguity_hint(&self) -> String {
match self {
&IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
let self_desc = if let &Some(ref ty) = self_desc {
format!(" for type `{}`", ty)
} else {
String::new()
};
format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
}
&IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
let self_desc = if let &Some(ref ty) = self_desc {
format!(" for type `{}`", ty)
} else {
String::new()
};
format!(
"upstream crates may add a new impl of trait `{}`{} \
in future versions",
trait_desc, self_desc
)
}
&IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
}
}
}
Loading