Skip to content

Commit

Permalink
avoid using skip_binder and instead look for bound vars properly
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Oct 2, 2019
1 parent 3f277e1 commit a96bce7
Showing 1 changed file with 25 additions and 12 deletions.
37 changes: 25 additions & 12 deletions src/librustc_typeck/check/closure.rs
Expand Up @@ -698,39 +698,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {


/// Given a projection like /// Given a projection like
/// ///
/// `<_ as Future>::Output = T` /// `<X as Future>::Output = T`
/// ///
/// returns `Some(T)`. If the projection is for some other trait, /// where `X` is some type that has no late-bound regions, returns
/// returns `None`. /// `Some(T)`. If the projection is for some other trait, returns
/// `None`.
fn deduce_future_output_from_projection( fn deduce_future_output_from_projection(
&self, &self,
cause_span: Span, cause_span: Span,
projection: &ty::PolyProjectionPredicate<'tcx>, predicate: &ty::PolyProjectionPredicate<'tcx>,
) -> Option<Ty<'tcx>> { ) -> Option<Ty<'tcx>> {
debug!("deduce_future_output_from_projection(projection={:?})", projection); debug!("deduce_future_output_from_projection(predicate={:?})", predicate);

// We do not expect any bound regions in our predicate, so
// skip past the bound vars.
let predicate = match predicate.no_bound_vars() {
Some(p) => p,
None => {
debug!("deduce_future_output_from_projection: has late-bound regions");
return None;
}
};


let trait_ref = projection.to_poly_trait_ref(self.tcx); // Check that this is a projection from the `Future` trait.
let trait_ref = predicate.projection_ty.trait_ref(self.tcx);
let future_trait = self.tcx.lang_items().future_trait().unwrap(); let future_trait = self.tcx.lang_items().future_trait().unwrap();
if trait_ref.def_id() != future_trait { if trait_ref.def_id != future_trait {
debug!("deduce_future_output_from_projection: not a future"); debug!("deduce_future_output_from_projection: not a future");
return None; return None;
} }


// The `Future` trait has only one associted item, `Output`, // The `Future` trait has only one associted item, `Output`,
// so check that this is what we see. // so check that this is what we see.
let output_assoc_item = self.tcx.associated_items(future_trait).nth(0).unwrap().def_id; let output_assoc_item = self.tcx.associated_items(future_trait).nth(0).unwrap().def_id;
if output_assoc_item != projection.projection_def_id() { if output_assoc_item != predicate.projection_ty.item_def_id {
span_bug!( span_bug!(
cause_span, cause_span,
"projecting associated item `{:?}` from future, which is not Output `{:?}`", "projecting associated item `{:?}` from future, which is not Output `{:?}`",
projection.projection_def_id(), predicate.projection_ty.item_def_id,
output_assoc_item, output_assoc_item,
); );
} }


// Extract the type from the projection. // Extract the type from the projection. Note that there can
let output_ty = projection.skip_binder().ty; // be no bound variables in this type because the "self type"
let output_ty = self.resolve_vars_if_possible(&output_ty); // does not have any regions in it.
let output_ty = self.resolve_vars_if_possible(&predicate.ty);
debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
Some(output_ty) Some(output_ty)
} }
Expand Down

0 comments on commit a96bce7

Please sign in to comment.