about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNoah Lev <camelidcamel@gmail.com>2021-09-02 09:54:32 -0700
committerNoah Lev <camelidcamel@gmail.com>2021-09-02 14:28:10 -0700
commit3a3f99a79b00b5efcb1bf061404112a281084b97 (patch)
treef82ffa2ceb43add67ffe692a0f2bf69b06ab8d97
parent2a6022949077176bfff9f72282dc52e51a175cb7 (diff)
downloadrust-3a3f99a79b00b5efcb1bf061404112a281084b97.tar.gz
rust-3a3f99a79b00b5efcb1bf061404112a281084b97.zip
rustdoc: Higher-ranked lifetimes can't have bounds
This cleans up the other spot I found where rustdoc was rendering bounds
into the lifetime name itself. However, in this case, I don't think it
could have actually happened because higher-ranked lifetime definitions
aren't currently allowed to have bounds.
-rw-r--r--src/librustdoc/clean/mod.rs54
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/test/rustdoc-ui/bounded-hr-lifetime.rs9
-rw-r--r--src/test/rustdoc-ui/bounded-hr-lifetime.stderr10
4 files changed, 45 insertions, 29 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index bb22da00576..3664687cbb7 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -30,6 +30,7 @@ use rustc_target::spec::abi::Abi;
 use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
 use rustc_typeck::hir_ty_to_ty;
 
+use std::assert_matches::assert_matches;
 use std::collections::hash_map::Entry;
 use std::default::Default;
 use std::hash::Hash;
@@ -242,30 +243,6 @@ impl Clean<Lifetime> for hir::Lifetime {
     }
 }
 
-impl Clean<Lifetime> for hir::GenericParam<'_> {
-    fn clean(&self, _: &mut DocContext<'_>) -> Lifetime {
-        match self.kind {
-            hir::GenericParamKind::Lifetime { .. } => {
-                if !self.bounds.is_empty() {
-                    let mut bounds = self.bounds.iter().map(|bound| match bound {
-                        hir::GenericBound::Outlives(lt) => lt,
-                        _ => panic!(),
-                    });
-                    let name = bounds.next().expect("no more bounds").name.ident();
-                    let mut s = format!("{}: {}", self.name.ident(), name);
-                    for bound in bounds {
-                        s.push_str(&format!(" + {}", bound.name.ident()));
-                    }
-                    Lifetime(Symbol::intern(&s))
-                } else {
-                    Lifetime(self.name.ident().name)
-                }
-            }
-            _ => panic!(),
-        }
-    }
-}
-
 impl Clean<Constant> for hir::ConstArg {
     fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
         Constant {
@@ -303,11 +280,30 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
 impl Clean<WherePredicate> for hir::WherePredicate<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
         match *self {
-            hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
-                ty: wbp.bounded_ty.clean(cx),
-                bounds: wbp.bounds.clean(cx),
-                bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(),
-            },
+            hir::WherePredicate::BoundPredicate(ref wbp) => {
+                let bound_params = wbp
+                    .bound_generic_params
+                    .into_iter()
+                    .map(|param| {
+                        // Higher-ranked params must be lifetimes.
+                        // Higher-ranked lifetimes can't have bounds.
+                        assert_matches!(
+                            param,
+                            hir::GenericParam {
+                                kind: hir::GenericParamKind::Lifetime { .. },
+                                bounds: [],
+                                ..
+                            }
+                        );
+                        Lifetime(param.name.ident().name)
+                    })
+                    .collect();
+                WherePredicate::BoundPredicate {
+                    ty: wbp.bounded_ty.clean(cx),
+                    bounds: wbp.bounds.clean(cx),
+                    bound_params,
+                }
+            }
 
             hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
                 lifetime: wrp.lifetime.clean(cx),
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b81acd1a93f..2dbe4c42b88 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -4,6 +4,7 @@
 )]
 #![feature(rustc_private)]
 #![feature(array_methods)]
+#![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(in_band_lifetimes)]
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.rs b/src/test/rustdoc-ui/bounded-hr-lifetime.rs
new file mode 100644
index 00000000000..b2e000b9757
--- /dev/null
+++ b/src/test/rustdoc-ui/bounded-hr-lifetime.rs
@@ -0,0 +1,9 @@
+// This test ensures that rustdoc doesn't panic on higher-ranked lifetimes
+// with bounds, because an error should have already been emitted by rustc.
+
+pub fn hrlt<'b, 'c>()
+where
+    for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+}
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.stderr b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr
new file mode 100644
index 00000000000..d8fcd6cb4b1
--- /dev/null
+++ b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr
@@ -0,0 +1,10 @@
+error: lifetime bounds cannot be used in this context
+  --> $DIR/bounded-hr-lifetime.rs:6:13
+   |
+LL |     for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+   |             ^^   ^^
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+