/// ```
/// struct Foo<T> { data: Box<T> }
/// ```
-
+ ///
/// then this might return that Foo<T>: Send if T: Send (encoded in the AutoTraitResult type).
/// The analysis attempts to account for custom impls as well as other complex cases. This
/// result is intended for use by rustdoc and other such consumers.
-
+ ///
/// (Note that due to the coinductive nature of Send, the full and correct result is actually
/// quite simple to generate. That is, when a type has no custom impl, it is Send iff its field
/// types are all Send. So, in our example, we might have that Foo<T>: Send if Box<T>: Send.
/// But this is often not the best way to present to the user.)
-
+ ///
/// Warning: The API should be considered highly unstable, and it may be refactored or removed
/// in the future.
pub fn find_auto_trait_generics<A>(
// hold.
//
// One additional consideration is supertrait bounds. Normally, a ParamEnv is only ever
- // consutrcted once for a given type. As part of the construction process, the ParamEnv will
+ // constructed once for a given type. As part of the construction process, the ParamEnv will
// have any supertrait bounds normalized - e.g. if we have a type 'struct Foo<T: Copy>', the
// ParamEnv will contain 'T: Copy' and 'T: Clone', since 'Copy: Clone'. When we construct our
// own ParamEnv, we need to do this ourselves, through traits::elaborate_predicates, or else
/// along. Once all type inference constraints have been generated, the
/// method `select_all_or_error` can be used to report any remaining
/// ambiguous cases as errors.
-
pub struct FulfillmentContext<'tcx> {
// A list of all obligations that have been registered with this
// fulfillment context.
/// Attempts to select obligations using `selcx`.
fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>)
- -> Result<(),Vec<FulfillmentError<'tcx>>> {
+ -> Result<(), Vec<FulfillmentError<'tcx>>> {
debug!("select(obligation-forest-size={})", self.predicates.len());
let mut errors = Vec::new();
// have the errors get reported at a defined place (e.g.,
// during typeck). Instead I have all parameter
// environments, in effect, going through this function
- // and hence potentially reporting errors. This ensurse of
+ // and hence potentially reporting errors. This ensures of
// course that we never forget to normalize (the
// alternative seemed like it would involve a lot of
// manual invocations of this fn -- and then we'd have to
match self.confirm_candidate(obligation, candidate) {
Err(SelectionError::Overflow) => {
assert!(self.query_mode == TraitQueryMode::Canonical);
- return Err(SelectionError::Overflow);
+ Err(SelectionError::Overflow)
},
Err(e) => Err(e),
Ok(candidate) => Ok(Some(candidate))
// must be met of course). One obvious case this comes up is
// marker traits like `Send`. Think of a linked list:
//
- // struct List<T> { data: T, next: Option<Box<List<T>>> {
+ // struct List<T> { data: T, next: Option<Box<List<T>>> }
//
// `Box<List<T>>` will be `Send` if `T` is `Send` and
// `Option<Box<List<T>>>` is `Send`, and in turn
stack: &TraitObligationStack<'o, 'tcx>)
-> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>>
{
- let TraitObligationStack { obligation, .. } = *stack;
+ let obligation = stack.obligation;
let ref obligation = Obligation {
param_env: obligation.param_env,
cause: obligation.cause.clone(),
}
fn assemble_candidates_from_auto_impls(&mut self,
- obligation: &TraitObligation<'tcx>,
- candidates: &mut SelectionCandidateSet<'tcx>)
- -> Result<(), SelectionError<'tcx>>
+ obligation: &TraitObligation<'tcx>,
+ candidates: &mut SelectionCandidateSet<'tcx>)
+ -> Result<(), SelectionError<'tcx>>
{
// OK to skip binder here because the tests we do below do not involve bound regions
let self_ty = *obligation.self_ty().skip_binder();
fn confirm_candidate(&mut self,
obligation: &TraitObligation<'tcx>,
candidate: SelectionCandidate<'tcx>)
- -> Result<Selection<'tcx>,SelectionError<'tcx>>
+ -> Result<Selection<'tcx>, SelectionError<'tcx>>
{
debug!("confirm_candidate({:?}, {:?})",
obligation,
let mut obligations = self.collect_predicates_for_types(
obligation.param_env,
cause,
- obligation.recursion_depth+1,
+ obligation.recursion_depth + 1,
trait_def_id,
nested);
- let trait_obligations = self.in_snapshot(|this, snapshot| {
+ let trait_obligations: Vec<PredicateObligation<'_>> = self.in_snapshot(|this, snapshot| {
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
let (trait_ref, skol_map) =
this.infcx().skolemize_late_bound_regions(&poly_trait_ref);
snapshot)
});
+ // Adds the predicates from the trait. Note that this contains a `Self: Trait`
+ // predicate as usual. It won't have any effect since auto traits are coinductive.
obligations.extend(trait_obligations);
debug!("vtable_auto_impl: obligations={:?}", obligations);
-> Result<(), ()>
{
if self.done_cache.contains(obligation.as_predicate()) {
- return Ok(())
+ return Ok(());
}
match self.waiting_cache.entry(obligation.as_predicate().clone()) {
self.nodes[index]);
let result = match self.nodes[index] {
- Node { state: ref _state, ref mut obligation, .. }
- if _state.get() == NodeState::Pending =>
+ Node { ref state, ref mut obligation, .. }
+ if state.get() == NodeState::Pending =>
{
processor.process_obligation(obligation)
}
fn process_backedge<'c, I>(&mut self, _cycle: I,
_marker: PhantomData<&'c Self::Obligation>)
- where I: Clone + Iterator<Item=&'c Self::Obligation> {
- }
+ where I: Clone + Iterator<Item=&'c Self::Obligation>
+ {
+ }
}
}, |_|{}));
assert_eq!(ok, vec!["(A,B,C): Sized"]);
assert_eq!(err.len(), 0);
-
-
}
-
#[test]
fn orphan() {
// check that orphaned nodes are handled correctly