diff options
| author | Igor Matuszewski <Xanewok@gmail.com> | 2019-10-29 16:19:16 +0100 |
|---|---|---|
| committer | Igor Matuszewski <Xanewok@gmail.com> | 2019-10-29 16:25:37 +0100 |
| commit | e755963cbdbdfb97994eb861360f1aa0de1888c2 (patch) | |
| tree | aa71854b46ece73d23c216eeca7479908564330a | |
| parent | eb5ef813f0d6e3fe8edd3abb046a18f5b1a8cc48 (diff) | |
| download | rust-e755963cbdbdfb97994eb861360f1aa0de1888c2.tar.gz rust-e755963cbdbdfb97994eb861360f1aa0de1888c2.zip | |
save-analysis: Account for async desugaring in async fn return types
| -rw-r--r-- | src/librustc_save_analysis/dump_visitor.rs | 27 | ||||
| -rw-r--r-- | src/test/ui/save-analysis/issue-65590.rs | 21 |
2 files changed, 44 insertions, 4 deletions
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index e282936b5d9..a372106d379 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 00000000000..27874f8655e --- /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: Trait>() -> T::Assoc { + unimplemented!() +} + +impl Struct { + async fn foo<T: Trait>(&self) -> T::Assoc { + unimplemented!() + } +} + +fn main() {} |
