Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
905a7e0
Track placeholder assumptions for created universes
Dnreikronos Jul 16, 2026
8211f90
Add coverage for placeholder assumption ICE
Dnreikronos Jul 16, 2026
74c230e
ci: Enable autodiff tests on x86_64 linux
sgasho Jul 10, 2026
4ee71fe
docs: add autodiff CI job document
sgasho Jul 19, 2026
4e53ac1
Add allow_list checking for eii implementation attributes
chenyukang Jul 14, 2026
f68af89
rdg: Move Autodiff CI job below performance testing
sgasho Jul 21, 2026
2bb8a3b
Delete autodiff.sh and move the test command to the Dockerfile
sgasho Jul 21, 2026
7372202
Make some parser structured suggestions verbose
estebank Jul 21, 2026
1b7ae04
Tweak code and diagnostic formatting and messages
estebank Jul 21, 2026
6860c6b
Drop redundant canonical universe assumptions
Dnreikronos Jul 22, 2026
0eb2348
Keep cfg predicate in `CfgAttrTrace` so it can be used by rustdoc
GuillaumeGomez Jul 22, 2026
9d0c58d
Retrieve `cfg_attr` information for derived impls for rustdoc `doc_cf…
GuillaumeGomez Jul 22, 2026
35c57b5
Add regression test for `doc_cfg` feature on derive impl blocks
GuillaumeGomez Jul 22, 2026
ed30e03
Update `AttributeKind::CfgAttrTrace` variant usage in `clippy`
GuillaumeGomez Jul 22, 2026
b1342c9
constify vec![1, 2, 3] macro arm functions
Lars-Schumann Jul 22, 2026
7f88868
Extend `cfg_attr` retrieval for all impls, including ones without the…
GuillaumeGomez Jul 22, 2026
f9d9939
make `DocLinkResMap` an `FxIndexMap`
jprochazk Jul 22, 2026
5c012f5
Promote riscv64-unknown-linux-musl to tier 2 with host tools
eshattow May 28, 2026
3086aff
don't build riscv64gc-unknown-linux-musl twice
marcoieni Jul 21, 2026
e3712ee
x test cargo-miri: run all subcrate tests as well
RalfJung Jul 22, 2026
2af4af2
update download-ci-llvm-stamp
marcoieni Jul 23, 2026
219d6bb
Filter derive impls earlier on
GuillaumeGomez Jul 23, 2026
7e294a5
Fix `tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs` test
GuillaumeGomez Jul 23, 2026
5ad773b
fix(lld): route version mismatch warnings to linker_info on macOS
r3v5 Jul 23, 2026
220fbca
Avoid spurious rebuilds of JSON docs in bootstrap
Kobzol Jul 23, 2026
7395449
reuse regular exported_non_generic_symbols logic in Miri
RalfJung Jul 22, 2026
fe37a8a
Update bootstrap to use -Zembed-metadata=no instead of -Zno-embed-met…
dpaoliello Jul 23, 2026
2b73c57
Rollup merge of #159765 - Kobzol:bootstrap-docs-json-rebuild, r=Mark-…
jhpratt Jul 24, 2026
0dedada
Rollup merge of #159781 - dpaoliello:noembed, r=Kobzol
jhpratt Jul 24, 2026
5c606dc
Rollup merge of #158362 - Dnreikronos:trait_solver/placeholder_univer…
jhpratt Jul 24, 2026
c1cebea
Rollup merge of #159173 - chenyukang:yukang-fix-159015-no-mangle-eii,…
jhpratt Jul 24, 2026
b420be6
Rollup merge of #159718 - jprochazk:doc-link-res-index-map, r=petroch…
jhpratt Jul 24, 2026
ecef7c5
Rollup merge of #159722 - GuillaumeGomez:cfg_attr-doc_cfg, r=petroche…
jhpratt Jul 24, 2026
498189d
Rollup merge of #159740 - RalfJung:miri-dedup-exported-symbols, r=bjorn3
jhpratt Jul 24, 2026
2afc0b9
Rollup merge of #155795 - Lars-Schumann:const-vec-macro, r=oli-obk
jhpratt Jul 24, 2026
14e4c53
Rollup merge of #157776 - sgasho:linux_autodiff_tests_ci, r=ZuseZ4
jhpratt Jul 24, 2026
ee7e42a
Rollup merge of #158766 - eshattow:linux-musl-riscv64-ci, r=marcoieni
jhpratt Jul 24, 2026
5d22729
Rollup merge of #159666 - r3v5:fix-llvm-ld64-lld-linker-stderr-warnin…
jhpratt Jul 24, 2026
fb08e9b
Rollup merge of #159667 - estebank:verbose-parse-suggestions, r=TaKO8Ki
jhpratt Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3514,7 +3514,7 @@ pub enum SyntheticAttr {
/// because they are not needed.
///
/// The attribute is used by some clippy lints.
CfgAttrTrace,
CfgAttrTrace(CfgEntry),
}

impl AttrItem {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl AttributeExt for Attribute {
use SyntheticAttr::*;
match &self.kind {
AttrKind::Normal(normal) => normal.item.name(),
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) => None,
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace(_)) => None,
AttrKind::DocComment(..) => None,
}
}
Expand All @@ -117,7 +117,7 @@ impl AttributeExt for Attribute {
AttrKind::Normal(normal) => {
Some(normal.item.path.segments.iter().map(|i| i.ident.name).collect())
}
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) => None,
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace(_)) => None,
AttrKind::DocComment(_, _) => None,
}
}
Expand Down
48 changes: 46 additions & 2 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ impl<'a> AstValidator<'a> {
[sym::allow, sym::deny, sym::expect, sym::forbid, sym::splat, sym::warn];
!attr.has_any_name(&arr) && rustc_attr_parsing::is_builtin_attr(&normal.item)
}
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) => false,
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace(_)) => false,
AttrKind::DocComment(..) => true,
})
.for_each(|attr| {
Expand Down Expand Up @@ -1202,6 +1202,48 @@ impl<'a> AstValidator<'a> {
self.visit_vis(vis);
self.visit_ident(ident);
}

// Check EII implementation attributes against an allowlist.
fn check_eii_impl_attrs(&self, attrs: &[Attribute], eii_impls: &[EiiImpl]) {
if eii_impls.is_empty() {
return;
}

let allowed_attrs: &[Symbol] = &[
sym::allow,
sym::warn,
sym::deny,
sym::forbid,
sym::expect,
sym::doc,
sym::inline,
sym::cold,
sym::optimize,
sym::coverage,
sym::sanitize,
sym::must_use,
sym::deprecated,
];

for attr in attrs {
let AttrKind::Normal(normal) = &attr.kind else {
continue;
};
if attr.has_any_name(allowed_attrs) {
continue;
}

let attr_name = pprust::path_to_string(&normal.item.path);
for eii_impl in eii_impls {
self.dcx().emit_err(diagnostics::EiiImplAttributeNotSupported {
attr_span: attr.span,
attr_name: &attr_name,
eii_span: eii_impl.span,
eii_name: pprust::path_to_string(&eii_impl.eii_macro_path),
});
}
}
}
}

/// Checks that generic parameters are in the correct order,
Expand Down Expand Up @@ -1391,6 +1433,7 @@ impl Visitor<'_> for AstValidator<'_> {
for EiiImpl { eii_macro_path, .. } in eii_impls {
self.visit_path(eii_macro_path);
}
self.check_eii_impl_attrs(&item.attrs, eii_impls);

let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
if body.is_none() && !is_intrinsic && !self.is_sdylib_interface {
Expand Down Expand Up @@ -1566,8 +1609,9 @@ impl Visitor<'_> for AstValidator<'_> {

visit::walk_item(self, item);
}
ItemKind::Static(StaticItem { expr, safety, .. }) => {
ItemKind::Static(StaticItem { expr, safety, eii_impls, .. }) => {
self.check_item_safety(item.span, *safety);
self.check_eii_impl_attrs(&item.attrs, eii_impls);
if matches!(safety, Safety::Unsafe(_)) {
self.dcx().emit_err(diagnostics::UnsafeStatic { span: item.span });
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_ast_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,17 @@ pub(crate) struct FnParamForbiddenAttr {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("`#[{$eii_name}]` is not allowed to have `#[{$attr_name}]`")]
pub(crate) struct EiiImplAttributeNotSupported<'a> {
#[primary_span]
pub attr_span: Span,
pub attr_name: &'a str,
pub eii_name: String,
#[label("`#[{$eii_name}]` is not allowed to have `#[{$attr_name}]`")]
pub eii_span: Span,
}

#[derive(Diagnostic)]
#[diag("`self` parameter is only allowed in associated functions")]
#[note("associated functions are those in `impl` or `trait` definitions")]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool {
use ast::SyntheticAttr::*;
match attr.kind {
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) => {
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace(_)) => {
// These are internal synthetic attributes with no syntax, so avoid printing them
// to keep the printed code reasonably parse-able.
return false;
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_attr_parsing/src/synthetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ pub(crate) struct SyntheticAttrState {
cfg_trace: ThinVec<(CfgEntry, Span)>,

/// Attribute state for `SyntheticAttr::CfgAttrTrace` attributes.
/// The arguments of these attributes is no longer relevant for any later passes, only their
/// presence. So we discard the arguments here.
cfg_attr_trace: bool,
cfg_attr_trace: ThinVec<(CfgEntry, Span)>,
}

impl SyntheticAttrState {
Expand All @@ -33,8 +31,10 @@ impl SyntheticAttrState {
cfg.lower_spans(lower_span);
self.cfg_trace.push((cfg, attr_span));
}
SyntheticAttr::CfgAttrTrace => {
self.cfg_attr_trace = true;
SyntheticAttr::CfgAttrTrace(cfg) => {
let mut cfg = cfg.clone();
cfg.lower_spans(lower_span);
self.cfg_attr_trace.push((cfg, attr_span));
}
}
}
Expand All @@ -43,8 +43,8 @@ impl SyntheticAttrState {
if !self.cfg_trace.is_empty() {
attributes.push(Attribute::Parsed(AttributeKind::CfgTrace(self.cfg_trace)));
}
if self.cfg_attr_trace {
attributes.push(Attribute::Parsed(AttributeKind::CfgAttrTrace));
if !self.cfg_attr_trace.is_empty() {
attributes.push(Attribute::Parsed(AttributeKind::CfgAttrTrace(self.cfg_attr_trace)));
}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
use ast::SyntheticAttr::*;
match &attr.kind {
AttrKind::Normal(_) => {}
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) | AttrKind::DocComment(..) => return,
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace(_)) | AttrKind::DocComment(..) => return,
}

let builtin_attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name));
Expand Down
13 changes: 0 additions & 13 deletions compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,6 @@ index 2e16f2cf27..3ac3df99a8 100644
# Add RUSTFLAGS_BOOTSTRAP to RUSTFLAGS for bootstrap compilation.
# Note that RUSTFLAGS_BOOTSTRAP should always be added to the end of
# RUSTFLAGS, since that causes RUSTFLAGS_BOOTSTRAP to override RUSTFLAGS.
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 6de70c7d70c..d5035b581ce 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -1197,7 +1197,7 @@ fn cargo(
cargo.env("RUSTC_BOOTSTRAP", "1");

if matches!(mode, Mode::Std) {
- cargo.arg("-Zno-embed-metadata");
+ cargo.arg("-Zembed-metadata=no");
}

if self.config.dump_bootstrap_shims {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index bc68bfe396..00143ef3ed 100644
--- a/src/bootstrap/src/core/config/config.rs
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -884,9 +884,9 @@ fn is_msvc_link_exe(sess: &Session) -> bool {
&& linker_path.to_str() == Some("link.exe")
}

fn is_macos_ld(sess: &Session) -> bool {
fn is_macos_linker(sess: &Session) -> bool {
let (_, flavor) = linker_and_flavor(sess);
sess.target.is_like_darwin && matches!(flavor, LinkerFlavor::Darwin(_, Lld::No))
sess.target.is_like_darwin && matches!(flavor, LinkerFlavor::Darwin(..))
}

fn is_windows_gnu_ld(sess: &Session) -> bool {
Expand Down Expand Up @@ -953,8 +953,8 @@ fn report_linker_output(
*output += "\r\n"
}
});
} else if is_macos_ld(sess) {
info!("inferred macOS LD");
} else if is_macos_linker(sess) {
info!("inferred macOS linker");

// FIXME: Tracked by https://github.com/rust-lang/rust/issues/136113
let deployment_mismatch = |line: &str| {
Expand All @@ -967,6 +967,8 @@ fn report_linker_output(
&& line.contains("building for")
&& line.contains("but linking with")
&& line.contains("which was built for newer version"))
// lld (ld64.lld / rust-lld):
|| line.contains("which is newer than target minimum of")
};
// FIXME: This is a real warning we would like to show, but it hits too many crates
// to want to turn it on immediately.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ mod symbol_edit;
pub mod symbol_export;
pub mod write;

pub use symbol_export::{exported_non_generic_symbols_helper, reachable_non_generics_helper};

/// The target triple depends on the deployment target, and is required to
/// enable features such as cross-language LTO, and for picking the right
/// Mach-O commands.
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
return Default::default();
}

reachable_non_generics_helper(tcx)
}

/// Exposed separately *without* the "should codegen" check so Miri can access it.
pub fn reachable_non_generics_helper(tcx: TyCtxt<'_>) -> DefIdMap<SymbolExportInfo> {
let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);

let mut reachable_non_generics: DefIdMap<_> = tcx
Expand Down Expand Up @@ -176,6 +181,13 @@ fn exported_non_generic_symbols_provider_local<'tcx>(
return &[];
}

exported_non_generic_symbols_helper(tcx)
}

/// Exposed separately *without* the "should codegen" check so Miri can access it.
pub fn exported_non_generic_symbols_helper<'tcx>(
tcx: TyCtxt<'tcx>,
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
// FIXME: Sorting this is unnecessary since we are sorting later anyway.
// Can we skip the later sorting?
let sorted = tcx.with_stable_hashing_context(|mut hcx| {
Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::iter;

use rustc_ast::attr::data_structures::CfgEntry;
use rustc_ast::token::{Delimiter, Token, TokenKind};
use rustc_ast::tokenstream::{
AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree, WithTokens,
Expand Down Expand Up @@ -248,16 +249,15 @@ impl<'a> StripUnconfigured<'a> {
/// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect.
pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
// A synthetic trace attribute left in AST in place of the original `cfg_attr` attribute.
// It can later be used by lints or other diagnostics.
let trace_attr = cfg_attr.clone().convert_normal_to_synthetic(SyntheticAttr::CfgAttrTrace);

let Some((cfg_predicate, expanded_attrs)) = rustc_attr_parsing::parse_cfg_attr(
cfg_attr,
self.sess,
self.features,
self.lint_node_id,
) else {
let trace_attr = cfg_attr.clone().convert_normal_to_synthetic(
SyntheticAttr::CfgAttrTrace(CfgEntry::Bool(true, cfg_attr.span)),
);
return vec![trace_attr];
};

Expand All @@ -271,7 +271,15 @@ impl<'a> StripUnconfigured<'a> {
);
}

if !attr::eval_config_entry(self.sess, &cfg_predicate).as_bool() {
let cfg_eval = attr::eval_config_entry(self.sess, &cfg_predicate).as_bool();

// A synthetic trace attribute left in AST in place of the original `cfg_attr` attribute.
// It can later be used by lints or other diagnostics.
let trace_attr = cfg_attr
.clone()
.convert_normal_to_synthetic(SyntheticAttr::CfgAttrTrace(cfg_predicate));

if !cfg_eval {
return vec![trace_attr];
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2276,7 +2276,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
);
}
AttrKind::Normal(_) => {}
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace) => {}
AttrKind::Synthetic(CfgTrace(_) | CfgAttrTrace(_)) => {}
AttrKind::DocComment(..) => unreachable!(), // handled above
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ pub enum AttributeKind {
AutomaticallyDerived,

/// Represents the trace attribute of `#[cfg_attr]`
CfgAttrTrace,
CfgAttrTrace(ThinVec<(CfgEntry, Span)>),

/// Represents the trace attribute of `#[cfg]`
CfgTrace(ThinVec<(CfgEntry, Span)>),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl AttributeKind {
AllowInternalUnsafe(..) => Yes,
AllowInternalUnstable(..) => Yes,
AutomaticallyDerived => Yes,
CfgAttrTrace => Yes,
CfgAttrTrace(..) => Yes,
CfgTrace(..) => Yes,
CfiEncoding { .. } => Yes,
Cold => No,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::fmt::Debug;

use rustc_ast as ast;
use rustc_ast::NodeId;
use rustc_data_structures::unord::UnordMap;
use rustc_data_structures::fx::FxIndexMap;
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
use rustc_macros::{Decodable, Encodable, StableHash};
use rustc_span::Symbol;
Expand Down Expand Up @@ -962,4 +962,6 @@ pub enum LifetimeRes {
ElidedAnchor { start: NodeId, end: NodeId },
}

pub type DocLinkResMap = UnordMap<(Symbol, Namespace), Option<Res<NodeId>>>;
// FxIndexMap is necessary because its data ends up in .rmeta files,
// so its iteration order must be consistent. See #159677 for context.
pub type DocLinkResMap = FxIndexMap<(Symbol, Namespace), Option<Res<NodeId>>>;
24 changes: 23 additions & 1 deletion compiler/rustc_next_trait_solver/src/placeholder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ where
IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
) {
let old_universes = universe_indices.clone();
let mut replacer = BoundVarReplacer {
infcx,
mapped_regions: Default::default(),
Expand All @@ -57,8 +58,29 @@ where
};

let value = value.fold_with(&mut replacer);
let BoundVarReplacer {
mapped_regions,
mapped_types,
mapped_consts,
universe_indices,
infcx: _,
current_index: _,
} = replacer;

if infcx.cx().assumptions_on_binders() {
for (old, new) in old_universes.into_iter().zip(universe_indices.iter()) {
if let (None, Some(new)) = (old, new) {
// FIXME(-Zassumptions-on-binders): `replace_bound_vars` does not have enough
// context to compute placeholder assumptions for the binders it enters.
infcx.insert_placeholder_assumptions(
*new,
Some(rustc_type_ir::region_constraint::Assumptions::empty()),
);
}
}
}

(value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
(value, mapped_regions, mapped_types, mapped_consts)
}

fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
let lo = start + BytePos(possible_offset);
let hi = lo + BytePos(found_terminators);
let span = self.mk_sp(lo, hi);
err.span_suggestion(
err.span_suggestion_verbose(
span,
"consider terminating the string here",
"#".repeat(n_hashes as usize),
Expand Down
Loading
Loading