Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix async-std by special-casing rustdoc in typeck #75127

Merged
merged 5 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..)
Expand Down
14 changes: 10 additions & 4 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
12 changes: 11 additions & 1 deletion src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 2 additions & 5 deletions src/test/rustdoc-ui/error-in-impl-trait/async.rs
Original file line number Diff line number Diff line change
@@ -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<Output = u32>`, 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
}
12 changes: 0 additions & 12 deletions src/test/rustdoc-ui/error-in-impl-trait/async.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/rustdoc-ui/error-in-impl-trait/closure.rs
Original file line number Diff line number Diff line change
@@ -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
}
12 changes: 0 additions & 12 deletions src/test/rustdoc-ui/error-in-impl-trait/closure.stderr

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// check-pass
trait ValidTrait {}

/// This has docs
pub fn f() -> impl ValidTrait {
Vec::<DoesNotExist>::new()
//~^ ERROR failed to resolve
}
12 changes: 0 additions & 12 deletions src/test/rustdoc-ui/error-in-impl-trait/generic-argument.stderr

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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
}

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.rs
Original file line number Diff line number Diff line change
@@ -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
}
12 changes: 0 additions & 12 deletions src/test/rustdoc-ui/error-in-impl-trait/impl-keyword.stderr

This file was deleted.

28 changes: 28 additions & 0 deletions src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs
Original file line number Diff line number Diff line change
@@ -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()
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// check-pass
#![feature(type_alias_impl_trait)]

pub trait ValidTrait {}
Expand All @@ -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
}
12 changes: 0 additions & 12 deletions src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// check-pass
#![feature(type_alias_impl_trait)]

pub trait ValidTrait {}
Expand All @@ -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
}
12 changes: 0 additions & 12 deletions src/test/rustdoc-ui/error-in-impl-trait/trait-alias.stderr

This file was deleted.

15 changes: 15 additions & 0 deletions src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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<E>),
| ^^^^ ^

error: aborting due to previous error

For more information about this error, try `DEF_ID`.
7 changes: 7 additions & 0 deletions src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn f() -> impl Sized {
enum E {
//~^ ERROR recursive type `f::E` has infinite size
V(E),
}
unimplemented!()
}
17 changes: 17 additions & 0 deletions src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
Original file line number Diff line number Diff line change
@@ -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<E>),
| ^^^^ ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0072`.