Rollup merge of #149252 - madsmtm:miri-jemalloc, r=RalfJung miri: use `tikv-jemalloc-sys` from sysroot This allows LTO to work when compiling jemalloc (which is currently broken due to https://github.com/rust-lang/cc-rs/issues/1613), which should yield a small performance boost, and makes Miri's behaviour here match Clippy and Rustdoc. Follow-up to https://github.com/rust-lang/rust/pull/148925 / https://github.com/rust-lang/rust/pull/146627 after discussion in https://github.com/rust-lang/rust/pull/148925#pullrequestreview-3465393783. r? RalfJung
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 876297d..3092c6e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs
@@ -589,13 +589,13 @@ fn for_each_relevant_impl( | ty::Never | ty::Tuple(_) | ty::UnsafeBinder(_) => { - let simp = ty::fast_reject::simplify_type( + if let Some(simp) = ty::fast_reject::simplify_type( tcx, self_ty, ty::fast_reject::TreatParams::AsRigid, - ) - .unwrap(); - consider_impls_for_simplified_type(simp); + ) { + consider_impls_for_simplified_type(simp); + } } // HACK: For integer and float variables we have to manually look at all impls
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index c74333f..7055e60 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl
@@ -732,8 +732,6 @@ 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
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index bde179c..62a333f 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs
@@ -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]
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index ec59a1a..895374a 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -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();
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index b33ccba..44177d4 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl
@@ -126,6 +126,14 @@ passes_doc_alias_start_end = {$attr_str} cannot start or end with ' ' +passes_doc_attr_expects_no_value = + `doc({$attr_name})` does not accept a value + .suggestion = use `doc({$attr_name})` + +passes_doc_attr_expects_string = + `doc({$attr_name})` expects a string value + .suggestion = use `doc({$attr_name} = "...")` + passes_doc_attr_not_crate_level = `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 30bb7d6..58e5521 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1123,6 +1123,28 @@ fn check_attr_crate_level( true } + fn check_doc_attr_string_value(&self, meta: &MetaItemInner, hir_id: HirId) { + if meta.value_str().is_none() { + self.tcx.emit_node_span_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + errors::DocAttrExpectsString { attr_name: meta.name().unwrap() }, + ); + } + } + + fn check_doc_attr_no_value(&self, meta: &MetaItemInner, hir_id: HirId) { + if !meta.is_word() { + self.tcx.emit_node_span_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + errors::DocAttrExpectsNoValue { attr_name: meta.name().unwrap() }, + ); + } + } + /// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place. fn check_test_attr( &self, @@ -1293,10 +1315,15 @@ fn check_doc_attrs( | sym::html_logo_url | sym::html_playground_url | sym::issue_tracker_base_url - | sym::html_root_url - | sym::html_no_source, + | sym::html_root_url, ) => { self.check_attr_crate_level(attr_span, style, meta, hir_id); + self.check_doc_attr_string_value(meta, hir_id); + } + + Some(sym::html_no_source) => { + self.check_attr_crate_level(attr_span, style, meta, hir_id); + self.check_doc_attr_no_value(meta, hir_id); } Some(sym::auto_cfg) => {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index ed4cf77..e4826cc 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs
@@ -24,6 +24,18 @@ #[diag(passes_incorrect_do_not_recommend_args)] pub(crate) struct DoNotRecommendDoesNotExpectArgs; +#[derive(LintDiagnostic)] +#[diag(passes_doc_attr_expects_string)] +pub(crate) struct DocAttrExpectsString { + pub(crate) attr_name: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(passes_doc_attr_expects_no_value)] +pub(crate) struct DocAttrExpectsNoValue { + pub(crate) attr_name: Symbol, +} + #[derive(Diagnostic)] #[diag(passes_autodiff_attr)] pub(crate) struct AutoDiffAttr {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 13d38d3..6f587df 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs
@@ -433,6 +433,8 @@ #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Vec"] #[rustc_insignificant_dtor] +#[doc(alias = "list")] +#[doc(alias = "vector")] pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> { buf: RawVec<T, A>, len: usize,
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index a26ae7d..08465ea 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md
@@ -197,6 +197,37 @@ 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>
diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands index 508296c..eff065d 100644 --- a/src/etc/lldb_commands +++ b/src/etc/lldb_commands
@@ -1,6 +1,5 @@ # Forces test-compliant formatting to all other types type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust -type summary add -F _ -e -x -h "^.*$" --category Rust # Std String type synthetic add -l lldb_lookup.StdStringSyntheticProvider -x "^(alloc::([a-z_]+::)+)String$" --category Rust type summary add -F lldb_lookup.StdStringSummaryProvider -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust @@ -66,6 +65,7 @@ type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust # Enum +# type summary add -F lldb_lookup.ClangEncodedEnumSummaryProvider -e -h "lldb_lookup.is_sum_type_enum" --recognizer-function --category Rust ## MSVC type synthetic add -l lldb_lookup.MSVCEnumSyntheticProvider -x "^enum2\$<.+>$" --category Rust type summary add -F lldb_lookup.MSVCEnumSummaryProvider -e -x -h "^enum2\$<.+>$" --category Rust @@ -74,6 +74,7 @@ type summary add -F lldb_lookup.summary_lookup -e -x -h "^enum2\$<.+>::.*$" --category Rust # Tuple type synthetic add -l lldb_lookup.synthetic_lookup -x "^\(.*\)$" --category Rust +type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^\(.*\)$" --category Rust ## MSVC type synthetic add -l lldb_lookup.MSVCTupleSyntheticProvider -x "^tuple\$<.+>$" --category Rust type summary add -F lldb_lookup.TupleSummaryProvider -e -x -h "^tuple\$<.+>$" --category Rust
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py index f43d2c6..2b90d40 100644 --- a/src/etc/lldb_lookup.py +++ b/src/etc/lldb_lookup.py
@@ -10,9 +10,6 @@ def classify_rust_type(type: lldb.SBType) -> str: - if type.IsPointerType(): - type = type.GetPointeeType() - type_class = type.GetTypeClass() if type_class == lldb.eTypeClassStruct: return classify_struct(type.name, type.fields) @@ -88,6 +85,26 @@ if rust_type == RustType.SINGLETON_ENUM: return synthetic_lookup(valobj.GetChildAtIndex(0), _dict) if rust_type == RustType.ENUM: + # this little trick lets us treat `synthetic_lookup` as a "recognizer function" for the enum + # summary providers, reducing the number of lookups we have to do. This is a huge time save + # because there's no way (via type name) to recognize sum-type enums on `*-gnu` targets. The + # alternative would be to shove every single type through `summary_lookup`, which is + # incredibly wasteful. Once these scripts are updated for LLDB 19.0 and we can use + # `--recognizer-function`, this hack will only be needed for backwards compatibility. + summary: lldb.SBTypeSummary = valobj.GetTypeSummary() + if ( + summary.summary_data is None + or summary.summary_data.strip() + != "lldb_lookup.ClangEncodedEnumSummaryProvider(valobj,internal_dict)" + ): + rust_category: lldb.SBTypeCategory = lldb.debugger.GetCategory("Rust") + rust_category.AddTypeSummary( + lldb.SBTypeNameSpecifier(valobj.GetTypeName()), + lldb.SBTypeSummary().CreateWithFunctionName( + "lldb_lookup.ClangEncodedEnumSummaryProvider" + ), + ) + return ClangEncodedEnumProvider(valobj, _dict) if rust_type == RustType.STD_VEC: return StdVecSyntheticProvider(valobj, _dict)
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 13c66ee..5824716 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py
@@ -1,7 +1,6 @@ from __future__ import annotations -import re import sys -from typing import List, TYPE_CHECKING, Generator +from typing import Generator, List, TYPE_CHECKING from lldb import ( SBData, @@ -12,6 +11,8 @@ eFormatChar, ) +from rust_types import is_tuple_fields + if TYPE_CHECKING: from lldb import SBValue, SBType, SBTypeStaticField, SBTarget @@ -206,6 +207,34 @@ return result +def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: + # structs need the field name before the field value + output = ( + f"{valobj.GetChildAtIndex(i).GetName()}:{child}" + for i, child in enumerate(aggregate_field_summary(valobj, _dict)) + ) + + return "{" + ", ".join(output) + "}" + + +def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque): + return "(" + ", ".join(aggregate_field_summary(valobj, _dict)) + ")" + + +def aggregate_field_summary(valobj: SBValue, _dict) -> Generator[str, None, None]: + for i in range(0, valobj.GetNumChildren()): + child: SBValue = valobj.GetChildAtIndex(i) + summary = child.summary + if summary is None: + summary = child.value + if summary is None: + if is_tuple_fields(child): + summary = TupleSummaryProvider(child, _dict) + else: + summary = StructSummaryProvider(child, _dict) + yield summary + + def SizeSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: return "size=" + str(valobj.GetNumChildren()) @@ -454,49 +483,55 @@ return "&str" -def _getVariantName(variant) -> str: +def _getVariantName(variant: SBValue) -> str: """ Since the enum variant's type name is in the form `TheEnumName::TheVariantName$Variant`, we can extract `TheVariantName` from it for display purpose. """ s = variant.GetType().GetName() - match = re.search(r"::([^:]+)\$Variant$", s) - return match.group(1) if match else "" + if not s.endswith("$Variant"): + return "" + + # trim off path and "$Variant" + # len("$Variant") == 8 + return s.rsplit("::", 1)[1][:-8] class ClangEncodedEnumProvider: """Pretty-printer for 'clang-encoded' enums support implemented in LLDB""" + valobj: SBValue + variant: SBValue + value: SBValue + DISCRIMINANT_MEMBER_NAME = "$discr$" VALUE_MEMBER_NAME = "value" + __slots__ = ("valobj", "variant", "value") + def __init__(self, valobj: SBValue, _dict: LLDBOpaque): self.valobj = valobj self.update() def has_children(self) -> bool: - return True + return self.value.MightHaveChildren() def num_children(self) -> int: - return 1 + return self.value.GetNumChildren() - def get_child_index(self, _name: str) -> int: - return -1 + def get_child_index(self, name: str) -> int: + return self.value.GetIndexOfChildWithName(name) def get_child_at_index(self, index: int) -> SBValue: - if index == 0: - value = self.variant.GetChildMemberWithName( - ClangEncodedEnumProvider.VALUE_MEMBER_NAME - ) - return value.CreateChildAtOffset( - _getVariantName(self.variant), 0, value.GetType() - ) - return None + return self.value.GetChildAtIndex(index) def update(self): all_variants = self.valobj.GetChildAtIndex(0) index = self._getCurrentVariantIndex(all_variants) self.variant = all_variants.GetChildAtIndex(index) + self.value = self.variant.GetChildMemberWithName( + ClangEncodedEnumProvider.VALUE_MEMBER_NAME + ).GetSyntheticValue() def _getCurrentVariantIndex(self, all_variants: SBValue) -> int: default_index = 0 @@ -514,6 +549,23 @@ return default_index +def ClangEncodedEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: + enum_synth = ClangEncodedEnumProvider(valobj.GetNonSyntheticValue(), _dict) + variant = enum_synth.variant + name = _getVariantName(variant) + + if valobj.GetNumChildren() == 0: + return name + + child_name: str = valobj.GetChildAtIndex(0).name + if child_name == "0" or child_name == "__0": + # enum variant is a tuple struct + return name + TupleSummaryProvider(valobj, _dict) + else: + # enum variant is a regular struct + return name + StructSummaryProvider(valobj, _dict) + + class MSVCEnumSyntheticProvider: """ Synthetic provider for sum-type enums on MSVC. For a detailed explanation of the internals, @@ -522,12 +574,14 @@ https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs """ + valobj: SBValue + variant: SBValue + value: SBValue + __slots__ = ["valobj", "variant", "value"] def __init__(self, valobj: SBValue, _dict: LLDBOpaque): self.valobj = valobj - self.variant: SBValue - self.value: SBValue self.update() def update(self): @@ -695,21 +749,6 @@ return name -def StructSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: - output = [] - for i in range(valobj.GetNumChildren()): - child: SBValue = valobj.GetChildAtIndex(i) - summary = child.summary - if summary is None: - summary = child.value - if summary is None: - summary = StructSummaryProvider(child, _dict) - summary = child.GetName() + ":" + summary - output.append(summary) - - return "{" + ", ".join(output) + "}" - - def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: enum_synth = MSVCEnumSyntheticProvider(valobj.GetNonSyntheticValue(), _dict) variant_names: SBType = valobj.target.FindFirstType( @@ -826,21 +865,6 @@ return "(" + name + ")" -def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque): - output: List[str] = [] - - for i in range(0, valobj.GetNumChildren()): - child: SBValue = valobj.GetChildAtIndex(i) - summary = child.summary - if summary is None: - summary = child.value - if summary is None: - summary = "{...}" - output.append(summary) - - return "(" + ", ".join(output) + ")" - - class StdVecSyntheticProvider: """Pretty-printer for alloc::vec::Vec<T>
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index da19f50..5d16dff 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs
@@ -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 @@ fn from_flag(path: String) -> Result<PathToParts, String> { )) } 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); }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index dd91cec..eee13ff 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs
@@ -1252,9 +1252,9 @@ fn write_str(&mut self, s: &str) -> fmt::Result { 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(()) } }
diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs index fdb1ddc..f786215 100644 --- a/src/librustdoc/html/length_limit.rs +++ b/src/librustdoc/html/length_limit.rs
@@ -87,7 +87,7 @@ pub(super) fn open_tag(&mut self, tag_name: &'static str) { 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 @@ pub(super) fn close_tag(&mut self) { /// 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); }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 871ed53..9c8e599 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs
@@ -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 doc_impl_item( // 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 doc_impl_item( } } } 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`.
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index fa7c9e7..0c51173 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs
@@ -457,7 +457,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering { "<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 @@ fn render_union(&self) -> impl Display { 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 @@ fn render_into<W: fmt::Write>( 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 @@ fn render_into<W: fmt::Write>( 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},",
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 6045b9a..8b6776f 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs
@@ -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>>() } }
diff --git a/tests/debuginfo/basic-types-globals.rs b/tests/debuginfo/basic-types-globals.rs index 6e41508..b56a710 100644 --- a/tests/debuginfo/basic-types-globals.rs +++ b/tests/debuginfo/basic-types-globals.rs
@@ -13,7 +13,7 @@ // lldb-command:v I // lldb-check: ::I = -1 // lldb-command:v --format=d C -// lldb-check: ::C = 97 +// lldb-check: ::C = 97 U+0x00000061 U'a' // lldb-command:v --format=d I8 // lldb-check: ::I8 = 68 // lldb-command:v I16
diff --git a/tests/debuginfo/borrowed-enum.rs b/tests/debuginfo/borrowed-enum.rs index 48dce13..f376917 100644 --- a/tests/debuginfo/borrowed-enum.rs +++ b/tests/debuginfo/borrowed-enum.rs
@@ -23,11 +23,11 @@ // lldb-command:run // lldb-command:v *the_a_ref -// lldb-check:(borrowed_enum::ABC) *the_a_ref = { TheA = { x = 0 y = 8970181431921507452 } } +// lldb-check:(borrowed_enum::ABC) *the_a_ref = TheA{x:0, y:8970181431921507452} { x = 0 y = 8970181431921507452 } // lldb-command:v *the_b_ref -// lldb-check:(borrowed_enum::ABC) *the_b_ref = { TheB = { 0 = 0 1 = 286331153 2 = 286331153 } } +// lldb-check:(borrowed_enum::ABC) *the_b_ref = TheB(0, 286331153, 286331153) { 0 = 0 1 = 286331153 2 = 286331153 } // lldb-command:v *univariant_ref -// lldb-check:(borrowed_enum::Univariant) *univariant_ref = { TheOnlyCase = { 0 = 4820353753753434 } } +// lldb-check:(borrowed_enum::Univariant) *univariant_ref = TheOnlyCase(4820353753753434) { 0 = 4820353753753434 } #![allow(unused_variables)]
diff --git a/tests/debuginfo/c-style-enum-in-composite.rs b/tests/debuginfo/c-style-enum-in-composite.rs index dd5e4f8..137cb26 100644 --- a/tests/debuginfo/c-style-enum-in-composite.rs +++ b/tests/debuginfo/c-style-enum-in-composite.rs
@@ -35,7 +35,7 @@ // lldb-check:[...] { 0 = 0 1 = OneHundred } // lldb-command:v tuple_padding_at_end -// lldb-check:[...] { 0 = { 0 = 1 1 = OneThousand } 1 = 2 } +// lldb-check:[...] ((1, OneThousand), 2) { 0 = (1, OneThousand) { 0 = 1 1 = OneThousand } 1 = 2 } // lldb-command:v tuple_different_enums // lldb-check:[...] { 0 = OneThousand 1 = MountainView 2 = OneMillion 3 = Vienna }
diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs index f1165de..b9d015e 100644 --- a/tests/debuginfo/coroutine-objects.rs +++ b/tests/debuginfo/coroutine-objects.rs
@@ -27,7 +27,7 @@ // lldb-command:run // lldb-command:v b -// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = { value = { _ref__a = 0x[...] } $discr$ = [...] } +// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = 0{_ref__a:0x[...]} { _ref__a = 0x[...] } // === CDB TESTS ===================================================================================
diff --git a/tests/debuginfo/enum-thinlto.rs b/tests/debuginfo/enum-thinlto.rs index 7897554..9b77b1d 100644 --- a/tests/debuginfo/enum-thinlto.rs +++ b/tests/debuginfo/enum-thinlto.rs
@@ -15,7 +15,7 @@ // lldb-command:run // lldb-command:v *abc -// lldb-check:(enum_thinlto::ABC) *abc = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } +// lldb-check:(enum_thinlto::ABC) *abc = TheA{x:0, y:8970181431921507452} { x = 0 y = 8970181431921507452 } #![allow(unused_variables)]
diff --git a/tests/debuginfo/generic-method-on-generic-struct.rs b/tests/debuginfo/generic-method-on-generic-struct.rs index c549a14..9c1d87a 100644 --- a/tests/debuginfo/generic-method-on-generic-struct.rs +++ b/tests/debuginfo/generic-method-on-generic-struct.rs
@@ -58,7 +58,7 @@ // STACK BY REF // lldb-command:v *self -// lldb-check:[...] { x = { 0 = 8888 1 = -8888 } } +// lldb-check:[...] { x = (8888, -8888) { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 // lldb-check:[...] -1 // lldb-command:v arg2 @@ -67,7 +67,7 @@ // STACK BY VAL // lldb-command:v self -// lldb-check:[...] { x = { 0 = 8888 1 = -8888 } } +// lldb-check:[...] { x = (8888, -8888) { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 // lldb-check:[...] -3 // lldb-command:v arg2
diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs index 59c0759..aa829df 100644 --- a/tests/debuginfo/issue-57822.rs +++ b/tests/debuginfo/issue-57822.rs
@@ -24,7 +24,7 @@ // lldb-check:(issue_57822::main::{closure_env#1}) g = { f = { x = 1 } } // lldb-command:v b -// lldb-check:(issue_57822::main::{coroutine_env#3}) b = { value = { a = { value = { y = 2 } $discr$ = '\x02' } } $discr$ = '\x02' } +// lldb-check:(issue_57822::main::{coroutine_env#3}) b = 2{a:2{y:2}} { a = 2{y:2} { y = 2 } } #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
diff --git a/tests/debuginfo/method-on-generic-struct.rs b/tests/debuginfo/method-on-generic-struct.rs index b9627f2..01e7ffc 100644 --- a/tests/debuginfo/method-on-generic-struct.rs +++ b/tests/debuginfo/method-on-generic-struct.rs
@@ -58,7 +58,7 @@ // STACK BY REF // lldb-command:v *self -// lldb-check:[...]Struct<(u32, i32)>) *self = { x = { 0 = 8888 1 = -8888 } } +// lldb-check:[...]Struct<(u32, i32)>) *self = { x = (8888, -8888) { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 // lldb-check:[...] -1 // lldb-command:v arg2 @@ -67,7 +67,7 @@ // STACK BY VAL // lldb-command:v self -// lldb-check:[...]Struct<(u32, i32)>) self = { x = { 0 = 8888 1 = -8888 } } +// lldb-check:[...]Struct<(u32, i32)>) self = { x = (8888, -8888) { 0 = 8888 1 = -8888 } } // lldb-command:v arg1 // lldb-check:[...] -3 // lldb-command:v arg2
diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs index aa6629e..7d9f867 100644 --- a/tests/debuginfo/msvc-pretty-enums.rs +++ b/tests/debuginfo/msvc-pretty-enums.rs
@@ -1,3 +1,4 @@ +//@ only-msvc //@ min-lldb-version: 1800 //@ ignore-gdb //@ compile-flags:-g
diff --git a/tests/debuginfo/option-like-enum.rs b/tests/debuginfo/option-like-enum.rs index 5a55b14..0e41997 100644 --- a/tests/debuginfo/option-like-enum.rs +++ b/tests/debuginfo/option-like-enum.rs
@@ -40,31 +40,31 @@ // lldb-command:run // lldb-command:v some -// lldb-check:[...] Some(&0x[...]) +// lldb-check:[...] Some(0x[...]) { 0 = 0x[...] } // lldb-command:v none // lldb-check:[...] None // lldb-command:v full -// lldb-check:[...] Full(454545, &0x[...], 9988) +// lldb-check:[...] Full(454545, 0x[...], 9988) { 0 = 454545 1 = 0x[...] 2 = 9988 } // lldb-command:v empty // lldb-check:[...] Empty // lldb-command:v droid -// lldb-check:[...] Droid { id: 675675, range: 10000001, internals: &0x[...] } +// lldb-check:[...] Droid{id:675675, range:10000001, internals:0x[...]} { id = 675675 range = 10000001 internals = 0x[...] } // lldb-command:v void_droid // lldb-check:[...] Void // lldb-command:v some_str -// lldb-check:[...] Some("abc") +// lldb-check:[...] Some("abc") [...] // lldb-command:v none_str // lldb-check:[...] None // lldb-command:v nested_non_zero_yep -// lldb-check:[...] Yep(10.5, NestedNonZeroField { a: 10, b: 20, c: &[...] }) +// lldb-check:[...] Yep(10.5, {a:10, b:20, c:[...]}) { 0 = 10.5 1 = { a = 10 b = 20 c = [...] } } // lldb-command:v nested_non_zero_nope // lldb-check:[...] Nope
diff --git a/tests/debuginfo/pretty-std-collections.rs b/tests/debuginfo/pretty-std-collections.rs index 568ca0f..3592122 100644 --- a/tests/debuginfo/pretty-std-collections.rs +++ b/tests/debuginfo/pretty-std-collections.rs
@@ -59,7 +59,7 @@ // lldb-check:[...] size=7 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 } // lldb-command:v hash_map -// lldb-check:[...] size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } } +// lldb-check:[...] size=4 { [0] = (1, 10) { 0 = 1 1 = 10 } [1] = (2, 20) { 0 = 2 1 = 20 } [2] = (3, 30) { 0 = 3 1 = 30 } [3] = (4, 40) { 0 = 4 1 = 40 } } // lldb-command:v hash_set // lldb-check:[...] size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }
diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 392cf69..baeebda 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs
@@ -31,15 +31,14 @@ // lldb-check:(&str) plain_str = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } // lldb-command:v str_in_struct -// lldb-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } +// lldb-check:(strings_and_strs::Foo) str_in_struct = { inner = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } // lldb-command:v str_in_tuple -// lldb-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } +// lldb-check:((&str, &str)) str_in_tuple = ("Hello", "World") { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } // lldb-command:v str_in_rc // lldb-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } - #![allow(unused_variables)] pub struct Foo<'a> {
diff --git a/tests/debuginfo/struct-in-enum.rs b/tests/debuginfo/struct-in-enum.rs index bd61e7c..640066b 100644 --- a/tests/debuginfo/struct-in-enum.rs +++ b/tests/debuginfo/struct-in-enum.rs
@@ -24,12 +24,13 @@ // lldb-command:run // lldb-command:v case1 -// lldb-check:[...] Case1(0, Struct { x: 2088533116, y: 2088533116, z: 31868 }) +// lldb-check:[...] Case1(0, {x:2088533116, y:2088533116, z:31868}) { 0 = 0 1 = { x = 2088533116 y = 2088533116 z = 31868 } } + // lldb-command:v case2 -// lldb-check:[...] Case2(0, 1229782938247303441, 4369) +// lldb-check:[...] Case2(0, 1229782938247303441, 4369) { 0 = 0 1 = 1229782938247303441 2 = 4369 } // lldb-command:v univariant -// lldb-check:[...] TheOnlyCase(Struct { x: 123, y: 456, z: 789 }) +// lldb-check:[...] TheOnlyCase({x:123, y:456, z:789}) { 0 = { x = 123 y = 456 z = 789 } } #![allow(unused_variables)]
diff --git a/tests/debuginfo/struct-style-enum.rs b/tests/debuginfo/struct-style-enum.rs index 48ef978..4bbd879 100644 --- a/tests/debuginfo/struct-style-enum.rs +++ b/tests/debuginfo/struct-style-enum.rs
@@ -26,16 +26,16 @@ // lldb-command:run // lldb-command:v case1 -// lldb-check:(struct_style_enum::Regular) case1 = { value = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } $discr$ = 0 } +// lldb-check:(struct_style_enum::Regular) case1 = Case1{a:0, b:31868, c:31868, d:31868, e:31868} { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } // lldb-command:v case2 -// lldb-check:(struct_style_enum::Regular) case2 = { value = { a = 0 b = 286331153 c = 286331153 } $discr$ = 1 } +// lldb-check:(struct_style_enum::Regular) case2 = Case2{a:0, b:286331153, c:286331153} { a = 0 b = 286331153 c = 286331153 } // lldb-command:v case3 -// lldb-check:(struct_style_enum::Regular) case3 = { value = { a = 0 b = 6438275382588823897 } $discr$ = 2 } +// lldb-check:(struct_style_enum::Regular) case3 = Case3{a:0, b:6438275382588823897} { a = 0 b = 6438275382588823897 } // lldb-command:v univariant -// lldb-check:(struct_style_enum::Univariant) univariant = { value = { a = -1 } } +// lldb-check:(struct_style_enum::Univariant) univariant = TheOnlyCase{a:-1} { a = -1 } #![allow(unused_variables)]
diff --git a/tests/debuginfo/tuple-in-tuple.rs b/tests/debuginfo/tuple-in-tuple.rs index e906cbe..40e88f1 100644 --- a/tests/debuginfo/tuple-in-tuple.rs +++ b/tests/debuginfo/tuple-in-tuple.rs
@@ -29,21 +29,21 @@ // lldb-command:run // lldb-command:v no_padding1 -// lldb-check:[...] { 0 = { 0 = 0 1 = 1 } 1 = 2 2 = 3 } +// lldb-check:[...] ((0, 1), 2, 3) { 0 = (0, 1) { 0 = 0 1 = 1 } 1 = 2 2 = 3 } // lldb-command:v no_padding2 -// lldb-check:[...] { 0 = 4 1 = { 0 = 5 1 = 6 } 2 = 7 } +// lldb-check:[...] (4, (5, 6), 7) { 0 = 4 1 = (5, 6) { 0 = 5 1 = 6 } 2 = 7 } // lldb-command:v no_padding3 -// lldb-check:[...] { 0 = 8 1 = 9 2 = { 0 = 10 1 = 11 } } +// lldb-check:[...] (8, 9, (10, 11)) { 0 = 8 1 = 9 2 = (10, 11) { 0 = 10 1 = 11 } } // lldb-command:v internal_padding1 -// lldb-check:[...] { 0 = 12 1 = { 0 = 13 1 = 14 } } +// lldb-check:[...] (12, (13, 14)) { 0 = 12 1 = (13, 14) { 0 = 13 1 = 14 } } // lldb-command:v internal_padding2 -// lldb-check:[...] { 0 = 15 1 = { 0 = 16 1 = 17 } } +// lldb-check:[...] (15, (16, 17)) { 0 = 15 1 = (16, 17) { 0 = 16 1 = 17 } } // lldb-command:v padding_at_end1 -// lldb-check:[...] { 0 = 18 1 = { 0 = 19 1 = 20 } } +// lldb-check:[...] (18, (19, 20)) { 0 = 18 1 = (19, 20) { 0 = 19 1 = 20 } } // lldb-command:v padding_at_end2 -// lldb-check:[...] { 0 = { 0 = 21 1 = 22 } 1 = 23 } +// lldb-check:[...] ((21, 22), 23) { 0 = (21, 22) { 0 = 21 1 = 22 } 1 = 23 } // === CDB TESTS ==================================================================================
diff --git a/tests/debuginfo/tuple-style-enum.rs b/tests/debuginfo/tuple-style-enum.rs index a452c57..6568a2f 100644 --- a/tests/debuginfo/tuple-style-enum.rs +++ b/tests/debuginfo/tuple-style-enum.rs
@@ -27,16 +27,16 @@ // lldb-command:run // lldb-command:v case1 -// lldb-check:(tuple_style_enum::Regular) case1 = { value = { 0 = 0 1 = 31868 2 = 31868 3 = 31868 4 = 31868 } $discr$ = 0 } +// lldb-check:(tuple_style_enum::Regular) case1 = Case1(0, 31868, 31868, 31868, 31868) { 0 = 0 1 = 31868 2 = 31868 3 = 31868 4 = 31868 } // lldb-command:v case2 -// lldb-check:(tuple_style_enum::Regular) case2 = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } +// lldb-check:(tuple_style_enum::Regular) case2 = Case2(0, 286331153, 286331153) { 0 = 0 1 = 286331153 2 = 286331153 } // lldb-command:v case3 -// lldb-check:(tuple_style_enum::Regular) case3 = { value = { 0 = 0 1 = 6438275382588823897 } $discr$ = 2 } +// lldb-check:(tuple_style_enum::Regular) case3 = Case3(0, 6438275382588823897) { 0 = 0 1 = 6438275382588823897 } // lldb-command:v univariant -// lldb-check:(tuple_style_enum::Univariant) univariant = { value = { 0 = -1 } } +// lldb-check:(tuple_style_enum::Univariant) univariant = TheOnlyCase(-1) { 0 = -1 } #![allow(unused_variables)]
diff --git a/tests/debuginfo/union-smoke.rs b/tests/debuginfo/union-smoke.rs index beaf4c8..be6a9d5 100644 --- a/tests/debuginfo/union-smoke.rs +++ b/tests/debuginfo/union-smoke.rs
@@ -14,10 +14,10 @@ // lldb-command:run // lldb-command:v u -// lldb-check:[...] { a = { 0 = '\x02' 1 = '\x02' } b = 514 } +// lldb-check:[...] { a = ('\x02', '\x02') { 0 = '\x02' 1 = '\x02' } b = 514 } // lldb-command:print union_smoke::SU -// lldb-check:[...] { a = { 0 = '\x01' 1 = '\x01' } b = 257 } +// lldb-check:[...] { a = ('\x01', '\x01') { 0 = '\x01' 1 = '\x01' } b = 257 } #![allow(unused)]
diff --git a/tests/debuginfo/unique-enum.rs b/tests/debuginfo/unique-enum.rs index a9b9284..6a742f9 100644 --- a/tests/debuginfo/unique-enum.rs +++ b/tests/debuginfo/unique-enum.rs
@@ -23,13 +23,13 @@ // lldb-command:run // lldb-command:v *the_a -// lldb-check:(unique_enum::ABC) *the_a = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } +// lldb-check:(unique_enum::ABC) *the_a = TheA{x:0, y:8970181431921507452} { x = 0 y = 8970181431921507452 } // lldb-command:v *the_b -// lldb-check:(unique_enum::ABC) *the_b = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } +// lldb-check:(unique_enum::ABC) *the_b = TheB(0, 286331153, 286331153) { 0 = 0 1 = 286331153 2 = 286331153 } // lldb-command:v *univariant -// lldb-check:(unique_enum::Univariant) *univariant = { value = { 0 = 123234 } } +// lldb-check:(unique_enum::Univariant) *univariant = TheOnlyCase(123234) { 0 = 123234 } #![allow(unused_variables)]
diff --git a/tests/debuginfo/vec-slices.rs b/tests/debuginfo/vec-slices.rs index 7ed6b0c..fdfc701 100644 --- a/tests/debuginfo/vec-slices.rs +++ b/tests/debuginfo/vec-slices.rs
@@ -67,7 +67,7 @@ // lldb-check:[...] size=2 { [0] = 3 [1] = 4 } // lldb-command:v padded_tuple -// lldb-check:[...] size=2 { [0] = { 0 = 6 1 = 7 } [1] = { 0 = 8 1 = 9 } } +// lldb-check:[...] size=2 { [0] = (6, 7) { 0 = 6 1 = 7 } [1] = (8, 9) { 0 = 8 1 = 9 } } // lldb-command:v padded_struct // lldb-check:[...] size=2 { [0] = { x = 10 y = 11 z = 12 } [1] = { x = 13 y = 14 z = 15 } }
diff --git a/tests/run-make/rustdoc-merge-directory/dep1.rs b/tests/run-make/rustdoc-merge-directory/dep1.rs new file mode 100644 index 0000000..5a1238a --- /dev/null +++ b/tests/run-make/rustdoc-merge-directory/dep1.rs
@@ -0,0 +1,4 @@ +//@ hasraw crates.js 'dep1' +//@ hasraw search.index/name/*.js 'Dep1' +//@ has dep1/index.html +pub struct Dep1;
diff --git a/tests/run-make/rustdoc-merge-directory/dep2.rs b/tests/run-make/rustdoc-merge-directory/dep2.rs new file mode 100644 index 0000000..238ff2e --- /dev/null +++ b/tests/run-make/rustdoc-merge-directory/dep2.rs
@@ -0,0 +1,4 @@ +//@ hasraw crates.js 'dep1' +//@ hasraw search.index/name/*.js 'Dep1' +//@ has dep2/index.html +pub struct Dep2;
diff --git a/tests/run-make/rustdoc-merge-directory/dep_missing.rs b/tests/run-make/rustdoc-merge-directory/dep_missing.rs new file mode 100644 index 0000000..74236ae --- /dev/null +++ b/tests/run-make/rustdoc-merge-directory/dep_missing.rs
@@ -0,0 +1,4 @@ +//@ !hasraw crates.js 'dep_missing' +//@ !hasraw search.index/name/*.js 'DepMissing' +//@ has dep_missing/index.html +pub struct DepMissing;
diff --git a/tests/run-make/rustdoc-merge-directory/rmake.rs b/tests/run-make/rustdoc-merge-directory/rmake.rs new file mode 100644 index 0000000..e4695dd --- /dev/null +++ b/tests/run-make/rustdoc-merge-directory/rmake.rs
@@ -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(); +}
diff --git a/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs index d750a36..4dad01f 100644 --- a/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs +++ b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs
@@ -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")
diff --git a/tests/rustdoc-ui/bad-render-options.rs b/tests/rustdoc-ui/bad-render-options.rs new file mode 100644 index 0000000..f2cfd4b --- /dev/null +++ b/tests/rustdoc-ui/bad-render-options.rs
@@ -0,0 +1,11 @@ +// regression test for https://github.com/rust-lang/rust/issues/149187 + +#![doc(html_favicon_url)] //~ ERROR: `doc(html_favicon_url)` expects a string value [invalid_doc_attributes] +#![doc(html_logo_url)] //~ ERROR: `doc(html_logo_url)` expects a string value [invalid_doc_attributes] +#![doc(html_playground_url)] //~ ERROR: `doc(html_playground_url)` expects a string value [invalid_doc_attributes] +#![doc(issue_tracker_base_url)] //~ ERROR expects a string value +#![doc(html_favicon_url = 1)] //~ ERROR expects a string value +#![doc(html_logo_url = 2)] //~ ERROR expects a string value +#![doc(html_playground_url = 3)] //~ ERROR expects a string value +#![doc(issue_tracker_base_url = 4)] //~ ERROR expects a string value +#![doc(html_no_source = "asdf")] //~ ERROR `doc(html_no_source)` does not accept a value [invalid_doc_attributes]
diff --git a/tests/rustdoc-ui/bad-render-options.stderr b/tests/rustdoc-ui/bad-render-options.stderr new file mode 100644 index 0000000..9d50336 --- /dev/null +++ b/tests/rustdoc-ui/bad-render-options.stderr
@@ -0,0 +1,58 @@ +error: `doc(html_favicon_url)` expects a string value + --> $DIR/bad-render-options.rs:3:8 + | +LL | #![doc(html_favicon_url)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[deny(invalid_doc_attributes)]` on by default + +error: `doc(html_logo_url)` expects a string value + --> $DIR/bad-render-options.rs:4:8 + | +LL | #![doc(html_logo_url)] + | ^^^^^^^^^^^^^ + +error: `doc(html_playground_url)` expects a string value + --> $DIR/bad-render-options.rs:5:8 + | +LL | #![doc(html_playground_url)] + | ^^^^^^^^^^^^^^^^^^^ + +error: `doc(issue_tracker_base_url)` expects a string value + --> $DIR/bad-render-options.rs:6:8 + | +LL | #![doc(issue_tracker_base_url)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `doc(html_favicon_url)` expects a string value + --> $DIR/bad-render-options.rs:7:8 + | +LL | #![doc(html_favicon_url = 1)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: `doc(html_logo_url)` expects a string value + --> $DIR/bad-render-options.rs:8:8 + | +LL | #![doc(html_logo_url = 2)] + | ^^^^^^^^^^^^^^^^^ + +error: `doc(html_playground_url)` expects a string value + --> $DIR/bad-render-options.rs:9:8 + | +LL | #![doc(html_playground_url = 3)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: `doc(issue_tracker_base_url)` expects a string value + --> $DIR/bad-render-options.rs:10:8 + | +LL | #![doc(issue_tracker_base_url = 4)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `doc(html_no_source)` does not accept a value + --> $DIR/bad-render-options.rs:11:8 + | +LL | #![doc(html_no_source = "asdf")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors +
diff --git a/tests/ui/dyn-compatibility/no-duplicate-e0038.rs b/tests/ui/dyn-compatibility/no-duplicate-e0038.rs new file mode 100644 index 0000000..2831645 --- /dev/null +++ b/tests/ui/dyn-compatibility/no-duplicate-e0038.rs
@@ -0,0 +1,17 @@ +// Test that E0038 is not emitted twice for the same trait object coercion +// regression test for issue <https://github.com/rust-lang/rust/issues/128705> + +#![allow(dead_code)] + +trait Tr { + const N: usize; +} + +impl Tr for u8 { + const N: usize = 1; +} + +fn main() { + let x: &dyn Tr = &0_u8; + //~^ ERROR E0038 +}
diff --git a/tests/ui/dyn-compatibility/no-duplicate-e0038.stderr b/tests/ui/dyn-compatibility/no-duplicate-e0038.stderr new file mode 100644 index 0000000..9403738 --- /dev/null +++ b/tests/ui/dyn-compatibility/no-duplicate-e0038.stderr
@@ -0,0 +1,20 @@ +error[E0038]: the trait `Tr` is not dyn compatible + --> $DIR/no-duplicate-e0038.rs:15:17 + | +LL | let x: &dyn Tr = &0_u8; + | ^^ `Tr` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/no-duplicate-e0038.rs:7:11 + | +LL | trait Tr { + | -- this trait is not dyn compatible... +LL | const N: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `N` to another trait + = help: only type `u8` implements `Tr`; consider using it directly instead. + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/parser/ascii-only-character-escape.stderr b/tests/ui/parser/ascii-only-character-escape.stderr index b599b35..78844ae 100644 --- a/tests/ui/parser/ascii-only-character-escape.stderr +++ b/tests/ui/parser/ascii-only-character-escape.stderr
@@ -3,18 +3,27 @@ | 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
diff --git a/tests/ui/parser/out-of-range-hex-escape-suggestions-148917.rs b/tests/ui/parser/out-of-range-hex-escape-suggestions-148917.rs new file mode 100644 index 0000000..ee8489f --- /dev/null +++ b/tests/ui/parser/out-of-range-hex-escape-suggestions-148917.rs
@@ -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 +}
diff --git a/tests/ui/parser/out-of-range-hex-escape-suggestions-148917.stderr b/tests/ui/parser/out-of-range-hex-escape-suggestions-148917.stderr new file mode 100644 index 0000000..e0485bf --- /dev/null +++ b/tests/ui/parser/out-of-range-hex-escape-suggestions-148917.stderr
@@ -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 +
diff --git a/tests/ui/traits/dispatch-from-dyn-blanket-impl.rs b/tests/ui/traits/dispatch-from-dyn-blanket-impl.rs new file mode 100644 index 0000000..4e0e7ca --- /dev/null +++ b/tests/ui/traits/dispatch-from-dyn-blanket-impl.rs
@@ -0,0 +1,10 @@ +// Test that blanket impl of DispatchFromDyn is rejected. +// regression test for issue <https://github.com/rust-lang/rust/issues/148062> + +#![feature(dispatch_from_dyn)] + +impl<T> std::ops::DispatchFromDyn<T> for T {} +//~^ ERROR type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) +//~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures + +fn main() {}
diff --git a/tests/ui/traits/dispatch-from-dyn-blanket-impl.stderr b/tests/ui/traits/dispatch-from-dyn-blanket-impl.stderr new file mode 100644 index 0000000..69f3608 --- /dev/null +++ b/tests/ui/traits/dispatch-from-dyn-blanket-impl.stderr
@@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) + --> $DIR/dispatch-from-dyn-blanket-impl.rs:6:6 + | +LL | impl<T> std::ops::DispatchFromDyn<T> for T {} + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0377]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures + --> $DIR/dispatch-from-dyn-blanket-impl.rs:6:1 + | +LL | impl<T> std::ops::DispatchFromDyn<T> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0210, E0377. +For more information about an error, try `rustc --explain E0210`.