Skip to content

Commit a77da35

Browse files
committed
Move traits::select datatypes to traits::types.
1 parent a2cd071 commit a77da35

File tree

4 files changed

+290
-295
lines changed

4 files changed

+290
-295
lines changed

src/librustc/traits/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
5252
pub use self::project::MismatchedProjectionTypes;
5353
pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type};
5454
pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot};
55-
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
56-
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
55+
pub use self::select::{IntercrateAmbiguityCause, SelectionContext};
5756
pub use self::specialize::find_associated_item;
5857
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
5958
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;

src/librustc/traits/select.rs

Lines changed: 2 additions & 293 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, Wit
4141
use rustc_hir::def_id::DefId;
4242

4343
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44-
use rustc_data_structures::sync::Lock;
4544
use rustc_hir as hir;
4645
use rustc_index::bit_set::GrowableBitSet;
4746
use rustc_span::symbol::sym;
@@ -53,6 +52,8 @@ use std::iter;
5352
use std::rc::Rc;
5453
use syntax::{ast, attr};
5554

55+
pub use rustc::traits::types::select::*;
56+
5657
pub struct SelectionContext<'cx, 'tcx> {
5758
infcx: &'cx InferCtxt<'cx, 'tcx>,
5859

@@ -181,146 +182,6 @@ struct TraitObligationStack<'prev, 'tcx> {
181182
dfn: usize,
182183
}
183184

184-
#[derive(Clone, Default)]
185-
pub struct SelectionCache<'tcx> {
186-
hashmap: Lock<
187-
FxHashMap<
188-
ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
189-
WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>,
190-
>,
191-
>,
192-
}
193-
194-
/// The selection process begins by considering all impls, where
195-
/// clauses, and so forth that might resolve an obligation. Sometimes
196-
/// we'll be able to say definitively that (e.g.) an impl does not
197-
/// apply to the obligation: perhaps it is defined for `usize` but the
198-
/// obligation is for `int`. In that case, we drop the impl out of the
199-
/// list. But the other cases are considered *candidates*.
200-
///
201-
/// For selection to succeed, there must be exactly one matching
202-
/// candidate. If the obligation is fully known, this is guaranteed
203-
/// by coherence. However, if the obligation contains type parameters
204-
/// or variables, there may be multiple such impls.
205-
///
206-
/// It is not a real problem if multiple matching impls exist because
207-
/// of type variables - it just means the obligation isn't sufficiently
208-
/// elaborated. In that case we report an ambiguity, and the caller can
209-
/// try again after more type information has been gathered or report a
210-
/// "type annotations needed" error.
211-
///
212-
/// However, with type parameters, this can be a real problem - type
213-
/// parameters don't unify with regular types, but they *can* unify
214-
/// with variables from blanket impls, and (unless we know its bounds
215-
/// will always be satisfied) picking the blanket impl will be wrong
216-
/// for at least *some* substitutions. To make this concrete, if we have
217-
///
218-
/// trait AsDebug { type Out : fmt::Debug; fn debug(self) -> Self::Out; }
219-
/// impl<T: fmt::Debug> AsDebug for T {
220-
/// type Out = T;
221-
/// fn debug(self) -> fmt::Debug { self }
222-
/// }
223-
/// fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
224-
///
225-
/// we can't just use the impl to resolve the `<T as AsDebug>` obligation
226-
/// -- a type from another crate (that doesn't implement `fmt::Debug`) could
227-
/// implement `AsDebug`.
228-
///
229-
/// Because where-clauses match the type exactly, multiple clauses can
230-
/// only match if there are unresolved variables, and we can mostly just
231-
/// report this ambiguity in that case. This is still a problem - we can't
232-
/// *do anything* with ambiguities that involve only regions. This is issue
233-
/// #21974.
234-
///
235-
/// If a single where-clause matches and there are no inference
236-
/// variables left, then it definitely matches and we can just select
237-
/// it.
238-
///
239-
/// In fact, we even select the where-clause when the obligation contains
240-
/// inference variables. The can lead to inference making "leaps of logic",
241-
/// for example in this situation:
242-
///
243-
/// pub trait Foo<T> { fn foo(&self) -> T; }
244-
/// impl<T> Foo<()> for T { fn foo(&self) { } }
245-
/// impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
246-
///
247-
/// pub fn foo<T>(t: T) where T: Foo<bool> {
248-
/// println!("{:?}", <T as Foo<_>>::foo(&t));
249-
/// }
250-
/// fn main() { foo(false); }
251-
///
252-
/// Here the obligation `<T as Foo<$0>>` can be matched by both the blanket
253-
/// impl and the where-clause. We select the where-clause and unify `$0=bool`,
254-
/// so the program prints "false". However, if the where-clause is omitted,
255-
/// the blanket impl is selected, we unify `$0=()`, and the program prints
256-
/// "()".
257-
///
258-
/// Exactly the same issues apply to projection and object candidates, except
259-
/// that we can have both a projection candidate and a where-clause candidate
260-
/// for the same obligation. In that case either would do (except that
261-
/// different "leaps of logic" would occur if inference variables are
262-
/// present), and we just pick the where-clause. This is, for example,
263-
/// required for associated types to work in default impls, as the bounds
264-
/// are visible both as projection bounds and as where-clauses from the
265-
/// parameter environment.
266-
#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)]
267-
enum SelectionCandidate<'tcx> {
268-
BuiltinCandidate {
269-
/// `false` if there are no *further* obligations.
270-
has_nested: bool,
271-
},
272-
ParamCandidate(ty::PolyTraitRef<'tcx>),
273-
ImplCandidate(DefId),
274-
AutoImplCandidate(DefId),
275-
276-
/// This is a trait matching with a projected type as `Self`, and
277-
/// we found an applicable bound in the trait definition.
278-
ProjectionCandidate,
279-
280-
/// Implementation of a `Fn`-family trait by one of the anonymous types
281-
/// generated for a `||` expression.
282-
ClosureCandidate,
283-
284-
/// Implementation of a `Generator` trait by one of the anonymous types
285-
/// generated for a generator.
286-
GeneratorCandidate,
287-
288-
/// Implementation of a `Fn`-family trait by one of the anonymous
289-
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
290-
FnPointerCandidate,
291-
292-
TraitAliasCandidate(DefId),
293-
294-
ObjectCandidate,
295-
296-
BuiltinObjectCandidate,
297-
298-
BuiltinUnsizeCandidate,
299-
}
300-
301-
impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
302-
type Lifted = SelectionCandidate<'tcx>;
303-
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
304-
Some(match *self {
305-
BuiltinCandidate { has_nested } => BuiltinCandidate { has_nested },
306-
ImplCandidate(def_id) => ImplCandidate(def_id),
307-
AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
308-
ProjectionCandidate => ProjectionCandidate,
309-
ClosureCandidate => ClosureCandidate,
310-
GeneratorCandidate => GeneratorCandidate,
311-
FnPointerCandidate => FnPointerCandidate,
312-
TraitAliasCandidate(def_id) => TraitAliasCandidate(def_id),
313-
ObjectCandidate => ObjectCandidate,
314-
BuiltinObjectCandidate => BuiltinObjectCandidate,
315-
BuiltinUnsizeCandidate => BuiltinUnsizeCandidate,
316-
317-
ParamCandidate(ref trait_ref) => {
318-
return tcx.lift(trait_ref).map(ParamCandidate);
319-
}
320-
})
321-
}
322-
}
323-
324185
struct SelectionCandidateSet<'tcx> {
325186
// A list of candidates that definitely apply to the current
326187
// obligation (meaning: types unify).
@@ -350,134 +211,6 @@ enum BuiltinImplConditions<'tcx> {
350211
Ambiguous,
351212
}
352213

353-
/// The result of trait evaluation. The order is important
354-
/// here as the evaluation of a list is the maximum of the
355-
/// evaluations.
356-
///
357-
/// The evaluation results are ordered:
358-
/// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
359-
/// implies `EvaluatedToAmbig` implies `EvaluatedToUnknown`
360-
/// - `EvaluatedToErr` implies `EvaluatedToRecur`
361-
/// - the "union" of evaluation results is equal to their maximum -
362-
/// all the "potential success" candidates can potentially succeed,
363-
/// so they are noops when unioned with a definite error, and within
364-
/// the categories it's easy to see that the unions are correct.
365-
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, HashStable)]
366-
pub enum EvaluationResult {
367-
/// Evaluation successful.
368-
EvaluatedToOk,
369-
/// Evaluation successful, but there were unevaluated region obligations.
370-
EvaluatedToOkModuloRegions,
371-
/// Evaluation is known to be ambiguous -- it *might* hold for some
372-
/// assignment of inference variables, but it might not.
373-
///
374-
/// While this has the same meaning as `EvaluatedToUnknown` -- we can't
375-
/// know whether this obligation holds or not -- it is the result we
376-
/// would get with an empty stack, and therefore is cacheable.
377-
EvaluatedToAmbig,
378-
/// Evaluation failed because of recursion involving inference
379-
/// variables. We are somewhat imprecise there, so we don't actually
380-
/// know the real result.
381-
///
382-
/// This can't be trivially cached for the same reason as `EvaluatedToRecur`.
383-
EvaluatedToUnknown,
384-
/// Evaluation failed because we encountered an obligation we are already
385-
/// trying to prove on this branch.
386-
///
387-
/// We know this branch can't be a part of a minimal proof-tree for
388-
/// the "root" of our cycle, because then we could cut out the recursion
389-
/// and maintain a valid proof tree. However, this does not mean
390-
/// that all the obligations on this branch do not hold -- it's possible
391-
/// that we entered this branch "speculatively", and that there
392-
/// might be some other way to prove this obligation that does not
393-
/// go through this cycle -- so we can't cache this as a failure.
394-
///
395-
/// For example, suppose we have this:
396-
///
397-
/// ```rust,ignore (pseudo-Rust)
398-
/// pub trait Trait { fn xyz(); }
399-
/// // This impl is "useless", but we can still have
400-
/// // an `impl Trait for SomeUnsizedType` somewhere.
401-
/// impl<T: Trait + Sized> Trait for T { fn xyz() {} }
402-
///
403-
/// pub fn foo<T: Trait + ?Sized>() {
404-
/// <T as Trait>::xyz();
405-
/// }
406-
/// ```
407-
///
408-
/// When checking `foo`, we have to prove `T: Trait`. This basically
409-
/// translates into this:
410-
///
411-
/// ```plain,ignore
412-
/// (T: Trait + Sized →_\impl T: Trait), T: Trait ⊢ T: Trait
413-
/// ```
414-
///
415-
/// When we try to prove it, we first go the first option, which
416-
/// recurses. This shows us that the impl is "useless" -- it won't
417-
/// tell us that `T: Trait` unless it already implemented `Trait`
418-
/// by some other means. However, that does not prevent `T: Trait`
419-
/// does not hold, because of the bound (which can indeed be satisfied
420-
/// by `SomeUnsizedType` from another crate).
421-
//
422-
// FIXME: when an `EvaluatedToRecur` goes past its parent root, we
423-
// ought to convert it to an `EvaluatedToErr`, because we know
424-
// there definitely isn't a proof tree for that obligation. Not
425-
// doing so is still sound -- there isn't any proof tree, so the
426-
// branch still can't be a part of a minimal one -- but does not re-enable caching.
427-
EvaluatedToRecur,
428-
/// Evaluation failed.
429-
EvaluatedToErr,
430-
}
431-
432-
impl EvaluationResult {
433-
/// Returns `true` if this evaluation result is known to apply, even
434-
/// considering outlives constraints.
435-
pub fn must_apply_considering_regions(self) -> bool {
436-
self == EvaluatedToOk
437-
}
438-
439-
/// Returns `true` if this evaluation result is known to apply, ignoring
440-
/// outlives constraints.
441-
pub fn must_apply_modulo_regions(self) -> bool {
442-
self <= EvaluatedToOkModuloRegions
443-
}
444-
445-
pub fn may_apply(self) -> bool {
446-
match self {
447-
EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
448-
true
449-
}
450-
451-
EvaluatedToErr | EvaluatedToRecur => false,
452-
}
453-
}
454-
455-
fn is_stack_dependent(self) -> bool {
456-
match self {
457-
EvaluatedToUnknown | EvaluatedToRecur => true,
458-
459-
EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
460-
}
461-
}
462-
}
463-
464-
/// Indicates that trait evaluation caused overflow.
465-
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
466-
pub struct OverflowError;
467-
468-
impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
469-
fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
470-
SelectionError::Overflow
471-
}
472-
}
473-
474-
#[derive(Clone, Default)]
475-
pub struct EvaluationCache<'tcx> {
476-
hashmap: Lock<
477-
FxHashMap<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, WithDepNode<EvaluationResult>>,
478-
>,
479-
}
480-
481214
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
482215
pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
483216
SelectionContext {
@@ -3827,13 +3560,6 @@ impl<'tcx> TraitObligation<'tcx> {
38273560
}
38283561
}
38293562

3830-
impl<'tcx> SelectionCache<'tcx> {
3831-
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
3832-
pub fn clear(&self) {
3833-
*self.hashmap.borrow_mut() = Default::default();
3834-
}
3835-
}
3836-
38373563
impl<'tcx> EvaluationCache<'tcx> {
38383564
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
38393565
pub fn clear(&self) {
@@ -4126,20 +3852,3 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
41263852
write!(f, "TraitObligationStack({:?})", self.obligation)
41273853
}
41283854
}
4129-
4130-
#[derive(Clone, Eq, PartialEq)]
4131-
pub struct WithDepNode<T> {
4132-
dep_node: DepNodeIndex,
4133-
cached_value: T,
4134-
}
4135-
4136-
impl<T: Clone> WithDepNode<T> {
4137-
pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
4138-
WithDepNode { dep_node, cached_value }
4139-
}
4140-
4141-
pub fn get(&self, tcx: TyCtxt<'_>) -> T {
4142-
tcx.dep_graph.read_index(self.dep_node);
4143-
self.cached_value.clone()
4144-
}
4145-
}

src/librustc/traits/types/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//!
33
//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
44
5+
pub mod select;
6+
57
use crate::mir::interpret::ErrorHandled;
68
use crate::ty::fold::{TypeFolder, TypeVisitor};
79
use crate::ty::subst::SubstsRef;
@@ -15,6 +17,8 @@ use syntax::ast;
1517
use std::fmt::Debug;
1618
use std::rc::Rc;
1719

20+
pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
21+
1822
pub use self::ObligationCauseCode::*;
1923
pub use self::SelectionError::*;
2024
pub use self::Vtable::*;

0 commit comments

Comments
 (0)