Skip to content

Commit

Permalink
Rollup merge of #65936 - Xanewok:save-analysis-async, r=nikomatsakis
Browse files Browse the repository at this point in the history
save-analysis: Account for async desugaring in async fn return types

Closes #65590

When visiting the return type of an async function we need to take into account its desugaring, since it introduces a new definition under which the return type is redefined.

r? @nikomatsakis
  • Loading branch information
tmandry authored Oct 29, 2019
2 parents 73dcb96 + e755963 commit db49686
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
27 changes: 23 additions & 4 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,16 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}

if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
v.visit_ty(ret_ty);
// In async functions, return types are desugared and redefined
// as an `impl Trait` existential type. Because of this, to match
// the definition paths when resolving nested types we need to
// start walking from the newly-created definition.
match sig.header.asyncness.node {
ast::IsAsync::Async { return_impl_trait_id, .. } => {
v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty))
}
_ => v.visit_ty(ret_ty)
}
}

// walk the fn body
Expand Down Expand Up @@ -369,6 +378,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
&mut self,
item: &'l ast::Item,
decl: &'l ast::FnDecl,
header: &'l ast::FnHeader,
ty_params: &'l ast::Generics,
body: &'l ast::Block,
) {
Expand All @@ -391,7 +401,16 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
// FIXME: Opaque type desugaring prevents us from easily
// processing trait bounds. See `visit_ty` for more details.
} else {
v.visit_ty(&ret_ty);
// In async functions, return types are desugared and redefined
// as an `impl Trait` existential type. Because of this, to match
// the definition paths when resolving nested types we need to
// start walking from the newly-created definition.
match header.asyncness.node {
ast::IsAsync::Async { return_impl_trait_id, .. } => {
v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty))
}
_ => v.visit_ty(ret_ty)
}
}
}

Expand Down Expand Up @@ -1315,8 +1334,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
);
}
}
Fn(ref decl, .., ref ty_params, ref body) => {
self.process_fn(item, &decl, ty_params, &body)
Fn(ref decl, ref header, ref ty_params, ref body) => {
self.process_fn(item, &decl, &header, ty_params, &body)
}
Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr),
Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr),
Expand Down
21 changes: 21 additions & 0 deletions src/test/ui/save-analysis/issue-65590.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// check-pass
// compile-flags: -Zsave-analysis
// edition:2018

// Async desugaring for return types in (associated) functions introduces a
// separate definition internally, which we need to take into account
// (or else we ICE).
trait Trait { type Assoc; }
struct Struct;

async fn foobar<T: Trait>() -> T::Assoc {
unimplemented!()
}

impl Struct {
async fn foo<T: Trait>(&self) -> T::Assoc {
unimplemented!()
}
}

fn main() {}

0 comments on commit db49686

Please sign in to comment.