Auto merge of #106472 - matthiaskrgr:rollup-4w4v50e, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #106391 (rustdoc: allow popover child links to work) - #106398 (Fix a few clippy lints in libtest) - #106412 (Fix link generation for local primitive types in rustdoc JSON output) - #106437 (rustdoc: fix buggy JS check for absolute URL) - #106451 (Merge borrowck permission checks) - #106460 (Move tests) - #106461 (docs: fix broken link "search bar") Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d26242d35f
52 changed files with 150 additions and 104 deletions
|
@ -863,7 +863,6 @@ enum WriteKind {
|
|||
/// local place can be mutated.
|
||||
//
|
||||
// FIXME: @nikomatsakis suggested that this flag could be removed with the following modifications:
|
||||
// - Merge `check_access_permissions()` and `check_if_reassignment_to_immutable_state()`.
|
||||
// - Split `is_mutable()` into `is_assignable()` (can be directly assigned) and
|
||||
// `is_declared_mutable()`.
|
||||
// - Take flow state into consideration in `is_assignable()` for local variables.
|
||||
|
@ -1132,20 +1131,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// Write of P[i] or *P requires P init'd.
|
||||
self.check_if_assigned_path_is_moved(location, place_span, flow_state);
|
||||
|
||||
// Special case: you can assign an immutable local variable
|
||||
// (e.g., `x = ...`) so long as it has never been initialized
|
||||
// before (at this point in the flow).
|
||||
if let Some(local) = place_span.0.as_local() {
|
||||
if let Mutability::Not = self.body.local_decls[local].mutability {
|
||||
// check for reassignments to immutable local variables
|
||||
self.check_if_reassignment_to_immutable_state(
|
||||
location, local, place_span, flow_state,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use the normal access permission rules.
|
||||
self.access_place(
|
||||
location,
|
||||
place_span,
|
||||
|
@ -1554,24 +1539,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_if_reassignment_to_immutable_state(
|
||||
&mut self,
|
||||
location: Location,
|
||||
local: Local,
|
||||
place_span: (Place<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
) {
|
||||
debug!("check_if_reassignment_to_immutable_state({:?})", local);
|
||||
|
||||
// Check if any of the initializations of `local` have happened yet:
|
||||
if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) {
|
||||
// And, if so, report an error.
|
||||
let init = &self.move_data.inits[init_index];
|
||||
let span = init.span(&self.body);
|
||||
self.report_illegal_reassignment(location, place_span, span, place_span.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_if_full_path_is_moved(
|
||||
&mut self,
|
||||
location: Location,
|
||||
|
@ -2037,12 +2004,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// partial initialization, do not complain about mutability
|
||||
// errors except for actual mutation (as opposed to an attempt
|
||||
// to do a partial initialization).
|
||||
let previously_initialized =
|
||||
self.is_local_ever_initialized(place.local, flow_state).is_some();
|
||||
let previously_initialized = self.is_local_ever_initialized(place.local, flow_state);
|
||||
|
||||
// at this point, we have set up the error reporting state.
|
||||
if previously_initialized {
|
||||
self.report_mutability_error(place, span, the_place_err, error_access, location);
|
||||
if let Some(init_index) = previously_initialized {
|
||||
if let (AccessKind::Mutate, Some(_)) = (error_access, place.as_local()) {
|
||||
// If this is a mutate access to an immutable local variable with no projections
|
||||
// report the error as an illegal reassignment
|
||||
let init = &self.move_data.inits[init_index];
|
||||
let assigned_span = init.span(&self.body);
|
||||
self.report_illegal_reassignment(location, (place, span), assigned_span, place);
|
||||
} else {
|
||||
self.report_mutability_error(place, span, the_place_err, error_access, location)
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
//! # How to read this documentation
|
||||
//!
|
||||
//! If you already know the name of what you are looking for, the fastest way to
|
||||
//! find it is to use the <a href="#" onclick="focusSearchBar();">search
|
||||
//! find it is to use the <a href="#" onclick="window.searchState.focus();">search
|
||||
//! bar</a> at the top of the page.
|
||||
//!
|
||||
//! Otherwise, you may want to jump to one of these useful sections:
|
||||
|
|
|
@ -147,7 +147,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
|
|||
let mut ntest = 0;
|
||||
let mut nbench = 0;
|
||||
|
||||
for test in filter_tests(&opts, tests).into_iter() {
|
||||
for test in filter_tests(opts, tests).into_iter() {
|
||||
use crate::TestFn::*;
|
||||
|
||||
let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test;
|
||||
|
@ -244,7 +244,7 @@ fn on_test_event(
|
|||
let stdout = &completed_test.stdout;
|
||||
|
||||
st.write_log_result(test, result, exec_time.as_ref())?;
|
||||
out.write_result(test, result, exec_time.as_ref(), &*stdout, st)?;
|
||||
out.write_result(test, result, exec_time.as_ref(), stdout, st)?;
|
||||
handle_test_result(st, completed_test);
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
|
|||
|
||||
let max_name_len = tests
|
||||
.iter()
|
||||
.max_by_key(|t| len_if_padded(*t))
|
||||
.max_by_key(|t| len_if_padded(t))
|
||||
.map(|t| t.desc.name.as_slice().len())
|
||||
.unwrap_or(0);
|
||||
|
||||
|
|
|
@ -40,20 +40,20 @@ impl<T: Write> JsonFormatter<T> {
|
|||
extra: Option<&str>,
|
||||
) -> io::Result<()> {
|
||||
// A doc test's name includes a filename which must be escaped for correct json.
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
r#"{{ "type": "{}", "name": "{}", "event": "{}""#,
|
||||
ty,
|
||||
EscapedString(name),
|
||||
evt
|
||||
))?;
|
||||
if let Some(exec_time) = exec_time {
|
||||
self.write_message(&*format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?;
|
||||
self.write_message(&format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?;
|
||||
}
|
||||
if let Some(stdout) = stdout {
|
||||
self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
|
||||
self.write_message(&format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
|
||||
}
|
||||
if let Some(extra) = extra {
|
||||
self.write_message(&*format!(r#", {extra}"#))?;
|
||||
self.write_message(&format!(r#", {extra}"#))?;
|
||||
}
|
||||
self.writeln_message(" }")
|
||||
}
|
||||
|
@ -66,13 +66,13 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
|
|||
} else {
|
||||
String::new()
|
||||
};
|
||||
self.writeln_message(&*format!(
|
||||
self.writeln_message(&format!(
|
||||
r#"{{ "type": "suite", "event": "started", "test_count": {test_count}{shuffle_seed_json} }}"#
|
||||
))
|
||||
}
|
||||
|
||||
fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
self.writeln_message(&*format!(
|
||||
self.writeln_message(&format!(
|
||||
r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
|
||||
EscapedString(desc.name.as_slice())
|
||||
))
|
||||
|
@ -151,20 +151,20 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
|
|||
mbps
|
||||
);
|
||||
|
||||
self.writeln_message(&*line)
|
||||
self.writeln_message(&line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
self.writeln_message(&*format!(
|
||||
self.writeln_message(&format!(
|
||||
r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
|
||||
EscapedString(desc.name.as_slice())
|
||||
))
|
||||
}
|
||||
|
||||
fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
"{{ \"type\": \"suite\", \
|
||||
\"event\": \"{}\", \
|
||||
\"passed\": {}, \
|
||||
|
|
|
@ -64,7 +64,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||
fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
|
||||
self.write_message("<testsuites>")?;
|
||||
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
"<testsuite name=\"test\" package=\"test\" id=\"0\" \
|
||||
errors=\"0\" \
|
||||
failures=\"{}\" \
|
||||
|
@ -73,12 +73,12 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||
>",
|
||||
state.failed, state.total, state.ignored
|
||||
))?;
|
||||
for (desc, result, duration) in std::mem::replace(&mut self.results, Vec::new()) {
|
||||
for (desc, result, duration) in std::mem::take(&mut self.results) {
|
||||
let (class_name, test_name) = parse_class_name(&desc);
|
||||
match result {
|
||||
TestResult::TrIgnored => { /* no-op */ }
|
||||
TestResult::TrFailed => {
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
"<testcase classname=\"{}\" \
|
||||
name=\"{}\" time=\"{}\">",
|
||||
class_name,
|
||||
|
@ -90,19 +90,19 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||
}
|
||||
|
||||
TestResult::TrFailedMsg(ref m) => {
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
"<testcase classname=\"{}\" \
|
||||
name=\"{}\" time=\"{}\">",
|
||||
class_name,
|
||||
test_name,
|
||||
duration.as_secs_f64()
|
||||
))?;
|
||||
self.write_message(&*format!("<failure message=\"{m}\" type=\"assert\"/>"))?;
|
||||
self.write_message(&format!("<failure message=\"{m}\" type=\"assert\"/>"))?;
|
||||
self.write_message("</testcase>")?;
|
||||
}
|
||||
|
||||
TestResult::TrTimedFail => {
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
"<testcase classname=\"{}\" \
|
||||
name=\"{}\" time=\"{}\">",
|
||||
class_name,
|
||||
|
@ -114,7 +114,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||
}
|
||||
|
||||
TestResult::TrBench(ref b) => {
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
"<testcase classname=\"benchmark::{}\" \
|
||||
name=\"{}\" time=\"{}\" />",
|
||||
class_name, test_name, b.ns_iter_summ.sum
|
||||
|
@ -122,7 +122,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||
}
|
||||
|
||||
TestResult::TrOk => {
|
||||
self.write_message(&*format!(
|
||||
self.write_message(&format!(
|
||||
"<testcase classname=\"{}\" \
|
||||
name=\"{}\" time=\"{}\"/>",
|
||||
class_name,
|
||||
|
|
|
@ -134,7 +134,7 @@ impl<T: Write> PrettyFormatter<T> {
|
|||
|
||||
let mut results = Vec::new();
|
||||
let mut stdouts = String::new();
|
||||
for &(ref f, ref stdout) in inputs {
|
||||
for (f, stdout) in inputs {
|
||||
results.push(f.name.to_string());
|
||||
if !stdout.is_empty() {
|
||||
stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
|
||||
|
@ -171,9 +171,9 @@ impl<T: Write> PrettyFormatter<T> {
|
|||
fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
let name = desc.padded_name(self.max_name_len, desc.name.padding());
|
||||
if let Some(test_mode) = desc.test_mode() {
|
||||
self.write_plain(&format!("test {name} - {test_mode} ... "))?;
|
||||
self.write_plain(format!("test {name} - {test_mode} ... "))?;
|
||||
} else {
|
||||
self.write_plain(&format!("test {name} ... "))?;
|
||||
self.write_plain(format!("test {name} ... "))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -188,7 +188,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
|
|||
} else {
|
||||
String::new()
|
||||
};
|
||||
self.write_plain(&format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
|
||||
self.write_plain(format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
|
||||
}
|
||||
|
||||
fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
|
@ -221,7 +221,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
|
|||
TestResult::TrIgnored => self.write_ignored(desc.ignore_message)?,
|
||||
TestResult::TrBench(ref bs) => {
|
||||
self.write_bench()?;
|
||||
self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?;
|
||||
self.write_plain(format!(": {}", fmt_bench_samples(bs)))?;
|
||||
}
|
||||
TestResult::TrTimedFail => self.write_time_failed()?,
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
|
|||
}
|
||||
|
||||
fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
self.write_plain(&format!(
|
||||
self.write_plain(format!(
|
||||
"test {} has been running for over {} seconds\n",
|
||||
desc.name,
|
||||
time::TEST_WARN_TIMEOUT_S
|
||||
|
@ -267,11 +267,11 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
|
|||
state.passed, state.failed, state.ignored, state.measured, state.filtered_out
|
||||
);
|
||||
|
||||
self.write_plain(&s)?;
|
||||
self.write_plain(s)?;
|
||||
|
||||
if let Some(ref exec_time) = state.exec_time {
|
||||
let time_str = format!("; finished in {exec_time}");
|
||||
self.write_plain(&time_str)?;
|
||||
self.write_plain(time_str)?;
|
||||
}
|
||||
|
||||
self.write_plain("\n\n")?;
|
||||
|
|
|
@ -70,7 +70,7 @@ impl<T: Write> TerseFormatter<T> {
|
|||
// screen when dealing with line-buffered output (e.g., piping to
|
||||
// `stamp` in the rust CI).
|
||||
let out = format!(" {}/{}\n", self.test_count + 1, self.total_test_count);
|
||||
self.write_plain(&out)?;
|
||||
self.write_plain(out)?;
|
||||
}
|
||||
|
||||
self.test_count += 1;
|
||||
|
@ -106,7 +106,7 @@ impl<T: Write> TerseFormatter<T> {
|
|||
self.write_plain("\nsuccesses:\n")?;
|
||||
let mut successes = Vec::new();
|
||||
let mut stdouts = String::new();
|
||||
for &(ref f, ref stdout) in &state.not_failures {
|
||||
for (f, stdout) in &state.not_failures {
|
||||
successes.push(f.name.to_string());
|
||||
if !stdout.is_empty() {
|
||||
stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
|
||||
|
@ -132,7 +132,7 @@ impl<T: Write> TerseFormatter<T> {
|
|||
self.write_plain("\nfailures:\n")?;
|
||||
let mut failures = Vec::new();
|
||||
let mut fail_out = String::new();
|
||||
for &(ref f, ref stdout) in &state.failures {
|
||||
for (f, stdout) in &state.failures {
|
||||
failures.push(f.name.to_string());
|
||||
if !stdout.is_empty() {
|
||||
fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
|
||||
|
@ -157,9 +157,9 @@ impl<T: Write> TerseFormatter<T> {
|
|||
fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
let name = desc.padded_name(self.max_name_len, desc.name.padding());
|
||||
if let Some(test_mode) = desc.test_mode() {
|
||||
self.write_plain(&format!("test {name} - {test_mode} ... "))?;
|
||||
self.write_plain(format!("test {name} - {test_mode} ... "))?;
|
||||
} else {
|
||||
self.write_plain(&format!("test {name} ... "))?;
|
||||
self.write_plain(format!("test {name} ... "))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -175,7 +175,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
|
|||
} else {
|
||||
String::new()
|
||||
};
|
||||
self.write_plain(&format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
|
||||
self.write_plain(format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
|
||||
}
|
||||
|
||||
fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
|
@ -209,13 +209,13 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
|
|||
self.write_test_name(desc)?;
|
||||
}
|
||||
self.write_bench()?;
|
||||
self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))
|
||||
self.write_plain(format!(": {}\n", fmt_bench_samples(bs)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
|
||||
self.write_plain(&format!(
|
||||
self.write_plain(format!(
|
||||
"test {} has been running for over {} seconds\n",
|
||||
desc.name,
|
||||
time::TEST_WARN_TIMEOUT_S
|
||||
|
@ -245,11 +245,11 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
|
|||
state.passed, state.failed, state.ignored, state.measured, state.filtered_out
|
||||
);
|
||||
|
||||
self.write_plain(&s)?;
|
||||
self.write_plain(s)?;
|
||||
|
||||
if let Some(ref exec_time) = state.exec_time {
|
||||
let time_str = format!("; finished in {exec_time}");
|
||||
self.write_plain(&time_str)?;
|
||||
self.write_plain(time_str)?;
|
||||
}
|
||||
|
||||
self.write_plain("\n\n")?;
|
||||
|
|
|
@ -789,7 +789,7 @@ fn run_test_in_spawned_subprocess(
|
|||
}
|
||||
});
|
||||
let record_result2 = record_result.clone();
|
||||
panic::set_hook(Box::new(move |info| record_result2(Some(&info))));
|
||||
panic::set_hook(Box::new(move |info| record_result2(Some(info))));
|
||||
if let Err(message) = testfn() {
|
||||
panic!("{}", message);
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
|
|||
// are there any terminals that have color/attrs and not sgr0?
|
||||
// Try falling back to sgr, then op
|
||||
let cmd = match ["sgr0", "sgr", "op"].iter().find_map(|cap| self.ti.strings.get(*cap)) {
|
||||
Some(op) => match expand(&op, &[], &mut Variables::new()) {
|
||||
Some(op) => match expand(op, &[], &mut Variables::new()) {
|
||||
Ok(cmd) => cmd,
|
||||
Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
|
||||
},
|
||||
|
@ -180,12 +180,12 @@ impl<T: Write + Send> TerminfoTerminal<T> {
|
|||
}
|
||||
|
||||
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
|
||||
if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color }
|
||||
if color >= self.num_colors && (8..16).contains(&color) { color - 8 } else { color }
|
||||
}
|
||||
|
||||
fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
|
||||
match self.ti.strings.get(cmd) {
|
||||
Some(cmd) => match expand(&cmd, params, &mut Variables::new()) {
|
||||
Some(cmd) => match expand(cmd, params, &mut Variables::new()) {
|
||||
Ok(s) => self.out.write_all(&s).and(Ok(true)),
|
||||
Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
|
||||
},
|
||||
|
|
|
@ -282,14 +282,14 @@ pub(crate) fn expand(
|
|||
);
|
||||
}
|
||||
SetVar => {
|
||||
if cur >= 'A' && cur <= 'Z' {
|
||||
if cur.is_ascii_uppercase() {
|
||||
if let Some(arg) = stack.pop() {
|
||||
let idx = (cur as u8) - b'A';
|
||||
vars.sta_va[idx as usize] = arg;
|
||||
} else {
|
||||
return Err("stack is empty".to_string());
|
||||
}
|
||||
} else if cur >= 'a' && cur <= 'z' {
|
||||
} else if cur.is_ascii_lowercase() {
|
||||
if let Some(arg) = stack.pop() {
|
||||
let idx = (cur as u8) - b'a';
|
||||
vars.dyn_va[idx as usize] = arg;
|
||||
|
@ -301,10 +301,10 @@ pub(crate) fn expand(
|
|||
}
|
||||
}
|
||||
GetVar => {
|
||||
if cur >= 'A' && cur <= 'Z' {
|
||||
if cur.is_ascii_uppercase() {
|
||||
let idx = (cur as u8) - b'A';
|
||||
stack.push(vars.sta_va[idx as usize].clone());
|
||||
} else if cur >= 'a' && cur <= 'z' {
|
||||
} else if cur.is_ascii_lowercase() {
|
||||
let idx = (cur as u8) - b'a';
|
||||
stack.push(vars.dyn_va[idx as usize].clone());
|
||||
} else {
|
||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
|
|||
|
||||
if let Ok(dirs) = env::var("TERMINFO_DIRS") {
|
||||
for i in dirs.split(':') {
|
||||
if i == "" {
|
||||
if i.is_empty() {
|
||||
dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
|
||||
} else {
|
||||
dirs_to_search.push(PathBuf::from(i));
|
||||
|
@ -49,7 +49,7 @@ pub(crate) fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
|
|||
for mut p in dirs_to_search {
|
||||
if fs::metadata(&p).is_ok() {
|
||||
p.push(&first_char.to_string());
|
||||
p.push(&term);
|
||||
p.push(term);
|
||||
if fs::metadata(&p).is_ok() {
|
||||
return Some(p);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ pub fn calc_result<'a>(
|
|||
) -> TestResult {
|
||||
let result = match (&desc.should_panic, task_result) {
|
||||
(&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk,
|
||||
(&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
|
||||
(&ShouldPanic::YesWithMessage(msg), Err(err)) => {
|
||||
let maybe_panic_str = err
|
||||
.downcast_ref::<String>()
|
||||
.map(|e| &**e)
|
||||
|
@ -52,7 +52,7 @@ pub fn calc_result<'a>(
|
|||
r#"expected panic with string value,
|
||||
found non-string value: `{:?}`
|
||||
expected substring: `{:?}`"#,
|
||||
(**err).type_id(),
|
||||
(*err).type_id(),
|
||||
msg
|
||||
))
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ impl TestName {
|
|||
match *self {
|
||||
StaticTestName(s) => s,
|
||||
DynTestName(ref s) => s,
|
||||
AlignedTestName(ref s, _) => &*s,
|
||||
AlignedTestName(ref s, _) => s,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -563,7 +563,7 @@ function loadCss(cssUrl) {
|
|||
onEachLazy(code.getElementsByTagName("a"), elem => {
|
||||
const href = elem.getAttribute("href");
|
||||
|
||||
if (href && href.indexOf("http") !== 0) {
|
||||
if (href && !/^(?:[a-z+]+:)?\/\//.test(href)) {
|
||||
elem.setAttribute("href", window.rootPath + href);
|
||||
}
|
||||
});
|
||||
|
@ -1040,9 +1040,6 @@ function loadCss(cssUrl) {
|
|||
help_button.appendChild(container);
|
||||
|
||||
container.onblur = helpBlurHandler;
|
||||
container.onclick = event => {
|
||||
event.preventDefault();
|
||||
};
|
||||
help_button.onblur = helpBlurHandler;
|
||||
help_button.children[0].onblur = helpBlurHandler;
|
||||
}
|
||||
|
|
|
@ -8,8 +8,9 @@ use std::convert::From;
|
|||
use std::fmt;
|
||||
|
||||
use rustc_ast::ast;
|
||||
use rustc_hir::{def::CtorKind, def_id::DefId};
|
||||
use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Pos, Symbol};
|
||||
use rustc_target::spec::abi::Abi as RustcAbi;
|
||||
|
||||
|
@ -217,13 +218,27 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
|
|||
|
||||
impl<'a> fmt::Display for DisplayDefId<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let name = match self.2 {
|
||||
let DisplayDefId(def_id, tcx, name) = self;
|
||||
let name = match name {
|
||||
Some(name) => format!(":{}", name.as_u32()),
|
||||
None => self
|
||||
.1
|
||||
.opt_item_name(self.0)
|
||||
.map(|n| format!(":{}", n.as_u32()))
|
||||
.unwrap_or_default(),
|
||||
None => {
|
||||
// We need this workaround because primitive types' DefId actually refers to
|
||||
// their parent module, which isn't present in the output JSON items. So
|
||||
// instead, we directly get the primitive symbol and convert it to u32 to
|
||||
// generate the ID.
|
||||
if matches!(tcx.def_kind(def_id), DefKind::Mod) &&
|
||||
let Some(prim) = tcx.get_attrs(*def_id, sym::doc)
|
||||
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
|
||||
.filter(|attr| attr.has_name(sym::primitive))
|
||||
.find_map(|attr| attr.value_str()) {
|
||||
format!(":{}", prim.as_u32())
|
||||
} else {
|
||||
tcx
|
||||
.opt_item_name(*def_id)
|
||||
.map(|n| format!(":{}", n.as_u32()))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
};
|
||||
write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
|
||||
}
|
||||
|
@ -237,7 +252,7 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
|
|||
ItemId::Auto { for_, trait_ } => {
|
||||
Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
|
||||
}
|
||||
ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
|
||||
ItemId::Primitive(_, _) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,3 +61,12 @@ click: "#help-button > a"
|
|||
assert-css: ("#help", {"display": "none"})
|
||||
compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
|
||||
compare-elements-position-false: (".sub", "#help", ("x"))
|
||||
|
||||
// This test ensures that the "the rustdoc book" anchor link within the help popover works.
|
||||
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
size: (1000, 1000) // Popover only appears when the screen width is >700px.
|
||||
assert-false: "#help"
|
||||
click: "#help-button > a"
|
||||
click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']"
|
||||
wait-for: 2000
|
||||
assert-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"}
|
||||
|
|
|
@ -33,3 +33,9 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.TraitToReexport.html"
|
|||
assert-count: ("#implementors-list .impl", 1)
|
||||
goto: "file://" + |DOC_PATH| + "/implementors/trait.TraitToReexport.html"
|
||||
assert-count: ("#implementors-list .impl", 1)
|
||||
|
||||
// Now check that the link is properly rewritten for a crate called `http`.
|
||||
// An older version of rustdoc had a buggy check for absolute links.
|
||||
goto: "file://" + |DOC_PATH| + "/http/trait.HttpTrait.html"
|
||||
assert-count: ("#implementors-list .impl", 1)
|
||||
assert-attribute: ("#implementors-list .impl a.trait", {"href": "../http/trait.HttpTrait.html"})
|
||||
|
|
|
@ -15,6 +15,7 @@ click: "#crate-search"
|
|||
press-key: "ArrowDown"
|
||||
press-key: "ArrowDown"
|
||||
press-key: "ArrowDown"
|
||||
press-key: "ArrowDown"
|
||||
press-key: "Enter"
|
||||
// Waiting for the search results to appear...
|
||||
wait-for: "#search-tabs"
|
||||
|
@ -39,6 +40,7 @@ click: "#crate-search"
|
|||
press-key: "ArrowUp"
|
||||
press-key: "ArrowUp"
|
||||
press-key: "ArrowUp"
|
||||
press-key: "ArrowUp"
|
||||
press-key: "Enter"
|
||||
// Waiting for the search results to appear...
|
||||
wait-for: "#search-tabs"
|
||||
|
|
|
@ -73,7 +73,7 @@ assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']"
|
|||
// Only "another_folder" should be "open" in "lib2".
|
||||
assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']"
|
||||
// All other trees should be collapsed.
|
||||
assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 7)
|
||||
assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 8)
|
||||
|
||||
// We now switch to mobile mode.
|
||||
size: (600, 600)
|
||||
|
|
|
@ -102,7 +102,7 @@ assert: ".source-sidebar-expanded"
|
|||
|
||||
// We check that the first entry of the sidebar is collapsed
|
||||
assert-property: ("#source-sidebar details:first-of-type", {"open": "false"})
|
||||
assert-text: ("#source-sidebar details:first-of-type > summary", "huge_logo")
|
||||
assert-text: ("#source-sidebar details:first-of-type > summary", "http")
|
||||
// We now click on it.
|
||||
click: "#source-sidebar details:first-of-type > summary"
|
||||
assert-property: ("#source-sidebar details:first-of-type", {"open": "true"})
|
||||
|
|
|
@ -2,13 +2,21 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "implementors"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lib2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"http",
|
||||
"implementors",
|
||||
]
|
||||
|
|
|
@ -8,3 +8,4 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
implementors = { path = "./implementors" }
|
||||
http = { path = "./http" }
|
||||
|
|
7
src/test/rustdoc-gui/src/lib2/http/Cargo.toml
Normal file
7
src/test/rustdoc-gui/src/lib2/http/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "http"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
1
src/test/rustdoc-gui/src/lib2/http/lib.rs
Normal file
1
src/test/rustdoc-gui/src/lib2/http/lib.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub trait HttpTrait {}
|
|
@ -5,3 +5,6 @@ edition = "2018"
|
|||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
http = { path = "../http/" }
|
||||
|
|
|
@ -10,6 +10,8 @@ impl Whatever for Struct {
|
|||
type Foo = u8;
|
||||
}
|
||||
|
||||
impl http::HttpTrait for Struct {}
|
||||
|
||||
mod traits {
|
||||
pub trait TraitToReexport {
|
||||
fn method() {}
|
||||
|
|
21
src/test/rustdoc-json/primitives/local_primitive.rs
Normal file
21
src/test/rustdoc-json/primitives/local_primitive.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Regression test for <https://github.com/rust-lang/rust/issues/104064>.
|
||||
|
||||
#![feature(no_core)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![no_core]
|
||||
#![rustc_coherence_is_core]
|
||||
|
||||
//! Link to [i32][prim@i32] [i64][prim@i64]
|
||||
|
||||
#[doc(primitive = "i32")]
|
||||
mod prim_i32 {}
|
||||
|
||||
// @set local_i32 = "$.index[*][?(@.name=='i32')].id"
|
||||
|
||||
// @has "$.index[*][?(@.name=='local_primitive')]"
|
||||
// @ismany "$.index[*][?(@.name=='local_primitive')].inner.items[*]" $local_i32
|
||||
// @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
|
||||
|
||||
// Let's ensure the `prim_i32` module isn't present in the output JSON:
|
||||
// @!has "$.index[*][?(@.name=='prim_i32')]"
|
|
@ -10,7 +10,7 @@ use std::path::Path;
|
|||
const ENTRY_LIMIT: usize = 1000;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
const ROOT_ENTRY_LIMIT: usize = 939;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 2050;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 1998;
|
||||
|
||||
fn check_entries(path: &Path, bad: &mut bool) {
|
||||
for dir in Walk::new(&path.join("test/ui")) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue