From e755963cbdbdfb97994eb861360f1aa0de1888c2 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 29 Oct 2019 16:19:16 +0100 Subject: [PATCH] save-analysis: Account for async desugaring in async fn return types --- src/librustc_save_analysis/dump_visitor.rs | 27 ++++++++++++++++++---- src/test/ui/save-analysis/issue-65590.rs | 21 +++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/save-analysis/issue-65590.rs diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index e282936b5d9e7..a372106d3795b 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -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 @@ -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, ) { @@ -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) + } } } @@ -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), diff --git a/src/test/ui/save-analysis/issue-65590.rs b/src/test/ui/save-analysis/issue-65590.rs new file mode 100644 index 0000000000000..27874f8655e56 --- /dev/null +++ b/src/test/ui/save-analysis/issue-65590.rs @@ -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::Assoc { + unimplemented!() +} + +impl Struct { + async fn foo(&self) -> T::Assoc { + unimplemented!() + } +} + +fn main() {}