From 50983ba6df8effdeae993b2d4ed5eefe8c863bbf Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 1 Sep 2021 14:59:07 -0700 Subject: [PATCH] rustdoc: Don't panic on ambiguous inherent associated types Instead, return `Type::Infer` since compilation should fail anyway. That's how rustdoc handles `hir::TyKind::Err`s, so this just extends that behavior to `ty::Err`s when analyzing associated types. For some reason, the error is printed twice with rustdoc (though only once with rustc). I'm not sure why that is, but it's better than panicking. This commit also makes rustdoc fail early in the non-projection, non-error case, instead of returning a `Res::Err` that would likely cause rustdoc to panic later on. This change is originally from #88379. --- src/librustdoc/clean/mod.rs | 10 ++++++---- .../rustdoc-ui/ambiguous-inherent-assoc-ty.rs | 17 +++++++++++++++++ .../ambiguous-inherent-assoc-ty.stderr | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs create mode 100644 src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b566239423e04..d59c6bfdd36fa 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1311,10 +1311,11 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { } hir::QPath::TypeRelative(ref qself, ref segment) => { let ty = hir_ty_to_ty(cx.tcx, hir_ty); - let res = if let ty::Projection(proj) = ty.kind() { - Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id) - } else { - Res::Err + let res = match ty.kind() { + ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id), + // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s. + ty::Error(_) => return Type::Infer, + _ => bug!("clean: expected associated type, found `{:?}`", ty), }; let trait_path = hir::Path { span, res, segments: &[] }.clean(cx); Type::QPath { @@ -1379,6 +1380,7 @@ impl Clean for hir::Ty<'_> { DynTrait(bounds, lifetime) } TyKind::BareFn(ref barefn) => BareFunction(Box::new(barefn.clean(cx))), + // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. TyKind::Infer | TyKind::Err => Infer, TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind), } diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs new file mode 100644 index 0000000000000..3ad56aebc21c5 --- /dev/null +++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs @@ -0,0 +1,17 @@ +// This test ensures that rustdoc does not panic on inherented associated types +// that are referred to without fully-qualified syntax. + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +pub struct Struct; + +impl Struct { + pub type AssocTy = usize; + pub const AssocConst: Self::AssocTy = 42; + //~^ ERROR ambiguous associated type + //~| HELP use fully-qualified syntax + // FIXME: for some reason, the error is shown twice with rustdoc but only once with rustc + //~| ERROR ambiguous associated type + //~| HELP use fully-qualified syntax +} diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr new file mode 100644 index 0000000000000..b963b722f6620 --- /dev/null +++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr @@ -0,0 +1,15 @@ +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27 + | +LL | pub const AssocConst: Self::AssocTy = 42; + | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27 + | +LL | pub const AssocConst: Self::AssocTy = 42; + | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0223`.