Properly account for binders in get_impl_future_output_ty
This commit is contained in:
parent
5e57faa78a
commit
6487845884
4 changed files with 31 additions and 20 deletions
|
@ -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 {
|
||||||
if projection_predicate.projection_ty.item_def_id == item_def_id {
|
ty::PredicateKind::Projection(projection_predicate)
|
||||||
// We don't account for multiple `Future::Output = Ty` contraints.
|
if projection_predicate.projection_ty.item_def_id == item_def_id =>
|
||||||
return projection_predicate.term.ty();
|
{
|
||||||
}
|
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, .. }) => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
|
.tcx
|
||||||
span_bug!(
|
.infer_ctxt()
|
||||||
fn_decl.output.span(),
|
.enter(|infcx| {
|
||||||
"failed to get output type of async function"
|
infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
|
||||||
)
|
span_bug!(
|
||||||
|
fn_decl.output.span(),
|
||||||
|
"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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue