Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #91865

Merged
merged 15 commits into from
Dec 13, 2021
Merged
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(bool_to_option)]
#![feature(const_cstr_unchecked)]
#![feature(crate_visibility_modifier)]
#![feature(extern_types)]
#![feature(in_band_lifetimes)]
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/free_regions.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Lift, Region, TyCtxt};
///
/// This stuff is a bit convoluted and should be refactored, but as we
/// transition to NLL, it'll all go away anyhow.
pub struct RegionRelations<'a, 'tcx> {
pub(crate) struct RegionRelations<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,

/// The context used for debug messages
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ use std::fmt;
/// assuming such values can be found. It returns the final values of
/// all the variables as well as a set of errors that must be reported.
#[instrument(level = "debug", skip(region_rels, var_infos, data))]
pub fn resolve<'tcx>(
pub(crate) fn resolve<'tcx>(
region_rels: &RegionRelations<'_, 'tcx>,
var_infos: VarInfos,
data: RegionConstraintData<'tcx>,
88 changes: 33 additions & 55 deletions compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
@@ -414,34 +414,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
arg: &GenericArg<'_>,
) -> subst::GenericArg<'tcx> {
let tcx = self.astconv.tcx();

let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| {
if has_default {
tcx.check_optional_stability(
param.def_id,
Some(arg.id()),
arg.span(),
None,
|_, _| {
// Default generic parameters may not be marked
// with stability attributes, i.e. when the
// default parameter was defined at the same time
// as the rest of the type. As such, we ignore missing
// stability attributes.
},
)
}
if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
self.inferred_params.push(ty.span);
tcx.ty_error().into()
} else {
self.astconv.ast_ty_to_ty(ty).into()
}
};

match (&param.kind, arg) {
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
self.astconv.ast_region_to_region(lt, Some(param)).into()
}
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
if has_default {
tcx.check_optional_stability(
param.def_id,
Some(arg.id()),
arg.span(),
None,
|_, _| {
// Default generic parameters may not be marked
// with stability attributes, i.e. when the
// default parameter was defined at the same time
// as the rest of the type. As such, we ignore missing
// stability attributes.
},
)
}
if let (hir::TyKind::Infer, false) =
(&ty.kind, self.astconv.allow_ty_infer())
{
self.inferred_params.push(ty.span);
tcx.ty_error().into()
} else {
self.astconv.ast_ty_to_ty(ty).into()
}
handle_ty_args(has_default, ty)
}
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
handle_ty_args(has_default, &inf.to_ty())
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
ty::Const::from_opt_const_arg_anon_const(
@@ -453,41 +459,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
.into()
}
(&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
if has_default {
tcx.const_param_default(param.def_id).into()
} else if self.astconv.allow_ty_infer() {
// FIXME(const_generics): Actually infer parameter here?
todo!()
} else {
self.inferred_params.push(inf.span);
tcx.ty_error().into()
}
}
(
&GenericParamDefKind::Type { has_default, .. },
hir::GenericArg::Infer(inf),
) => {
if has_default {
tcx.check_optional_stability(
param.def_id,
Some(arg.id()),
arg.span(),
None,
|_, _| {
// Default generic parameters may not be marked
// with stability attributes, i.e. when the
// default parameter was defined at the same time
// as the rest of the type. As such, we ignore missing
// stability attributes.
},
);
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
let ty = tcx.at(self.span).type_of(param.def_id);
if self.astconv.allow_ty_infer() {
self.astconv.ast_ty_to_ty(&inf.to_ty()).into()
self.astconv.ct_infer(ty, Some(param), inf.span).into()
} else {
self.inferred_params.push(inf.span);
tcx.ty_error().into()
tcx.const_error(ty).into()
}
}
_ => unreachable!(),
54 changes: 46 additions & 8 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -426,22 +426,48 @@ fn check_gat_where_clauses(
}
}

// If there are any missing clauses, emit an error
let mut clauses = clauses.unwrap_or_default();
// If there are any clauses that aren't provable, emit an error
let clauses = clauses.unwrap_or_default();
debug!(?clauses);
if !clauses.is_empty() {
let written_predicates: ty::GenericPredicates<'_> =
tcx.explicit_predicates_of(trait_item.def_id);
let param_env = tcx.param_env(trait_item.def_id);

let mut clauses: Vec<_> = clauses
.drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause))
.into_iter()
.filter(|clause| match clause.kind().skip_binder() {
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
!region_known_to_outlive(
tcx,
trait_item.hir_id(),
param_env,
&FxHashSet::default(),
a,
b,
)
}
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
!ty_known_to_outlive(
tcx,
trait_item.hir_id(),
param_env,
&FxHashSet::default(),
a,
b,
)
}
_ => bug!("Unexpected PredicateKind"),
})
.map(|clause| format!("{}", clause))
.collect();

// We sort so that order is predictable
clauses.sort();

if !clauses.is_empty() {
let plural = if clauses.len() > 1 { "s" } else { "" };
let mut err = tcx.sess.struct_span_err(
trait_item.span,
&format!("Missing required bounds on {}", trait_item.ident),
&format!("missing required bound{} on `{}`", plural, trait_item.ident),
);

let suggestion = format!(
@@ -455,11 +481,22 @@ fn check_gat_where_clauses(
);
err.span_suggestion(
trait_item.generics.where_clause.tail_span_for_suggestion(),
"add the required where clauses",
&format!("add the required where clause{}", plural),
suggestion,
Applicability::MachineApplicable,
);

let bound = if clauses.len() > 1 { "these bounds are" } else { "this bound is" };
err.note(&format!(
"{} currently required to ensure that impls have maximum flexibility",
bound
));
err.note(
"we are soliciting feedback, see issue #87479 \
<https://github.com/rust-lang/rust/issues/87479> \
for more information",
);

err.emit()
}
}
@@ -541,7 +578,8 @@ fn region_known_to_outlive<'tcx>(
});

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

let errors = infcx.resolve_regions(
id.expect_owner().to_def_id(),
2 changes: 1 addition & 1 deletion library/std/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
@@ -1259,7 +1259,7 @@ impl CStr {
#[inline]
#[must_use]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")]
#[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
// SAFETY: Casting to CStr is safe because its internal representation
// is a [u8] too (safe only inside std).
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
@@ -252,7 +252,6 @@
#![feature(char_internals)]
#![cfg_attr(not(bootstrap), feature(concat_bytes))]
#![feature(concat_idents)]
#![feature(const_cstr_unchecked)]
#![feature(const_fn_floating_point_arithmetic)]
#![feature(const_fn_fn_ptr_basics)]
#![feature(const_fn_trait_bound)]
95 changes: 45 additions & 50 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
@@ -29,20 +29,21 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};

use crate::clean::{types::AttributesExt, Attributes};
use crate::config::Options;
use crate::config::Options as RustdocOptions;
use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
use crate::lint::init_lints;
use crate::passes::span_of_attrs;

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

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

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:
}

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

let mut opts = TestOptions { no_crate_inject: false, attrs: Vec::new() };
let mut opts = GlobalTestOptions { no_crate_inject: false, attrs: Vec::new() };

let test_attrs: Vec<_> = attrs
.iter()
@@ -292,66 +293,63 @@ fn run_test(
test: &str,
crate_name: &str,
line: usize,
options: Options,
should_panic: bool,
rustdoc_options: RustdocOptions,
mut lang_string: LangString,
no_run: bool,
as_test_harness: bool,
runtool: Option<String>,
runtool_args: Vec<String>,
target: TargetTriple,
compile_fail: bool,
mut error_codes: Vec<String>,
opts: &TestOptions,
opts: &GlobalTestOptions,
edition: Edition,
outdir: DirState,
path: PathBuf,
test_id: &str,
report_unused_externs: impl Fn(UnusedExterns),
) -> Result<(), TestFailure> {
let (test, line_offset, supports_color) =
make_test(test, Some(crate_name), as_test_harness, opts, edition, Some(test_id));
make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id));

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

let rustc_binary = options
let rustc_binary = rustdoc_options
.test_builder
.as_deref()
.unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
let mut compiler = Command::new(&rustc_binary);
compiler.arg("--crate-type").arg("bin");
for cfg in &options.cfgs {
for cfg in &rustdoc_options.cfgs {
compiler.arg("--cfg").arg(&cfg);
}
if let Some(sysroot) = options.maybe_sysroot {
if let Some(sysroot) = rustdoc_options.maybe_sysroot {
compiler.arg("--sysroot").arg(sysroot);
}
compiler.arg("--edition").arg(&edition.to_string());
compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path);
compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", format!("{}", line as isize - line_offset as isize));
compiler.arg("-o").arg(&output_file);
if as_test_harness {
if lang_string.test_harness {
compiler.arg("--test");
}
if options.json_unused_externs && !compile_fail {
if rustdoc_options.json_unused_externs && !lang_string.compile_fail {
compiler.arg("--error-format=json");
compiler.arg("--json").arg("unused-externs");
compiler.arg("-Z").arg("unstable-options");
compiler.arg("-W").arg("unused_crate_dependencies");
}
for lib_str in &options.lib_strs {
for lib_str in &rustdoc_options.lib_strs {
compiler.arg("-L").arg(&lib_str);
}
for extern_str in &options.extern_strs {
for extern_str in &rustdoc_options.extern_strs {
compiler.arg("--extern").arg(&extern_str);
}
compiler.arg("-Ccodegen-units=1");
for codegen_options_str in &options.codegen_options_strs {
for codegen_options_str in &rustdoc_options.codegen_options_strs {
compiler.arg("-C").arg(&codegen_options_str);
}
for debugging_option_str in &options.debugging_opts_strs {
for debugging_option_str in &rustdoc_options.debugging_opts_strs {
compiler.arg("-Z").arg(&debugging_option_str);
}
if no_run && !compile_fail && options.persist_doctests.is_none() {
if no_run && !lang_string.compile_fail && rustdoc_options.persist_doctests.is_none() {
compiler.arg("--emit=metadata");
}
compiler.arg("--target").arg(match target {
@@ -360,7 +358,7 @@ fn run_test(
path.to_str().expect("target path must be valid unicode").to_string()
}
});
if let ErrorOutputType::HumanReadable(kind) = options.error_format {
if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format {
let (short, color_config) = kind.unzip();

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

let out = out_lines.join("\n");
let _bomb = Bomb(&out);
match (output.status.success(), compile_fail) {
match (output.status.success(), lang_string.compile_fail) {
(true, true) => {
return Err(TestFailure::UnexpectedCompilePass);
}
(true, false) => {}
(false, true) => {
if !error_codes.is_empty() {
if !lang_string.error_codes.is_empty() {
// We used to check if the output contained "error[{}]: " but since we added the
// colored output, we can't anymore because of the color escape characters before
// the ":".
error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
lang_string.error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));

if !error_codes.is_empty() {
return Err(TestFailure::MissingErrorCodes(error_codes));
if !lang_string.error_codes.is_empty() {
return Err(TestFailure::MissingErrorCodes(lang_string.error_codes));
}
}
}
@@ -454,11 +452,11 @@ fn run_test(
} else {
cmd = Command::new(output_file);
}
if let Some(run_directory) = options.test_run_directory {
if let Some(run_directory) = rustdoc_options.test_run_directory {
cmd.current_dir(run_directory);
}

let result = if options.nocapture {
let result = if rustdoc_options.nocapture {
cmd.status().map(|status| process::Output {
status,
stdout: Vec::new(),
@@ -470,9 +468,9 @@ fn run_test(
match result {
Err(e) => return Err(TestFailure::ExecutionError(e)),
Ok(out) => {
if should_panic && out.status.success() {
if lang_string.should_panic && out.status.success() {
return Err(TestFailure::UnexpectedRunPass);
} else if !should_panic && !out.status.success() {
} else if !lang_string.should_panic && !out.status.success() {
return Err(TestFailure::ExecutionFailure(out));
}
}
@@ -487,7 +485,7 @@ crate fn make_test(
s: &str,
crate_name: Option<&str>,
dont_insert_main: bool,
opts: &TestOptions,
opts: &GlobalTestOptions,
edition: Edition,
test_id: Option<&str>,
) -> (String, usize, bool) {
@@ -804,11 +802,11 @@ crate struct Collector {
// the `names` vector of that test will be `["Title", "Subtitle"]`.
names: Vec<String>,

options: Options,
rustdoc_options: RustdocOptions,
use_headers: bool,
enable_per_target_ignores: bool,
crate_name: Symbol,
opts: TestOptions,
opts: GlobalTestOptions,
position: Span,
source_map: Option<Lrc<SourceMap>>,
filename: Option<PathBuf>,
@@ -820,17 +818,17 @@ crate struct Collector {
impl Collector {
crate fn new(
crate_name: Symbol,
options: Options,
rustdoc_options: RustdocOptions,
use_headers: bool,
opts: TestOptions,
opts: GlobalTestOptions,
source_map: Option<Lrc<SourceMap>>,
filename: Option<PathBuf>,
enable_per_target_ignores: bool,
) -> Collector {
Collector {
tests: Vec::new(),
names: Vec::new(),
options,
rustdoc_options,
use_headers,
enable_per_target_ignores,
crate_name,
@@ -884,14 +882,14 @@ impl Tester for Collector {
let name = self.generate_name(line, &filename);
let crate_name = self.crate_name.to_string();
let opts = self.opts.clone();
let edition = config.edition.unwrap_or(self.options.edition);
let options = self.options.clone();
let runtool = self.options.runtool.clone();
let runtool_args = self.options.runtool_args.clone();
let target = self.options.target.clone();
let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
let rustdoc_options = self.rustdoc_options.clone();
let runtool = self.rustdoc_options.runtool.clone();
let runtool_args = self.rustdoc_options.runtool_args.clone();
let target = self.rustdoc_options.target.clone();
let target_str = target.to_string();
let unused_externs = self.unused_extern_reports.clone();
let no_run = config.no_run || options.no_run;
let no_run = config.no_run || rustdoc_options.no_run;
if !config.compile_fail {
self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
}
@@ -925,7 +923,7 @@ impl Tester for Collector {
self.visited_tests.entry((file.clone(), line)).and_modify(|v| *v += 1).or_insert(0)
},
);
let outdir = if let Some(mut path) = options.persist_doctests.clone() {
let outdir = if let Some(mut path) = rustdoc_options.persist_doctests.clone() {
path.push(&test_id);

std::fs::create_dir_all(&path)
@@ -965,15 +963,12 @@ impl Tester for Collector {
&test,
&crate_name,
line,
options,
config.should_panic,
rustdoc_options,
config,
no_run,
config.test_harness,
runtool,
runtool_args,
target,
config.compile_fail,
config.error_codes,
&opts,
edition,
outdir,
34 changes: 17 additions & 17 deletions src/librustdoc/doctest/tests.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::{make_test, TestOptions};
use super::{make_test, GlobalTestOptions};
use rustc_span::edition::DEFAULT_EDITION;

#[test]
fn make_test_basic() {
//basic use: wraps with `fn main`, adds `#![allow(unused)]`
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
fn main() {
@@ -19,7 +19,7 @@ assert_eq!(2+2, 4);
fn make_test_crate_name_no_use() {
// If you give a crate name but *don't* use it within the test, it won't bother inserting
// the `extern crate` statement.
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
fn main() {
@@ -34,7 +34,7 @@ assert_eq!(2+2, 4);
fn make_test_crate_name() {
// If you give a crate name and use it within the test, it will insert an `extern crate`
// statement before `fn main`.
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
@@ -52,7 +52,7 @@ assert_eq!(2+2, 4);
fn make_test_no_crate_inject() {
// Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
// adding it anyway.
let opts = TestOptions { no_crate_inject: true, attrs: vec![] };
let opts = GlobalTestOptions { no_crate_inject: true, attrs: vec![] };
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
@@ -70,7 +70,7 @@ fn make_test_ignore_std() {
// Even if you include a crate name, and use it in the doctest, we still won't include an
// `extern crate` statement if the crate is "std" -- that's included already by the
// compiler!
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "use std::*;
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
@@ -87,7 +87,7 @@ assert_eq!(2+2, 4);
fn make_test_manual_extern_crate() {
// When you manually include an `extern crate` statement in your doctest, `make_test`
// assumes you've included one for your own crate too.
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "extern crate asdf;
use asdf::qwop;
assert_eq!(2+2, 4);";
@@ -104,7 +104,7 @@ assert_eq!(2+2, 4);

#[test]
fn make_test_manual_extern_crate_with_macro_use() {
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "#[macro_use] extern crate asdf;
use asdf::qwop;
assert_eq!(2+2, 4);";
@@ -123,7 +123,7 @@ assert_eq!(2+2, 4);
fn make_test_opts_attrs() {
// If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use
// those instead of the stock `#![allow(unused)]`.
let mut opts = TestOptions::default();
let mut opts = GlobalTestOptions::default();
opts.attrs.push("feature(sick_rad)".to_string());
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
@@ -155,7 +155,7 @@ assert_eq!(2+2, 4);
fn make_test_crate_attrs() {
// Including inner attributes in your doctest will apply them to the whole "crate", pasting
// them outside the generated main function.
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "#![feature(sick_rad)]
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
@@ -171,7 +171,7 @@ assert_eq!(2+2, 4);
#[test]
fn make_test_with_main() {
// Including your own `fn main` wrapper lets the test use it verbatim.
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "fn main() {
assert_eq!(2+2, 4);
}";
@@ -187,7 +187,7 @@ fn main() {
#[test]
fn make_test_fake_main() {
// ... but putting it in a comment will still provide a wrapper.
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "//Ceci n'est pas une `fn main`
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
@@ -203,7 +203,7 @@ assert_eq!(2+2, 4);
#[test]
fn make_test_dont_insert_main() {
// Even with that, if you set `dont_insert_main`, it won't create the `fn main` wrapper.
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "//Ceci n'est pas une `fn main`
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
@@ -216,7 +216,7 @@ assert_eq!(2+2, 4);"

#[test]
fn make_test_issues_21299_33731() {
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();

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

#[test]
fn make_test_main_in_macro() {
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "#[macro_use] extern crate my_crate;
test_wrapper! {
fn main() {}
@@ -267,7 +267,7 @@ test_wrapper! {
#[test]
fn make_test_returns_result() {
// creates an inner function and unwraps it
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "use std::io;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
@@ -287,7 +287,7 @@ Ok::<(), io:Error>(())
#[test]
fn make_test_named_wrapper() {
// creates an inner function with a specific name
let opts = TestOptions::default();
let opts = GlobalTestOptions::default();
let input = "assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() {
4 changes: 4 additions & 0 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
@@ -892,6 +892,10 @@ h2.small-section-header > .anchor {
top: 10px;
}
.search-input {
/* Override Normalize.css: it has a rule that sets
-webkit-appearance: textfield for search inputs. That
causes rounded corners and no border on iOS Safari. */
-webkit-appearance: none;
/* Override Normalize.css: we have margins and do
not want to overflow - the `moz` attribute is necessary
until Firefox 29, too early to drop at this point */
4 changes: 2 additions & 2 deletions src/librustdoc/markdown.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ use rustc_span::source_map::DUMMY_SP;
use rustc_span::Symbol;

use crate::config::{Options, RenderOptions};
use crate::doctest::{Collector, TestOptions};
use crate::doctest::{Collector, GlobalTestOptions};
use crate::html::escape::Escape;
use crate::html::markdown;
use crate::html::markdown::{
@@ -129,7 +129,7 @@ crate fn render<P: AsRef<Path>>(
crate fn test(options: Options) -> Result<(), String> {
let input_str = read_to_string(&options.input)
.map_err(|err| format!("{}: {}", options.input.display(), err))?;
let mut opts = TestOptions::default();
let mut opts = GlobalTestOptions::default();
opts.no_crate_inject = true;
let mut collector = Collector::new(
Symbol::intern(&options.input.display().to_string()),
15 changes: 15 additions & 0 deletions src/test/ui/const-generics/generic_arg_infer/dont-use-defaults.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// run-pass
#![feature(generic_arg_infer)]

// test that we dont use defaults to aide in type inference

struct Foo<const N: usize = 2>;
impl<const N: usize> Foo<N> {
fn make_arr() -> [(); N] {
[(); N]
}
}

fn main() {
let [(), (), ()] = Foo::<_>::make_arr();
}
8 changes: 8 additions & 0 deletions src/test/ui/const-generics/generic_arg_infer/issue-91614.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![feature(portable_simd)]
#![feature(generic_arg_infer)]
use std::simd::Mask;

fn main() {
let y = Mask::<_, _>::splat(false);
//~^ error: type annotations needed for `Mask<_, {_: usize}>`
}
18 changes: 18 additions & 0 deletions src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0283]: type annotations needed for `Mask<_, {_: usize}>`
--> $DIR/issue-91614.rs:6:13
|
LL | let y = Mask::<_, _>::splat(false);
| - ^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
| |
| consider giving `y` the explicit type `Mask<_, LANES>`, where the type parameter `T` is specified
|
= note: cannot satisfy `_: MaskElement`
note: required by a bound in `Mask::<T, LANES>::splat`
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
|
LL | T: MaskElement,
| ^^^^^^^^^^^ required by this bound in `Mask::<T, LANES>::splat`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0283`.
2 changes: 1 addition & 1 deletion src/test/ui/generic-associated-types/issue-86787.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ enum Either<L, R> {
pub trait HasChildrenOf {
type T;
type TRef<'a>;
//~^ Missing required bounds
//~^ missing required

fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>;
fn take_children(self) -> Vec<Self::T>;
7 changes: 5 additions & 2 deletions src/test/ui/generic-associated-types/issue-86787.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
error: Missing required bounds on TRef
error: missing required bound on `TRef`
--> $DIR/issue-86787.rs:11:5
|
LL | type TRef<'a>;
| ^^^^^^^^^^^^^-
| |
| help: add the required where clauses: `where Self: 'a`
| help: add the required where clause: `where Self: 'a`
|
= note: this bound is currently required to ensure that impls have maximum flexibility
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information

error: aborting due to previous error

45 changes: 32 additions & 13 deletions src/test/ui/generic-associated-types/self-outlives-lint.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ use std::fmt::Debug;
// We have a `&'a self`, so we need a `Self: 'a`
trait Iterable {
type Item<'x>;
//~^ Missing required bounds
//~^ missing required
fn iter<'a>(&'a self) -> Self::Item<'a>;
}

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

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

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

@@ -59,7 +59,7 @@ struct Wrap<T>(T);
// We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x`
trait Des {
type Out<'x, D>;
//~^ Missing required bounds
//~^ missing required
fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
}
/*
@@ -75,7 +75,7 @@ impl Des for () {
// implied bound that `T: 'z`, so we require `D: 'x`
trait Des2 {
type Out<'x, D>;
//~^ Missing required bounds
//~^ missing required
fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>;
}
/*
@@ -90,7 +90,7 @@ impl Des2 for () {
// We see `&'z T`, so we require `D: 'x`
trait Des3 {
type Out<'x, D>;
//~^ Missing required bounds
//~^ missing required
fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>;
}
/*
@@ -112,22 +112,22 @@ trait NoGat<'a> {
// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
trait TraitLifetime<'a> {
type Bar<'b>;
//~^ Missing required bounds
//~^ missing required
fn method(&'a self) -> Self::Bar<'a>;
}

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

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

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

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

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

// Similar to the above, except with explicit bounds
trait ExplicitRegionOutlives<'ctx> {
type Fut<'out>;
//~^ missing required

fn test<'out>(ctx: &'ctx i32) -> Self::Fut<'out>
where
'ctx: 'out;
}


// If there are multiple methods that return the GAT, require a set of clauses
// that can be satisfied by *all* methods
trait MultipleMethods {
@@ -170,4 +182,11 @@ trait MultipleMethods {
fn gimme_default(&self) -> Self::Bar<'static>;
}

// We would normally require `Self: 'a`, but we can prove that `Self: 'static`
// because of the the bounds on the trait, so the bound is proven
trait Trait: 'static {
type Assoc<'a>;
fn make_assoc(_: &u32) -> Self::Assoc<'_>;
}

fn main() {}
95 changes: 71 additions & 24 deletions src/test/ui/generic-associated-types/self-outlives-lint.stderr
Original file line number Diff line number Diff line change
@@ -1,98 +1,145 @@
error: Missing required bounds on Item
error: missing required bound on `Item`
--> $DIR/self-outlives-lint.rs:9:5
|
LL | type Item<'x>;
| ^^^^^^^^^^^^^-
| |
| help: add the required where clauses: `where Self: 'x`
| help: add the required where clause: `where Self: 'x`
|
= note: this bound is currently required to ensure that impls have maximum flexibility
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information

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

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

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

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

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

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

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

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

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

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

error: Missing required bounds on Bar
--> $DIR/self-outlives-lint.rs:150:5
error: missing required bound on `Bar`
--> $DIR/self-outlives-lint.rs:151:5
|
LL | type Bar<'a, 'b>;
| ^^^^^^^^^^^^^^^^-
| |
| help: add the required where clauses: `where 'a: 'b`
| help: add the required where clause: `where 'b: 'a`
|
= note: this bound is currently required to ensure that impls have maximum flexibility
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information

error: missing required bound on `Fut`
--> $DIR/self-outlives-lint.rs:167:5
|
LL | type Fut<'out>;
| ^^^^^^^^^^^^^^-
| |
| help: add the required where clause: `where 'ctx: 'out`
|
= note: this bound is currently required to ensure that impls have maximum flexibility
= note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information

error: aborting due to 12 previous errors
error: aborting due to 13 previous errors