Skip to content
Closed
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
110 changes: 58 additions & 52 deletions compiler/rustc_infer/src/infer/fudge.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};

use super::type_variable::TypeVariableOrigin;
@@ -99,69 +100,74 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
where
F: FnOnce() -> Result<T, E>,
T: TypeFoldable<'tcx>,
E: TypeVisitable<'tcx>,
{
let variable_lengths = self.variable_lengths();
let (mut fudger, value) = self.probe(|_| {
match f() {
Ok(value) => {
let value = self.resolve_vars_if_possible(value);

// At this point, `value` could in principle refer
// to inference variables that have been created during
// the snapshot. Once we exit `probe()`, those are
// going to be popped, so we will have to
// eliminate any references to them.

let mut inner = self.inner.borrow_mut();
let type_vars =
inner.type_variables().vars_since_snapshot(variable_lengths.type_var_len);
let int_vars = vars_since_snapshot(
&mut inner.int_unification_table(),
variable_lengths.int_var_len,
);
let float_vars = vars_since_snapshot(
&mut inner.float_unification_table(),
variable_lengths.float_var_len,
);
let region_vars = inner
.unwrap_region_constraints()
.vars_since_snapshot(variable_lengths.region_constraints_len);
let const_vars = const_vars_since_snapshot(
&mut inner.const_unification_table(),
variable_lengths.const_var_len,
);

let fudger = InferenceFudger {
let snapshot = self.start_snapshot();

match f() {
Ok(value) => {
let value = self.resolve_vars_if_possible(value);

// At this point, `value` could in principle refer
// to inference variables that have been created during
// the snapshot. Once we exit the snapshot, those are
// going to be popped, so we will have to
// eliminate any references to them.

let mut inner = self.inner.borrow_mut();
let type_vars =
inner.type_variables().vars_since_snapshot(variable_lengths.type_var_len);
let int_vars = vars_since_snapshot(
&mut inner.int_unification_table(),
variable_lengths.int_var_len,
);
let float_vars = vars_since_snapshot(
&mut inner.float_unification_table(),
variable_lengths.float_var_len,
);
let region_vars = inner
.unwrap_region_constraints()
.vars_since_snapshot(variable_lengths.region_constraints_len);
let const_vars = const_vars_since_snapshot(
&mut inner.const_unification_table(),
variable_lengths.const_var_len,
);
drop(inner);

self.rollback_to("fudge_inference_if_ok -- ok", snapshot);

// At this point, we need to replace any of the now-popped
// type/region variables that appear in `value` with a fresh
// variable of the appropriate kind. We can't do this during
// the probe because they would just get popped then too. =)

// Micro-optimization: if no variables have been created, then
// `value` can't refer to any of them. =) So we can just return it.
if type_vars.0.is_empty()
&& int_vars.is_empty()
&& float_vars.is_empty()
&& region_vars.0.is_empty()
&& const_vars.0.is_empty()
{
Ok(value)
} else {
Ok(value.fold_with(&mut InferenceFudger {
infcx: self,
type_vars,
int_vars,
float_vars,
region_vars,
const_vars,
};

Ok((fudger, value))
}))
}
Err(e) => Err(e),
}
})?;

// At this point, we need to replace any of the now-popped
// type/region variables that appear in `value` with a fresh
// variable of the appropriate kind. We can't do this during
// the probe because they would just get popped then too. =)

// Micro-optimization: if no variables have been created, then
// `value` can't refer to any of them. =) So we can just return it.
if fudger.type_vars.0.is_empty()
&& fudger.int_vars.is_empty()
&& fudger.float_vars.is_empty()
&& fudger.region_vars.0.is_empty()
&& fudger.const_vars.0.is_empty()
{
Ok(value)
} else {
Ok(value.fold_with(&mut fudger))
Err(e) => {
debug_assert!(!e.needs_infer(), "fudge_inference_if_ok: leaking infer vars: {e:?}");
self.rollback_to("fudge_inference_if_ok -- error", snapshot);
return Err(e);
}
}
}
}
14 changes: 11 additions & 3 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
@@ -71,14 +71,13 @@ pub mod type_variable;
mod undo_log;

#[must_use]
#[derive(Debug)]
#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
pub struct InferOk<'tcx, T> {
pub value: T,
pub obligations: PredicateObligations<'tcx>,
}
pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>;

pub type Bound<T> = Option<T>;
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"

@@ -845,6 +844,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>,
E: TypeVisitable<'tcx>,
{
let snapshot = self.start_snapshot();
let r = f(&snapshot);
@@ -853,7 +853,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Ok(_) => {
self.commit_from(snapshot);
}
Err(_) => {
Err(ref e) => {
debug_assert!(!e.needs_infer(), "commit_if_ok: leaking infer vars: {e:?}");
self.rollback_to("commit_if_ok -- error", snapshot);
}
}
@@ -865,9 +866,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn probe<R, F>(&self, f: F) -> R
where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
R: TypeVisitable<'tcx>,
{
let snapshot = self.start_snapshot();

let r = f(&snapshot);

debug_assert!(!r.needs_infer(), "probe: leaking infer vars: {r:?}");
self.rollback_to("probe", snapshot);
r
}
@@ -877,13 +882,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R
where
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
R: TypeVisitable<'tcx>,
{
let snapshot = self.start_snapshot();
let was_skip_leak_check = self.skip_leak_check.get();
if should_skip {
self.skip_leak_check.set(true);
}
let r = f(&snapshot);

debug_assert!(!r.needs_infer(), "probe_maybe_skip_leak_check: leaking infer vars: {r:?}");
self.rollback_to("probe", snapshot);
self.skip_leak_check.set(was_skip_leak_check);
r
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/traits/project.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ pub use rustc_middle::traits::{EvaluationResult, Reveal};
pub(crate) type UndoLog<'tcx> =
snapshot_map::UndoLog<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>;

#[derive(Clone)]
#[derive(Clone, TypeFoldable, TypeVisitable)]
pub struct MismatchedProjectionTypes<'tcx> {
pub err: ty::error::TypeError<'tcx>,
}
9 changes: 6 additions & 3 deletions compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
@@ -301,9 +301,12 @@ TrivialTypeTraversalAndLiftImpls! {
}
}

TrivialTypeTraversalImpls! {
for <'tcx> {
crate::infer::canonical::CanonicalVarInfos<'tcx>,
impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> {
fn try_fold_with<F: ty::FallibleTypeFolder<'tcx>>(
self,
_: &mut F,
) -> ::std::result::Result<CanonicalVarInfos<'tcx>, F::Error> {
Ok(self)
}
}

7 changes: 0 additions & 7 deletions compiler/rustc_middle/src/mir/type_visitable.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! `TypeVisitable` implementations for MIR types
use super::*;
use crate::ty;

impl<'tcx> TypeVisitable<'tcx> for Terminator<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -67,12 +66,6 @@ impl<'tcx> TypeVisitable<'tcx> for Place<'tcx> {
}
}

impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

impl<'tcx> TypeVisitable<'tcx> for Rvalue<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
use crate::mir::Rvalue::*;
9 changes: 8 additions & 1 deletion compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -88,7 +88,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, Debug, PartialEq, Eq, Lift)]
#[derive(Clone, Debug, PartialEq, Eq, Lift, TypeVisitable)]
pub struct ObligationCause<'tcx> {
pub span: Span,

@@ -186,13 +186,15 @@ impl<'tcx> ObligationCause<'tcx> {
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
#[derive(TypeVisitable)]
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, Lift, Default)]
#[derive(TypeVisitable)]
pub struct InternedObligationCauseCode<'tcx> {
/// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of
/// the time). `Some` otherwise.
@@ -221,6 +223,7 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
#[derive(TypeVisitable)]
pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from the span.
MiscObligation,
@@ -415,6 +418,7 @@ pub enum ObligationCauseCode<'tcx> {
/// we can walk in order to obtain precise spans for any
/// 'nested' types (e.g. `Foo` in `Option<Foo>`).
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
#[derive(TypeVisitable)]
pub enum WellFormedLoc {
/// Use the type of the provided definition.
Ty(LocalDefId),
@@ -432,6 +436,7 @@ pub enum WellFormedLoc {
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
#[derive(TypeVisitable)]
pub struct ImplDerivedObligationCause<'tcx> {
pub derived: DerivedObligationCause<'tcx>,
pub impl_def_id: DefId,
@@ -479,6 +484,7 @@ impl<'tcx> ty::Lift<'tcx> for StatementAsExpression {
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
#[derive(TypeVisitable)]
pub struct MatchExpressionArmCause<'tcx> {
pub arm_block_id: Option<hir::HirId>,
pub arm_ty: Ty<'tcx>,
@@ -505,6 +511,7 @@ pub struct IfExpressionCause<'tcx> {
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
#[derive(TypeVisitable)]
pub struct DerivedObligationCause<'tcx> {
/// The trait predicate of the parent obligation that led to the
/// current obligation. Note that only trait obligations lead to
8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/traits/query.rs
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;

#[derive(Copy, Clone, Debug, HashStable)]
#[derive(Copy, Clone, Debug, HashStable, TypeVisitable)]
pub struct NoSolution;

pub type Fallible<T> = Result<T, NoSolution>;
@@ -178,7 +178,7 @@ impl<'tcx> FromIterator<DropckConstraint<'tcx>> for DropckConstraint<'tcx> {
}
}

#[derive(Debug, HashStable)]
#[derive(Debug, HashStable, TypeVisitable)]
pub struct CandidateStep<'tcx> {
pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
pub autoderefs: usize,
@@ -191,7 +191,7 @@ pub struct CandidateStep<'tcx> {
pub unsize: bool,
}

#[derive(Copy, Clone, Debug, HashStable)]
#[derive(Copy, Clone, Debug, HashStable, TypeVisitable)]
pub struct MethodAutoderefStepsResult<'tcx> {
/// The valid autoderef steps that could be find.
pub steps: &'tcx [CandidateStep<'tcx>],
@@ -202,7 +202,7 @@ pub struct MethodAutoderefStepsResult<'tcx> {
pub reached_recursion_limit: bool,
}

#[derive(Debug, HashStable)]
#[derive(Debug, HashStable, TypeVisitable)]
pub struct MethodAutoderefBadTy<'tcx> {
pub reached_raw_pointer: bool,
pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
@@ -175,6 +175,7 @@ pub enum SelectionCandidate<'tcx> {
/// so they are noops when unioned with a definite error, and within
/// the categories it's easy to see that the unions are correct.
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, HashStable)]
#[derive(TypeVisitable)]
pub enum EvaluationResult {
/// Evaluation successful.
EvaluatedToOk,
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/fold.rs
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ use std::collections::BTreeMap;
///
/// To implement this conveniently, use the derive macro located in
/// `rustc_macros`.
pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> {
pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> + Clone {
/// The entry point for folding. To fold a value `t` with a folder `f`
/// call: `t.try_fold_with(f)`.
///
56 changes: 35 additions & 21 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
@@ -9,10 +9,11 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt};
use rustc_data_structures::functor::IdFunctor;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_index::vec::{Idx, IndexVec};

use smallvec::SmallVec;
use std::fmt;
use std::mem::ManuallyDrop;
use std::ops::ControlFlow;
@@ -189,6 +190,7 @@ TrivialTypeTraversalAndLiftImpls! {
bool,
usize,
::rustc_target::abi::VariantIdx,
u16,
u32,
u64,
String,
@@ -198,7 +200,9 @@ TrivialTypeTraversalAndLiftImpls! {
::rustc_ast::InlineAsmTemplatePiece,
::rustc_ast::NodeId,
::rustc_span::symbol::Symbol,
::rustc_span::symbol::Ident,
::rustc_hir::def::Res,
::rustc_hir::def::DefKind,
::rustc_hir::def_id::DefId,
::rustc_hir::def_id::LocalDefId,
::rustc_hir::HirId,
@@ -844,6 +848,30 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Vec<T> {
}
}

impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &T {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
T::visit_with(self, visitor)
}
}

impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &[T] {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &ty::List<T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

impl<'tcx, T: TypeVisitable<'tcx>, const N: usize> TypeVisitable<'tcx> for SmallVec<[T; N]> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_id(|t| t.try_fold_with(folder))
@@ -901,26 +929,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::Existentia
}
}

impl<'tcx> TypeVisitable<'tcx>
for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>
{
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|p| p.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
}
}

impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<ProjectionKind> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
use crate::ty::InstanceDef::*;
@@ -1156,12 +1170,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
}
}

impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|p| p.visit_with(visitor))
}
}

impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_id(|x| x.try_fold_with(folder))
@@ -1174,6 +1182,12 @@ impl<'tcx, T: TypeVisitable<'tcx>, I: Idx> TypeVisitable<'tcx> for IndexVec<I, T
}
}

impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for FxIndexSet<T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_const(self)
12 changes: 0 additions & 12 deletions compiler/rustc_middle/src/ty/subst.rs
Original file line number Diff line number Diff line change
@@ -459,12 +459,6 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
}
}

impl<'tcx> TypeVisitable<'tcx> for SubstsRef<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
// This code is fairly hot, though not as hot as `SubstsRef`.
@@ -497,12 +491,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
}
}

impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}

// Just call `foo.subst(tcx, substs)` to perform a substitution across `foo`.
#[rustc_on_unimplemented(message = "Calling `subst` must now be done through an `EarlyBinder`")]
pub trait Subst<'tcx>: Sized {
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/visit.rs
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ use std::ops::ControlFlow;
///
/// To implement this conveniently, use the derive macro located in
/// `rustc_macros`.
pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
pub trait TypeVisitable<'tcx>: fmt::Debug {
/// The entry point for visiting. To visit a value `t` with a visitor `v`
/// call: `t.visit_with(v)`.
///
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ pub enum Conflict {
Downstream,
}

#[derive(Debug, TypeVisitable)]
pub struct OverlapResult<'tcx> {
pub impl_header: ty::ImplHeader<'tcx>,
pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause>,
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
@@ -154,6 +154,7 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
/// MismatchedProjectionTypes<'tcx>,
/// >
/// ```
#[derive(Debug, Clone, TypeVisitable)]
pub(super) enum ProjectAndUnifyResult<'tcx> {
/// The projection bound holds subject to the given obligations. If the
/// projection cannot be normalized because the required trait bound does
2 changes: 2 additions & 0 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -53,6 +53,7 @@ mod candidate_assembly;
mod confirmation;

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[derive(TypeVisitable)]
pub enum IntercrateAmbiguityCause {
DownstreamCrate { trait_desc: String, self_desc: Option<String> },
UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
@@ -2691,6 +2692,7 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
}
}

#[derive(Debug, Clone, TypeVisitable)]
pub enum ProjectionMatchesProjection {
Yes,
Ambiguous,
5 changes: 3 additions & 2 deletions compiler/rustc_typeck/src/check/method/mod.rs
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ pub struct MethodCallee<'tcx> {
pub sig: ty::FnSig<'tcx>,
}

#[derive(Debug)]
#[derive(Debug, TypeVisitable)]
pub enum MethodError<'tcx> {
// Did not find an applicable method, but we did find various near-misses that may work.
NoMatch(NoMatchData<'tcx>),
@@ -69,7 +69,7 @@ pub enum MethodError<'tcx> {

// Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
// could lead to matches if satisfied, and a list of not-in-scope traits which may work.
#[derive(Debug)]
#[derive(Debug, TypeVisitable)]
pub struct NoMatchData<'tcx> {
pub static_candidates: Vec<CandidateSource>,
pub unsatisfied_predicates:
@@ -82,6 +82,7 @@ pub struct NoMatchData<'tcx> {
// A pared down enum describing just the places from which a method
// candidate can arise. Used for error reporting only.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[derive(TypeVisitable)]
pub enum CandidateSource {
Impl(DefId),
Trait(DefId /* trait id */),
7 changes: 6 additions & 1 deletion compiler/rustc_typeck/src/check/method/probe.rs
Original file line number Diff line number Diff line change
@@ -152,6 +152,7 @@ enum CandidateKind<'tcx> {
}

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[derive(TypeVisitable)]
enum ProbeResult {
NoMatch,
BadReturnType,
@@ -171,6 +172,7 @@ enum ProbeResult {
/// (at most) one of these. Either the receiver has type `T` and we convert it to `&T` (or with
/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
#[derive(Debug, PartialEq, Copy, Clone)]
#[derive(TypeVisitable)]
pub enum AutorefOrPtrAdjustment {
/// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it.
/// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing.
@@ -195,6 +197,7 @@ impl AutorefOrPtrAdjustment {
}

#[derive(Debug, PartialEq, Clone)]
#[derive(TypeVisitable)]
pub struct Pick<'tcx> {
pub item: ty::AssocItem,
pub kind: PickKind<'tcx>,
@@ -213,6 +216,7 @@ pub struct Pick<'tcx> {
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(TypeVisitable)]
pub enum PickKind<'tcx> {
InherentImplPick,
ObjectPick,
@@ -226,6 +230,7 @@ pub enum PickKind<'tcx> {
pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>;

#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[derive(TypeVisitable)]
pub enum Mode {
// An expression of the form `receiver.method_name(...)`.
// Autoderefs are performed on `receiver`, lookup is done based on the
@@ -327,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
}

fn probe_op<OP, R>(
fn probe_op<OP, R: TypeVisitable<'tcx>>(
&'a self,
span: Span,
mode: Mode,
1 change: 0 additions & 1 deletion compiler/rustc_typeck/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Errors emitted by typeck.
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
use rustc_middle::ty::Ty;
use rustc_session::{parse::ParseSess, SessionDiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};
3 changes: 3 additions & 0 deletions compiler/rustc_typeck/src/lib.rs
Original file line number Diff line number Diff line change
@@ -80,6 +80,9 @@ extern crate tracing;
#[macro_use]
extern crate rustc_middle;

#[macro_use]
extern crate rustc_macros;

// These are used by Clippy.
pub mod check;
pub mod expr_use_visitor;