1
Fork 0

Properly account for binders in get_impl_future_output_ty

This commit is contained in:
Tyler Mandry 2021-12-21 22:08:47 +00:00
parent 5e57faa78a
commit 6487845884
4 changed files with 31 additions and 20 deletions

View file

@ -69,7 +69,7 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, self,
subst::{GenericArgKind, Subst, SubstsRef}, subst::{GenericArgKind, Subst, SubstsRef},
Region, Ty, TyCtxt, TypeFoldable, Binder, Region, Ty, TyCtxt, TypeFoldable,
}; };
use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span};
use rustc_target::spec::abi; use rustc_target::spec::abi;
@ -1765,7 +1765,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.note_error_origin(diag, cause, exp_found, terr); self.note_error_origin(diag, cause, exp_found, terr);
} }
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> {
if let ty::Opaque(def_id, substs) = ty.kind() { if let ty::Opaque(def_id, substs) = ty.kind() {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None); let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
// Future::Output // Future::Output
@ -1775,13 +1775,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
for (predicate, _) in bounds { for (predicate, _) in bounds {
let predicate = predicate.subst(self.tcx, substs); let predicate = predicate.subst(self.tcx, substs);
if let ty::PredicateKind::Projection(projection_predicate) = let output = predicate
predicate.kind().skip_binder() .kind()
.map_bound(|kind| match kind {
ty::PredicateKind::Projection(projection_predicate)
if projection_predicate.projection_ty.item_def_id == item_def_id =>
{ {
if projection_predicate.projection_ty.item_def_id == item_def_id { projection_predicate.term.ty()
// We don't account for multiple `Future::Output = Ty` contraints.
return projection_predicate.term.ty();
} }
_ => None,
})
.transpose();
if output.is_some() {
// We don't account for multiple `Future::Output = Ty` contraints.
return output;
} }
} }
} }
@ -1823,8 +1830,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
match ( match (
self.get_impl_future_output_ty(exp_found.expected), self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder),
self.get_impl_future_output_ty(exp_found.found), self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder),
) { ) {
(Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() { (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() {
ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => {

View file

@ -1909,7 +1909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => return, _ => return,
}; };
let mut add_label = true; let mut add_label = true;
if let ty::Adt(def, _) = output_ty.kind() { if let ty::Adt(def, _) = output_ty.skip_binder().kind() {
// no field access on enum type // no field access on enum type
if !def.is_enum() { if !def.is_enum() {
if def if def

View file

@ -609,14 +609,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = self.normalize_associated_types_in(expr.span, ty); let ty = self.normalize_associated_types_in(expr.span, ty);
let ty = match self.tcx.asyncness(fn_id.owner) { let ty = match self.tcx.asyncness(fn_id.owner) {
hir::IsAsync::Async => self.tcx.infer_ctxt().enter(|infcx| { hir::IsAsync::Async => self
.tcx
.infer_ctxt()
.enter(|infcx| {
infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| { infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!( span_bug!(
fn_decl.output.span(), fn_decl.output.span(),
"failed to get output type of async function" "failed to get output type of async function"
) )
}) })
}), })
.skip_binder(),
hir::IsAsync::NotAsync => ty, hir::IsAsync::NotAsync => ty,
}; };
if self.can_coerce(found, ty) { if self.can_coerce(found, ty) {

View file

@ -1274,7 +1274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span, span: Span,
) { ) {
let output_ty = match self.infcx.get_impl_future_output_ty(ty) { let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
Some(output_ty) => self.resolve_vars_if_possible(output_ty), Some(output_ty) => self.resolve_vars_if_possible(output_ty).skip_binder(),
_ => return, _ => return,
}; };
let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true); let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);