Auto merge of #92609 - matthiaskrgr:rollup-ldp47ot, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #92058 (Make Run button visible on hover) - #92288 (Fix a pair of mistyped test cases in `std::net::ip`) - #92349 (Fix rustdoc::private_doc_tests lint for public re-exported items) - #92360 (Some cleanups around check_argument_types) - #92389 (Regression test for borrowck ICE #92015) - #92404 (Fix font size for [src] links in headers) - #92443 (Rustdoc: resolve associated traits for non-generic primitive types) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
cfa4ac66c1
21 changed files with 353 additions and 155 deletions
|
|
@ -1080,8 +1080,11 @@ body.blur > :not(#help) {
|
|||
|
||||
.impl-items .srclink, .impl .srclink, .methods .srclink {
|
||||
/* Override header settings otherwise it's too bold */
|
||||
font-size: 1.0625rem;
|
||||
font-weight: normal;
|
||||
font-size: 1rem;
|
||||
}
|
||||
.impl .srclink {
|
||||
font-size: 1.0625rem;
|
||||
}
|
||||
|
||||
.rightside {
|
||||
|
|
@ -1117,6 +1120,7 @@ pre.rust .question-mark {
|
|||
|
||||
a.test-arrow {
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
padding: 5px 10px 5px 10px;
|
||||
border-radius: 5px;
|
||||
|
|
@ -1125,10 +1129,12 @@ a.test-arrow {
|
|||
right: 5px;
|
||||
z-index: 1;
|
||||
}
|
||||
.example-wrap:hover .test-arrow {
|
||||
visibility: visible;
|
||||
}
|
||||
a.test-arrow:hover{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.section-header:hover a:before {
|
||||
position: absolute;
|
||||
left: -25px;
|
||||
|
|
|
|||
|
|
@ -351,11 +351,8 @@ a.test-arrow:hover {
|
|||
color: #999;
|
||||
}
|
||||
|
||||
:target, :target > * {
|
||||
background: rgba(255, 236, 164, 0.06);
|
||||
}
|
||||
|
||||
:target {
|
||||
background: rgba(255, 236, 164, 0.06);
|
||||
border-right: 3px solid rgba(255, 180, 76, 0.85);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -295,11 +295,8 @@ a.test-arrow:hover{
|
|||
color: #999;
|
||||
}
|
||||
|
||||
:target, :target > * {
|
||||
background-color: #494a3d;
|
||||
}
|
||||
|
||||
:target {
|
||||
background-color: #494a3d;
|
||||
border-right: 3px solid #bb7410;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -284,11 +284,8 @@ a.test-arrow:hover{
|
|||
color: #999;
|
||||
}
|
||||
|
||||
:target, :target > * {
|
||||
background: #FDFFD3;
|
||||
}
|
||||
|
||||
:target {
|
||||
background: #FDFFD3;
|
||||
border-right: 3px solid #AD7C37;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
|
|||
);
|
||||
}
|
||||
} else if tests.found_tests > 0
|
||||
&& !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
|
||||
&& !cx.cache.access_levels.is_exported(item.def_id.expect_def_id())
|
||||
{
|
||||
cx.tcx.struct_span_lint_hir(
|
||||
crate::lint::PRIVATE_DOC_TESTS,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_hir::def::{
|
|||
PerNS,
|
||||
};
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug, ty};
|
||||
use rustc_resolve::ParentScope;
|
||||
use rustc_session::lint::Lint;
|
||||
|
|
@ -618,6 +618,39 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Convert a PrimitiveType to a Ty, where possible.
|
||||
///
|
||||
/// This is used for resolving trait impls for primitives
|
||||
fn primitive_type_to_ty(&mut self, prim: PrimitiveType) -> Option<Ty<'tcx>> {
|
||||
use PrimitiveType::*;
|
||||
let tcx = self.cx.tcx;
|
||||
|
||||
// FIXME: Only simple types are supported here, see if we can support
|
||||
// other types such as Tuple, Array, Slice, etc.
|
||||
// See https://github.com/rust-lang/rust/issues/90703#issuecomment-1004263455
|
||||
Some(tcx.mk_ty(match prim {
|
||||
Bool => ty::Bool,
|
||||
Str => ty::Str,
|
||||
Char => ty::Char,
|
||||
Never => ty::Never,
|
||||
I8 => ty::Int(ty::IntTy::I8),
|
||||
I16 => ty::Int(ty::IntTy::I16),
|
||||
I32 => ty::Int(ty::IntTy::I32),
|
||||
I64 => ty::Int(ty::IntTy::I64),
|
||||
I128 => ty::Int(ty::IntTy::I128),
|
||||
Isize => ty::Int(ty::IntTy::Isize),
|
||||
F32 => ty::Float(ty::FloatTy::F32),
|
||||
F64 => ty::Float(ty::FloatTy::F64),
|
||||
U8 => ty::Uint(ty::UintTy::U8),
|
||||
U16 => ty::Uint(ty::UintTy::U16),
|
||||
U32 => ty::Uint(ty::UintTy::U32),
|
||||
U64 => ty::Uint(ty::UintTy::U64),
|
||||
U128 => ty::Uint(ty::UintTy::U128),
|
||||
Usize => ty::Uint(ty::UintTy::Usize),
|
||||
_ => return None,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Returns:
|
||||
/// - None if no associated item was found
|
||||
/// - Some((_, _, Some(_))) if an item was found and should go through a side channel
|
||||
|
|
@ -632,7 +665,25 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
let tcx = self.cx.tcx;
|
||||
|
||||
match root_res {
|
||||
Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name),
|
||||
Res::Primitive(prim) => {
|
||||
self.resolve_primitive_associated_item(prim, ns, item_name).or_else(|| {
|
||||
let assoc_item = self
|
||||
.primitive_type_to_ty(prim)
|
||||
.map(|ty| {
|
||||
resolve_associated_trait_item(ty, module_id, item_name, ns, self.cx)
|
||||
})
|
||||
.flatten();
|
||||
|
||||
assoc_item.map(|item| {
|
||||
let kind = item.kind;
|
||||
let fragment = UrlFragment::from_assoc_item(item_name, kind, false);
|
||||
// HACK(jynelson): `clean` expects the type, not the associated item
|
||||
// but the disambiguator logic expects the associated item.
|
||||
// Store the kind in a side channel so that only the disambiguator logic looks at it.
|
||||
(root_res, fragment, Some((kind.as_def_kind(), item.def_id)))
|
||||
})
|
||||
})
|
||||
}
|
||||
Res::Def(DefKind::TyAlias, did) => {
|
||||
// Resolve the link on the type the alias points to.
|
||||
// FIXME: if the associated item is defined directly on the type alias,
|
||||
|
|
@ -666,8 +717,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
// To handle that properly resolve() would have to support
|
||||
// something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
|
||||
.or_else(|| {
|
||||
let item =
|
||||
resolve_associated_trait_item(did, module_id, item_name, ns, self.cx);
|
||||
let item = resolve_associated_trait_item(
|
||||
tcx.type_of(did),
|
||||
module_id,
|
||||
item_name,
|
||||
ns,
|
||||
self.cx,
|
||||
);
|
||||
debug!("got associated item {:?}", item);
|
||||
item
|
||||
});
|
||||
|
|
@ -767,12 +823,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
/// Given `[std::io::Error::source]`, where `source` is unresolved, this would
|
||||
/// find `std::error::Error::source` and return
|
||||
/// `<io::Error as error::Error>::source`.
|
||||
fn resolve_associated_trait_item(
|
||||
did: DefId,
|
||||
fn resolve_associated_trait_item<'a>(
|
||||
ty: Ty<'a>,
|
||||
module: DefId,
|
||||
item_name: Symbol,
|
||||
ns: Namespace,
|
||||
cx: &mut DocContext<'_>,
|
||||
cx: &mut DocContext<'a>,
|
||||
) -> Option<ty::AssocItem> {
|
||||
// FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
|
||||
// `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
|
||||
|
|
@ -780,7 +836,7 @@ fn resolve_associated_trait_item(
|
|||
|
||||
// Next consider explicit impls: `impl MyTrait for MyType`
|
||||
// Give precedence to inherent impls.
|
||||
let traits = traits_implemented_by(cx, did, module);
|
||||
let traits = traits_implemented_by(cx, ty, module);
|
||||
debug!("considering traits {:?}", traits);
|
||||
let mut candidates = traits.iter().filter_map(|&trait_| {
|
||||
cx.tcx.associated_items(trait_).find_by_name_and_namespace(
|
||||
|
|
@ -799,7 +855,11 @@ fn resolve_associated_trait_item(
|
|||
///
|
||||
/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
|
||||
/// So it is not stable to serialize cross-crate.
|
||||
fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -> FxHashSet<DefId> {
|
||||
fn traits_implemented_by<'a>(
|
||||
cx: &mut DocContext<'a>,
|
||||
ty: Ty<'a>,
|
||||
module: DefId,
|
||||
) -> FxHashSet<DefId> {
|
||||
let mut resolver = cx.resolver.borrow_mut();
|
||||
let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| {
|
||||
resolver.access(|resolver| {
|
||||
|
|
@ -813,7 +873,6 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
|
|||
});
|
||||
|
||||
let tcx = cx.tcx;
|
||||
let ty = tcx.type_of(type_);
|
||||
let iter = in_scope_traits.iter().flat_map(|&trait_| {
|
||||
trace!("considering explicit impl for trait {:?}", trait_);
|
||||
|
||||
|
|
@ -826,19 +885,10 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
|
|||
"comparing type {} with kind {:?} against type {:?}",
|
||||
impl_type,
|
||||
impl_type.kind(),
|
||||
type_
|
||||
ty
|
||||
);
|
||||
// Fast path: if this is a primitive simple `==` will work
|
||||
let saw_impl = impl_type == ty
|
||||
|| match impl_type.kind() {
|
||||
// Check if these are the same def_id
|
||||
ty::Adt(def, _) => {
|
||||
debug!("adt def_id: {:?}", def.did);
|
||||
def.did == type_
|
||||
}
|
||||
ty::Foreign(def_id) => *def_id == type_,
|
||||
_ => false,
|
||||
};
|
||||
let saw_impl = impl_type == ty;
|
||||
|
||||
if saw_impl { Some(trait_) } else { None }
|
||||
})
|
||||
|
|
|
|||
7
src/test/rustdoc-gui/run-on-hover.goml
Normal file
7
src/test/rustdoc-gui/run-on-hover.goml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// Example code blocks sometimes have a "Run" button to run them on the
|
||||
// Playground. That button is hidden until the user hovers over the code block.
|
||||
// This test checks that it is hidden, and that it shows on hover.
|
||||
goto: file://|DOC_PATH|/test_docs/fn.foo.html
|
||||
assert-css: (".test-arrow", {"visibility": "hidden"})
|
||||
move-cursor-to: ".example-wrap"
|
||||
assert-css: (".test-arrow", {"visibility": "visible"})
|
||||
12
src/test/rustdoc-gui/src-font-size.goml
Normal file
12
src/test/rustdoc-gui/src-font-size.goml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// This test ensures that the "[src]" have the same font size as their headers
|
||||
// to avoid having some weird height difference in the background when the element
|
||||
// is selected.
|
||||
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
|
||||
show-text: true
|
||||
// Check the impl headers.
|
||||
assert-css: (".impl.has-srclink .srclink", {"font-size": "17px"}, ALL)
|
||||
// The ".6" part is because the font-size is actually "1.1em".
|
||||
assert-css: (".impl.has-srclink .code-header.in-band", {"font-size": "17.6px"}, ALL)
|
||||
// Check the impl items.
|
||||
assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px"}, ALL)
|
||||
assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px"}, ALL)
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
//! The point of this crate is to be able to have enough different "kinds" of
|
||||
//! documentation generated so we can test each different features.
|
||||
#![doc(html_playground_url="https://play.rust-lang.org/")]
|
||||
|
||||
#![crate_name = "test_docs"]
|
||||
#![feature(rustdoc_internals)]
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
//! [unit::eq] //~ ERROR unresolved
|
||||
//! [tuple::eq] //~ ERROR unresolved
|
||||
//! [fn::eq] //~ ERROR unresolved
|
||||
//! [never::eq] //~ ERROR unresolved
|
||||
|
||||
// FIXME(#78800): This breaks because it's a blanket impl
|
||||
// (I think? Might break for other reasons too.)
|
||||
|
|
|
|||
|
|
@ -53,17 +53,11 @@ error: unresolved link to `fn::eq`
|
|||
LL | //! [fn::eq]
|
||||
| ^^^^^^ the builtin type `fn` has no associated item named `eq`
|
||||
|
||||
error: unresolved link to `never::eq`
|
||||
--> $DIR/non-path-primitives.rs:31:6
|
||||
|
|
||||
LL | //! [never::eq]
|
||||
| ^^^^^^^^^ the builtin type `never` has no associated item named `eq`
|
||||
|
||||
error: unresolved link to `reference::deref`
|
||||
--> $DIR/non-path-primitives.rs:35:6
|
||||
--> $DIR/non-path-primitives.rs:34:6
|
||||
|
|
||||
LL | //! [reference::deref]
|
||||
| ^^^^^^^^^^^^^^^^ the builtin type `reference` has no associated item named `deref`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
|
|||
11
src/test/rustdoc-ui/private-public-item-doc-test.rs
Normal file
11
src/test/rustdoc-ui/private-public-item-doc-test.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#![deny(rustdoc::private_doc_tests)]
|
||||
|
||||
mod foo {
|
||||
/// private doc test
|
||||
///
|
||||
/// ```
|
||||
/// assert!(false);
|
||||
/// ```
|
||||
//~^^^^^ ERROR documentation test in private item
|
||||
pub fn bar() {}
|
||||
}
|
||||
18
src/test/rustdoc-ui/private-public-item-doc-test.stderr
Normal file
18
src/test/rustdoc-ui/private-public-item-doc-test.stderr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
error: documentation test in private item
|
||||
--> $DIR/private-public-item-doc-test.rs:4:5
|
||||
|
|
||||
LL | / /// private doc test
|
||||
LL | | ///
|
||||
LL | | /// ```
|
||||
LL | | /// assert!(false);
|
||||
LL | | /// ```
|
||||
| |___________^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/private-public-item-doc-test.rs:1:9
|
||||
|
|
||||
LL | #![deny(rustdoc::private_doc_tests)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
16
src/test/rustdoc-ui/public-reexported-item-doc-test.rs
Normal file
16
src/test/rustdoc-ui/public-reexported-item-doc-test.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// check-pass
|
||||
|
||||
#![deny(rustdoc::private_doc_tests)]
|
||||
|
||||
pub fn foo() {}
|
||||
|
||||
mod private {
|
||||
/// re-exported doc test
|
||||
///
|
||||
/// ```
|
||||
/// assert!(true);
|
||||
/// ```
|
||||
pub fn bar() {}
|
||||
}
|
||||
|
||||
pub use private::bar;
|
||||
46
src/test/rustdoc/intra-doc/prim-associated-traits.rs
Normal file
46
src/test/rustdoc/intra-doc/prim-associated-traits.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#![feature(never_type)]
|
||||
use std::str::FromStr;
|
||||
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.f64.html#method.from_str"]' 'f64::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.f32.html#method.from_str"]' 'f32::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.isize.html#method.from_str"]' 'isize::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i8.html#method.from_str"]' 'i8::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i16.html#method.from_str"]' 'i16::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i32.html#method.from_str"]' 'i32::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i64.html#method.from_str"]' 'i64::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.i128.html#method.from_str"]' 'i128::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.usize.html#method.from_str"]' 'usize::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u8.html#method.from_str"]' 'u8::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u16.html#method.from_str"]' 'u16::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u32.html#method.from_str"]' 'u32::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u64.html#method.from_str"]' 'u64::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.u128.html#method.from_str"]' 'u128::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.char.html#method.from_str"]' 'char::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.bool.html#method.from_str"]' 'bool::from_str()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.str.html#method.eq"]' 'str::eq()'
|
||||
// @has 'prim_associated_traits/struct.Number.html' '//a[@href="{{channel}}/std/primitive.never.html#method.eq"]' 'never::eq()'
|
||||
/// [`f64::from_str()`] [`f32::from_str()`] [`isize::from_str()`] [`i8::from_str()`]
|
||||
/// [`i16::from_str()`] [`i32::from_str()`] [`i64::from_str()`] [`i128::from_str()`]
|
||||
/// [`u16::from_str()`] [`u32::from_str()`] [`u64::from_str()`] [`u128::from_str()`]
|
||||
/// [`usize::from_str()`] [`u8::from_str()`] [`char::from_str()`] [`bool::from_str()`]
|
||||
/// [`str::eq()`] [`never::eq()`]
|
||||
pub struct Number {
|
||||
pub f_64: f64,
|
||||
pub f_32: f32,
|
||||
pub i_size: isize,
|
||||
pub i_8: i8,
|
||||
pub i_16: i16,
|
||||
pub i_32: i32,
|
||||
pub i_64: i64,
|
||||
pub i_128: i128,
|
||||
pub u_size: usize,
|
||||
pub u_8: u8,
|
||||
pub u_16: u16,
|
||||
pub u_32: u32,
|
||||
pub u_64: u64,
|
||||
pub u_128: u128,
|
||||
pub ch: char,
|
||||
pub boolean: bool,
|
||||
pub string: str,
|
||||
pub n: !,
|
||||
}
|
||||
7
src/test/ui/borrowck/issue-92015.rs
Normal file
7
src/test/ui/borrowck/issue-92015.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// Regression test for #92105.
|
||||
// ICE when mutating immutable reference from last statement of a block.
|
||||
|
||||
fn main() {
|
||||
let foo = Some(&0).unwrap();
|
||||
*foo = 1; //~ ERROR cannot assign
|
||||
}
|
||||
11
src/test/ui/borrowck/issue-92015.stderr
Normal file
11
src/test/ui/borrowck/issue-92015.stderr
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
|
||||
--> $DIR/issue-92015.rs:6:5
|
||||
|
|
||||
LL | let foo = Some(&0).unwrap();
|
||||
| --- help: consider changing this to be a mutable reference: `&mut i32`
|
||||
LL | *foo = 1;
|
||||
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0594`.
|
||||
14
src/test/ui/c-variadic/variadic-unreachable-arg-error.rs
Normal file
14
src/test/ui/c-variadic/variadic-unreachable-arg-error.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(c_variadic)]
|
||||
|
||||
extern "C" {
|
||||
fn foo(f: isize, x: u8, ...);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// FIXME: Ideally we could give an unreachable warning
|
||||
foo(1, loop {}, 1usize);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue