Auto merge of #149276 - matthiaskrgr:rollup-wlrpdrr, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang/rust#148234 (rustdoc: make mergeable crate info more usable) - rust-lang/rust#149201 (Add suggest alternatives for Out-of-range \x escapes) - rust-lang/rust#149208 ([rustdoc] Make more functions return `fmt::Result` and reduce number of `.unwrap()` calls) - rust-lang/rust#149252 (miri: use `tikv-jemalloc-sys` from sysroot) - rust-lang/rust#149255 (Use `let...else` consistently in user-facing diagnostics) - rust-lang/rust#149275 (Fix missing double-quote in `std::env::consts::OS` values) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c871d09d1c
44 changed files with 365 additions and 142 deletions
|
|
@ -2486,7 +2486,6 @@ dependencies = [
|
|||
"serde_json",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"tikv-jemalloc-sys",
|
||||
"ui_test",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ fn resolve_block<'tcx>(
|
|||
for (i, statement) in blk.stmts.iter().enumerate() {
|
||||
match statement.kind {
|
||||
hir::StmtKind::Let(LetStmt { els: Some(els), .. }) => {
|
||||
// Let-else has a special lexical structure for variables.
|
||||
// let-else has a special lexical structure for variables.
|
||||
// First we take a checkpoint of the current scope context here.
|
||||
let mut prev_cx = visitor.cx;
|
||||
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count
|
|||
*[other] variants that aren't
|
||||
} matched
|
||||
|
||||
mir_build_suggest_let_else = you might want to use `let else` to handle the {$count ->
|
||||
mir_build_suggest_let_else = you might want to use `let...else` to handle the {$count ->
|
||||
[one] variant that isn't
|
||||
*[other] variants that aren't
|
||||
} matched
|
||||
|
|
|
|||
|
|
@ -732,8 +732,6 @@ parse_or_in_let_chain = `||` operators are not supported in let chain conditions
|
|||
|
||||
parse_or_pattern_not_allowed_in_fn_parameters = function parameters require top-level or-patterns in parentheses
|
||||
parse_or_pattern_not_allowed_in_let_binding = `let` bindings require top-level or-patterns in parentheses
|
||||
parse_out_of_range_hex_escape = out of range hex escape
|
||||
.label = must be a character in the range [\x00-\x7f]
|
||||
|
||||
parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
|
||||
|
||||
|
|
|
|||
|
|
@ -2455,12 +2455,6 @@ pub(crate) enum UnescapeError {
|
|||
is_hex: bool,
|
||||
ch: String,
|
||||
},
|
||||
#[diag(parse_out_of_range_hex_escape)]
|
||||
OutOfRangeHexEscape(
|
||||
#[primary_span]
|
||||
#[label]
|
||||
Span,
|
||||
),
|
||||
#[diag(parse_leading_underscore_unicode_escape)]
|
||||
LeadingUnderscoreUnicodeEscape {
|
||||
#[primary_span]
|
||||
|
|
|
|||
|
|
@ -226,7 +226,24 @@ pub(crate) fn emit_unescape_error(
|
|||
err.emit()
|
||||
}
|
||||
EscapeError::OutOfRangeHexEscape => {
|
||||
dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span))
|
||||
let mut err = dcx.struct_span_err(err_span, "out of range hex escape");
|
||||
err.span_label(err_span, "must be a character in the range [\\x00-\\x7f]");
|
||||
|
||||
let escape_str = &lit[range];
|
||||
if lit.len() <= 4
|
||||
&& escape_str.len() == 4
|
||||
&& escape_str.starts_with("\\x")
|
||||
&& let Ok(value) = u8::from_str_radix(&escape_str[2..4], 16)
|
||||
&& matches!(mode, Mode::Char | Mode::Str)
|
||||
{
|
||||
err.help(format!("if you want to write a byte literal, use `b'{}'`", escape_str));
|
||||
err.help(format!(
|
||||
"if you want to write a Unicode character, use `'\\u{{{:X}}}'`",
|
||||
value
|
||||
));
|
||||
}
|
||||
|
||||
err.emit()
|
||||
}
|
||||
EscapeError::LeadingUnderscoreUnicodeEscape => {
|
||||
let (c, span) = last_char();
|
||||
|
|
|
|||
|
|
@ -867,7 +867,7 @@ impl<'a> Parser<'a> {
|
|||
if let_else || !if_let {
|
||||
err.span_suggestion_verbose(
|
||||
block_span.shrink_to_lo(),
|
||||
format!("{alternatively}you might have meant to use `let else`"),
|
||||
format!("{alternatively}you might have meant to use `let...else`"),
|
||||
"else ".to_string(),
|
||||
if let_else {
|
||||
Applicability::MachineApplicable
|
||||
|
|
|
|||
|
|
@ -1097,7 +1097,7 @@ pub mod consts {
|
|||
/// * `"nto"`
|
||||
/// * `"redox"`
|
||||
/// * `"solaris"`
|
||||
/// * `"solid_asp3`
|
||||
/// * `"solid_asp3"`
|
||||
/// * `"vexos"`
|
||||
/// * `"vita"`
|
||||
/// * `"vxworks"`
|
||||
|
|
|
|||
|
|
@ -1567,6 +1567,11 @@ tool_rustc_extended!(Miri {
|
|||
tool_name: "miri",
|
||||
stable: false,
|
||||
add_bins_to_sysroot: ["miri"],
|
||||
add_features: |builder, target, features| {
|
||||
if builder.config.jemalloc(target) {
|
||||
features.push("jemalloc".to_string());
|
||||
}
|
||||
},
|
||||
// Always compile also tests when building miri. Otherwise feature unification can cause rebuilds between building and testing miri.
|
||||
cargo_args: &["--all-targets"],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -197,6 +197,37 @@ themselves marked as unstable. To use any of these options, pass `-Z unstable-op
|
|||
the flag in question to Rustdoc on the command-line. To do this from Cargo, you can either use the
|
||||
`RUSTDOCFLAGS` environment variable or the `cargo rustdoc` command.
|
||||
|
||||
### `--merge`, `--parts-out-dir`, and `--include-parts-dir`
|
||||
|
||||
These options control how rustdoc handles files that combine data from multiple crates.
|
||||
|
||||
By default, they act like `--merge=shared` is set, and `--parts-out-dir` and `--include-parts-dir`
|
||||
are turned off. The `--merge=shared` mode causes rustdoc to load the existing data in the out-dir,
|
||||
combine the new crate data into it, and write the result. This is very easy to use in scripts that
|
||||
manually invoke rustdoc, but it's also slow, because it performs O(crates) work on
|
||||
every crate, meaning it performs O(crates<sup>2</sup>) work.
|
||||
|
||||
```console
|
||||
$ rustdoc crate1.rs --out-dir=doc
|
||||
$ cat doc/search.index/crateNames/*
|
||||
rd_("fcrate1")
|
||||
$ rustdoc crate2.rs --out-dir=doc
|
||||
$ cat doc/search.index/crateNames/*
|
||||
rd_("fcrate1fcrate2")
|
||||
```
|
||||
|
||||
To delay shared-data merging until the end of a build, so that you only have to perform O(crates)
|
||||
work, use `--merge=none` on every crate except the last one, which will use `--merge=finalize`.
|
||||
|
||||
```console
|
||||
$ rustdoc +nightly crate1.rs --merge=none --parts-out-dir=crate1.d -Zunstable-options
|
||||
$ cat doc/search.index/crateNames/*
|
||||
cat: 'doc/search.index/crateNames/*': No such file or directory
|
||||
$ rustdoc +nightly crate2.rs --merge=finalize --include-parts-dir=crate1.d -Zunstable-options
|
||||
$ cat doc/search.index/crateNames/*
|
||||
rd_("fcrate1fcrate2")
|
||||
```
|
||||
|
||||
### `--document-hidden-items`: Show items that are `#[doc(hidden)]`
|
||||
<span id="document-hidden-items"></span>
|
||||
|
||||
|
|
|
|||
|
|
@ -978,15 +978,16 @@ fn parse_extern_html_roots(
|
|||
Ok(externs)
|
||||
}
|
||||
|
||||
/// Path directly to crate-info file.
|
||||
/// Path directly to crate-info directory.
|
||||
///
|
||||
/// For example, `/home/user/project/target/doc.parts/<crate>/crate-info`.
|
||||
/// For example, `/home/user/project/target/doc.parts`.
|
||||
/// Each crate has its info stored in a file called `CRATENAME.json`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct PathToParts(pub(crate) PathBuf);
|
||||
|
||||
impl PathToParts {
|
||||
fn from_flag(path: String) -> Result<PathToParts, String> {
|
||||
let mut path = PathBuf::from(path);
|
||||
let path = PathBuf::from(path);
|
||||
// check here is for diagnostics
|
||||
if path.exists() && !path.is_dir() {
|
||||
Err(format!(
|
||||
|
|
@ -995,20 +996,22 @@ impl PathToParts {
|
|||
))
|
||||
} else {
|
||||
// if it doesn't exist, we'll create it. worry about that in write_shared
|
||||
path.push("crate-info");
|
||||
Ok(PathToParts(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reports error if --include-parts-dir / crate-info is not a file
|
||||
/// Reports error if --include-parts-dir is not a directory
|
||||
fn parse_include_parts_dir(m: &getopts::Matches) -> Result<Vec<PathToParts>, String> {
|
||||
let mut ret = Vec::new();
|
||||
for p in m.opt_strs("include-parts-dir") {
|
||||
let p = PathToParts::from_flag(p)?;
|
||||
// this is just for diagnostic
|
||||
if !p.0.is_file() {
|
||||
return Err(format!("--include-parts-dir expected {} to be a file", p.0.display()));
|
||||
if !p.0.is_dir() {
|
||||
return Err(format!(
|
||||
"--include-parts-dir expected {} to be a directory",
|
||||
p.0.display()
|
||||
));
|
||||
}
|
||||
ret.push(p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1252,9 +1252,9 @@ struct Indent(usize);
|
|||
|
||||
impl Display for Indent {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
(0..self.0).for_each(|_| {
|
||||
f.write_char(' ').unwrap();
|
||||
});
|
||||
for _ in 0..self.0 {
|
||||
f.write_char(' ')?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ impl HtmlWithLimit {
|
|||
pub(super) fn close_tag(&mut self) {
|
||||
if let Some(tag_name) = self.unclosed_tags.pop() {
|
||||
// Close the most recently opened tag.
|
||||
write!(self.buf, "</{tag_name}>").unwrap()
|
||||
write!(self.buf, "</{tag_name}>").expect("infallible string operation");
|
||||
}
|
||||
// There are valid cases where `close_tag()` is called without
|
||||
// there being any tags to close. For example, this occurs when
|
||||
|
|
@ -99,7 +99,7 @@ impl HtmlWithLimit {
|
|||
/// Write all queued tags and add them to the `unclosed_tags` list.
|
||||
fn flush_queue(&mut self) {
|
||||
for tag_name in self.queued_tags.drain(..) {
|
||||
write!(self.buf, "<{tag_name}>").unwrap();
|
||||
write!(self.buf, "<{tag_name}>").expect("infallible string operation");
|
||||
|
||||
self.unclosed_tags.push(tag_name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -916,7 +916,7 @@ fn render_impls(
|
|||
impls: &[&Impl],
|
||||
containing_item: &clean::Item,
|
||||
toggle_open_by_default: bool,
|
||||
) {
|
||||
) -> fmt::Result {
|
||||
let mut rendered_impls = impls
|
||||
.iter()
|
||||
.map(|i| {
|
||||
|
|
@ -942,7 +942,7 @@ fn render_impls(
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
rendered_impls.sort();
|
||||
w.write_str(&rendered_impls.join("")).unwrap();
|
||||
w.write_str(&rendered_impls.join(""))
|
||||
}
|
||||
|
||||
/// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item.
|
||||
|
|
@ -1037,7 +1037,7 @@ fn assoc_const(
|
|||
) -> impl fmt::Display {
|
||||
let tcx = cx.tcx();
|
||||
fmt::from_fn(move |w| {
|
||||
render_attributes_in_code(w, it, &" ".repeat(indent), cx);
|
||||
render_attributes_in_code(w, it, &" ".repeat(indent), cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
|
||||
|
|
@ -1145,10 +1145,10 @@ fn assoc_method(
|
|||
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
|
||||
header_len += 4;
|
||||
let indent_str = " ";
|
||||
render_attributes_in_code(w, meth, indent_str, cx);
|
||||
render_attributes_in_code(w, meth, indent_str, cx)?;
|
||||
(4, indent_str, Ending::NoNewline)
|
||||
} else {
|
||||
render_attributes_in_code(w, meth, "", cx);
|
||||
render_attributes_in_code(w, meth, "", cx)?;
|
||||
(0, "", Ending::Newline)
|
||||
};
|
||||
write!(
|
||||
|
|
@ -1365,10 +1365,10 @@ fn render_all_impls(
|
|||
concrete: &[&Impl],
|
||||
synthetic: &[&Impl],
|
||||
blanket_impl: &[&Impl],
|
||||
) {
|
||||
) -> fmt::Result {
|
||||
let impls = {
|
||||
let mut buf = String::new();
|
||||
render_impls(cx, &mut buf, concrete, containing_item, true);
|
||||
render_impls(cx, &mut buf, concrete, containing_item, true)?;
|
||||
buf
|
||||
};
|
||||
if !impls.is_empty() {
|
||||
|
|
@ -1376,8 +1376,7 @@ fn render_all_impls(
|
|||
w,
|
||||
"{}<div id=\"trait-implementations-list\">{impls}</div>",
|
||||
write_impl_section_heading("Trait Implementations", "trait-implementations")
|
||||
)
|
||||
.unwrap();
|
||||
)?;
|
||||
}
|
||||
|
||||
if !synthetic.is_empty() {
|
||||
|
|
@ -1385,10 +1384,9 @@ fn render_all_impls(
|
|||
w,
|
||||
"{}<div id=\"synthetic-implementations-list\">",
|
||||
write_impl_section_heading("Auto Trait Implementations", "synthetic-implementations",)
|
||||
)
|
||||
.unwrap();
|
||||
render_impls(cx, &mut w, synthetic, containing_item, false);
|
||||
w.write_str("</div>").unwrap();
|
||||
)?;
|
||||
render_impls(cx, &mut w, synthetic, containing_item, false)?;
|
||||
w.write_str("</div>")?;
|
||||
}
|
||||
|
||||
if !blanket_impl.is_empty() {
|
||||
|
|
@ -1396,11 +1394,11 @@ fn render_all_impls(
|
|||
w,
|
||||
"{}<div id=\"blanket-implementations-list\">",
|
||||
write_impl_section_heading("Blanket Implementations", "blanket-implementations")
|
||||
)
|
||||
.unwrap();
|
||||
render_impls(cx, &mut w, blanket_impl, containing_item, false);
|
||||
w.write_str("</div>").unwrap();
|
||||
)?;
|
||||
render_impls(cx, &mut w, blanket_impl, containing_item, false)?;
|
||||
w.write_str("</div>")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_assoc_items(
|
||||
|
|
@ -1412,8 +1410,7 @@ fn render_assoc_items(
|
|||
fmt::from_fn(move |f| {
|
||||
let mut derefs = DefIdSet::default();
|
||||
derefs.insert(it);
|
||||
render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs);
|
||||
Ok(())
|
||||
render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1424,10 +1421,10 @@ fn render_assoc_items_inner(
|
|||
it: DefId,
|
||||
what: AssocItemRender<'_>,
|
||||
derefs: &mut DefIdSet,
|
||||
) {
|
||||
) -> fmt::Result {
|
||||
info!("Documenting associated items of {:?}", containing_item.name);
|
||||
let cache = &cx.shared.cache;
|
||||
let Some(v) = cache.impls.get(&it) else { return };
|
||||
let Some(v) = cache.impls.get(&it) else { return Ok(()) };
|
||||
let (mut non_trait, traits): (Vec<_>, _) =
|
||||
v.iter().partition(|i| i.inner_impl().trait_.is_none());
|
||||
if !non_trait.is_empty() {
|
||||
|
|
@ -1511,8 +1508,7 @@ fn render_assoc_items_inner(
|
|||
matches!(what, AssocItemRender::DerefFor { .. })
|
||||
.then_some("</details>")
|
||||
.maybe_display(),
|
||||
)
|
||||
.unwrap();
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1522,13 +1518,13 @@ fn render_assoc_items_inner(
|
|||
if let Some(impl_) = deref_impl {
|
||||
let has_deref_mut =
|
||||
traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
|
||||
render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs);
|
||||
render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs)?;
|
||||
}
|
||||
|
||||
// If we were already one level into rendering deref methods, we don't want to render
|
||||
// anything after recursing into any further deref methods above.
|
||||
if let AssocItemRender::DerefFor { .. } = what {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||
|
|
@ -1536,8 +1532,9 @@ fn render_assoc_items_inner(
|
|||
let (blanket_impl, concrete): (Vec<&Impl>, _) =
|
||||
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
|
||||
|
||||
render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl);
|
||||
render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `derefs` is the set of all deref targets that have already been handled.
|
||||
|
|
@ -1548,7 +1545,7 @@ fn render_deref_methods(
|
|||
container_item: &clean::Item,
|
||||
deref_mut: bool,
|
||||
derefs: &mut DefIdSet,
|
||||
) {
|
||||
) -> fmt::Result {
|
||||
let cache = cx.cache();
|
||||
let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
|
||||
let (target, real_target) = impl_
|
||||
|
|
@ -1574,15 +1571,16 @@ fn render_deref_methods(
|
|||
// `impl Deref<Target = S> for S`
|
||||
if did == type_did || !derefs.insert(did) {
|
||||
// Avoid infinite cycles
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
|
||||
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs)?;
|
||||
} else if let Some(prim) = target.primitive_type()
|
||||
&& let Some(&did) = cache.primitive_locations.get(&prim)
|
||||
{
|
||||
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
|
||||
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
|
||||
|
|
@ -1805,8 +1803,7 @@ fn render_impl(
|
|||
// because impls can't have a stability.
|
||||
if !item.doc_value().is_empty() {
|
||||
document_item_info(cx, it, Some(parent))
|
||||
.render_into(&mut info_buffer)
|
||||
.unwrap();
|
||||
.render_into(&mut info_buffer)?;
|
||||
doc_buffer = document_full(item, cx, HeadingOffset::H5).to_string();
|
||||
short_documented = false;
|
||||
} else {
|
||||
|
|
@ -1823,9 +1820,7 @@ fn render_impl(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
document_item_info(cx, item, Some(parent))
|
||||
.render_into(&mut info_buffer)
|
||||
.unwrap();
|
||||
document_item_info(cx, item, Some(parent)).render_into(&mut info_buffer)?;
|
||||
if rendering_params.show_def_docs {
|
||||
doc_buffer = document_full(item, cx, HeadingOffset::H5).to_string();
|
||||
short_documented = false;
|
||||
|
|
@ -2920,7 +2915,7 @@ fn render_attributes_in_code(
|
|||
item: &clean::Item,
|
||||
prefix: &str,
|
||||
cx: &Context<'_>,
|
||||
) {
|
||||
) -> fmt::Result {
|
||||
for attr in &item.attrs.other_attrs {
|
||||
let hir::Attribute::Parsed(kind) = attr else { continue };
|
||||
let attr = match kind {
|
||||
|
|
@ -2934,24 +2929,30 @@ fn render_attributes_in_code(
|
|||
AttributeKind::NonExhaustive(..) => Cow::Borrowed("#[non_exhaustive]"),
|
||||
_ => continue,
|
||||
};
|
||||
render_code_attribute(prefix, attr.as_ref(), w);
|
||||
render_code_attribute(prefix, attr.as_ref(), w)?;
|
||||
}
|
||||
|
||||
if let Some(def_id) = item.def_id()
|
||||
&& let Some(repr) = repr_attribute(cx.tcx(), cx.cache(), def_id)
|
||||
{
|
||||
render_code_attribute(prefix, &repr, w);
|
||||
render_code_attribute(prefix, &repr, w)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_repr_attribute_in_code(w: &mut impl fmt::Write, cx: &Context<'_>, def_id: DefId) {
|
||||
fn render_repr_attribute_in_code(
|
||||
w: &mut impl fmt::Write,
|
||||
cx: &Context<'_>,
|
||||
def_id: DefId,
|
||||
) -> fmt::Result {
|
||||
if let Some(repr) = repr_attribute(cx.tcx(), cx.cache(), def_id) {
|
||||
render_code_attribute("", &repr, w);
|
||||
render_code_attribute("", &repr, w)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_code_attribute(prefix: &str, attr: &str, w: &mut impl fmt::Write) {
|
||||
write!(w, "<div class=\"code-attribute\">{prefix}{attr}</div>").unwrap();
|
||||
fn render_code_attribute(prefix: &str, attr: &str, w: &mut impl fmt::Write) -> fmt::Result {
|
||||
write!(w, "<div class=\"code-attribute\">{prefix}{attr}</div>")
|
||||
}
|
||||
|
||||
/// Compute the *public* `#[repr]` of the item given by `DefId`.
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
|
|||
"<dt{id}>\
|
||||
<code>"
|
||||
)?;
|
||||
render_attributes_in_code(w, myitem, "", cx);
|
||||
render_attributes_in_code(w, myitem, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{vis}{imp}</code>{stab_tags}\
|
||||
|
|
@ -625,7 +625,7 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
|
|||
let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display();
|
||||
|
||||
wrap_item(w, |w| {
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{vis}{constness}{asyncness}{safety}{abi}fn \
|
||||
|
|
@ -666,7 +666,7 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
|
|||
|
||||
// Output the trait definition
|
||||
wrap_item(w, |mut w| {
|
||||
render_attributes_in_code(&mut w, it, "", cx);
|
||||
render_attributes_in_code(&mut w, it, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
|
||||
|
|
@ -1240,7 +1240,7 @@ fn item_trait_alias(
|
|||
) -> impl fmt::Display {
|
||||
fmt::from_fn(|w| {
|
||||
wrap_item(w, |w| {
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"trait {name}{generics} = {bounds}{where_clause};",
|
||||
|
|
@ -1268,7 +1268,7 @@ fn item_trait_alias(
|
|||
fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display {
|
||||
fmt::from_fn(|w| {
|
||||
wrap_item(w, |w| {
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{vis}type {name}{generics}{where_clause} = {type_};",
|
||||
|
|
@ -1464,7 +1464,7 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
|
|||
|
||||
fn print_field_attrs(&self, field: &'a clean::Item) -> impl Display {
|
||||
fmt::from_fn(move |w| {
|
||||
render_attributes_in_code(w, field, "", self.cx);
|
||||
render_attributes_in_code(w, field, "", self.cx)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
@ -1554,9 +1554,9 @@ impl<'clean> DisplayEnum<'clean> {
|
|||
wrap_item(w, |w| {
|
||||
if is_type_alias {
|
||||
// For now the only attributes we render for type aliases are `repr` attributes.
|
||||
render_repr_attribute_in_code(w, cx, self.def_id);
|
||||
render_repr_attribute_in_code(w, cx, self.def_id)?;
|
||||
} else {
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
}
|
||||
write!(
|
||||
w,
|
||||
|
|
@ -1695,7 +1695,7 @@ fn render_enum_fields(
|
|||
if v.is_stripped() {
|
||||
continue;
|
||||
}
|
||||
render_attributes_in_code(w, v, TAB, cx);
|
||||
render_attributes_in_code(w, v, TAB, cx)?;
|
||||
w.write_str(TAB)?;
|
||||
match v.kind {
|
||||
clean::VariantItem(ref var) => match var.kind {
|
||||
|
|
@ -1779,7 +1779,7 @@ fn item_variants(
|
|||
)
|
||||
.maybe_display()
|
||||
)?;
|
||||
render_attributes_in_code(w, variant, "", cx);
|
||||
render_attributes_in_code(w, variant, "", cx)?;
|
||||
if let clean::VariantItem(ref var) = variant.kind
|
||||
&& let clean::VariantKind::CLike = var.kind
|
||||
{
|
||||
|
|
@ -1855,7 +1855,7 @@ fn item_variants(
|
|||
<a href=\"#{id}\" class=\"anchor field\">§</a>\
|
||||
<code>"
|
||||
)?;
|
||||
render_attributes_in_code(w, field, "", cx);
|
||||
render_attributes_in_code(w, field, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{f}: {t}</code>\
|
||||
|
|
@ -1881,7 +1881,7 @@ fn item_macro(cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) -> impl fmt:
|
|||
fmt::from_fn(|w| {
|
||||
wrap_item(w, |w| {
|
||||
// FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
if !t.macro_rules {
|
||||
write!(w, "{}", visibility_print_with_space(it, cx))?;
|
||||
}
|
||||
|
|
@ -1927,16 +1927,15 @@ fn item_primitive(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
|
|||
let def_id = it.item_id.expect_def_id();
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
|
||||
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
|
||||
write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All))?;
|
||||
write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All))
|
||||
} else {
|
||||
// We handle the "reference" primitive type on its own because we only want to list
|
||||
// implementations on generic types.
|
||||
let (concrete, synthetic, blanket_impl) =
|
||||
get_filtered_impls_for_reference(&cx.shared, it);
|
||||
|
||||
render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
|
||||
render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl)
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1950,7 +1949,7 @@ fn item_constant(
|
|||
fmt::from_fn(|w| {
|
||||
wrap_item(w, |w| {
|
||||
let tcx = cx.tcx();
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
|
||||
write!(
|
||||
w,
|
||||
|
|
@ -2016,9 +2015,9 @@ impl<'a> DisplayStruct<'a> {
|
|||
wrap_item(w, |w| {
|
||||
if is_type_alias {
|
||||
// For now the only attributes we render for type aliases are `repr` attributes.
|
||||
render_repr_attribute_in_code(w, cx, self.def_id);
|
||||
render_repr_attribute_in_code(w, cx, self.def_id)?;
|
||||
} else {
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
}
|
||||
write!(
|
||||
w,
|
||||
|
|
@ -2097,7 +2096,7 @@ fn item_fields(
|
|||
<code>",
|
||||
item_type = ItemType::StructField,
|
||||
)?;
|
||||
render_attributes_in_code(w, field, "", cx);
|
||||
render_attributes_in_code(w, field, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{field_name}: {ty}</code>\
|
||||
|
|
@ -2120,7 +2119,7 @@ fn item_static(
|
|||
) -> impl fmt::Display {
|
||||
fmt::from_fn(move |w| {
|
||||
wrap_item(w, |w| {
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
write!(
|
||||
w,
|
||||
"{vis}{safe}static {mutability}{name}: {typ}",
|
||||
|
|
@ -2140,8 +2139,8 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
|
|||
fmt::from_fn(|w| {
|
||||
wrap_item(w, |w| {
|
||||
w.write_str("extern {\n")?;
|
||||
render_attributes_in_code(w, it, "", cx);
|
||||
write!(w, " {}type {};\n}}", visibility_print_with_space(it, cx), it.name.unwrap(),)
|
||||
render_attributes_in_code(w, it, "", cx)?;
|
||||
write!(w, " {}type {};\n}}", visibility_print_with_space(it, cx), it.name.unwrap())
|
||||
})?;
|
||||
|
||||
write!(
|
||||
|
|
@ -2292,15 +2291,14 @@ fn print_bounds(
|
|||
.maybe_display()
|
||||
}
|
||||
|
||||
fn wrap_item<W, F, T>(w: &mut W, f: F) -> T
|
||||
fn wrap_item<W, F>(w: &mut W, f: F) -> fmt::Result
|
||||
where
|
||||
W: fmt::Write,
|
||||
F: FnOnce(&mut W) -> T,
|
||||
F: FnOnce(&mut W) -> fmt::Result,
|
||||
{
|
||||
write!(w, r#"<pre class="rust item-decl"><code>"#).unwrap();
|
||||
let res = f(w);
|
||||
write!(w, "</code></pre>").unwrap();
|
||||
res
|
||||
w.write_str(r#"<pre class="rust item-decl"><code>"#)?;
|
||||
f(w)?;
|
||||
w.write_str("</code></pre>")
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
|
|
@ -2370,9 +2368,9 @@ fn render_union(
|
|||
fmt::from_fn(move |mut f| {
|
||||
if is_type_alias {
|
||||
// For now the only attributes we render for type aliases are `repr` attributes.
|
||||
render_repr_attribute_in_code(f, cx, def_id);
|
||||
render_repr_attribute_in_code(f, cx, def_id)?;
|
||||
} else {
|
||||
render_attributes_in_code(f, it, "", cx);
|
||||
render_attributes_in_code(f, it, "", cx)?;
|
||||
}
|
||||
write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;
|
||||
|
||||
|
|
@ -2403,7 +2401,7 @@ fn render_union(
|
|||
|
||||
for field in fields {
|
||||
if let clean::StructFieldItem(ref ty) = field.kind {
|
||||
render_attributes_in_code(&mut f, field, " ", cx);
|
||||
render_attributes_in_code(&mut f, field, " ", cx)?;
|
||||
writeln!(
|
||||
f,
|
||||
" {}{}: {},",
|
||||
|
|
@ -2500,7 +2498,7 @@ fn render_struct_fields(
|
|||
}
|
||||
for field in fields {
|
||||
if let clean::StructFieldItem(ref ty) = field.kind {
|
||||
render_attributes_in_code(w, field, &format!("{tab} "), cx);
|
||||
render_attributes_in_code(w, field, &format!("{tab} "), cx)?;
|
||||
writeln!(
|
||||
w,
|
||||
"{tab} {vis}{name}: {ty},",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
//! or contains "invocation-specific".
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::OsString;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs::File;
|
||||
use std::io::{self, Write as _};
|
||||
use std::iter::once;
|
||||
|
|
@ -84,9 +84,11 @@ pub(crate) fn write_shared(
|
|||
};
|
||||
|
||||
if let Some(parts_out_dir) = &opt.parts_out_dir {
|
||||
create_parents(&parts_out_dir.0)?;
|
||||
let mut parts_out_file = parts_out_dir.0.clone();
|
||||
parts_out_file.push(&format!("{crate_name}.json"));
|
||||
create_parents(&parts_out_file)?;
|
||||
try_err!(
|
||||
fs::write(&parts_out_dir.0, serde_json::to_string(&info).unwrap()),
|
||||
fs::write(&parts_out_file, serde_json::to_string(&info).unwrap()),
|
||||
&parts_out_dir.0
|
||||
);
|
||||
}
|
||||
|
|
@ -238,13 +240,25 @@ impl CrateInfo {
|
|||
pub(crate) fn read_many(parts_paths: &[PathToParts]) -> Result<Vec<Self>, Error> {
|
||||
parts_paths
|
||||
.iter()
|
||||
.map(|parts_path| {
|
||||
let path = &parts_path.0;
|
||||
let parts = try_err!(fs::read(path), &path);
|
||||
let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path);
|
||||
Ok::<_, Error>(parts)
|
||||
.fold(Ok(Vec::new()), |acc, parts_path| {
|
||||
let mut acc = acc?;
|
||||
let dir = &parts_path.0;
|
||||
acc.append(&mut try_err!(std::fs::read_dir(dir), dir.as_path())
|
||||
.filter_map(|file| {
|
||||
let to_crate_info = |file: Result<std::fs::DirEntry, std::io::Error>| -> Result<Option<CrateInfo>, Error> {
|
||||
let file = try_err!(file, dir.as_path());
|
||||
if file.path().extension() != Some(OsStr::new("json")) {
|
||||
return Ok(None);
|
||||
}
|
||||
let parts = try_err!(fs::read(file.path()), file.path());
|
||||
let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), file.path());
|
||||
Ok(Some(parts))
|
||||
};
|
||||
to_crate_info(file).transpose()
|
||||
})
|
||||
.collect::<Result<Vec<CrateInfo>, Error>>()?);
|
||||
Ok(acc)
|
||||
})
|
||||
.collect::<Result<Vec<CrateInfo>, Error>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,6 @@ directories = "6"
|
|||
bitflags = "2.6"
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
|
||||
# Copied from `compiler/rustc/Cargo.toml`.
|
||||
# But only for some targets, it fails for others. Rustc configures this in its CI, but we can't
|
||||
# easily use that since we support of-tree builds.
|
||||
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.tikv-jemalloc-sys]
|
||||
version = "0.6.1"
|
||||
features = ['override_allocator_on_supported_platforms']
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
# native-lib dependencies
|
||||
|
|
@ -75,6 +68,7 @@ stack-cache = []
|
|||
expensive-consistency-checks = ["stack-cache"]
|
||||
tracing = ["serde_json"]
|
||||
native-lib = ["dep:libffi", "dep:libloading", "dep:capstone", "dep:ipc-channel", "dep:nix", "dep:serde"]
|
||||
jemalloc = []
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
level = "warn"
|
||||
|
|
|
|||
|
|
@ -21,9 +21,13 @@ extern crate rustc_session;
|
|||
extern crate rustc_span;
|
||||
|
||||
/// See docs in https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc/src/main.rs
|
||||
/// and https://github.com/rust-lang/rust/pull/146627 for why we need this `use` statement.
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
use tikv_jemalloc_sys as _;
|
||||
/// and https://github.com/rust-lang/rust/pull/146627 for why we need this.
|
||||
///
|
||||
/// FIXME(madsmtm): This is loaded from the sysroot that was built with the other `rustc` crates
|
||||
/// above, instead of via Cargo as you'd normally do. This is currently needed for LTO due to
|
||||
/// https://github.com/rust-lang/cc-rs/issues/1613.
|
||||
#[cfg(feature = "jemalloc")]
|
||||
extern crate tikv_jemalloc_sys as _;
|
||||
|
||||
mod log;
|
||||
|
||||
|
|
|
|||
4
tests/run-make/rustdoc-merge-directory/dep1.rs
Normal file
4
tests/run-make/rustdoc-merge-directory/dep1.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
//@ hasraw crates.js 'dep1'
|
||||
//@ hasraw search.index/name/*.js 'Dep1'
|
||||
//@ has dep1/index.html
|
||||
pub struct Dep1;
|
||||
4
tests/run-make/rustdoc-merge-directory/dep2.rs
Normal file
4
tests/run-make/rustdoc-merge-directory/dep2.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
//@ hasraw crates.js 'dep1'
|
||||
//@ hasraw search.index/name/*.js 'Dep1'
|
||||
//@ has dep2/index.html
|
||||
pub struct Dep2;
|
||||
4
tests/run-make/rustdoc-merge-directory/dep_missing.rs
Normal file
4
tests/run-make/rustdoc-merge-directory/dep_missing.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
//@ !hasraw crates.js 'dep_missing'
|
||||
//@ !hasraw search.index/name/*.js 'DepMissing'
|
||||
//@ has dep_missing/index.html
|
||||
pub struct DepMissing;
|
||||
46
tests/run-make/rustdoc-merge-directory/rmake.rs
Normal file
46
tests/run-make/rustdoc-merge-directory/rmake.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Running --merge=finalize without an input crate root should not trigger ICE.
|
||||
// Issue: https://github.com/rust-lang/rust/issues/146646
|
||||
|
||||
//@ needs-target-std
|
||||
|
||||
use run_make_support::{htmldocck, path, rustdoc};
|
||||
|
||||
fn main() {
|
||||
let out_dir = path("out");
|
||||
let merged_dir = path("merged");
|
||||
let parts_out_dir = path("parts");
|
||||
|
||||
rustdoc()
|
||||
.input("dep1.rs")
|
||||
.out_dir(&out_dir)
|
||||
.arg("-Zunstable-options")
|
||||
.arg(format!("--parts-out-dir={}", parts_out_dir.display()))
|
||||
.arg("--merge=none")
|
||||
.run();
|
||||
assert!(parts_out_dir.join("dep1.json").exists());
|
||||
|
||||
rustdoc()
|
||||
.input("dep2.rs")
|
||||
.out_dir(&out_dir)
|
||||
.arg("-Zunstable-options")
|
||||
.arg(format!("--parts-out-dir={}", parts_out_dir.display()))
|
||||
.arg("--merge=none")
|
||||
.run();
|
||||
assert!(parts_out_dir.join("dep2.json").exists());
|
||||
|
||||
// dep_missing is different, because --parts-out-dir is not supplied
|
||||
rustdoc().input("dep_missing.rs").out_dir(&out_dir).run();
|
||||
assert!(parts_out_dir.join("dep2.json").exists());
|
||||
|
||||
let output = rustdoc()
|
||||
.arg("-Zunstable-options")
|
||||
.out_dir(&out_dir)
|
||||
.arg(format!("--include-parts-dir={}", parts_out_dir.display()))
|
||||
.arg("--merge=finalize")
|
||||
.run();
|
||||
output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug.");
|
||||
|
||||
htmldocck().arg(&out_dir).arg("dep1.rs").run();
|
||||
htmldocck().arg(&out_dir).arg("dep2.rs").run();
|
||||
htmldocck().arg(out_dir).arg("dep_missing.rs").run();
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ fn main() {
|
|||
.arg(format!("--parts-out-dir={}", parts_out_dir.display()))
|
||||
.arg("--merge=none")
|
||||
.run();
|
||||
assert!(parts_out_dir.join("crate-info").exists());
|
||||
assert!(parts_out_dir.join("sierra.json").exists());
|
||||
|
||||
let output = rustdoc()
|
||||
.arg("-Zunstable-options")
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ LL | enum Helper<T, U> {
|
|||
LL | T(T, [!; 0]),
|
||||
| - not covered
|
||||
= note: the matched value is of type `Helper<T, U>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Helper::U(u) = Helper::T(t, []) else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ LL | let Some(y) = x;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `Option<i32>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Some(y) = x else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ LL | let Ok(_x) = &foo();
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `&Result<u32, !>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(_x) = &foo() else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `[i32; 8]`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `[i32; 8]`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -3,18 +3,27 @@ error: out of range hex escape
|
|||
|
|
||||
LL | let x = "\x80";
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\x80'`
|
||||
= help: if you want to write a Unicode character, use `'\u{80}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/ascii-only-character-escape.rs:3:14
|
||||
|
|
||||
LL | let y = "\xff";
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\xff'`
|
||||
= help: if you want to write a Unicode character, use `'\u{FF}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/ascii-only-character-escape.rs:4:14
|
||||
|
|
||||
LL | let z = "\xe2";
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\xe2'`
|
||||
= help: if you want to write a Unicode character, use `'\u{E2}'`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
fn main() {
|
||||
let _c = '\xFF'; //~ ERROR out of range hex escape
|
||||
let _s = "\xFF"; //~ ERROR out of range hex escape
|
||||
|
||||
let _c2 = '\xff'; //~ ERROR out of range hex escape
|
||||
let _s2 = "\xff"; //~ ERROR out of range hex escape
|
||||
|
||||
let _c3 = '\x80'; //~ ERROR out of range hex escape
|
||||
let _s3 = "\x80"; //~ ERROR out of range hex escape
|
||||
|
||||
// Byte literals should not get suggestions (they're already valid)
|
||||
let _b = b'\xFF'; // OK
|
||||
let _bs = b"\xFF"; // OK
|
||||
|
||||
dbg!('\xFF'); //~ ERROR out of range hex escape
|
||||
|
||||
// do not suggest for out of range escapes that are too long
|
||||
dbg!("\xFFFFF"); //~ ERROR out of range hex escape
|
||||
|
||||
dbg!("this is some kind of string \xa7"); //~ ERROR out of range hex escape
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:2:15
|
||||
|
|
||||
LL | let _c = '\xFF';
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\xFF'`
|
||||
= help: if you want to write a Unicode character, use `'\u{FF}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:3:15
|
||||
|
|
||||
LL | let _s = "\xFF";
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\xFF'`
|
||||
= help: if you want to write a Unicode character, use `'\u{FF}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:5:16
|
||||
|
|
||||
LL | let _c2 = '\xff';
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\xff'`
|
||||
= help: if you want to write a Unicode character, use `'\u{FF}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:6:16
|
||||
|
|
||||
LL | let _s2 = "\xff";
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\xff'`
|
||||
= help: if you want to write a Unicode character, use `'\u{FF}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:8:16
|
||||
|
|
||||
LL | let _c3 = '\x80';
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\x80'`
|
||||
= help: if you want to write a Unicode character, use `'\u{80}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:9:16
|
||||
|
|
||||
LL | let _s3 = "\x80";
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\x80'`
|
||||
= help: if you want to write a Unicode character, use `'\u{80}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:15:11
|
||||
|
|
||||
LL | dbg!('\xFF');
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
|
||||
= help: if you want to write a byte literal, use `b'\xFF'`
|
||||
= help: if you want to write a Unicode character, use `'\u{FF}'`
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:18:11
|
||||
|
|
||||
LL | dbg!("\xFFFFF");
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
||||
error: out of range hex escape
|
||||
--> $DIR/out-of-range-hex-escape-suggestions-148917.rs:20:39
|
||||
|
|
||||
LL | dbg!("this is some kind of string \xa7");
|
||||
| ^^^^ must be a character in the range [\x00-\x7f]
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ LL | let x @ 5 = 6;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `i32`
|
||||
help: you might want to use `let else` to handle the variants that aren't matched
|
||||
help: you might want to use `let...else` to handle the variants that aren't matched
|
||||
|
|
||||
LL | let x @ 5 = 6 else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ LL | let Ok(_x) = res_u32_never.as_ref();
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `Result<&u32, &!>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ LL | let Ok(_x) = res_u32_never.as_ref();
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `Result<&u32, &!>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
@ -120,7 +120,7 @@ LL | let Ok(_x) = &res_u32_never;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `&Result<u32, !>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(_x) = &res_u32_never else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ LL | let Ok(_x) = res_u32_never.as_ref();
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `Result<&u32, &!>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
@ -111,7 +111,7 @@ LL | let Ok(_x) = &res_u32_never;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `&Result<u32, !>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(_x) = &res_u32_never else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ LL | Bar,
|
|||
LL | Baz
|
||||
| --- not covered
|
||||
= note: the matched value is of type `Thing`
|
||||
help: you might want to use `let else` to handle the variants that aren't matched
|
||||
help: you might want to use `let...else` to handle the variants that aren't matched
|
||||
|
|
||||
LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ LL | enum Opt {
|
|||
LL | None,
|
||||
| ---- not covered
|
||||
= note: the matched value is of type `Opt`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Opt::Some(ref _x) = e else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ LL | let Ok(x) = res;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `Result<u32, &R<'_>>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(x) = res else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `NonExhaustiveEnum`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ fn a() {
|
|||
}
|
||||
fn b() {
|
||||
let Some(x) = foo() { //~ ERROR expected one of
|
||||
//~^ HELP you might have meant to use `let else`
|
||||
//~^ HELP you might have meant to use `let...else`
|
||||
return;
|
||||
}
|
||||
}
|
||||
fn c() {
|
||||
let Some(x) = foo() { //~ ERROR expected one of
|
||||
//~^ HELP you might have meant to use `if let`
|
||||
//~| HELP alternatively, you might have meant to use `let else`
|
||||
//~| HELP alternatively, you might have meant to use `let...else`
|
||||
// The parser check happens pre-macro-expansion, so we don't know for sure.
|
||||
println!("{x}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `{`
|
|||
LL | let Some(x) = foo() {
|
||||
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
|
||||
|
|
||||
help: you might have meant to use `let else`
|
||||
help: you might have meant to use `let...else`
|
||||
|
|
||||
LL | let Some(x) = foo() else {
|
||||
| ++++
|
||||
|
|
@ -30,7 +30,7 @@ help: you might have meant to use `if let`
|
|||
|
|
||||
LL | if let Some(x) = foo() {
|
||||
| ++
|
||||
help: alternatively, you might have meant to use `let else`
|
||||
help: alternatively, you might have meant to use `let...else`
|
||||
|
|
||||
LL | let Some(x) = foo() else {
|
||||
| ++++
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ LL | A(foo::SecretlyEmpty),
|
|||
| - not covered
|
||||
= note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
|
||||
= note: the matched value is of type `Foo`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Foo::D(_y, _z) = x else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ LL | A(foo::SecretlyEmpty),
|
|||
| - not covered
|
||||
= note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
|
||||
= note: the matched value is of type `Foo`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
help: you might want to use `let...else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Foo::D(_y, _z) = x else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ fn main() {
|
|||
//~| NOTE for more information
|
||||
//~| NOTE pattern `Foo::A(_)` is currently uninhabited
|
||||
//~| NOTE the matched value is of type `Foo`
|
||||
//~| HELP you might want to use `let else`
|
||||
//~| HELP you might want to use `let...else`
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue