Auto merge of #88914 - GuillaumeGomez:rollup-h5svc6w, r=GuillaumeGomez

Rollup of 7 pull requests

Successful merges:

 - #88033 (Add links for primitives in "jump to definition" feature)
 - #88722 (Make `UnsafeCell::get_mut` const)
 - #88851 (Fix duplicate bounds for const_trait_impl)
 - #88859 (interpreter PointerArithmetic: use new Size helper methods)
 - #88885 (Fix jump def background)
 - #88894 (Improve error message for missing trait in trait impl)
 - #88896 (Reduce possibility of flaky tests)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-09-14 08:46:22 +00:00
commit ec9a1bdc45
19 changed files with 165 additions and 25 deletions

View File

@ -3,7 +3,7 @@
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
use std::convert::TryFrom;
use std::convert::{TryFrom, TryInto};
use std::fmt;
////////////////////////////////////////////////////////////////////////////////
@ -20,29 +20,27 @@ fn pointer_size(&self) -> Size {
#[inline]
fn machine_usize_max(&self) -> u64 {
let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
u64::try_from(max_usize_plus_1 - 1).unwrap()
self.pointer_size().unsigned_int_max().try_into().unwrap()
}
#[inline]
fn machine_isize_min(&self) -> i64 {
let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1);
i64::try_from(-max_isize_plus_1).unwrap()
self.pointer_size().signed_int_min().try_into().unwrap()
}
#[inline]
fn machine_isize_max(&self) -> i64 {
let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1);
i64::try_from(max_isize_plus_1 - 1).unwrap()
self.pointer_size().signed_int_max().try_into().unwrap()
}
#[inline]
fn machine_usize_to_isize(&self, val: u64) -> i64 {
let val = val as i64;
// Now clamp into the machine_isize range.
// Now wrap-around into the machine_isize range.
if val > self.machine_isize_max() {
// This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into
// i64.
debug_assert!(self.pointer_size().bits() < 64);
let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
val - i64::try_from(max_usize_plus_1).unwrap()
} else {

View File

@ -493,7 +493,20 @@ fn parse_item_impl(
let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
{
let span = self.prev_token.span.between(self.token.span);
self.struct_span_err(span, "missing trait in a trait impl").emit();
self.struct_span_err(span, "missing trait in a trait impl")
.span_suggestion(
span,
"add a trait here",
" Trait ".into(),
Applicability::HasPlaceholders,
)
.span_suggestion(
span.to(self.token.span),
"for an inherent impl, drop this `for`",
"".into(),
Applicability::MaybeIncorrect,
)
.emit();
P(Ty {
kind: TyKind::Path(None, err_path(span)),
span,

View File

@ -1487,10 +1487,11 @@ fn candidate_should_be_dropped_in_favor_of(
) => false,
(ParamCandidate(other), ParamCandidate(victim)) => {
let value_same_except_bound_vars = other.value.skip_binder()
let same_except_bound_vars = other.value.skip_binder()
== victim.value.skip_binder()
&& other.constness == victim.constness
&& !other.value.skip_binder().has_escaping_bound_vars();
if value_same_except_bound_vars {
if same_except_bound_vars {
// See issue #84398. In short, we can generate multiple ParamCandidates which are
// the same except for unused bound vars. Just pick the one with the fewest bound vars
// or the current one if tied (they should both evaluate to the same answer). This is

View File

@ -1916,7 +1916,8 @@ pub const fn get(&self) -> *mut T {
/// ```
#[inline(always)]
#[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")]
pub fn get_mut(&mut self) -> &mut T {
#[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")]
pub const fn get_mut(&mut self) -> &mut T {
&mut self.value
}

View File

@ -925,6 +925,11 @@ fn run(self, builder: &Builder<'_>) {
.env("RUSTDOC", builder.rustdoc(self.compiler))
.env("RUSTC", builder.rustc(self.compiler))
.current_dir(path);
// FIXME: implement a `// compile-flags` command or similar
// instead of hard-coding this test
if entry.file_name() == "link_to_definition" {
cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
}
builder.run(&mut cargo);
}
}

View File

@ -5,6 +5,7 @@
//!
//! Use the `render_with_highlighting` to highlight some rust code.
use crate::clean::PrimitiveType;
use crate::html::escape::Escape;
use crate::html::render::Context;
@ -584,6 +585,13 @@ fn string<T: Display>(
.ok()
.map(|(url, _, _)| url)
}
LinkFromSrc::Primitive(prim) => format::href_with_root_path(
PrimitiveType::primitive_locations(context.tcx())[&prim],
context,
Some(context_info.root_path),
)
.ok()
.map(|(url, _, _)| url),
}
})
{

View File

@ -1,4 +1,4 @@
use crate::clean;
use crate::clean::{self, PrimitiveType};
use crate::html::sources;
use rustc_data_structures::fx::FxHashMap;
@ -22,6 +22,7 @@
crate enum LinkFromSrc {
Local(clean::Span),
External(DefId),
Primitive(PrimitiveType),
}
/// This function will do at most two things:
@ -73,17 +74,20 @@ fn handle_path(&mut self, path: &rustc_hir::Path<'_>, path_span: Option<Span>) {
Some(def_id)
}
Res::Local(_) => None,
Res::PrimTy(p) => {
// FIXME: Doesn't handle "path-like" primitives like arrays or tuples.
let span = path_span.unwrap_or(path.span);
self.matches.insert(span, LinkFromSrc::Primitive(PrimitiveType::from(p)));
return;
}
Res::Err => return,
_ => return,
};
if let Some(span) = self.tcx.hir().res_span(path.res) {
self.matches.insert(
path_span.unwrap_or_else(|| path.span),
LinkFromSrc::Local(clean::Span::new(span)),
);
} else if let Some(def_id) = info {
self.matches
.insert(path_span.unwrap_or_else(|| path.span), LinkFromSrc::External(def_id));
.insert(path_span.unwrap_or(path.span), LinkFromSrc::Local(clean::Span::new(span)));
} else if let Some(def_id) = info {
self.matches.insert(path_span.unwrap_or(path.span), LinkFromSrc::External(def_id));
}
}
}

View File

@ -217,7 +217,7 @@ a {
color: #c5c5c5;
}
body.source .example-wrap pre.rust a {
background: #c5c5c5;
background: #333;
}
.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),

View File

@ -1,5 +1,6 @@
goto: file://|DOC_PATH|/test_docs/index.html
click: ".srclink"
wait-for: "#sidebar-toggle"
click: "#sidebar-toggle"
wait-for: 500
fail: true

View File

@ -0,0 +1,23 @@
// We check the background color on the jump to definition links in the source code page.
goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html
// Set the theme to dark.
local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
// We reload the page so the local storage settings are being used.
reload:
assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
// Set the theme to ayu.
local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
// We reload the page so the local storage settings are being used.
reload:
assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
// Set the theme to light.
local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
// We reload the page so the local storage settings are being used.
reload:
assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(238, 238, 238)"}, ALL)

View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "link_to_definition"
version = "0.1.0"

View File

@ -0,0 +1,7 @@
[package]
name = "link_to_definition"
version = "0.1.0"
edition = "2018"
[lib]
path = "lib.rs"

View File

@ -0,0 +1,6 @@
pub struct Bar {
pub a: String,
pub b: u32,
}
pub fn foo(_b: &Bar) {}

View File

@ -0,0 +1,17 @@
// compile-flags: -Zunstable-options --generate-link-to-definition
#![crate_name = "foo"]
// @has 'src/foo/check-source-code-urls-to-def-std.rs.html'
fn babar() {}
// @has - '//a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str'
// @has - '//a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
// @has - '//a[@href="../../src/foo/check-source-code-urls-to-def-std.rs.html#7"]' 'babar'
pub fn foo(a: u32, b: &str, c: String) {
let x = 12;
let y: bool = true;
babar();
}

View File

@ -27,6 +27,8 @@ fn hello(&self) {}
fn babar() {}
// @has - '//a/@href' '/struct.String.html'
// @has - '//a/@href' '/primitive.u32.html'
// @has - '//a/@href' '/primitive.str.html'
// @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5
// @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode'
pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
@ -40,5 +42,9 @@ pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::Sour
// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait'
// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait'
pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V) {
pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {
}
// @has - '//a[@href="../../foo/primitive.bool.html"]' 'bool'
#[doc(primitive = "bool")]
mod whatever {}

View File

@ -3,6 +3,16 @@ error: missing trait in a trait impl
|
LL | impl for T {}
| ^
|
help: add a trait here
|
LL | impl Trait for T {}
| +++++
help: for an inherent impl, drop this `for`
|
LL - impl for T {}
LL + impl T {}
|
error: aborting due to previous error

View File

@ -0,0 +1,10 @@
// Regression test for #88818 (improve error message for missing trait
// in `impl for X`).
struct S { }
impl for S { }
//~^ ERROR: missing trait in a trait impl
//~| HELP: add a trait here
//~| HELP: for an inherent impl, drop this `for`
fn main() {}

View File

@ -0,0 +1,18 @@
error: missing trait in a trait impl
--> $DIR/issue-88818.rs:5:5
|
LL | impl for S { }
| ^
|
help: add a trait here
|
LL | impl Trait for S { }
| +++++
help: for an inherent impl, drop this `for`
|
LL - impl for S { }
LL + impl S { }
|
error: aborting due to previous error

View File

@ -16,12 +16,17 @@ fn ne(&self, other: &S) -> bool {
// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const
// bound.
// const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
// FIXME(fee1-dead)^ why should the order matter here?
const fn equals_self<T: ~const PartialEq + PartialEq>(t: &T) -> bool {
const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
*t == *t
}
pub const EQ: bool = equals_self(&S);
trait A: PartialEq {}
impl<T: PartialEq> A for T {}
const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
*t == *t
}
pub const EQ: bool = equals_self(&S) && equals_self2(&S);
fn main() {}