From 034cd20f528c88be114cbd10c9a28d971ac12acc Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 15 Aug 2017 06:58:47 +0800 Subject: [PATCH] Exclude `impl Trait` functions from everybody_loops. Fixes #43869. --- src/librustc_driver/pretty.rs | 41 ++++++++++++++++++++++++++++----- src/test/rustdoc/issue-43869.rs | 32 +++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 src/test/rustdoc/issue-43869.rs diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 84d3ab65b1c1f..bdc6f3bb56c9f 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -620,6 +620,15 @@ impl UserIdentifiedItem { } // Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere. +// +// FIXME: Currently the `everybody_loops` transformation is not applied to: +// * `const fn`, due to issue #43636 that `loop` is not supported for const evaluation. We are +// waiting for miri to fix that. +// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging. +// Solving this may require `!` to implement every trait, which relies on the an even more +// ambitious form of the closed RFC #1637. See also [#34511]. +// +// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 pub struct ReplaceBodyWithLoop { within_static_or_const: bool, } @@ -635,14 +644,34 @@ impl ReplaceBodyWithLoop { self.within_static_or_const = old_const; ret } + + fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool { + if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output { + fn involves_impl_trait(ty: &ast::Ty) -> bool { + match ty.node { + ast::TyKind::ImplTrait(_) => true, + ast::TyKind::Slice(ref subty) | + ast::TyKind::Array(ref subty, _) | + ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) | + ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) | + ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), + ast::TyKind::Tup(ref tys) => tys.iter().any(|subty| involves_impl_trait(subty)), + _ => false, + } + } + involves_impl_trait(ty) + } else { + false + } + } } impl fold::Folder for ReplaceBodyWithLoop { fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind { let is_const = match i { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, - ast::ItemKind::Fn(_, _, ref constness, _, _, _) => - constness.node == ast::Constness::Const, + ast::ItemKind::Fn(ref decl, _, ref constness, _, _, _) => + constness.node == ast::Constness::Const || Self::should_ignore_fn(decl), _ => false, }; self.run(is_const, |s| fold::noop_fold_item_kind(i, s)) @@ -651,8 +680,8 @@ impl fold::Folder for ReplaceBodyWithLoop { fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector { let is_const = match i.node { ast::TraitItemKind::Const(..) => true, - ast::TraitItemKind::Method(ast::MethodSig { ref constness, .. }, _) => - constness.node == ast::Constness::Const, + ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) => + constness.node == ast::Constness::Const || Self::should_ignore_fn(decl), _ => false, }; self.run(is_const, |s| fold::noop_fold_trait_item(i, s)) @@ -661,8 +690,8 @@ impl fold::Folder for ReplaceBodyWithLoop { fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector { let is_const = match i.node { ast::ImplItemKind::Const(..) => true, - ast::ImplItemKind::Method(ast::MethodSig { ref constness, .. }, _) => - constness.node == ast::Constness::Const, + ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) => + constness.node == ast::Constness::Const || Self::should_ignore_fn(decl), _ => false, }; self.run(is_const, |s| fold::noop_fold_impl_item(i, s)) diff --git a/src/test/rustdoc/issue-43869.rs b/src/test/rustdoc/issue-43869.rs new file mode 100644 index 0000000000000..2d18e4be53286 --- /dev/null +++ b/src/test/rustdoc/issue-43869.rs @@ -0,0 +1,32 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(conservative_impl_trait)] + +pub fn g() -> impl Iterator { + Some(1u8).into_iter() +} + +pub fn h() -> (impl Iterator) { + Some(1u8).into_iter() +} + +pub fn i() -> impl Iterator + 'static { + Some(1u8).into_iter() +} + +pub fn j() -> impl Iterator + Clone { + Some(1u8).into_iter() +} + +// @has issue_43869/fn.g.html +// @has issue_43869/fn.h.html +// @has issue_43869/fn.i.html +// @has issue_43869/fn.j.html