From 7e79c575e9676e27d2ccee3ef40b177a99a86cea Mon Sep 17 00:00:00 2001
From: Maybe Waffle
Date: Fri, 9 Dec 2022 12:26:01 +0000
Subject: [PATCH 1/8] Help rust-analyzer normalize query return types
---
compiler/rustc_middle/src/query/keys.rs | 98 ++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 1 deletion(-)
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 880632561b9e8..a96bc115e3b45 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -15,7 +15,7 @@ use rustc_span::{Span, DUMMY_SP};
/// The `Key` trait controls what types can legally be used as the key
/// for a query.
pub trait Key: Sized {
- type CacheSelector = DefaultCacheSelector;
+ type CacheSelector;
/// Given an instance of this key, what crate is it referring to?
/// This is used to find the provider.
@@ -37,6 +37,8 @@ pub trait Key: Sized {
}
impl Key for () {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -48,6 +50,8 @@ impl Key for () {
}
impl<'tcx> Key for ty::InstanceDef<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -59,6 +63,8 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> {
}
impl<'tcx> Key for ty::Instance<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -70,6 +76,8 @@ impl<'tcx> Key for ty::Instance<'tcx> {
}
impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -81,6 +89,8 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
}
impl<'tcx> Key for (Ty<'tcx>, Option>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -92,6 +102,8 @@ impl<'tcx> Key for (Ty<'tcx>, Option>) {
}
impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -145,6 +157,8 @@ impl Key for LocalDefId {
}
impl Key for DefId {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.krate == LOCAL_CRATE
@@ -159,6 +173,8 @@ impl Key for DefId {
}
impl Key for ty::WithOptConstParam {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -169,6 +185,8 @@ impl Key for ty::WithOptConstParam {
}
impl Key for SimplifiedType {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -179,6 +197,8 @@ impl Key for SimplifiedType {
}
impl Key for (DefId, DefId) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -189,6 +209,8 @@ impl Key for (DefId, DefId) {
}
impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -199,6 +221,8 @@ impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
}
impl Key for (DefId, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -209,6 +233,8 @@ impl Key for (DefId, LocalDefId) {
}
impl Key for (LocalDefId, DefId) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -219,6 +245,8 @@ impl Key for (LocalDefId, DefId) {
}
impl Key for (LocalDefId, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -229,6 +257,8 @@ impl Key for (LocalDefId, LocalDefId) {
}
impl Key for (DefId, Option) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -243,6 +273,8 @@ impl Key for (DefId, Option) {
}
impl Key for (DefId, LocalDefId, Ident) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -253,6 +285,8 @@ impl Key for (DefId, LocalDefId, Ident) {
}
impl Key for (CrateNum, DefId) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0 == LOCAL_CRATE
@@ -263,6 +297,8 @@ impl Key for (CrateNum, DefId) {
}
impl Key for (CrateNum, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0 == LOCAL_CRATE
@@ -273,6 +309,8 @@ impl Key for (CrateNum, SimplifiedType) {
}
impl Key for (DefId, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -283,6 +321,8 @@ impl Key for (DefId, SimplifiedType) {
}
impl<'tcx> Key for SubstsRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -293,6 +333,8 @@ impl<'tcx> Key for SubstsRef<'tcx> {
}
impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -303,6 +345,8 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
}
impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
(self.0).def.did.krate == LOCAL_CRATE
@@ -313,6 +357,8 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
}
impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -323,6 +369,8 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
}
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.1.def_id().krate == LOCAL_CRATE
@@ -333,6 +381,8 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
}
impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -343,6 +393,8 @@ impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
}
impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -353,6 +405,8 @@ impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
}
impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.def_id().krate == LOCAL_CRATE
@@ -363,6 +417,8 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
}
impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.def_id().krate == LOCAL_CRATE
@@ -373,6 +429,8 @@ impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
}
impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.def_id().krate == LOCAL_CRATE
@@ -383,6 +441,8 @@ impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
}
impl<'tcx> Key for GenericArg<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -393,6 +453,8 @@ impl<'tcx> Key for GenericArg<'tcx> {
}
impl<'tcx> Key for mir::ConstantKind<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -403,6 +465,8 @@ impl<'tcx> Key for mir::ConstantKind<'tcx> {
}
impl<'tcx> Key for ty::Const<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -413,6 +477,8 @@ impl<'tcx> Key for ty::Const<'tcx> {
}
impl<'tcx> Key for Ty<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -429,6 +495,8 @@ impl<'tcx> Key for Ty<'tcx> {
}
impl<'tcx> Key for TyAndLayout<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -439,6 +507,8 @@ impl<'tcx> Key for TyAndLayout<'tcx> {
}
impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -449,6 +519,8 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
}
impl<'tcx> Key for &'tcx ty::List> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -459,6 +531,8 @@ impl<'tcx> Key for &'tcx ty::List> {
}
impl<'tcx> Key for ty::ParamEnv<'tcx> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -469,6 +543,8 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> {
}
impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.value.query_crate_is_local()
@@ -479,6 +555,8 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
}
impl Key for Symbol {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -489,6 +567,8 @@ impl Key for Symbol {
}
impl Key for Option {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -501,6 +581,8 @@ impl Key for Option {
/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
impl<'tcx, T> Key for Canonical<'tcx, T> {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -512,6 +594,8 @@ impl<'tcx, T> Key for Canonical<'tcx, T> {
}
impl Key for (Symbol, u32, u32) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -523,6 +607,8 @@ impl Key for (Symbol, u32, u32) {
}
impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -534,6 +620,8 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
}
impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -545,6 +633,8 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
}
impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -556,6 +646,8 @@ impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List>) {
}
impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -567,6 +659,8 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List>) {
}
impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -578,6 +672,8 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
}
impl Key for HirId {
+ type CacheSelector = DefaultCacheSelector;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
From d0db3279ab251db3612204cc1e3f386e8beae996 Mon Sep 17 00:00:00 2001
From: Michael Goulet
Date: Wed, 14 Dec 2022 18:00:56 +0000
Subject: [PATCH 2/8] Don't bug if we're trying to cast dyn* to a nother type
---
compiler/rustc_hir_typeck/src/cast.rs | 4 +++-
src/test/ui/dyn-star/dyn-to-rigid.rs | 11 +++++++++++
src/test/ui/dyn-star/dyn-to-rigid.stderr | 9 +++++++++
3 files changed, 23 insertions(+), 1 deletion(-)
create mode 100644 src/test/ui/dyn-star/dyn-to-rigid.rs
create mode 100644 src/test/ui/dyn-star/dyn-to-rigid.stderr
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index b050ad20afbdb..042a50f2fd42e 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -847,13 +847,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
- (_, DynStar) | (DynStar, _) => {
+ (_, DynStar) => {
if fcx.tcx.features().dyn_star {
bug!("should be handled by `try_coerce`")
} else {
Err(CastError::IllegalCast)
}
}
+
+ (DynStar, _) => Err(CastError::IllegalCast),
}
}
diff --git a/src/test/ui/dyn-star/dyn-to-rigid.rs b/src/test/ui/dyn-star/dyn-to-rigid.rs
new file mode 100644
index 0000000000000..e80ee15902eef
--- /dev/null
+++ b/src/test/ui/dyn-star/dyn-to-rigid.rs
@@ -0,0 +1,11 @@
+#![feature(dyn_star)]
+#![allow(incomplete_features)]
+
+trait Tr {}
+
+fn f(x: dyn* Tr) -> usize {
+ x as usize
+ //~^ ERROR casting `(dyn* Tr + 'static)` as `usize` is invalid
+}
+
+fn main() {}
diff --git a/src/test/ui/dyn-star/dyn-to-rigid.stderr b/src/test/ui/dyn-star/dyn-to-rigid.stderr
new file mode 100644
index 0000000000000..588e6d97e5ca3
--- /dev/null
+++ b/src/test/ui/dyn-star/dyn-to-rigid.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `(dyn* Tr + 'static)` as `usize` is invalid
+ --> $DIR/dyn-to-rigid.rs:7:5
+ |
+LL | x as usize
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
From bcaf210575f8b8ca4ea7fd37ef2ef40e7c263ad9 Mon Sep 17 00:00:00 2001
From: Michael Goulet
Date: Wed, 14 Dec 2022 18:24:21 +0000
Subject: [PATCH 3/8] bail in collect_trait_impl_trait_tys if signatures
reference errors
---
.../src/check/compare_method.rs | 2 ++
.../ui/async-await/in-trait/bad-signatures.rs | 16 ++++++++++++
.../in-trait/bad-signatures.stderr | 26 +++++++++++++++++++
3 files changed, 44 insertions(+)
create mode 100644 src/test/ui/async-await/in-trait/bad-signatures.rs
create mode 100644 src/test/ui/async-await/in-trait/bad-signatures.stderr
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index ba7d31cea2e2f..13bd034a7b559 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -373,6 +373,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
tcx.fn_sig(impl_m.def_id),
),
);
+ impl_sig.error_reported()?;
let impl_return_ty = impl_sig.output();
// Normalize the trait signature with liberated bound vars, passing it through
@@ -387,6 +388,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
)
.fold_with(&mut collector);
let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
+ trait_sig.error_reported()?;
let trait_return_ty = trait_sig.output();
let wf_tys = FxIndexSet::from_iter(
diff --git a/src/test/ui/async-await/in-trait/bad-signatures.rs b/src/test/ui/async-await/in-trait/bad-signatures.rs
new file mode 100644
index 0000000000000..b86f1d1c13585
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/bad-signatures.rs
@@ -0,0 +1,16 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete
+
+trait MyTrait {
+ async fn bar(&abc self);
+ //~^ ERROR expected identifier, found keyword `self`
+ //~| ERROR expected one of `:`, `@`, or `|`, found keyword `self`
+}
+
+impl MyTrait for () {
+ async fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/bad-signatures.stderr b/src/test/ui/async-await/in-trait/bad-signatures.stderr
new file mode 100644
index 0000000000000..e0ba7b53ec415
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/bad-signatures.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `self`
+ --> $DIR/bad-signatures.rs:7:23
+ |
+LL | async fn bar(&abc self);
+ | ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `self`
+ --> $DIR/bad-signatures.rs:7:23
+ |
+LL | async fn bar(&abc self);
+ | -----^^^^
+ | | |
+ | | expected one of `:`, `@`, or `|`
+ | help: declare the type after the parameter binding: `: `
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/bad-signatures.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
From 14b508fbec6d9fdebda3397b0df908d829bbdb0b Mon Sep 17 00:00:00 2001
From: Guillaume Gomez
Date: Fri, 16 Dec 2022 14:51:48 +0100
Subject: [PATCH 4/8] Don't add "Read more" link if there is no extra content
---
src/librustdoc/html/markdown.rs | 27 +++++++++++++++++++++------
src/librustdoc/html/render/mod.rs | 5 +++--
2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b141820fe423c..aeaee524fd453 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -567,11 +567,12 @@ struct SummaryLine<'a, I: Iterator- >> {
inner: I,
started: bool,
depth: u32,
+ skipped_tags: u32,
}
impl<'a, I: Iterator
- >> SummaryLine<'a, I> {
fn new(iter: I) -> Self {
- SummaryLine { inner: iter, started: false, depth: 0 }
+ SummaryLine { inner: iter, started: false, depth: 0, skipped_tags: 0 }
}
}
@@ -601,6 +602,7 @@ impl<'a, I: Iterator
- >> Iterator for SummaryLine<'a, I> {
let is_allowed_tag = match event {
Event::Start(ref c) => {
if is_forbidden_tag(c) {
+ self.skipped_tags += 1;
return None;
}
self.depth += 1;
@@ -608,6 +610,7 @@ impl<'a, I: Iterator
- >> Iterator for SummaryLine<'a, I> {
}
Event::End(ref c) => {
if is_forbidden_tag(c) {
+ self.skipped_tags += 1;
return None;
}
self.depth -= 1;
@@ -616,6 +619,9 @@ impl<'a, I: Iterator
- >> Iterator for SummaryLine<'a, I> {
}
_ => true,
};
+ if !is_allowed_tag {
+ self.skipped_tags += 1;
+ }
return if !is_allowed_tag {
if is_start {
Some(Event::Start(Tag::Paragraph))
@@ -1096,11 +1102,11 @@ impl MarkdownItemInfo<'_> {
}
impl MarkdownSummaryLine<'_> {
- pub(crate) fn into_string(self) -> String {
+ pub(crate) fn into_string_with_has_more_content(self) -> (String, bool) {
let MarkdownSummaryLine(md, links) = self;
// This is actually common enough to special-case
if md.is_empty() {
- return String::new();
+ return (String::new(), false);
}
let mut replacer = |broken_link: BrokenLink<'_>| {
@@ -1110,17 +1116,26 @@ impl MarkdownSummaryLine<'_> {
.map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
};
- let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
+ let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer))
+ .peekable();
+ let mut summary = SummaryLine::new(p);
let mut s = String::new();
- let without_paragraphs = LinkReplacer::new(SummaryLine::new(p), links).filter(|event| {
+ let without_paragraphs = LinkReplacer::new(&mut summary, links).filter(|event| {
!matches!(event, Event::Start(Tag::Paragraph) | Event::End(Tag::Paragraph))
});
html::push_html(&mut s, without_paragraphs);
- s
+ let has_more_content =
+ matches!(summary.inner.peek(), Some(Event::Start(_))) || summary.skipped_tags > 0;
+
+ (s, has_more_content)
+ }
+
+ pub(crate) fn into_string(self) -> String {
+ self.into_string_with_has_more_content().0
}
}
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 80fbe9c1f066c..146e5010e4e42 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -467,9 +467,10 @@ fn document_short(
return;
}
if let Some(s) = item.doc_value() {
- let mut summary_html = MarkdownSummaryLine(&s, &item.links(cx)).into_string();
+ let (mut summary_html, has_more_content) =
+ MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
- if s.contains('\n') {
+ if has_more_content {
let link = format!(r#" Read more"#, assoc_href_attr(item, link, cx));
if let Some(idx) = summary_html.rfind("
") {
From 80059e1b7274fc7ba8d9201ea075fd1c7b7608f1 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez
Date: Fri, 16 Dec 2022 14:52:25 +0100
Subject: [PATCH 5/8] Add test for presence of read more links
---
src/test/rustdoc/read-more-unneeded.rs | 34 ++++++++++++++++++++++++++
src/test/rustdoc/trait-impl.rs | 2 --
2 files changed, 34 insertions(+), 2 deletions(-)
create mode 100644 src/test/rustdoc/read-more-unneeded.rs
diff --git a/src/test/rustdoc/read-more-unneeded.rs b/src/test/rustdoc/read-more-unneeded.rs
new file mode 100644
index 0000000000000..0303e44426141
--- /dev/null
+++ b/src/test/rustdoc/read-more-unneeded.rs
@@ -0,0 +1,34 @@
+// Regression test for https://github.com/rust-lang/rust/issues/105677.
+// This test ensures that the "Read more" link is only generated when
+// there is actually more documentation to read after the short summary.
+
+#![crate_name = "foo"]
+
+pub trait MyFrom {
+ /// # Hello
+ /// ## Yolo
+ /// more!
+ fn try_from1();
+ /// a
+ /// b
+ /// c
+ fn try_from2();
+ /// a
+ ///
+ /// b
+ ///
+ /// c
+ fn try_from3();
+}
+
+pub struct NonZero;
+
+// @has 'foo/struct.NonZero.html'
+impl MyFrom for NonZero {
+ // @matches - '//*[@class="docblock"]' '^Hello Read more$'
+ fn try_from1() {}
+ // @matches - '//*[@class="docblock"]' '^a\sb\sc$'
+ fn try_from2() {}
+ // @matches - '//*[@class="docblock"]' '^a Read more$'
+ fn try_from3() {}
+}
diff --git a/src/test/rustdoc/trait-impl.rs b/src/test/rustdoc/trait-impl.rs
index 195cdf009b993..9cf3226f738c8 100644
--- a/src/test/rustdoc/trait-impl.rs
+++ b/src/test/rustdoc/trait-impl.rs
@@ -30,8 +30,6 @@ impl Trait for Struct {
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]' 'These docs contain'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'reference link'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'https://example.com'
- // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'Read more'
- // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'trait.Trait.html#tymethod.b'
fn b() {}
// @!has - '//*[@id="method.c"]/../../div[@class="docblock"]' 'code block'
From 08a0e71ec9de799f9d867348c24e1193b570d159 Mon Sep 17 00:00:00 2001
From: Deadbeef
Date: Fri, 16 Dec 2022 04:05:26 +0000
Subject: [PATCH 6/8] Detect inherent associated types not having CamelCase
Fixes #105341.
---
compiler/rustc_lint/src/nonstandard_style.rs | 12 +++++++++++-
src/test/ui/associated-inherent-types/style.rs | 12 ++++++++++++
src/test/ui/associated-inherent-types/style.stderr | 14 ++++++++++++++
3 files changed, 37 insertions(+), 1 deletion(-)
create mode 100644 src/test/ui/associated-inherent-types/style.rs
create mode 100644 src/test/ui/associated-inherent-types/style.stderr
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 7e50801f80c7b..91fcd6d690ee7 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -175,13 +175,23 @@ impl EarlyLintPass for NonCamelCaseTypes {
return;
}
- match it.kind {
+ match &it.kind {
ast::ItemKind::TyAlias(..)
| ast::ItemKind::Enum(..)
| ast::ItemKind::Struct(..)
| ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident),
ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident),
ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident),
+
+ // N.B. This check is only for inherent associated types, so that we don't lint against
+ // trait impls where we should have warned for the trait definition already.
+ ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => {
+ for it in items {
+ if let ast::AssocItemKind::Type(..) = it.kind {
+ self.check_case(cx, "associated type", &it.ident);
+ }
+ }
+ }
_ => (),
}
}
diff --git a/src/test/ui/associated-inherent-types/style.rs b/src/test/ui/associated-inherent-types/style.rs
new file mode 100644
index 0000000000000..8775bd19e1f98
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/style.rs
@@ -0,0 +1,12 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features, dead_code)]
+#![deny(non_camel_case_types)]
+
+struct S;
+
+impl S {
+ type typ = ();
+ //~^ ERROR associated type `typ` should have an upper camel case name
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-inherent-types/style.stderr b/src/test/ui/associated-inherent-types/style.stderr
new file mode 100644
index 0000000000000..f83061f8c4216
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/style.stderr
@@ -0,0 +1,14 @@
+error: associated type `typ` should have an upper camel case name
+ --> $DIR/style.rs:8:10
+ |
+LL | type typ = ();
+ | ^^^ help: convert the identifier to upper camel case: `Typ`
+ |
+note: the lint level is defined here
+ --> $DIR/style.rs:3:9
+ |
+LL | #![deny(non_camel_case_types)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
From 452c745518246484807bd8c73a30400a10cd5057 Mon Sep 17 00:00:00 2001
From: Maybe Waffle
Date: Fri, 16 Dec 2022 15:10:48 +0000
Subject: [PATCH 7/8] Add a comment warning against using associated type
defaults <3
---
compiler/rustc_middle/src/query/keys.rs | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index a96bc115e3b45..e4bb3ce3d5a99 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -15,6 +15,14 @@ use rustc_span::{Span, DUMMY_SP};
/// The `Key` trait controls what types can legally be used as the key
/// for a query.
pub trait Key: Sized {
+ // N.B. Most of the keys down below have `type CacheSelector = DefaultCacheSelector;`,
+ // it would be reasonable to use associated type defaults, to remove the duplication...
+ //
+ // ...But r-a doesn't support them yet and using a default here causes r-a to not infer
+ // return types of queries which is very annoying. Thus, until r-a support associated
+ // type defaults, plese restrain from using them here <3
+ //
+ // r-a issue:
type CacheSelector;
/// Given an instance of this key, what crate is it referring to?
From 8751d3b2e9a2fa903822a1f9061c0fe2c4c0bef2 Mon Sep 17 00:00:00 2001
From: Collin Baker
Date: Fri, 16 Dec 2022 17:32:29 -0500
Subject: [PATCH 8/8] Make enum-match.rs test robust against variable name
changes
https://reviews.llvm.org/D140192 caused the LLVM variable generated
for enum discriminant checks to be named differently (%narrow vs %1).
This adjusts the test CHECK directives to match any name.
---
src/test/codegen/enum-match.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/test/codegen/enum-match.rs b/src/test/codegen/enum-match.rs
index 44f1b408d21b8..827eb20154afd 100644
--- a/src/test/codegen/enum-match.rs
+++ b/src/test/codegen/enum-match.rs
@@ -34,8 +34,8 @@ pub enum Enum1 {
// CHECK: define i8 @match1{{.*}}
// CHECK-NEXT: start:
-// CHECK-NEXT: %1 = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
-// CHECK-NEXT: switch i8 %1, label {{.*}} [
+// CHECK-NEXT: [[DISCR:%.*]] = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
+// CHECK-NEXT: switch i8 [[DISCR]], label {{.*}} [
#[no_mangle]
pub fn match1(e: Enum1) -> u8 {
use Enum1::*;