diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index fc00050f40518..1f418fe7f7ff2 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -779,11 +779,18 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::OpaqueTy(..) => { - // FIXME: This is some serious pessimization intended to workaround deficiencies - // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time - // reachable if they are returned via `impl Trait`, even from private functions. - let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); - self.reach(item.hir_id, exist_level).generics().predicates().ty(); + // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general) + // Since rustdoc never need to do codegen and doesn't care about link-time reachability, + // mark this as unreachable. + // See https://github.com/rust-lang/rust/issues/75100 + if !self.tcx.sess.opts.actually_rustdoc { + // FIXME: This is some serious pessimization intended to workaround deficiencies + // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time + // reachable if they are returned via `impl Trait`, even from private functions. + let exist_level = + cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); + self.reach(item.hir_id, exist_level).generics().predicates().ty(); + } } // Visit everything. hir::ItemKind::Const(..) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6cefc99f7b171..9169b5aa58a1f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1967,10 +1967,16 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { check_union(tcx, it.hir_id, it.span); } hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - let def_id = tcx.hir().local_def_id(it.hir_id); - - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); - check_opaque(tcx, def_id, substs, it.span, &origin); + // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting + // `async-std` (and `pub async fn` in general). + // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it! + // See https://github.com/rust-lang/rust/issues/75100 + if !tcx.sess.opts.actually_rustdoc { + let def_id = tcx.hir().local_def_id(it.hir_id); + + let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + check_opaque(tcx, def_id, substs, it.span, &origin); + } } hir::ItemKind::TyAlias(..) => { let def_id = tcx.hir().local_def_id(it.hir_id); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9ba2545ba63cb..bea0f1e1f0845 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -356,6 +356,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { tcx.sess.time("wf_checking", || check::check_wf_new(tcx)); })?; + // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync. tcx.sess.time("item_types_checking", || { for &module in tcx.hir().krate().modules.keys() { tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index cbd0ca0de6414..b13acaae1bf23 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -452,10 +452,20 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // Certain queries assume that some checks were run elsewhere // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425), // so type-check everything other than function bodies in this crate before running lints. + // NOTE: this does not call `tcx.analysis()` so that we won't // typeck function bodies or run the default rustc lints. // (see `override_queries` in the `config`) - let _ = rustc_typeck::check_crate(tcx); + + // HACK(jynelson) this calls an _extremely_ limited subset of `typeck` + // and might break if queries change their assumptions in the future. + + // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes. + tcx.sess.time("item_types_checking", || { + for &module in tcx.hir().krate().modules.keys() { + tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); + } + }); tcx.sess.abort_if_errors(); sess.time("missing_docs", || { rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); diff --git a/src/test/rustdoc-ui/error-in-impl-trait/async.rs b/src/test/rustdoc-ui/error-in-impl-trait/async.rs index 112a2c494a5c2..cda53bff07a1b 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/async.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/async.rs @@ -1,10 +1,7 @@ // edition:2018 +// check-pass -/// This used to work with ResolveBodyWithLoop. -/// However now that we ignore type checking instead of modifying the function body, -/// the return type is seen as `impl Future`, not a `u32`. -/// So it no longer allows errors in the function body. +/// Should compile fine pub async fn a() -> u32 { error::_in::async_fn() - //~^ ERROR failed to resolve } diff --git a/src/test/rustdoc-ui/error-in-impl-trait/async.stderr b/src/test/rustdoc-ui/error-in-impl-trait/async.stderr deleted file mode 100644 index 086db1be72274..0000000000000 --- a/src/test/rustdoc-ui/error-in-impl-trait/async.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0433]: failed to resolve: could not resolve path `error::_in::async_fn` - --> $DIR/async.rs:8:5 - | -LL | error::_in::async_fn() - | ^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::async_fn` - | - = note: this error was originally ignored because you are running `rustdoc` - = note: try running again with `rustc` or `cargo check` and you may get a more detailed error - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/error-in-impl-trait/closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/closure.rs index df40c121d579e..f1fd85bb23cb6 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/closure.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/closure.rs @@ -1,5 +1,5 @@ +// check-pass // manually desugared version of an `async fn` (but with a closure instead of a generator) pub fn a() -> impl Fn() -> u32 { || content::doesnt::matter() - //~^ ERROR failed to resolve } diff --git a/src/test/rustdoc-ui/error-in-impl-trait/closure.stderr b/src/test/rustdoc-ui/error-in-impl-trait/closure.stderr deleted file mode 100644 index 4ee9c4d1f438d..0000000000000 --- a/src/test/rustdoc-ui/error-in-impl-trait/closure.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0433]: failed to resolve: could not resolve path `content::doesnt::matter` - --> $DIR/closure.rs:3:8 - | -LL | || content::doesnt::matter() - | ^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `content::doesnt::matter` - | - = note: this error was originally ignored because you are running `rustdoc` - = note: try running again with `rustc` or `cargo check` and you may get a more detailed error - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs index 0ccf2e3866fc9..dcec379d47e94 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.rs @@ -1,7 +1,7 @@ +// check-pass trait ValidTrait {} /// This has docs pub fn f() -> impl ValidTrait { Vec::::new() - //~^ ERROR failed to resolve } diff --git a/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr b/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr deleted file mode 100644 index 72716c258dc1e..0000000000000 --- a/src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0433]: failed to resolve: could not resolve path `DoesNotExist` - --> $DIR/generic-argument.rs:5:11 - | -LL | Vec::::new() - | ^^^^^^^^^^^^ could not resolve path `DoesNotExist` - | - = note: this error was originally ignored because you are running `rustdoc` - = note: try running again with `rustc` or `cargo check` and you may get a more detailed error - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs index 399fb827517fa..b935b0832f065 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.rs @@ -1,6 +1,6 @@ +// check-pass pub trait ValidTrait {} /// This returns impl trait pub fn g() -> impl ValidTrait { (|| error::_in::impl_trait::alias::nested::closure())() - //~^ ERROR failed to resolve } diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.stderr b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.stderr deleted file mode 100644 index 55f9b609a1105..0000000000000 --- a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword-closure.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias::nested::closure` - --> $DIR/impl-keyword-closure.rs:4:9 - | -LL | (|| error::_in::impl_trait::alias::nested::closure())() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias::nested::closure` - | - = note: this error was originally ignored because you are running `rustdoc` - = note: try running again with `rustc` or `cargo check` and you may get a more detailed error - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs index 24b5734dbd0bf..701126f87a1f0 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs @@ -1,6 +1,6 @@ +// check-pass pub trait ValidTrait {} /// This returns impl trait pub fn g() -> impl ValidTrait { error::_in::impl_trait() - //~^ ERROR failed to resolve } diff --git a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr b/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr deleted file mode 100644 index 3257079f94219..0000000000000 --- a/src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait` - --> $DIR/impl-keyword.rs:4:5 - | -LL | error::_in::impl_trait() - | ^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait` - | - = note: this error was originally ignored because you are running `rustdoc` - = note: try running again with `rustc` or `cargo check` and you may get a more detailed error - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs b/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs new file mode 100644 index 0000000000000..248575d352840 --- /dev/null +++ b/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs @@ -0,0 +1,28 @@ +// edition:2018 +// check-pass + +mod windows { + pub trait WinFoo { + fn foo(&self) {} + } + + impl WinFoo for () {} +} + +#[cfg(any(windows, doc))] +use windows::*; + +mod unix { + pub trait UnixFoo { + fn foo(&self) {} + } + + impl UnixFoo for () {} +} + +#[cfg(any(unix, doc))] +use unix::*; + +async fn bar() { + ().foo() +} diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs index 1498fa4f890d0..31dd786cbbf89 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(type_alias_impl_trait)] pub trait ValidTrait {} @@ -6,5 +7,4 @@ type ImplTrait = impl ValidTrait; /// This returns impl trait, but using a type alias pub fn h() -> ImplTrait { (|| error::_in::impl_trait::alias::nested::closure())() - //~^ ERROR failed to resolve } diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr deleted file mode 100644 index 84b28139dbcd5..0000000000000 --- a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias::nested::closure` - --> $DIR/trait-alias-closure.rs:8:9 - | -LL | (|| error::_in::impl_trait::alias::nested::closure())() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias::nested::closure` - | - = note: this error was originally ignored because you are running `rustdoc` - = note: try running again with `rustc` or `cargo check` and you may get a more detailed error - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs index cf9bc48c7f872..c18a024af4bbc 100644 --- a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs +++ b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(type_alias_impl_trait)] pub trait ValidTrait {} @@ -6,5 +7,4 @@ type ImplTrait = impl ValidTrait; /// This returns impl trait, but using a type alias pub fn h() -> ImplTrait { error::_in::impl_trait::alias() - //~^ ERROR failed to resolve } diff --git a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr b/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr deleted file mode 100644 index 9be6a3d8d6bba..0000000000000 --- a/src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0433]: failed to resolve: could not resolve path `error::_in::impl_trait::alias` - --> $DIR/trait-alias.rs:8:5 - | -LL | error::_in::impl_trait::alias() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not resolve path `error::_in::impl_trait::alias` - | - = note: this error was originally ignored because you are running `rustdoc` - = note: try running again with `rustc` or `cargo check` and you may get a more detailed error - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs new file mode 100644 index 0000000000000..acce0f77a258e --- /dev/null +++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs @@ -0,0 +1,15 @@ +// normalize-stderr-test: "`.*`" -> "`DEF_ID`" +// normalize-stdout-test: "`.*`" -> "`DEF_ID`" +// edition:2018 + +pub async fn f() -> impl std::fmt::Debug { + #[derive(Debug)] + enum E { + //~^ ERROR recursive type `f::{{closure}}#0::E` has infinite size + This(E), + Unit, + } + E::Unit +} + +fn main() {} diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr new file mode 100644 index 0000000000000..991dc6eec1d20 --- /dev/null +++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `DEF_ID` has infinite size + --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5 + | +LL | enum E { + | ^^^^^^ recursive type has infinite size +LL | +LL | This(E), + | - recursive without indirection + | +help: insert some indirection (e.g., a `DEF_ID` representable + | +LL | This(Box), + | ^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `DEF_ID`. diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs new file mode 100644 index 0000000000000..b3a7ee563130e --- /dev/null +++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs @@ -0,0 +1,7 @@ +fn f() -> impl Sized { + enum E { + //~^ ERROR recursive type `f::E` has infinite size + V(E), + } + unimplemented!() +} diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr new file mode 100644 index 0000000000000..ec1bb786fe5ad --- /dev/null +++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `f::E` has infinite size + --> $DIR/infinite-recursive-type-impl-trait.rs:2:5 + | +LL | enum E { + | ^^^^^^ recursive type has infinite size +LL | +LL | V(E), + | - recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `f::E` representable + | +LL | V(Box), + | ^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`.