Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8f117a7

Browse files
committedDec 13, 2021
Auto merge of #91865 - matthiaskrgr:rollup-rai9ecq, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #91699 (Add `-webkit-appearance: none` to search input) - #91846 (rustdoc: Reduce number of arguments for `run_test` a bit) - #91847 (Fix FIXME for `generic_arg_infer` in `create_substs_for_ast_path`) - #91849 (GATs outlives lint: Try to prove bounds) - #91855 (Stabilize const_cstr_unchecked) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1796de7 + ff214b7 commit 8f117a7

File tree

18 files changed

+300
-177
lines changed

18 files changed

+300
-177
lines changed
 

‎compiler/rustc_codegen_llvm/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
77
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
88
#![feature(bool_to_option)]
9-
#![feature(const_cstr_unchecked)]
109
#![feature(crate_visibility_modifier)]
1110
#![feature(extern_types)]
1211
#![feature(in_band_lifetimes)]

‎compiler/rustc_infer/src/infer/free_regions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Lift, Region, TyCtxt};
1111
///
1212
/// This stuff is a bit convoluted and should be refactored, but as we
1313
/// transition to NLL, it'll all go away anyhow.
14-
pub struct RegionRelations<'a, 'tcx> {
14+
pub(crate) struct RegionRelations<'a, 'tcx> {
1515
pub tcx: TyCtxt<'tcx>,
1616

1717
/// The context used for debug messages

‎compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use std::fmt;
2828
/// assuming such values can be found. It returns the final values of
2929
/// all the variables as well as a set of errors that must be reported.
3030
#[instrument(level = "debug", skip(region_rels, var_infos, data))]
31-
pub fn resolve<'tcx>(
31+
pub(crate) fn resolve<'tcx>(
3232
region_rels: &RegionRelations<'_, 'tcx>,
3333
var_infos: VarInfos,
3434
data: RegionConstraintData<'tcx>,

‎compiler/rustc_typeck/src/astconv/mod.rs

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -414,34 +414,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
414414
arg: &GenericArg<'_>,
415415
) -> subst::GenericArg<'tcx> {
416416
let tcx = self.astconv.tcx();
417+
418+
let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| {
419+
if has_default {
420+
tcx.check_optional_stability(
421+
param.def_id,
422+
Some(arg.id()),
423+
arg.span(),
424+
None,
425+
|_, _| {
426+
// Default generic parameters may not be marked
427+
// with stability attributes, i.e. when the
428+
// default parameter was defined at the same time
429+
// as the rest of the type. As such, we ignore missing
430+
// stability attributes.
431+
},
432+
)
433+
}
434+
if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
435+
self.inferred_params.push(ty.span);
436+
tcx.ty_error().into()
437+
} else {
438+
self.astconv.ast_ty_to_ty(ty).into()
439+
}
440+
};
441+
417442
match (&param.kind, arg) {
418443
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
419444
self.astconv.ast_region_to_region(lt, Some(param)).into()
420445
}
421446
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
422-
if has_default {
423-
tcx.check_optional_stability(
424-
param.def_id,
425-
Some(arg.id()),
426-
arg.span(),
427-
None,
428-
|_, _| {
429-
// Default generic parameters may not be marked
430-
// with stability attributes, i.e. when the
431-
// default parameter was defined at the same time
432-
// as the rest of the type. As such, we ignore missing
433-
// stability attributes.
434-
},
435-
)
436-
}
437-
if let (hir::TyKind::Infer, false) =
438-
(&ty.kind, self.astconv.allow_ty_infer())
439-
{
440-
self.inferred_params.push(ty.span);
441-
tcx.ty_error().into()
442-
} else {
443-
self.astconv.ast_ty_to_ty(ty).into()
444-
}
447+
handle_ty_args(has_default, ty)
448+
}
449+
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
450+
handle_ty_args(has_default, &inf.to_ty())
445451
}
446452
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
447453
ty::Const::from_opt_const_arg_anon_const(
@@ -453,41 +459,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
453459
)
454460
.into()
455461
}
456-
(&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
457-
if has_default {
458-
tcx.const_param_default(param.def_id).into()
459-
} else if self.astconv.allow_ty_infer() {
460-
// FIXME(const_generics): Actually infer parameter here?
461-
todo!()
462-
} else {
463-
self.inferred_params.push(inf.span);
464-
tcx.ty_error().into()
465-
}
466-
}
467-
(
468-
&GenericParamDefKind::Type { has_default, .. },
469-
hir::GenericArg::Infer(inf),
470-
) => {
471-
if has_default {
472-
tcx.check_optional_stability(
473-
param.def_id,
474-
Some(arg.id()),
475-
arg.span(),
476-
None,
477-
|_, _| {
478-
// Default generic parameters may not be marked
479-
// with stability attributes, i.e. when the
480-
// default parameter was defined at the same time
481-
// as the rest of the type. As such, we ignore missing
482-
// stability attributes.
483-
},
484-
);
485-
}
462+
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
463+
let ty = tcx.at(self.span).type_of(param.def_id);
486464
if self.astconv.allow_ty_infer() {
487-
self.astconv.ast_ty_to_ty(&inf.to_ty()).into()
465+
self.astconv.ct_infer(ty, Some(param), inf.span).into()
488466
} else {
489467
self.inferred_params.push(inf.span);
490-
tcx.ty_error().into()
468+
tcx.const_error(ty).into()
491469
}
492470
}
493471
_ => unreachable!(),

‎compiler/rustc_typeck/src/check/wfcheck.rs

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -426,22 +426,48 @@ fn check_gat_where_clauses(
426426
}
427427
}
428428

429-
// If there are any missing clauses, emit an error
430-
let mut clauses = clauses.unwrap_or_default();
429+
// If there are any clauses that aren't provable, emit an error
430+
let clauses = clauses.unwrap_or_default();
431431
debug!(?clauses);
432432
if !clauses.is_empty() {
433-
let written_predicates: ty::GenericPredicates<'_> =
434-
tcx.explicit_predicates_of(trait_item.def_id);
433+
let param_env = tcx.param_env(trait_item.def_id);
434+
435435
let mut clauses: Vec<_> = clauses
436-
.drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause))
436+
.into_iter()
437+
.filter(|clause| match clause.kind().skip_binder() {
438+
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
439+
!region_known_to_outlive(
440+
tcx,
441+
trait_item.hir_id(),
442+
param_env,
443+
&FxHashSet::default(),
444+
a,
445+
b,
446+
)
447+
}
448+
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
449+
!ty_known_to_outlive(
450+
tcx,
451+
trait_item.hir_id(),
452+
param_env,
453+
&FxHashSet::default(),
454+
a,
455+
b,
456+
)
457+
}
458+
_ => bug!("Unexpected PredicateKind"),
459+
})
437460
.map(|clause| format!("{}", clause))
438461
.collect();
462+
439463
// We sort so that order is predictable
440464
clauses.sort();
465+
441466
if !clauses.is_empty() {
467+
let plural = if clauses.len() > 1 { "s" } else { "" };
442468
let mut err = tcx.sess.struct_span_err(
443469
trait_item.span,
444-
&format!("Missing required bounds on {}", trait_item.ident),
470+
&format!("missing required bound{} on `{}`", plural, trait_item.ident),
445471
);
446472

447473
let suggestion = format!(
@@ -455,11 +481,22 @@ fn check_gat_where_clauses(
455481
);
456482
err.span_suggestion(
457483
trait_item.generics.where_clause.tail_span_for_suggestion(),
458-
"add the required where clauses",
484+
&format!("add the required where clause{}", plural),
459485
suggestion,
460486
Applicability::MachineApplicable,
461487
);
462488

489+
let bound = if clauses.len() > 1 { "these bounds are" } else { "this bound is" };
490+
err.note(&format!(
491+
"{} currently required to ensure that impls have maximum flexibility",
492+
bound
493+
));
494+
err.note(
495+
"we are soliciting feedback, see issue #87479 \
496+
<https://github.com/rust-lang/rust/issues/87479> \
497+
for more information",
498+
);
499+
463500
err.emit()
464501
}
465502
}
@@ -541,7 +578,8 @@ fn region_known_to_outlive<'tcx>(
541578
});
542579

543580
use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
544-
(&infcx).push_sub_region_constraint(origin, region_a, region_b);
581+
// `region_a: region_b` -> `region_b <= region_a`
582+
(&infcx).push_sub_region_constraint(origin, region_b, region_a);
545583

546584
let errors = infcx.resolve_regions(
547585
id.expect_owner().to_def_id(),

‎library/std/src/ffi/c_str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,7 @@ impl CStr {
12591259
#[inline]
12601260
#[must_use]
12611261
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
1262-
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")]
1262+
#[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
12631263
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
12641264
// SAFETY: Casting to CStr is safe because its internal representation
12651265
// is a [u8] too (safe only inside std).

‎library/std/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@
252252
#![feature(char_internals)]
253253
#![cfg_attr(not(bootstrap), feature(concat_bytes))]
254254
#![feature(concat_idents)]
255-
#![feature(const_cstr_unchecked)]
256255
#![feature(const_fn_floating_point_arithmetic)]
257256
#![feature(const_fn_fn_ptr_basics)]
258257
#![feature(const_fn_trait_bound)]

‎src/librustdoc/doctest.rs

Lines changed: 45 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,21 @@ use std::sync::atomic::{AtomicUsize, Ordering};
2929
use std::sync::{Arc, Mutex};
3030

3131
use crate::clean::{types::AttributesExt, Attributes};
32-
use crate::config::Options;
32+
use crate::config::Options as RustdocOptions;
3333
use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
3434
use crate::lint::init_lints;
3535
use crate::passes::span_of_attrs;
3636

37+
/// Options that apply to all doctests in a crate or Markdown file (for `rustdoc foo.md`).
3738
#[derive(Clone, Default)]
38-
crate struct TestOptions {
39+
crate struct GlobalTestOptions {
3940
/// Whether to disable the default `extern crate my_crate;` when creating doctests.
4041
crate no_crate_inject: bool,
4142
/// Additional crate-level attributes to add to doctests.
4243
crate attrs: Vec<String>,
4344
}
4445

45-
crate fn run(options: Options) -> Result<(), ErrorReported> {
46+
crate fn run(options: RustdocOptions) -> Result<(), ErrorReported> {
4647
let input = config::Input::File(options.input.clone());
4748

4849
let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
@@ -214,10 +215,10 @@ crate fn run_tests(mut test_args: Vec<String>, nocapture: bool, tests: Vec<test:
214215
}
215216

216217
// Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
217-
fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
218+
fn scrape_test_config(attrs: &[ast::Attribute]) -> GlobalTestOptions {
218219
use rustc_ast_pretty::pprust;
219220

220-
let mut opts = TestOptions { no_crate_inject: false, attrs: Vec::new() };
221+
let mut opts = GlobalTestOptions { no_crate_inject: false, attrs: Vec::new() };
221222

222223
let test_attrs: Vec<_> = attrs
223224
.iter()
@@ -292,66 +293,63 @@ fn run_test(
292293
test: &str,
293294
crate_name: &str,
294295
line: usize,
295-
options: Options,
296-
should_panic: bool,
296+
rustdoc_options: RustdocOptions,
297+
mut lang_string: LangString,
297298
no_run: bool,
298-
as_test_harness: bool,
299299
runtool: Option<String>,
300300
runtool_args: Vec<String>,
301301
target: TargetTriple,
302-
compile_fail: bool,
303-
mut error_codes: Vec<String>,
304-
opts: &TestOptions,
302+
opts: &GlobalTestOptions,
305303
edition: Edition,
306304
outdir: DirState,
307305
path: PathBuf,
308306
test_id: &str,
309307
report_unused_externs: impl Fn(UnusedExterns),
310308
) -> Result<(), TestFailure> {
311309
let (test, line_offset, supports_color) =
312-
make_test(test, Some(crate_name), as_test_harness, opts, edition, Some(test_id));
310+
make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id));
313311

314312
let output_file = outdir.path().join("rust_out");
315313

316-
let rustc_binary = options
314+
let rustc_binary = rustdoc_options
317315
.test_builder
318316
.as_deref()
319317
.unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
320318
let mut compiler = Command::new(&rustc_binary);
321319
compiler.arg("--crate-type").arg("bin");
322-
for cfg in &options.cfgs {
320+
for cfg in &rustdoc_options.cfgs {
323321
compiler.arg("--cfg").arg(&cfg);
324322
}
325-
if let Some(sysroot) = options.maybe_sysroot {
323+
if let Some(sysroot) = rustdoc_options.maybe_sysroot {
326324
compiler.arg("--sysroot").arg(sysroot);
327325
}
328326
compiler.arg("--edition").arg(&edition.to_string());
329327
compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path);
330328
compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", format!("{}", line as isize - line_offset as isize));
331329
compiler.arg("-o").arg(&output_file);
332-
if as_test_harness {
330+
if lang_string.test_harness {
333331
compiler.arg("--test");
334332
}
335-
if options.json_unused_externs && !compile_fail {
333+
if rustdoc_options.json_unused_externs && !lang_string.compile_fail {
336334
compiler.arg("--error-format=json");
337335
compiler.arg("--json").arg("unused-externs");
338336
compiler.arg("-Z").arg("unstable-options");
339337
compiler.arg("-W").arg("unused_crate_dependencies");
340338
}
341-
for lib_str in &options.lib_strs {
339+
for lib_str in &rustdoc_options.lib_strs {
342340
compiler.arg("-L").arg(&lib_str);
343341
}
344-
for extern_str in &options.extern_strs {
342+
for extern_str in &rustdoc_options.extern_strs {
345343
compiler.arg("--extern").arg(&extern_str);
346344
}
347345
compiler.arg("-Ccodegen-units=1");
348-
for codegen_options_str in &options.codegen_options_strs {
346+
for codegen_options_str in &rustdoc_options.codegen_options_strs {
349347
compiler.arg("-C").arg(&codegen_options_str);
350348
}
351-
for debugging_option_str in &options.debugging_opts_strs {
349+
for debugging_option_str in &rustdoc_options.debugging_opts_strs {
352350
compiler.arg("-Z").arg(&debugging_option_str);
353351
}
354-
if no_run && !compile_fail && options.persist_doctests.is_none() {
352+
if no_run && !lang_string.compile_fail && rustdoc_options.persist_doctests.is_none() {
355353
compiler.arg("--emit=metadata");
356354
}
357355
compiler.arg("--target").arg(match target {
@@ -360,7 +358,7 @@ fn run_test(
360358
path.to_str().expect("target path must be valid unicode").to_string()
361359
}
362360
});
363-
if let ErrorOutputType::HumanReadable(kind) = options.error_format {
361+
if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format {
364362
let (short, color_config) = kind.unzip();
365363

366364
if short {
@@ -418,20 +416,20 @@ fn run_test(
418416

419417
let out = out_lines.join("\n");
420418
let _bomb = Bomb(&out);
421-
match (output.status.success(), compile_fail) {
419+
match (output.status.success(), lang_string.compile_fail) {
422420
(true, true) => {
423421
return Err(TestFailure::UnexpectedCompilePass);
424422
}
425423
(true, false) => {}
426424
(false, true) => {
427-
if !error_codes.is_empty() {
425+
if !lang_string.error_codes.is_empty() {
428426
// We used to check if the output contained "error[{}]: " but since we added the
429427
// colored output, we can't anymore because of the color escape characters before
430428
// the ":".
431-
error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
429+
lang_string.error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
432430

433-
if !error_codes.is_empty() {
434-
return Err(TestFailure::MissingErrorCodes(error_codes));
431+
if !lang_string.error_codes.is_empty() {
432+
return Err(TestFailure::MissingErrorCodes(lang_string.error_codes));
435433
}
436434
}
437435
}
@@ -454,11 +452,11 @@ fn run_test(
454452
} else {
455453
cmd = Command::new(output_file);
456454
}
457-
if let Some(run_directory) = options.test_run_directory {
455+
if let Some(run_directory) = rustdoc_options.test_run_directory {
458456
cmd.current_dir(run_directory);
459457
}
460458

461-
let result = if options.nocapture {
459+
let result = if rustdoc_options.nocapture {
462460
cmd.status().map(|status| process::Output {
463461
status,
464462
stdout: Vec::new(),
@@ -470,9 +468,9 @@ fn run_test(
470468
match result {
471469
Err(e) => return Err(TestFailure::ExecutionError(e)),
472470
Ok(out) => {
473-
if should_panic && out.status.success() {
471+
if lang_string.should_panic && out.status.success() {
474472
return Err(TestFailure::UnexpectedRunPass);
475-
} else if !should_panic && !out.status.success() {
473+
} else if !lang_string.should_panic && !out.status.success() {
476474
return Err(TestFailure::ExecutionFailure(out));
477475
}
478476
}
@@ -487,7 +485,7 @@ crate fn make_test(
487485
s: &str,
488486
crate_name: Option<&str>,
489487
dont_insert_main: bool,
490-
opts: &TestOptions,
488+
opts: &GlobalTestOptions,
491489
edition: Edition,
492490
test_id: Option<&str>,
493491
) -> (String, usize, bool) {
@@ -804,11 +802,11 @@ crate struct Collector {
804802
// the `names` vector of that test will be `["Title", "Subtitle"]`.
805803
names: Vec<String>,
806804

807-
options: Options,
805+
rustdoc_options: RustdocOptions,
808806
use_headers: bool,
809807
enable_per_target_ignores: bool,
810808
crate_name: Symbol,
811-
opts: TestOptions,
809+
opts: GlobalTestOptions,
812810
position: Span,
813811
source_map: Option<Lrc<SourceMap>>,
814812
filename: Option<PathBuf>,
@@ -820,17 +818,17 @@ crate struct Collector {
820818
impl Collector {
821819
crate fn new(
822820
crate_name: Symbol,
823-
options: Options,
821+
rustdoc_options: RustdocOptions,
824822
use_headers: bool,
825-
opts: TestOptions,
823+
opts: GlobalTestOptions,
826824
source_map: Option<Lrc<SourceMap>>,
827825
filename: Option<PathBuf>,
828826
enable_per_target_ignores: bool,
829827
) -> Collector {
830828
Collector {
831829
tests: Vec::new(),
832830
names: Vec::new(),
833-
options,
831+
rustdoc_options,
834832
use_headers,
835833
enable_per_target_ignores,
836834
crate_name,
@@ -884,14 +882,14 @@ impl Tester for Collector {
884882
let name = self.generate_name(line, &filename);
885883
let crate_name = self.crate_name.to_string();
886884
let opts = self.opts.clone();
887-
let edition = config.edition.unwrap_or(self.options.edition);
888-
let options = self.options.clone();
889-
let runtool = self.options.runtool.clone();
890-
let runtool_args = self.options.runtool_args.clone();
891-
let target = self.options.target.clone();
885+
let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
886+
let rustdoc_options = self.rustdoc_options.clone();
887+
let runtool = self.rustdoc_options.runtool.clone();
888+
let runtool_args = self.rustdoc_options.runtool_args.clone();
889+
let target = self.rustdoc_options.target.clone();
892890
let target_str = target.to_string();
893891
let unused_externs = self.unused_extern_reports.clone();
894-
let no_run = config.no_run || options.no_run;
892+
let no_run = config.no_run || rustdoc_options.no_run;
895893
if !config.compile_fail {
896894
self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
897895
}
@@ -925,7 +923,7 @@ impl Tester for Collector {
925923
self.visited_tests.entry((file.clone(), line)).and_modify(|v| *v += 1).or_insert(0)
926924
},
927925
);
928-
let outdir = if let Some(mut path) = options.persist_doctests.clone() {
926+
let outdir = if let Some(mut path) = rustdoc_options.persist_doctests.clone() {
929927
path.push(&test_id);
930928

931929
std::fs::create_dir_all(&path)
@@ -965,15 +963,12 @@ impl Tester for Collector {
965963
&test,
966964
&crate_name,
967965
line,
968-
options,
969-
config.should_panic,
966+
rustdoc_options,
967+
config,
970968
no_run,
971-
config.test_harness,
972969
runtool,
973970
runtool_args,
974971
target,
975-
config.compile_fail,
976-
config.error_codes,
977972
&opts,
978973
edition,
979974
outdir,

‎src/librustdoc/doctest/tests.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use super::{make_test, TestOptions};
1+
use super::{make_test, GlobalTestOptions};
22
use rustc_span::edition::DEFAULT_EDITION;
33

44
#[test]
55
fn make_test_basic() {
66
//basic use: wraps with `fn main`, adds `#![allow(unused)]`
7-
let opts = TestOptions::default();
7+
let opts = GlobalTestOptions::default();
88
let input = "assert_eq!(2+2, 4);";
99
let expected = "#![allow(unused)]
1010
fn main() {
@@ -19,7 +19,7 @@ assert_eq!(2+2, 4);
1919
fn make_test_crate_name_no_use() {
2020
// If you give a crate name but *don't* use it within the test, it won't bother inserting
2121
// the `extern crate` statement.
22-
let opts = TestOptions::default();
22+
let opts = GlobalTestOptions::default();
2323
let input = "assert_eq!(2+2, 4);";
2424
let expected = "#![allow(unused)]
2525
fn main() {
@@ -34,7 +34,7 @@ assert_eq!(2+2, 4);
3434
fn make_test_crate_name() {
3535
// If you give a crate name and use it within the test, it will insert an `extern crate`
3636
// statement before `fn main`.
37-
let opts = TestOptions::default();
37+
let opts = GlobalTestOptions::default();
3838
let input = "use asdf::qwop;
3939
assert_eq!(2+2, 4);";
4040
let expected = "#![allow(unused)]
@@ -52,7 +52,7 @@ assert_eq!(2+2, 4);
5252
fn make_test_no_crate_inject() {
5353
// Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
5454
// adding it anyway.
55-
let opts = TestOptions { no_crate_inject: true, attrs: vec![] };
55+
let opts = GlobalTestOptions { no_crate_inject: true, attrs: vec![] };
5656
let input = "use asdf::qwop;
5757
assert_eq!(2+2, 4);";
5858
let expected = "#![allow(unused)]
@@ -70,7 +70,7 @@ fn make_test_ignore_std() {
7070
// Even if you include a crate name, and use it in the doctest, we still won't include an
7171
// `extern crate` statement if the crate is "std" -- that's included already by the
7272
// compiler!
73-
let opts = TestOptions::default();
73+
let opts = GlobalTestOptions::default();
7474
let input = "use std::*;
7575
assert_eq!(2+2, 4);";
7676
let expected = "#![allow(unused)]
@@ -87,7 +87,7 @@ assert_eq!(2+2, 4);
8787
fn make_test_manual_extern_crate() {
8888
// When you manually include an `extern crate` statement in your doctest, `make_test`
8989
// assumes you've included one for your own crate too.
90-
let opts = TestOptions::default();
90+
let opts = GlobalTestOptions::default();
9191
let input = "extern crate asdf;
9292
use asdf::qwop;
9393
assert_eq!(2+2, 4);";
@@ -104,7 +104,7 @@ assert_eq!(2+2, 4);
104104

105105
#[test]
106106
fn make_test_manual_extern_crate_with_macro_use() {
107-
let opts = TestOptions::default();
107+
let opts = GlobalTestOptions::default();
108108
let input = "#[macro_use] extern crate asdf;
109109
use asdf::qwop;
110110
assert_eq!(2+2, 4);";
@@ -123,7 +123,7 @@ assert_eq!(2+2, 4);
123123
fn make_test_opts_attrs() {
124124
// If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use
125125
// those instead of the stock `#![allow(unused)]`.
126-
let mut opts = TestOptions::default();
126+
let mut opts = GlobalTestOptions::default();
127127
opts.attrs.push("feature(sick_rad)".to_string());
128128
let input = "use asdf::qwop;
129129
assert_eq!(2+2, 4);";
@@ -155,7 +155,7 @@ assert_eq!(2+2, 4);
155155
fn make_test_crate_attrs() {
156156
// Including inner attributes in your doctest will apply them to the whole "crate", pasting
157157
// them outside the generated main function.
158-
let opts = TestOptions::default();
158+
let opts = GlobalTestOptions::default();
159159
let input = "#![feature(sick_rad)]
160160
assert_eq!(2+2, 4);";
161161
let expected = "#![allow(unused)]
@@ -171,7 +171,7 @@ assert_eq!(2+2, 4);
171171
#[test]
172172
fn make_test_with_main() {
173173
// Including your own `fn main` wrapper lets the test use it verbatim.
174-
let opts = TestOptions::default();
174+
let opts = GlobalTestOptions::default();
175175
let input = "fn main() {
176176
assert_eq!(2+2, 4);
177177
}";
@@ -187,7 +187,7 @@ fn main() {
187187
#[test]
188188
fn make_test_fake_main() {
189189
// ... but putting it in a comment will still provide a wrapper.
190-
let opts = TestOptions::default();
190+
let opts = GlobalTestOptions::default();
191191
let input = "//Ceci n'est pas une `fn main`
192192
assert_eq!(2+2, 4);";
193193
let expected = "#![allow(unused)]
@@ -203,7 +203,7 @@ assert_eq!(2+2, 4);
203203
#[test]
204204
fn make_test_dont_insert_main() {
205205
// Even with that, if you set `dont_insert_main`, it won't create the `fn main` wrapper.
206-
let opts = TestOptions::default();
206+
let opts = GlobalTestOptions::default();
207207
let input = "//Ceci n'est pas une `fn main`
208208
assert_eq!(2+2, 4);";
209209
let expected = "#![allow(unused)]
@@ -216,7 +216,7 @@ assert_eq!(2+2, 4);"
216216

217217
#[test]
218218
fn make_test_issues_21299_33731() {
219-
let opts = TestOptions::default();
219+
let opts = GlobalTestOptions::default();
220220

221221
let input = "// fn main
222222
assert_eq!(2+2, 4);";
@@ -248,7 +248,7 @@ assert_eq!(asdf::foo, 4);
248248

249249
#[test]
250250
fn make_test_main_in_macro() {
251-
let opts = TestOptions::default();
251+
let opts = GlobalTestOptions::default();
252252
let input = "#[macro_use] extern crate my_crate;
253253
test_wrapper! {
254254
fn main() {}
@@ -267,7 +267,7 @@ test_wrapper! {
267267
#[test]
268268
fn make_test_returns_result() {
269269
// creates an inner function and unwraps it
270-
let opts = TestOptions::default();
270+
let opts = GlobalTestOptions::default();
271271
let input = "use std::io;
272272
let mut input = String::new();
273273
io::stdin().read_line(&mut input)?;
@@ -287,7 +287,7 @@ Ok::<(), io:Error>(())
287287
#[test]
288288
fn make_test_named_wrapper() {
289289
// creates an inner function with a specific name
290-
let opts = TestOptions::default();
290+
let opts = GlobalTestOptions::default();
291291
let input = "assert_eq!(2+2, 4);";
292292
let expected = "#![allow(unused)]
293293
fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() {

‎src/librustdoc/html/static/css/rustdoc.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,10 @@ h2.small-section-header > .anchor {
892892
top: 10px;
893893
}
894894
.search-input {
895+
/* Override Normalize.css: it has a rule that sets
896+
-webkit-appearance: textfield for search inputs. That
897+
causes rounded corners and no border on iOS Safari. */
898+
-webkit-appearance: none;
895899
/* Override Normalize.css: we have margins and do
896900
not want to overflow - the `moz` attribute is necessary
897901
until Firefox 29, too early to drop at this point */

‎src/librustdoc/markdown.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_span::source_map::DUMMY_SP;
77
use rustc_span::Symbol;
88

99
use crate::config::{Options, RenderOptions};
10-
use crate::doctest::{Collector, TestOptions};
10+
use crate::doctest::{Collector, GlobalTestOptions};
1111
use crate::html::escape::Escape;
1212
use crate::html::markdown;
1313
use crate::html::markdown::{
@@ -129,7 +129,7 @@ crate fn render<P: AsRef<Path>>(
129129
crate fn test(options: Options) -> Result<(), String> {
130130
let input_str = read_to_string(&options.input)
131131
.map_err(|err| format!("{}: {}", options.input.display(), err))?;
132-
let mut opts = TestOptions::default();
132+
let mut opts = GlobalTestOptions::default();
133133
opts.no_crate_inject = true;
134134
let mut collector = Collector::new(
135135
Symbol::intern(&options.input.display().to_string()),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-pass
2+
#![feature(generic_arg_infer)]
3+
4+
// test that we dont use defaults to aide in type inference
5+
6+
struct Foo<const N: usize = 2>;
7+
impl<const N: usize> Foo<N> {
8+
fn make_arr() -> [(); N] {
9+
[(); N]
10+
}
11+
}
12+
13+
fn main() {
14+
let [(), (), ()] = Foo::<_>::make_arr();
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(portable_simd)]
2+
#![feature(generic_arg_infer)]
3+
use std::simd::Mask;
4+
5+
fn main() {
6+
let y = Mask::<_, _>::splat(false);
7+
//~^ error: type annotations needed for `Mask<_, {_: usize}>`
8+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0283]: type annotations needed for `Mask<_, {_: usize}>`
2+
--> $DIR/issue-91614.rs:6:13
3+
|
4+
LL | let y = Mask::<_, _>::splat(false);
5+
| - ^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
6+
| |
7+
| consider giving `y` the explicit type `Mask<_, LANES>`, where the type parameter `T` is specified
8+
|
9+
= note: cannot satisfy `_: MaskElement`
10+
note: required by a bound in `Mask::<T, LANES>::splat`
11+
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
12+
|
13+
LL | T: MaskElement,
14+
| ^^^^^^^^^^^ required by this bound in `Mask::<T, LANES>::splat`
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0283`.

‎src/test/ui/generic-associated-types/issue-86787.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ enum Either<L, R> {
99
pub trait HasChildrenOf {
1010
type T;
1111
type TRef<'a>;
12-
//~^ Missing required bounds
12+
//~^ missing required
1313

1414
fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>;
1515
fn take_children(self) -> Vec<Self::T>;
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
error: Missing required bounds on TRef
1+
error: missing required bound on `TRef`
22
--> $DIR/issue-86787.rs:11:5
33
|
44
LL | type TRef<'a>;
55
| ^^^^^^^^^^^^^-
66
| |
7-
| help: add the required where clauses: `where Self: 'a`
7+
| help: add the required where clause: `where Self: 'a`
8+
|
9+
= note: this bound is currently required to ensure that impls have maximum flexibility
10+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
811

912
error: aborting due to previous error
1013

‎src/test/ui/generic-associated-types/self-outlives-lint.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::fmt::Debug;
77
// We have a `&'a self`, so we need a `Self: 'a`
88
trait Iterable {
99
type Item<'x>;
10-
//~^ Missing required bounds
10+
//~^ missing required
1111
fn iter<'a>(&'a self) -> Self::Item<'a>;
1212
}
1313

@@ -23,7 +23,7 @@ impl<T> Iterable for T {
2323
// We have a `&'a T`, so we need a `T: 'x`
2424
trait Deserializer<T> {
2525
type Out<'x>;
26-
//~^ Missing required bounds
26+
//~^ missing required
2727
fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>;
2828
}
2929

@@ -37,14 +37,14 @@ impl<T> Deserializer<T> for () {
3737
// We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x`
3838
trait Deserializer2<T> {
3939
type Out<'x>;
40-
//~^ Missing required bounds
40+
//~^ missing required
4141
fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>;
4242
}
4343

4444
// We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y`
4545
trait Deserializer3<T, U> {
4646
type Out<'x, 'y>;
47-
//~^ Missing required bounds
47+
//~^ missing required
4848
fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>;
4949
}
5050

@@ -59,7 +59,7 @@ struct Wrap<T>(T);
5959
// We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x`
6060
trait Des {
6161
type Out<'x, D>;
62-
//~^ Missing required bounds
62+
//~^ missing required
6363
fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
6464
}
6565
/*
@@ -75,7 +75,7 @@ impl Des for () {
7575
// implied bound that `T: 'z`, so we require `D: 'x`
7676
trait Des2 {
7777
type Out<'x, D>;
78-
//~^ Missing required bounds
78+
//~^ missing required
7979
fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>;
8080
}
8181
/*
@@ -90,7 +90,7 @@ impl Des2 for () {
9090
// We see `&'z T`, so we require `D: 'x`
9191
trait Des3 {
9292
type Out<'x, D>;
93-
//~^ Missing required bounds
93+
//~^ missing required
9494
fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>;
9595
}
9696
/*
@@ -112,22 +112,22 @@ trait NoGat<'a> {
112112
// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
113113
trait TraitLifetime<'a> {
114114
type Bar<'b>;
115-
//~^ Missing required bounds
115+
//~^ missing required
116116
fn method(&'a self) -> Self::Bar<'a>;
117117
}
118118

119119
// Like above, but we have a where clause that can prove what we want
120120
// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
121121
trait TraitLifetimeWhere<'a> where Self: 'a {
122122
type Bar<'b>;
123-
//~^ Missing required bounds
123+
//~^ missing required
124124
fn method(&'a self) -> Self::Bar<'a>;
125125
}
126126

127127
// Explicit bound instead of implicit; we want to still error
128128
trait ExplicitBound {
129129
type Bar<'b>;
130-
//~^ Missing required bounds
130+
//~^ missing required
131131
fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b;
132132
}
133133

@@ -141,14 +141,15 @@ trait NotInReturn {
141141
trait IterableTwo {
142142
type Item<'a>;
143143
type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
144-
//~^ Missing required bounds
144+
//~^ missing required
145145
fn iter<'a>(&'a self) -> Self::Iterator<'a>;
146146
}
147147

148-
// We also should report region outlives clauses
148+
// We also should report region outlives clauses. Here, we know that `'y: 'x`,
149+
// because of `&'x &'y`, so we require that `'b: 'a`.
149150
trait RegionOutlives {
150151
type Bar<'a, 'b>;
151-
//~^ Missing required bounds
152+
//~^ missing required
152153
fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>;
153154
}
154155

@@ -161,6 +162,17 @@ impl Foo for () {
161162
}
162163
*/
163164

165+
// Similar to the above, except with explicit bounds
166+
trait ExplicitRegionOutlives<'ctx> {
167+
type Fut<'out>;
168+
//~^ missing required
169+
170+
fn test<'out>(ctx: &'ctx i32) -> Self::Fut<'out>
171+
where
172+
'ctx: 'out;
173+
}
174+
175+
164176
// If there are multiple methods that return the GAT, require a set of clauses
165177
// that can be satisfied by *all* methods
166178
trait MultipleMethods {
@@ -170,4 +182,11 @@ trait MultipleMethods {
170182
fn gimme_default(&self) -> Self::Bar<'static>;
171183
}
172184

185+
// We would normally require `Self: 'a`, but we can prove that `Self: 'static`
186+
// because of the the bounds on the trait, so the bound is proven
187+
trait Trait: 'static {
188+
type Assoc<'a>;
189+
fn make_assoc(_: &u32) -> Self::Assoc<'_>;
190+
}
191+
173192
fn main() {}
Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,145 @@
1-
error: Missing required bounds on Item
1+
error: missing required bound on `Item`
22
--> $DIR/self-outlives-lint.rs:9:5
33
|
44
LL | type Item<'x>;
55
| ^^^^^^^^^^^^^-
66
| |
7-
| help: add the required where clauses: `where Self: 'x`
7+
| help: add the required where clause: `where Self: 'x`
8+
|
9+
= note: this bound is currently required to ensure that impls have maximum flexibility
10+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
811

9-
error: Missing required bounds on Out
12+
error: missing required bound on `Out`
1013
--> $DIR/self-outlives-lint.rs:25:5
1114
|
1215
LL | type Out<'x>;
1316
| ^^^^^^^^^^^^-
1417
| |
15-
| help: add the required where clauses: `where T: 'x`
18+
| help: add the required where clause: `where T: 'x`
19+
|
20+
= note: this bound is currently required to ensure that impls have maximum flexibility
21+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
1622

17-
error: Missing required bounds on Out
23+
error: missing required bound on `Out`
1824
--> $DIR/self-outlives-lint.rs:39:5
1925
|
2026
LL | type Out<'x>;
2127
| ^^^^^^^^^^^^-
2228
| |
23-
| help: add the required where clauses: `where T: 'x`
29+
| help: add the required where clause: `where T: 'x`
30+
|
31+
= note: this bound is currently required to ensure that impls have maximum flexibility
32+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
2433

25-
error: Missing required bounds on Out
34+
error: missing required bounds on `Out`
2635
--> $DIR/self-outlives-lint.rs:46:5
2736
|
2837
LL | type Out<'x, 'y>;
2938
| ^^^^^^^^^^^^^^^^-
3039
| |
3140
| help: add the required where clauses: `where T: 'x, U: 'y`
41+
|
42+
= note: these bounds are currently required to ensure that impls have maximum flexibility
43+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
3244

33-
error: Missing required bounds on Out
45+
error: missing required bound on `Out`
3446
--> $DIR/self-outlives-lint.rs:61:5
3547
|
3648
LL | type Out<'x, D>;
3749
| ^^^^^^^^^^^^^^^-
3850
| |
39-
| help: add the required where clauses: `where D: 'x`
51+
| help: add the required where clause: `where D: 'x`
52+
|
53+
= note: this bound is currently required to ensure that impls have maximum flexibility
54+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
4055

41-
error: Missing required bounds on Out
56+
error: missing required bound on `Out`
4257
--> $DIR/self-outlives-lint.rs:77:5
4358
|
4459
LL | type Out<'x, D>;
4560
| ^^^^^^^^^^^^^^^-
4661
| |
47-
| help: add the required where clauses: `where D: 'x`
62+
| help: add the required where clause: `where D: 'x`
63+
|
64+
= note: this bound is currently required to ensure that impls have maximum flexibility
65+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
4866

49-
error: Missing required bounds on Out
67+
error: missing required bound on `Out`
5068
--> $DIR/self-outlives-lint.rs:92:5
5169
|
5270
LL | type Out<'x, D>;
5371
| ^^^^^^^^^^^^^^^-
5472
| |
55-
| help: add the required where clauses: `where D: 'x`
73+
| help: add the required where clause: `where D: 'x`
74+
|
75+
= note: this bound is currently required to ensure that impls have maximum flexibility
76+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
5677

57-
error: Missing required bounds on Bar
78+
error: missing required bounds on `Bar`
5879
--> $DIR/self-outlives-lint.rs:114:5
5980
|
6081
LL | type Bar<'b>;
6182
| ^^^^^^^^^^^^-
6283
| |
6384
| help: add the required where clauses: `where Self: 'a, Self: 'b`
85+
|
86+
= note: these bounds are currently required to ensure that impls have maximum flexibility
87+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
6488

65-
error: Missing required bounds on Bar
89+
error: missing required bound on `Bar`
6690
--> $DIR/self-outlives-lint.rs:122:5
6791
|
6892
LL | type Bar<'b>;
6993
| ^^^^^^^^^^^^-
7094
| |
71-
| help: add the required where clauses: `where Self: 'a, Self: 'b`
95+
| help: add the required where clause: `where Self: 'b`
96+
|
97+
= note: this bound is currently required to ensure that impls have maximum flexibility
98+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
7299

73-
error: Missing required bounds on Bar
100+
error: missing required bound on `Bar`
74101
--> $DIR/self-outlives-lint.rs:129:5
75102
|
76103
LL | type Bar<'b>;
77104
| ^^^^^^^^^^^^-
78105
| |
79-
| help: add the required where clauses: `where Self: 'b`
106+
| help: add the required where clause: `where Self: 'b`
107+
|
108+
= note: this bound is currently required to ensure that impls have maximum flexibility
109+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
80110

81-
error: Missing required bounds on Iterator
111+
error: missing required bound on `Iterator`
82112
--> $DIR/self-outlives-lint.rs:143:5
83113
|
84114
LL | type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
85115
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
86116
| |
87-
| help: add the required where clauses: `where Self: 'a`
117+
| help: add the required where clause: `where Self: 'a`
118+
|
119+
= note: this bound is currently required to ensure that impls have maximum flexibility
120+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
88121

89-
error: Missing required bounds on Bar
90-
--> $DIR/self-outlives-lint.rs:150:5
122+
error: missing required bound on `Bar`
123+
--> $DIR/self-outlives-lint.rs:151:5
91124
|
92125
LL | type Bar<'a, 'b>;
93126
| ^^^^^^^^^^^^^^^^-
94127
| |
95-
| help: add the required where clauses: `where 'a: 'b`
128+
| help: add the required where clause: `where 'b: 'a`
129+
|
130+
= note: this bound is currently required to ensure that impls have maximum flexibility
131+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
132+
133+
error: missing required bound on `Fut`
134+
--> $DIR/self-outlives-lint.rs:167:5
135+
|
136+
LL | type Fut<'out>;
137+
| ^^^^^^^^^^^^^^-
138+
| |
139+
| help: add the required where clause: `where 'ctx: 'out`
140+
|
141+
= note: this bound is currently required to ensure that impls have maximum flexibility
142+
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
96143

97-
error: aborting due to 12 previous errors
144+
error: aborting due to 13 previous errors
98145

0 commit comments

Comments
 (0)
Please sign in to comment.