From 992cfc16839d701e17f0437585a44102e83d4d14 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts <2467194+yoshuawuyts@users.noreply.github.com> Date: Thu, 30 Jun 2022 16:54:03 +0200 Subject: [PATCH 1/9] Stabilize `into_future` --- library/core/src/future/into_future.rs | 18 +++++------------- library/core/src/future/mod.rs | 2 +- src/test/ui/async-await/await-into-future.rs | 2 -- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs index ad9e80e117f1e..649b433877222 100644 --- a/library/core/src/future/into_future.rs +++ b/library/core/src/future/into_future.rs @@ -13,8 +13,6 @@ use crate::future::Future; /// on all futures. /// /// ```no_run -/// #![feature(into_future)] -/// /// use std::future::IntoFuture; /// /// # async fn foo() { @@ -33,8 +31,6 @@ use crate::future::Future; /// multiple times before being `.await`ed. /// /// ```rust -/// #![feature(into_future)] -/// /// use std::future::{ready, Ready, IntoFuture}; /// /// /// Eventually multiply two numbers @@ -91,8 +87,6 @@ use crate::future::Future; /// `IntoFuture::into_future` to obtain an instance of `Future`: /// /// ```rust -/// #![feature(into_future)] -/// /// use std::future::IntoFuture; /// /// /// Convert the output of a future to a string. @@ -104,14 +98,14 @@ use crate::future::Future; /// format!("{:?}", fut.await) /// } /// ``` -#[unstable(feature = "into_future", issue = "67644")] +#[stable(feature = "into_future", since = "1.64.0")] pub trait IntoFuture { /// The output that the future will produce on completion. - #[unstable(feature = "into_future", issue = "67644")] + #[stable(feature = "into_future", since = "1.64.0")] type Output; /// Which kind of future are we turning this into? - #[unstable(feature = "into_future", issue = "67644")] + #[stable(feature = "into_future", since = "1.64.0")] type IntoFuture: Future; /// Creates a future from a value. @@ -121,8 +115,6 @@ pub trait IntoFuture { /// Basic usage: /// /// ```no_run - /// #![feature(into_future)] - /// /// use std::future::IntoFuture; /// /// # async fn foo() { @@ -131,12 +123,12 @@ pub trait IntoFuture { /// assert_eq!("meow", fut.await); /// # } /// ``` - #[unstable(feature = "into_future", issue = "67644")] + #[stable(feature = "into_future", since = "1.64.0")] #[lang = "into_future"] fn into_future(self) -> Self::IntoFuture; } -#[unstable(feature = "into_future", issue = "67644")] +#[stable(feature = "into_future", since = "1.64.0")] impl IntoFuture for F { type Output = F::Output; type IntoFuture = F; diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 9b89f766c67bf..90eecb9d4a000 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -29,7 +29,7 @@ pub use self::future::Future; #[unstable(feature = "future_join", issue = "91642")] pub use self::join::join; -#[unstable(feature = "into_future", issue = "67644")] +#[stable(feature = "into_future", since = "1.64.0")] pub use into_future::IntoFuture; #[stable(feature = "future_readiness_fns", since = "1.48.0")] diff --git a/src/test/ui/async-await/await-into-future.rs b/src/test/ui/async-await/await-into-future.rs index 6e1b155e181ee..8bf1385b3c5cd 100644 --- a/src/test/ui/async-await/await-into-future.rs +++ b/src/test/ui/async-await/await-into-future.rs @@ -1,8 +1,6 @@ // run-pass // aux-build: issue-72470-lib.rs // edition:2021 -#![feature(into_future)] - extern crate issue_72470_lib; use std::{future::{Future, IntoFuture}, pin::Pin}; From 75dfd5e1c1a51c44c8eb8d7474879f6ae5969085 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 1 Jul 2022 23:47:48 -0500 Subject: [PATCH 2/9] Fix caching bug in `download-rustc = true` When moving this to rustbuild, I introduced a bug: if you had the file already downloaded, but deleted the sysroot for whatever reason, rustbuil would fail to unpack the cached tarball. This only affects people if they have a cached tarball, which is probably why we haven't seen an issue yet - wiping `build/cache` would work around the issue, or just not deleting `build/$TARGET/stage2`. --- src/bootstrap/builder.rs | 1 + src/bootstrap/config.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 62b5416cee8af..5eab464456b95 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -945,6 +945,7 @@ impl<'a> Builder<'a> { } pub(crate) fn download_component(&self, url: &str, dest_path: &Path, help_on_error: &str) { + self.verbose(&format!("download {url}")); // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/. let tempfile = self.tempdir().join(dest_path.file_name().unwrap()); // While bootstrap itself only supports http and https downloads, downstream forks might diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 14607741932ea..c7e15f4625ad0 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1560,7 +1560,7 @@ fn download_ci_rustc(builder: &Builder<'_>, commit: &str) { builder.fix_bin_or_dylib(&bin_root.join("bin").join("rustc")); builder.fix_bin_or_dylib(&bin_root.join("bin").join("rustdoc")); let lib_dir = bin_root.join("lib"); - for lib in t!(fs::read_dir(lib_dir)) { + for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) { let lib = t!(lib); if lib.path().extension() == Some(OsStr::new("so")) { builder.fix_bin_or_dylib(&lib.path()); @@ -1636,6 +1636,7 @@ fn download_component( } Some(sha256) } else if tarball.exists() { + builder.unpack(&tarball, &bin_root, prefix); return; } else { None From e5288842fa158081b89ddfb34f9fb87083e00634 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 14 Feb 2022 06:01:38 +0000 Subject: [PATCH 3/9] sess: stabilize `--terminal-width` Formerly `-Zterminal-width`, `--terminal-width` allows the user or build tool to inform rustc of the width of the terminal so that diagnostics can be truncated. Signed-off-by: David Wood --- compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_session/src/config.rs | 12 ++++++++++++ compiler/rustc_session/src/options.rs | 1 + compiler/rustc_session/src/session.rs | 6 +++--- src/librustdoc/config.rs | 6 +++++- src/librustdoc/core.rs | 7 +++++-- src/librustdoc/lib.rs | 15 ++++++++++++++- .../output-default.stdout | 3 +++ src/test/rustdoc-ui/terminal-width.rs | 5 +++++ src/test/rustdoc-ui/terminal-width.stderr | 15 +++++++++++++++ src/test/ui/terminal-width/flag-human.rs | 2 +- src/test/ui/terminal-width/flag-json.rs | 2 +- src/test/ui/terminal-width/flag-json.stderr | 2 +- 13 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 src/test/rustdoc-ui/terminal-width.rs create mode 100644 src/test/rustdoc-ui/terminal-width.stderr diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 30a29ed6ed38f..81145416437b7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -689,7 +689,6 @@ fn test_debugging_options_tracking_hash() { untracked!(span_debug, true); untracked!(span_free_formats, true); untracked!(temps_dir, Some(String::from("abc"))); - untracked!(terminal_width, Some(80)); untracked!(threads, 99); untracked!(time, true); untracked!(time_llvm_passes, true); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e7717f1367cb0..2650ad5287902 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -726,6 +726,7 @@ impl Default for Options { prints: Vec::new(), cg: Default::default(), error_format: ErrorOutputType::default(), + terminal_width: None, externs: Externs(BTreeMap::new()), crate_name: None, libs: Vec::new(), @@ -1427,6 +1428,12 @@ pub fn rustc_optgroups() -> Vec { never = never colorize output", "auto|always|never", ), + opt::opt_s( + "", + "terminal-width", + "Inform rustc of the width of the terminal so that errors can be truncated", + "WIDTH", + ), opt::multi_s( "", "remap-path-prefix", @@ -2202,6 +2209,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let error_format = parse_error_format(matches, color, json_rendered); + let terminal_width = matches.opt_get("terminal-width").unwrap_or_else(|_| { + early_error(error_format, "`--terminal-width` must be an positive integer"); + }); + let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) .unwrap_or_else(|e| early_error(error_format, &e)); @@ -2474,6 +2485,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { prints, cg, error_format, + terminal_width, externs, unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), crate_name, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index be70ea5d5e480..80e811bc1a745 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -170,6 +170,7 @@ top_level_options!( test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], + terminal_width: Option [UNTRACKED], /// If `Some`, enable incremental compilation, using the given /// directory to store intermediate results. diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 2a5ddd4e9e420..b5a72ed20c16a 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1162,7 +1162,7 @@ fn default_emitter( fallback_bundle, short, sopts.debugging_opts.teach, - sopts.debugging_opts.terminal_width, + sopts.terminal_width, macro_backtrace, ), Some(dst) => EmitterWriter::new( @@ -1188,7 +1188,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.debugging_opts.terminal_width, + sopts.terminal_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), @@ -1202,7 +1202,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.debugging_opts.terminal_width, + sopts.terminal_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 04638aa1af62b..0c913f8a07f9a 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -73,6 +73,8 @@ pub(crate) struct Options { pub(crate) proc_macro_crate: bool, /// How to format errors and warnings. pub(crate) error_format: ErrorOutputType, + /// Width of terminal to truncate errors appropriately. + pub(crate) terminal_width: Option, /// Library search paths to hand to the compiler. pub(crate) libs: Vec, /// Library search paths strings to hand to the compiler. @@ -334,11 +336,12 @@ impl Options { let config::JsonConfig { json_rendered, json_unused_externs, .. } = config::parse_json(matches); let error_format = config::parse_error_format(matches, color, json_rendered); + let terminal_width = matches.opt_get("terminal-width").unwrap_or_default(); let codegen_options = CodegenOptions::build(matches, error_format); let debugging_opts = DebuggingOptions::build(matches, error_format); - let diag = new_handler(error_format, None, &debugging_opts); + let diag = new_handler(error_format, None, terminal_width, &debugging_opts); // check for deprecated options check_deprecated_options(matches, &diag); @@ -702,6 +705,7 @@ impl Options { input, proc_macro_crate, error_format, + terminal_width, libs, lib_strs, externs, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 51b245e36ba3b..7ed7243cb99c4 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -154,6 +154,7 @@ impl<'tcx> DocContext<'tcx> { pub(crate) fn new_handler( error_format: ErrorOutputType, source_map: Option>, + terminal_width: Option, debugging_opts: &DebuggingOptions, ) -> rustc_errors::Handler { let fallback_bundle = @@ -169,7 +170,7 @@ pub(crate) fn new_handler( fallback_bundle, short, debugging_opts.teach, - debugging_opts.terminal_width, + terminal_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -187,7 +188,7 @@ pub(crate) fn new_handler( fallback_bundle, pretty, json_rendered, - debugging_opts.terminal_width, + terminal_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -208,6 +209,7 @@ pub(crate) fn create_config( crate_name, proc_macro_crate, error_format, + terminal_width, libs, externs, mut cfgs, @@ -266,6 +268,7 @@ pub(crate) fn create_config( actually_rustdoc: true, debugging_opts, error_format, + terminal_width, edition, describe_lints, crate_name, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ded3d9951bd35..d42bb02e0323e 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -462,6 +462,14 @@ fn opts() -> Vec { "human|json|short", ) }), + unstable("terminal-width", |o| { + o.optopt( + "", + "terminal-width", + "Provide width of the terminal for truncated error messages", + "WIDTH", + ) + }), stable("json", |o| { o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") }), @@ -733,7 +741,12 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } fn main_options(options: config::Options) -> MainResult { - let diag = core::new_handler(options.error_format, None, &options.debugging_opts); + let diag = core::new_handler( + options.error_format, + None, + options.terminal_width, + &options.debugging_opts, + ); match (options.should_test, options.markdown_input()) { (true, true) => return wrap_return(&diag, markdown::test(options)), diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout index 6d16fe5673bc1..6ca2143efbdea 100644 --- a/src/test/run-make/issue-88756-default-output/output-default.stdout +++ b/src/test/run-make/issue-88756-default-output/output-default.stdout @@ -110,6 +110,9 @@ Options: never = never colorize output --error-format human|json|short How errors and other messages are produced + --terminal-width WIDTH + Provide width of the terminal for truncated error + messages --json CONFIG Configure the structure of JSON diagnostics --disable-minification Disable minification applied on JS files diff --git a/src/test/rustdoc-ui/terminal-width.rs b/src/test/rustdoc-ui/terminal-width.rs new file mode 100644 index 0000000000000..72544d7ee53a1 --- /dev/null +++ b/src/test/rustdoc-ui/terminal-width.rs @@ -0,0 +1,5 @@ +// compile-flags: -Zunstable-options --terminal-width=10 +#![deny(rustdoc::bare_urls)] + +/// This is a long line that contains a http://link.com +pub struct Foo; //~^ ERROR diff --git a/src/test/rustdoc-ui/terminal-width.stderr b/src/test/rustdoc-ui/terminal-width.stderr new file mode 100644 index 0000000000000..16ab606eb9902 --- /dev/null +++ b/src/test/rustdoc-ui/terminal-width.stderr @@ -0,0 +1,15 @@ +error: this URL is not a hyperlink + --> $DIR/terminal-width.rs:4:41 + | +LL | ... a http://link.com + | ^^^^^^^^^^^^^^^ help: use an automatic link instead: `` + | +note: the lint level is defined here + --> $DIR/terminal-width.rs:2:9 + | +LL | ...ny(rustdoc::bare_url... + | ^^^^^^^^^^^^^^^^^^ + = note: bare URLs are not automatically turned into clickable links + +error: aborting due to previous error + diff --git a/src/test/ui/terminal-width/flag-human.rs b/src/test/ui/terminal-width/flag-human.rs index e445a84fd012e..4ae960ef967b9 100644 --- a/src/test/ui/terminal-width/flag-human.rs +++ b/src/test/ui/terminal-width/flag-human.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z terminal-width=20 +// compile-flags: --terminal-width=20 // This test checks that `-Z terminal-width` effects the human error output by restricting it to an // arbitrarily low value so that the effect is visible. diff --git a/src/test/ui/terminal-width/flag-json.rs b/src/test/ui/terminal-width/flag-json.rs index 3d2530e204b33..d4e51e80347d5 100644 --- a/src/test/ui/terminal-width/flag-json.rs +++ b/src/test/ui/terminal-width/flag-json.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z terminal-width=20 --error-format=json +// compile-flags: --terminal-width=20 --error-format=json // This test checks that `-Z terminal-width` effects the JSON error output by restricting it to an // arbitrarily low value so that the effect is visible. diff --git a/src/test/ui/terminal-width/flag-json.stderr b/src/test/ui/terminal-width/flag-json.stderr index 93c246cb3f501..b21391d1640ef 100644 --- a/src/test/ui/terminal-width/flag-json.stderr +++ b/src/test/ui/terminal-width/flag-json.stderr @@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":244,"byte_end":246,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":239,"byte_end":241,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":243,"byte_end":245,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":238,"byte_end":240,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types --> $DIR/flag-json.rs:7:17 | LL | ..._: () = 42; From cd23af6793857f1b73ecd76764876c482f183d31 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 16 Jun 2022 16:39:11 +0100 Subject: [PATCH 4/9] session: `terminal-width` -> `output-width` Rename the `--terminal-width` flag to `--output-width` as the behaviour doesn't just apply to terminals (and so is slightly less accurate). Signed-off-by: David Wood --- compiler/rustc_errors/src/emitter.rs | 16 ++++++++-------- compiler/rustc_errors/src/json.rs | 16 ++++++++-------- compiler/rustc_session/src/config.rs | 12 ++++++------ compiler/rustc_session/src/options.rs | 6 +++--- compiler/rustc_session/src/session.rs | 6 +++--- src/librustdoc/config.rs | 8 ++++---- src/librustdoc/core.rs | 10 +++++----- src/librustdoc/lib.rs | 8 ++++---- .../output-default.stdout | 4 ++-- .../{terminal-width.rs => output-width.rs} | 2 +- ...terminal-width.stderr => output-width.stderr} | 4 ++-- src/test/ui/output-width/flag-human.rs | 9 +++++++++ .../flag-human.stderr | 0 src/test/ui/output-width/flag-json.rs | 9 +++++++++ .../flag-json.stderr | 2 +- .../non-1-width-unicode-multiline-label.rs | 0 .../non-1-width-unicode-multiline-label.stderr | 0 .../non-whitespace-trimming-2.rs | 0 .../non-whitespace-trimming-2.stderr | 0 .../non-whitespace-trimming-unicode.rs | 0 .../non-whitespace-trimming-unicode.stderr | 0 .../non-whitespace-trimming.rs | 0 .../non-whitespace-trimming.stderr | 0 .../tabs-trimming.rs | 0 .../tabs-trimming.stderr | 0 .../whitespace-trimming-2.rs | 0 .../whitespace-trimming-2.stderr | 0 .../whitespace-trimming.rs | 0 .../whitespace-trimming.stderr | 0 src/test/ui/terminal-width/flag-human.rs | 9 --------- src/test/ui/terminal-width/flag-json.rs | 9 --------- 31 files changed, 65 insertions(+), 65 deletions(-) rename src/test/rustdoc-ui/{terminal-width.rs => output-width.rs} (66%) rename src/test/rustdoc-ui/{terminal-width.stderr => output-width.stderr} (84%) create mode 100644 src/test/ui/output-width/flag-human.rs rename src/test/ui/{terminal-width => output-width}/flag-human.stderr (100%) create mode 100644 src/test/ui/output-width/flag-json.rs rename src/test/ui/{terminal-width => output-width}/flag-json.stderr (93%) rename src/test/ui/{terminal-width => output-width}/non-1-width-unicode-multiline-label.rs (100%) rename src/test/ui/{terminal-width => output-width}/non-1-width-unicode-multiline-label.stderr (100%) rename src/test/ui/{terminal-width => output-width}/non-whitespace-trimming-2.rs (100%) rename src/test/ui/{terminal-width => output-width}/non-whitespace-trimming-2.stderr (100%) rename src/test/ui/{terminal-width => output-width}/non-whitespace-trimming-unicode.rs (100%) rename src/test/ui/{terminal-width => output-width}/non-whitespace-trimming-unicode.stderr (100%) rename src/test/ui/{terminal-width => output-width}/non-whitespace-trimming.rs (100%) rename src/test/ui/{terminal-width => output-width}/non-whitespace-trimming.stderr (100%) rename src/test/ui/{terminal-width => output-width}/tabs-trimming.rs (100%) rename src/test/ui/{terminal-width => output-width}/tabs-trimming.stderr (100%) rename src/test/ui/{terminal-width => output-width}/whitespace-trimming-2.rs (100%) rename src/test/ui/{terminal-width => output-width}/whitespace-trimming-2.stderr (100%) rename src/test/ui/{terminal-width => output-width}/whitespace-trimming.rs (100%) rename src/test/ui/{terminal-width => output-width}/whitespace-trimming.stderr (100%) delete mode 100644 src/test/ui/terminal-width/flag-human.rs delete mode 100644 src/test/ui/terminal-width/flag-json.rs diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6d74e9a9f2b9e..802cd1a165502 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -63,7 +63,7 @@ impl HumanReadableErrorType { bundle: Option>, fallback_bundle: LazyFallbackBundle, teach: bool, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, ) -> EmitterWriter { let (short, color_config) = self.unzip(); @@ -76,7 +76,7 @@ impl HumanReadableErrorType { short, teach, color, - terminal_width, + output_width, macro_backtrace, ) } @@ -710,7 +710,7 @@ pub struct EmitterWriter { short_message: bool, teach: bool, ui_testing: bool, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, } @@ -730,7 +730,7 @@ impl EmitterWriter { fallback_bundle: LazyFallbackBundle, short_message: bool, teach: bool, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, ) -> EmitterWriter { let dst = Destination::from_stderr(color_config); @@ -742,7 +742,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, - terminal_width, + output_width, macro_backtrace, } } @@ -755,7 +755,7 @@ impl EmitterWriter { short_message: bool, teach: bool, colored: bool, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, ) -> EmitterWriter { EmitterWriter { @@ -766,7 +766,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, - terminal_width, + output_width, macro_backtrace, } } @@ -1615,7 +1615,7 @@ impl EmitterWriter { width_offset + annotated_file.multiline_depth + 1 }; - let column_width = if let Some(width) = self.terminal_width { + let column_width = if let Some(width) = self.output_width { width.saturating_sub(code_offset) } else if self.ui_testing { DEFAULT_COLUMN_WIDTH diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index d4d1491c16945..1e87e70922b73 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -42,7 +42,7 @@ pub struct JsonEmitter { pretty: bool, ui_testing: bool, json_rendered: HumanReadableErrorType, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, } @@ -54,7 +54,7 @@ impl JsonEmitter { fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { @@ -66,7 +66,7 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, - terminal_width, + output_width, macro_backtrace, } } @@ -76,7 +76,7 @@ impl JsonEmitter { json_rendered: HumanReadableErrorType, fluent_bundle: Option>, fallback_bundle: LazyFallbackBundle, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, ) -> JsonEmitter { let file_path_mapping = FilePathMapping::empty(); @@ -87,7 +87,7 @@ impl JsonEmitter { fallback_bundle, pretty, json_rendered, - terminal_width, + output_width, macro_backtrace, ) } @@ -100,7 +100,7 @@ impl JsonEmitter { fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, - terminal_width: Option, + output_width: Option, macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { @@ -112,7 +112,7 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, - terminal_width, + output_width, macro_backtrace, } } @@ -345,7 +345,7 @@ impl Diagnostic { je.fluent_bundle.clone(), je.fallback_bundle.clone(), false, - je.terminal_width, + je.output_width, je.macro_backtrace, ) .ui_testing(je.ui_testing) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 2650ad5287902..bad9fb576bf3b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -726,7 +726,7 @@ impl Default for Options { prints: Vec::new(), cg: Default::default(), error_format: ErrorOutputType::default(), - terminal_width: None, + output_width: None, externs: Externs(BTreeMap::new()), crate_name: None, libs: Vec::new(), @@ -1430,8 +1430,8 @@ pub fn rustc_optgroups() -> Vec { ), opt::opt_s( "", - "terminal-width", - "Inform rustc of the width of the terminal so that errors can be truncated", + "output-width", + "Inform rustc of the width of the output so that errors can be truncated to fit", "WIDTH", ), opt::multi_s( @@ -2209,8 +2209,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let error_format = parse_error_format(matches, color, json_rendered); - let terminal_width = matches.opt_get("terminal-width").unwrap_or_else(|_| { - early_error(error_format, "`--terminal-width` must be an positive integer"); + let output_width = matches.opt_get("output-width").unwrap_or_else(|_| { + early_error(error_format, "`--output-width` must be an positive integer"); }); let unparsed_crate_types = matches.opt_strs("crate-type"); @@ -2485,7 +2485,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { prints, cg, error_format, - terminal_width, + output_width, externs, unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), crate_name, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 80e811bc1a745..b544965f6f23a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -170,7 +170,7 @@ top_level_options!( test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], - terminal_width: Option [UNTRACKED], + output_width: Option [UNTRACKED], /// If `Some`, enable incremental compilation, using the given /// directory to store intermediate results. @@ -1389,6 +1389,8 @@ options! { "panic strategy for out-of-memory handling"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], "pass `-install_name @rpath/...` to the macOS linker (default: no)"), + output_width: Option = (None, parse_opt_number, [UNTRACKED], + "set the current output width for diagnostic truncation"), panic_abort_tests: bool = (false, parse_bool, [TRACKED], "support compiling tests with panic=abort (default: no)"), panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED], @@ -1515,8 +1517,6 @@ options! { "show extended diagnostic help (default: no)"), temps_dir: Option = (None, parse_opt_string, [UNTRACKED], "the directory the intermediate files are written to"), - terminal_width: Option = (None, parse_opt_number, [UNTRACKED], - "set the current terminal width"), // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved // alongside query results and changes to translation options can affect diagnostics - so // translation options should be tracked. diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b5a72ed20c16a..e22b7a5539f7d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1162,7 +1162,7 @@ fn default_emitter( fallback_bundle, short, sopts.debugging_opts.teach, - sopts.terminal_width, + sopts.output_width, macro_backtrace, ), Some(dst) => EmitterWriter::new( @@ -1188,7 +1188,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.terminal_width, + sopts.output_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), @@ -1202,7 +1202,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.terminal_width, + sopts.output_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0c913f8a07f9a..0285f15dd76fa 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -74,7 +74,7 @@ pub(crate) struct Options { /// How to format errors and warnings. pub(crate) error_format: ErrorOutputType, /// Width of terminal to truncate errors appropriately. - pub(crate) terminal_width: Option, + pub(crate) output_width: Option, /// Library search paths to hand to the compiler. pub(crate) libs: Vec, /// Library search paths strings to hand to the compiler. @@ -336,12 +336,12 @@ impl Options { let config::JsonConfig { json_rendered, json_unused_externs, .. } = config::parse_json(matches); let error_format = config::parse_error_format(matches, color, json_rendered); - let terminal_width = matches.opt_get("terminal-width").unwrap_or_default(); + let output_width = matches.opt_get("output-width").unwrap_or_default(); let codegen_options = CodegenOptions::build(matches, error_format); let debugging_opts = DebuggingOptions::build(matches, error_format); - let diag = new_handler(error_format, None, terminal_width, &debugging_opts); + let diag = new_handler(error_format, None, output_width, &debugging_opts); // check for deprecated options check_deprecated_options(matches, &diag); @@ -705,7 +705,7 @@ impl Options { input, proc_macro_crate, error_format, - terminal_width, + output_width, libs, lib_strs, externs, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 7ed7243cb99c4..d85e9d974dbcd 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -154,7 +154,7 @@ impl<'tcx> DocContext<'tcx> { pub(crate) fn new_handler( error_format: ErrorOutputType, source_map: Option>, - terminal_width: Option, + output_width: Option, debugging_opts: &DebuggingOptions, ) -> rustc_errors::Handler { let fallback_bundle = @@ -170,7 +170,7 @@ pub(crate) fn new_handler( fallback_bundle, short, debugging_opts.teach, - terminal_width, + output_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -188,7 +188,7 @@ pub(crate) fn new_handler( fallback_bundle, pretty, json_rendered, - terminal_width, + output_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -209,7 +209,7 @@ pub(crate) fn create_config( crate_name, proc_macro_crate, error_format, - terminal_width, + output_width, libs, externs, mut cfgs, @@ -268,7 +268,7 @@ pub(crate) fn create_config( actually_rustdoc: true, debugging_opts, error_format, - terminal_width, + output_width, edition, describe_lints, crate_name, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index d42bb02e0323e..b0be3502baed3 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -462,11 +462,11 @@ fn opts() -> Vec { "human|json|short", ) }), - unstable("terminal-width", |o| { + unstable("output-width", |o| { o.optopt( "", - "terminal-width", - "Provide width of the terminal for truncated error messages", + "output-width", + "Provide width of the output for truncated error messages", "WIDTH", ) }), @@ -744,7 +744,7 @@ fn main_options(options: config::Options) -> MainResult { let diag = core::new_handler( options.error_format, None, - options.terminal_width, + options.output_width, &options.debugging_opts, ); diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout index 6ca2143efbdea..64b31adc63e4d 100644 --- a/src/test/run-make/issue-88756-default-output/output-default.stdout +++ b/src/test/run-make/issue-88756-default-output/output-default.stdout @@ -110,8 +110,8 @@ Options: never = never colorize output --error-format human|json|short How errors and other messages are produced - --terminal-width WIDTH - Provide width of the terminal for truncated error + --output-width WIDTH + Provide width of the output for truncated error messages --json CONFIG Configure the structure of JSON diagnostics --disable-minification diff --git a/src/test/rustdoc-ui/terminal-width.rs b/src/test/rustdoc-ui/output-width.rs similarity index 66% rename from src/test/rustdoc-ui/terminal-width.rs rename to src/test/rustdoc-ui/output-width.rs index 72544d7ee53a1..9fb680474475c 100644 --- a/src/test/rustdoc-ui/terminal-width.rs +++ b/src/test/rustdoc-ui/output-width.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zunstable-options --terminal-width=10 +// compile-flags: -Zunstable-options --output-width=10 #![deny(rustdoc::bare_urls)] /// This is a long line that contains a http://link.com diff --git a/src/test/rustdoc-ui/terminal-width.stderr b/src/test/rustdoc-ui/output-width.stderr similarity index 84% rename from src/test/rustdoc-ui/terminal-width.stderr rename to src/test/rustdoc-ui/output-width.stderr index 16ab606eb9902..dc790530300cf 100644 --- a/src/test/rustdoc-ui/terminal-width.stderr +++ b/src/test/rustdoc-ui/output-width.stderr @@ -1,11 +1,11 @@ error: this URL is not a hyperlink - --> $DIR/terminal-width.rs:4:41 + --> $DIR/output-width.rs:4:41 | LL | ... a http://link.com | ^^^^^^^^^^^^^^^ help: use an automatic link instead: `` | note: the lint level is defined here - --> $DIR/terminal-width.rs:2:9 + --> $DIR/output-width.rs:2:9 | LL | ...ny(rustdoc::bare_url... | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/output-width/flag-human.rs b/src/test/ui/output-width/flag-human.rs new file mode 100644 index 0000000000000..44e9ba044230a --- /dev/null +++ b/src/test/ui/output-width/flag-human.rs @@ -0,0 +1,9 @@ +// compile-flags: --output-width=20 + +// This test checks that `-Z output-width` effects the human error output by restricting it to an +// arbitrarily low value so that the effect is visible. + +fn main() { + let _: () = 42; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/terminal-width/flag-human.stderr b/src/test/ui/output-width/flag-human.stderr similarity index 100% rename from src/test/ui/terminal-width/flag-human.stderr rename to src/test/ui/output-width/flag-human.stderr diff --git a/src/test/ui/output-width/flag-json.rs b/src/test/ui/output-width/flag-json.rs new file mode 100644 index 0000000000000..ec01dcb88189a --- /dev/null +++ b/src/test/ui/output-width/flag-json.rs @@ -0,0 +1,9 @@ +// compile-flags: --output-width=20 --error-format=json + +// This test checks that `-Z output-width` effects the JSON error output by restricting it to an +// arbitrarily low value so that the effect is visible. + +fn main() { + let _: () = 42; + //~^ ERROR arguments to this function are incorrect +} diff --git a/src/test/ui/terminal-width/flag-json.stderr b/src/test/ui/output-width/flag-json.stderr similarity index 93% rename from src/test/ui/terminal-width/flag-json.stderr rename to src/test/ui/output-width/flag-json.stderr index b21391d1640ef..097ca1d6e1780 100644 --- a/src/test/ui/terminal-width/flag-json.stderr +++ b/src/test/ui/output-width/flag-json.stderr @@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":243,"byte_end":245,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":238,"byte_end":240,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":239,"byte_end":241,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":234,"byte_end":236,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types --> $DIR/flag-json.rs:7:17 | LL | ..._: () = 42; diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs b/src/test/ui/output-width/non-1-width-unicode-multiline-label.rs similarity index 100% rename from src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs rename to src/test/ui/output-width/non-1-width-unicode-multiline-label.rs diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/output-width/non-1-width-unicode-multiline-label.stderr similarity index 100% rename from src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr rename to src/test/ui/output-width/non-1-width-unicode-multiline-label.stderr diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.rs b/src/test/ui/output-width/non-whitespace-trimming-2.rs similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-2.rs rename to src/test/ui/output-width/non-whitespace-trimming-2.rs diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-2.stderr b/src/test/ui/output-width/non-whitespace-trimming-2.stderr similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-2.stderr rename to src/test/ui/output-width/non-whitespace-trimming-2.stderr diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs b/src/test/ui/output-width/non-whitespace-trimming-unicode.rs similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-unicode.rs rename to src/test/ui/output-width/non-whitespace-trimming-unicode.rs diff --git a/src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr b/src/test/ui/output-width/non-whitespace-trimming-unicode.stderr similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming-unicode.stderr rename to src/test/ui/output-width/non-whitespace-trimming-unicode.stderr diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.rs b/src/test/ui/output-width/non-whitespace-trimming.rs similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming.rs rename to src/test/ui/output-width/non-whitespace-trimming.rs diff --git a/src/test/ui/terminal-width/non-whitespace-trimming.stderr b/src/test/ui/output-width/non-whitespace-trimming.stderr similarity index 100% rename from src/test/ui/terminal-width/non-whitespace-trimming.stderr rename to src/test/ui/output-width/non-whitespace-trimming.stderr diff --git a/src/test/ui/terminal-width/tabs-trimming.rs b/src/test/ui/output-width/tabs-trimming.rs similarity index 100% rename from src/test/ui/terminal-width/tabs-trimming.rs rename to src/test/ui/output-width/tabs-trimming.rs diff --git a/src/test/ui/terminal-width/tabs-trimming.stderr b/src/test/ui/output-width/tabs-trimming.stderr similarity index 100% rename from src/test/ui/terminal-width/tabs-trimming.stderr rename to src/test/ui/output-width/tabs-trimming.stderr diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.rs b/src/test/ui/output-width/whitespace-trimming-2.rs similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming-2.rs rename to src/test/ui/output-width/whitespace-trimming-2.rs diff --git a/src/test/ui/terminal-width/whitespace-trimming-2.stderr b/src/test/ui/output-width/whitespace-trimming-2.stderr similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming-2.stderr rename to src/test/ui/output-width/whitespace-trimming-2.stderr diff --git a/src/test/ui/terminal-width/whitespace-trimming.rs b/src/test/ui/output-width/whitespace-trimming.rs similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming.rs rename to src/test/ui/output-width/whitespace-trimming.rs diff --git a/src/test/ui/terminal-width/whitespace-trimming.stderr b/src/test/ui/output-width/whitespace-trimming.stderr similarity index 100% rename from src/test/ui/terminal-width/whitespace-trimming.stderr rename to src/test/ui/output-width/whitespace-trimming.stderr diff --git a/src/test/ui/terminal-width/flag-human.rs b/src/test/ui/terminal-width/flag-human.rs deleted file mode 100644 index 4ae960ef967b9..0000000000000 --- a/src/test/ui/terminal-width/flag-human.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: --terminal-width=20 - -// This test checks that `-Z terminal-width` effects the human error output by restricting it to an -// arbitrarily low value so that the effect is visible. - -fn main() { - let _: () = 42; - //~^ ERROR mismatched types -} diff --git a/src/test/ui/terminal-width/flag-json.rs b/src/test/ui/terminal-width/flag-json.rs deleted file mode 100644 index d4e51e80347d5..0000000000000 --- a/src/test/ui/terminal-width/flag-json.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: --terminal-width=20 --error-format=json - -// This test checks that `-Z terminal-width` effects the JSON error output by restricting it to an -// arbitrarily low value so that the effect is visible. - -fn main() { - let _: () = 42; - //~^ ERROR arguments to this function are incorrect -} From 44c1fcc04dad7c59d1af5c7759afd121951e195c Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 6 Jul 2022 11:57:41 +0100 Subject: [PATCH 5/9] session: `output-width` -> `diagnostic-width` Rename the `--output-width` flag to `--diagnostic-width` as this appears to be the preferred name within the compiler team. Signed-off-by: David Wood --- compiler/rustc_errors/src/emitter.rs | 16 ++++++++-------- compiler/rustc_errors/src/json.rs | 16 ++++++++-------- compiler/rustc_session/src/config.rs | 12 ++++++------ compiler/rustc_session/src/options.rs | 4 ++-- compiler/rustc_session/src/session.rs | 8 ++++---- src/librustdoc/config.rs | 10 +++++----- src/librustdoc/core.rs | 10 +++++----- src/librustdoc/lib.rs | 6 +++--- .../output-default.stdout | 2 +- .../{output-width.rs => diagnostic-width.rs} | 2 +- ...tput-width.stderr => diagnostic-width.stderr} | 4 ++-- .../flag-human.rs | 2 +- .../flag-human.stderr | 0 .../flag-json.rs | 2 +- .../flag-json.stderr | 2 +- .../non-1-width-unicode-multiline-label.rs | 0 .../non-1-width-unicode-multiline-label.stderr | 0 .../non-whitespace-trimming-2.rs | 0 .../non-whitespace-trimming-2.stderr | 0 .../non-whitespace-trimming-unicode.rs | 0 .../non-whitespace-trimming-unicode.stderr | 0 .../non-whitespace-trimming.rs | 0 .../non-whitespace-trimming.stderr | 0 .../tabs-trimming.rs | 0 .../tabs-trimming.stderr | 0 .../whitespace-trimming-2.rs | 0 .../whitespace-trimming-2.stderr | 0 .../whitespace-trimming.rs | 0 .../whitespace-trimming.stderr | 0 29 files changed, 48 insertions(+), 48 deletions(-) rename src/test/rustdoc-ui/{output-width.rs => diagnostic-width.rs} (65%) rename src/test/rustdoc-ui/{output-width.stderr => diagnostic-width.stderr} (83%) rename src/test/ui/{output-width => diagnostic-width}/flag-human.rs (84%) rename src/test/ui/{output-width => diagnostic-width}/flag-human.stderr (100%) rename src/test/ui/{output-width => diagnostic-width}/flag-json.rs (80%) rename src/test/ui/{output-width => diagnostic-width}/flag-json.stderr (93%) rename src/test/ui/{output-width => diagnostic-width}/non-1-width-unicode-multiline-label.rs (100%) rename src/test/ui/{output-width => diagnostic-width}/non-1-width-unicode-multiline-label.stderr (100%) rename src/test/ui/{output-width => diagnostic-width}/non-whitespace-trimming-2.rs (100%) rename src/test/ui/{output-width => diagnostic-width}/non-whitespace-trimming-2.stderr (100%) rename src/test/ui/{output-width => diagnostic-width}/non-whitespace-trimming-unicode.rs (100%) rename src/test/ui/{output-width => diagnostic-width}/non-whitespace-trimming-unicode.stderr (100%) rename src/test/ui/{output-width => diagnostic-width}/non-whitespace-trimming.rs (100%) rename src/test/ui/{output-width => diagnostic-width}/non-whitespace-trimming.stderr (100%) rename src/test/ui/{output-width => diagnostic-width}/tabs-trimming.rs (100%) rename src/test/ui/{output-width => diagnostic-width}/tabs-trimming.stderr (100%) rename src/test/ui/{output-width => diagnostic-width}/whitespace-trimming-2.rs (100%) rename src/test/ui/{output-width => diagnostic-width}/whitespace-trimming-2.stderr (100%) rename src/test/ui/{output-width => diagnostic-width}/whitespace-trimming.rs (100%) rename src/test/ui/{output-width => diagnostic-width}/whitespace-trimming.stderr (100%) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 802cd1a165502..85ea8eb393782 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -63,7 +63,7 @@ impl HumanReadableErrorType { bundle: Option>, fallback_bundle: LazyFallbackBundle, teach: bool, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> EmitterWriter { let (short, color_config) = self.unzip(); @@ -76,7 +76,7 @@ impl HumanReadableErrorType { short, teach, color, - output_width, + diagnostic_width, macro_backtrace, ) } @@ -710,7 +710,7 @@ pub struct EmitterWriter { short_message: bool, teach: bool, ui_testing: bool, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, } @@ -730,7 +730,7 @@ impl EmitterWriter { fallback_bundle: LazyFallbackBundle, short_message: bool, teach: bool, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> EmitterWriter { let dst = Destination::from_stderr(color_config); @@ -742,7 +742,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, - output_width, + diagnostic_width, macro_backtrace, } } @@ -755,7 +755,7 @@ impl EmitterWriter { short_message: bool, teach: bool, colored: bool, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> EmitterWriter { EmitterWriter { @@ -766,7 +766,7 @@ impl EmitterWriter { short_message, teach, ui_testing: false, - output_width, + diagnostic_width, macro_backtrace, } } @@ -1615,7 +1615,7 @@ impl EmitterWriter { width_offset + annotated_file.multiline_depth + 1 }; - let column_width = if let Some(width) = self.output_width { + let column_width = if let Some(width) = self.diagnostic_width { width.saturating_sub(code_offset) } else if self.ui_testing { DEFAULT_COLUMN_WIDTH diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 1e87e70922b73..b8cd334b4c6c6 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -42,7 +42,7 @@ pub struct JsonEmitter { pretty: bool, ui_testing: bool, json_rendered: HumanReadableErrorType, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, } @@ -54,7 +54,7 @@ impl JsonEmitter { fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { @@ -66,7 +66,7 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, - output_width, + diagnostic_width, macro_backtrace, } } @@ -76,7 +76,7 @@ impl JsonEmitter { json_rendered: HumanReadableErrorType, fluent_bundle: Option>, fallback_bundle: LazyFallbackBundle, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> JsonEmitter { let file_path_mapping = FilePathMapping::empty(); @@ -87,7 +87,7 @@ impl JsonEmitter { fallback_bundle, pretty, json_rendered, - output_width, + diagnostic_width, macro_backtrace, ) } @@ -100,7 +100,7 @@ impl JsonEmitter { fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, - output_width: Option, + diagnostic_width: Option, macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { @@ -112,7 +112,7 @@ impl JsonEmitter { pretty, ui_testing: false, json_rendered, - output_width, + diagnostic_width, macro_backtrace, } } @@ -345,7 +345,7 @@ impl Diagnostic { je.fluent_bundle.clone(), je.fallback_bundle.clone(), false, - je.output_width, + je.diagnostic_width, je.macro_backtrace, ) .ui_testing(je.ui_testing) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index bad9fb576bf3b..b7da0f229420b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -726,7 +726,7 @@ impl Default for Options { prints: Vec::new(), cg: Default::default(), error_format: ErrorOutputType::default(), - output_width: None, + diagnostic_width: None, externs: Externs(BTreeMap::new()), crate_name: None, libs: Vec::new(), @@ -1430,8 +1430,8 @@ pub fn rustc_optgroups() -> Vec { ), opt::opt_s( "", - "output-width", - "Inform rustc of the width of the output so that errors can be truncated to fit", + "diagnostic-width", + "Inform rustc of the width of the output so that diagnostics can be truncated to fit", "WIDTH", ), opt::multi_s( @@ -2209,8 +2209,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let error_format = parse_error_format(matches, color, json_rendered); - let output_width = matches.opt_get("output-width").unwrap_or_else(|_| { - early_error(error_format, "`--output-width` must be an positive integer"); + let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { + early_error(error_format, "`--diagnostic-width` must be an positive integer"); }); let unparsed_crate_types = matches.opt_strs("crate-type"); @@ -2485,7 +2485,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { prints, cg, error_format, - output_width, + diagnostic_width, externs, unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), crate_name, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b544965f6f23a..b0c74ffb6dcc1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -170,7 +170,7 @@ top_level_options!( test: bool [TRACKED], error_format: ErrorOutputType [UNTRACKED], - output_width: Option [UNTRACKED], + diagnostic_width: Option [UNTRACKED], /// If `Some`, enable incremental compilation, using the given /// directory to store intermediate results. @@ -1389,7 +1389,7 @@ options! { "panic strategy for out-of-memory handling"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], "pass `-install_name @rpath/...` to the macOS linker (default: no)"), - output_width: Option = (None, parse_opt_number, [UNTRACKED], + diagnostic_width: Option = (None, parse_opt_number, [UNTRACKED], "set the current output width for diagnostic truncation"), panic_abort_tests: bool = (false, parse_bool, [TRACKED], "support compiling tests with panic=abort (default: no)"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index e22b7a5539f7d..52b9ee9471802 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1162,7 +1162,7 @@ fn default_emitter( fallback_bundle, short, sopts.debugging_opts.teach, - sopts.output_width, + sopts.diagnostic_width, macro_backtrace, ), Some(dst) => EmitterWriter::new( @@ -1173,7 +1173,7 @@ fn default_emitter( short, false, // no teach messages when writing to a buffer false, // no colors when writing to a buffer - None, // no terminal width + None, // no diagnostic width macro_backtrace, ), }; @@ -1188,7 +1188,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.output_width, + sopts.diagnostic_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), @@ -1202,7 +1202,7 @@ fn default_emitter( fallback_bundle, pretty, json_rendered, - sopts.output_width, + sopts.diagnostic_width, macro_backtrace, ) .ui_testing(sopts.debugging_opts.ui_testing), diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0285f15dd76fa..f0b54cb444de2 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -73,8 +73,8 @@ pub(crate) struct Options { pub(crate) proc_macro_crate: bool, /// How to format errors and warnings. pub(crate) error_format: ErrorOutputType, - /// Width of terminal to truncate errors appropriately. - pub(crate) output_width: Option, + /// Width of output buffer to truncate errors appropriately. + pub(crate) diagnostic_width: Option, /// Library search paths to hand to the compiler. pub(crate) libs: Vec, /// Library search paths strings to hand to the compiler. @@ -336,12 +336,12 @@ impl Options { let config::JsonConfig { json_rendered, json_unused_externs, .. } = config::parse_json(matches); let error_format = config::parse_error_format(matches, color, json_rendered); - let output_width = matches.opt_get("output-width").unwrap_or_default(); + let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default(); let codegen_options = CodegenOptions::build(matches, error_format); let debugging_opts = DebuggingOptions::build(matches, error_format); - let diag = new_handler(error_format, None, output_width, &debugging_opts); + let diag = new_handler(error_format, None, diagnostic_width, &debugging_opts); // check for deprecated options check_deprecated_options(matches, &diag); @@ -705,7 +705,7 @@ impl Options { input, proc_macro_crate, error_format, - output_width, + diagnostic_width, libs, lib_strs, externs, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index d85e9d974dbcd..8c494ee28cc1f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -154,7 +154,7 @@ impl<'tcx> DocContext<'tcx> { pub(crate) fn new_handler( error_format: ErrorOutputType, source_map: Option>, - output_width: Option, + diagnostic_width: Option, debugging_opts: &DebuggingOptions, ) -> rustc_errors::Handler { let fallback_bundle = @@ -170,7 +170,7 @@ pub(crate) fn new_handler( fallback_bundle, short, debugging_opts.teach, - output_width, + diagnostic_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -188,7 +188,7 @@ pub(crate) fn new_handler( fallback_bundle, pretty, json_rendered, - output_width, + diagnostic_width, false, ) .ui_testing(debugging_opts.ui_testing), @@ -209,7 +209,7 @@ pub(crate) fn create_config( crate_name, proc_macro_crate, error_format, - output_width, + diagnostic_width, libs, externs, mut cfgs, @@ -268,7 +268,7 @@ pub(crate) fn create_config( actually_rustdoc: true, debugging_opts, error_format, - output_width, + diagnostic_width, edition, describe_lints, crate_name, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b0be3502baed3..0d3ec7ecb6448 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -462,10 +462,10 @@ fn opts() -> Vec { "human|json|short", ) }), - unstable("output-width", |o| { + unstable("diagnostic-width", |o| { o.optopt( "", - "output-width", + "diagnostic-width", "Provide width of the output for truncated error messages", "WIDTH", ) @@ -744,7 +744,7 @@ fn main_options(options: config::Options) -> MainResult { let diag = core::new_handler( options.error_format, None, - options.output_width, + options.diagnostic_width, &options.debugging_opts, ); diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout index 64b31adc63e4d..08877af928657 100644 --- a/src/test/run-make/issue-88756-default-output/output-default.stdout +++ b/src/test/run-make/issue-88756-default-output/output-default.stdout @@ -110,7 +110,7 @@ Options: never = never colorize output --error-format human|json|short How errors and other messages are produced - --output-width WIDTH + --diagnostic-width WIDTH Provide width of the output for truncated error messages --json CONFIG Configure the structure of JSON diagnostics diff --git a/src/test/rustdoc-ui/output-width.rs b/src/test/rustdoc-ui/diagnostic-width.rs similarity index 65% rename from src/test/rustdoc-ui/output-width.rs rename to src/test/rustdoc-ui/diagnostic-width.rs index 9fb680474475c..61961d5ec710e 100644 --- a/src/test/rustdoc-ui/output-width.rs +++ b/src/test/rustdoc-ui/diagnostic-width.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zunstable-options --output-width=10 +// compile-flags: -Zunstable-options --diagnostic-width=10 #![deny(rustdoc::bare_urls)] /// This is a long line that contains a http://link.com diff --git a/src/test/rustdoc-ui/output-width.stderr b/src/test/rustdoc-ui/diagnostic-width.stderr similarity index 83% rename from src/test/rustdoc-ui/output-width.stderr rename to src/test/rustdoc-ui/diagnostic-width.stderr index dc790530300cf..fed049d2b37bc 100644 --- a/src/test/rustdoc-ui/output-width.stderr +++ b/src/test/rustdoc-ui/diagnostic-width.stderr @@ -1,11 +1,11 @@ error: this URL is not a hyperlink - --> $DIR/output-width.rs:4:41 + --> $DIR/diagnostic-width.rs:4:41 | LL | ... a http://link.com | ^^^^^^^^^^^^^^^ help: use an automatic link instead: `` | note: the lint level is defined here - --> $DIR/output-width.rs:2:9 + --> $DIR/diagnostic-width.rs:2:9 | LL | ...ny(rustdoc::bare_url... | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/output-width/flag-human.rs b/src/test/ui/diagnostic-width/flag-human.rs similarity index 84% rename from src/test/ui/output-width/flag-human.rs rename to src/test/ui/diagnostic-width/flag-human.rs index 44e9ba044230a..289bfbabd949b 100644 --- a/src/test/ui/output-width/flag-human.rs +++ b/src/test/ui/diagnostic-width/flag-human.rs @@ -1,4 +1,4 @@ -// compile-flags: --output-width=20 +// compile-flags: --diagnostic-width=20 // This test checks that `-Z output-width` effects the human error output by restricting it to an // arbitrarily low value so that the effect is visible. diff --git a/src/test/ui/output-width/flag-human.stderr b/src/test/ui/diagnostic-width/flag-human.stderr similarity index 100% rename from src/test/ui/output-width/flag-human.stderr rename to src/test/ui/diagnostic-width/flag-human.stderr diff --git a/src/test/ui/output-width/flag-json.rs b/src/test/ui/diagnostic-width/flag-json.rs similarity index 80% rename from src/test/ui/output-width/flag-json.rs rename to src/test/ui/diagnostic-width/flag-json.rs index ec01dcb88189a..51a1fb447c7d2 100644 --- a/src/test/ui/output-width/flag-json.rs +++ b/src/test/ui/diagnostic-width/flag-json.rs @@ -1,4 +1,4 @@ -// compile-flags: --output-width=20 --error-format=json +// compile-flags: --diagnostic-width=20 --error-format=json // This test checks that `-Z output-width` effects the JSON error output by restricting it to an // arbitrarily low value so that the effect is visible. diff --git a/src/test/ui/output-width/flag-json.stderr b/src/test/ui/diagnostic-width/flag-json.stderr similarity index 93% rename from src/test/ui/output-width/flag-json.stderr rename to src/test/ui/diagnostic-width/flag-json.stderr index 097ca1d6e1780..b21391d1640ef 100644 --- a/src/test/ui/output-width/flag-json.stderr +++ b/src/test/ui/diagnostic-width/flag-json.stderr @@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":239,"byte_end":241,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":234,"byte_end":236,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":243,"byte_end":245,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":238,"byte_end":240,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types --> $DIR/flag-json.rs:7:17 | LL | ..._: () = 42; diff --git a/src/test/ui/output-width/non-1-width-unicode-multiline-label.rs b/src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs similarity index 100% rename from src/test/ui/output-width/non-1-width-unicode-multiline-label.rs rename to src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs diff --git a/src/test/ui/output-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr similarity index 100% rename from src/test/ui/output-width/non-1-width-unicode-multiline-label.stderr rename to src/test/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr diff --git a/src/test/ui/output-width/non-whitespace-trimming-2.rs b/src/test/ui/diagnostic-width/non-whitespace-trimming-2.rs similarity index 100% rename from src/test/ui/output-width/non-whitespace-trimming-2.rs rename to src/test/ui/diagnostic-width/non-whitespace-trimming-2.rs diff --git a/src/test/ui/output-width/non-whitespace-trimming-2.stderr b/src/test/ui/diagnostic-width/non-whitespace-trimming-2.stderr similarity index 100% rename from src/test/ui/output-width/non-whitespace-trimming-2.stderr rename to src/test/ui/diagnostic-width/non-whitespace-trimming-2.stderr diff --git a/src/test/ui/output-width/non-whitespace-trimming-unicode.rs b/src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.rs similarity index 100% rename from src/test/ui/output-width/non-whitespace-trimming-unicode.rs rename to src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.rs diff --git a/src/test/ui/output-width/non-whitespace-trimming-unicode.stderr b/src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr similarity index 100% rename from src/test/ui/output-width/non-whitespace-trimming-unicode.stderr rename to src/test/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr diff --git a/src/test/ui/output-width/non-whitespace-trimming.rs b/src/test/ui/diagnostic-width/non-whitespace-trimming.rs similarity index 100% rename from src/test/ui/output-width/non-whitespace-trimming.rs rename to src/test/ui/diagnostic-width/non-whitespace-trimming.rs diff --git a/src/test/ui/output-width/non-whitespace-trimming.stderr b/src/test/ui/diagnostic-width/non-whitespace-trimming.stderr similarity index 100% rename from src/test/ui/output-width/non-whitespace-trimming.stderr rename to src/test/ui/diagnostic-width/non-whitespace-trimming.stderr diff --git a/src/test/ui/output-width/tabs-trimming.rs b/src/test/ui/diagnostic-width/tabs-trimming.rs similarity index 100% rename from src/test/ui/output-width/tabs-trimming.rs rename to src/test/ui/diagnostic-width/tabs-trimming.rs diff --git a/src/test/ui/output-width/tabs-trimming.stderr b/src/test/ui/diagnostic-width/tabs-trimming.stderr similarity index 100% rename from src/test/ui/output-width/tabs-trimming.stderr rename to src/test/ui/diagnostic-width/tabs-trimming.stderr diff --git a/src/test/ui/output-width/whitespace-trimming-2.rs b/src/test/ui/diagnostic-width/whitespace-trimming-2.rs similarity index 100% rename from src/test/ui/output-width/whitespace-trimming-2.rs rename to src/test/ui/diagnostic-width/whitespace-trimming-2.rs diff --git a/src/test/ui/output-width/whitespace-trimming-2.stderr b/src/test/ui/diagnostic-width/whitespace-trimming-2.stderr similarity index 100% rename from src/test/ui/output-width/whitespace-trimming-2.stderr rename to src/test/ui/diagnostic-width/whitespace-trimming-2.stderr diff --git a/src/test/ui/output-width/whitespace-trimming.rs b/src/test/ui/diagnostic-width/whitespace-trimming.rs similarity index 100% rename from src/test/ui/output-width/whitespace-trimming.rs rename to src/test/ui/diagnostic-width/whitespace-trimming.rs diff --git a/src/test/ui/output-width/whitespace-trimming.stderr b/src/test/ui/diagnostic-width/whitespace-trimming.stderr similarity index 100% rename from src/test/ui/output-width/whitespace-trimming.stderr rename to src/test/ui/diagnostic-width/whitespace-trimming.stderr From 933a9941114a9ac5ce92cc7197498f698a86c3f4 Mon Sep 17 00:00:00 2001 From: pierwill Date: Thu, 7 Jul 2022 11:32:52 -0500 Subject: [PATCH 6/9] Add doc comments in `rustc_middle::mir` --- compiler/rustc_middle/src/mir/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e7d7317456c74..156aad1ec39ad 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1156,6 +1156,8 @@ impl BasicBlock { /////////////////////////////////////////////////////////////////////////// // BasicBlockData +/// Data for a basic block, including a list of its statements. +/// /// See [`BasicBlock`] for documentation on what basic blocks are at a high level. #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct BasicBlockData<'tcx> { @@ -1187,7 +1189,7 @@ impl<'tcx> BasicBlockData<'tcx> { /// Accessor for terminator. /// /// Terminator may not be None after construction of the basic block is complete. This accessor - /// provides a convenience way to reach the terminator. + /// provides a convenient way to reach the terminator. #[inline] pub fn terminator(&self) -> &Terminator<'tcx> { self.terminator.as_ref().expect("invalid terminator state") @@ -1394,6 +1396,7 @@ impl fmt::Debug for AssertKind { /////////////////////////////////////////////////////////////////////////// // Statements +/// A statement in a basic block, including information about its source code. #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Statement<'tcx> { pub source_info: SourceInfo, From 98b84195a217f53659d8f88ff9427ac7e463ccfb Mon Sep 17 00:00:00 2001 From: Andrea Nall Date: Thu, 7 Jul 2022 19:30:37 +0000 Subject: [PATCH 7/9] Add test for and fix rust-lang/rust-clippy#9131 This lint seems to have been broken by #98446 --- src/tools/clippy/clippy_lints/src/misc.rs | 2 +- src/tools/clippy/tests/ui/used_underscore_binding.rs | 6 ++++++ src/tools/clippy/tests/ui/used_underscore_binding.stderr | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index df2430ced6b62..be7df08d89f05 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -301,7 +301,7 @@ fn in_attributes_expansion(expr: &Expr<'_>) -> bool { use rustc_span::hygiene::MacroKind; if expr.span.from_expansion() { let data = expr.span.ctxt().outer_expn_data(); - matches!(data.kind, ExpnKind::Macro(MacroKind::Attr, _)) + matches!(data.kind, ExpnKind::Macro(MacroKind::Attr|MacroKind::Derive, _)) } else { false } diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs index 21d66d5df79ec..d20977d55d29d 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.rs +++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs @@ -44,6 +44,12 @@ fn in_struct_field() { s._underscore_field += 1; } +/// Tests that we do not lint if the struct field is used in code created with derive. +#[derive(Clone, Debug)] +pub struct UnderscoreInStruct { + _foo: u32, +} + /// Tests that we do not lint if the underscore is not a prefix fn non_prefix_underscore(some_foo: u32) -> u32 { some_foo + 1 diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr index 790b849210c9b..61a9161d212da 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr +++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr @@ -31,7 +31,7 @@ LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used - --> $DIR/used_underscore_binding.rs:99:16 + --> $DIR/used_underscore_binding.rs:105:16 | LL | uses_i(_i); | ^^ From 24714310170f0d0214ceafe114c24b8d5b6746f0 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Tue, 28 Jun 2022 00:08:35 -0400 Subject: [PATCH 8/9] Move is_free and is_free_or_static to Region, change resolve_var to resolve_region, and remove RootEmptyRegion --- .../rustc_borrowck/src/region_infer/mod.rs | 18 +++++------- .../rustc_borrowck/src/universal_regions.rs | 2 +- .../rustc_infer/src/infer/free_regions.rs | 24 ++++------------ .../src/infer/lexical_region_resolve/mod.rs | 28 ++++++++++--------- compiler/rustc_infer/src/infer/mod.rs | 4 --- compiler/rustc_infer/src/infer/resolve.rs | 4 +-- compiler/rustc_middle/src/ty/sty.rs | 13 +++++++++ 7 files changed, 43 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index d0e0203bf8c44..ea3602e8a056a 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -495,8 +495,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Existential { .. } => { + NllRegionVariableOrigin::Existential { .. } => { // For existential, regions, nothing to do. } } @@ -1410,8 +1409,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_bound_universal_region(fr, placeholder, errors_buffer); } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Existential { .. } => { + NllRegionVariableOrigin::Existential { .. } => { // nothing to check here } } @@ -1513,8 +1511,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_bound_universal_region(fr, placeholder, errors_buffer); } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Existential { .. } => { + NllRegionVariableOrigin::Existential { .. } => { // nothing to check here } } @@ -1788,9 +1785,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { universe1.cannot_name(placeholder.universe) } - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::FreeRegion - | NllRegionVariableOrigin::Existential { .. } => false, + NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { .. } => { + false + } } } @@ -2152,8 +2149,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let blame_source = match from_region_origin { NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { from_forall: false } => true, - NllRegionVariableOrigin::RootEmptyRegion - | NllRegionVariableOrigin::Placeholder(_) + NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::Existential { from_forall: true } => false, }; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 89d84fcf09cfe..2a7713bc4df3b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -503,7 +503,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let root_empty = self .infcx - .next_nll_region_var(NllRegionVariableOrigin::RootEmptyRegion) + .next_nll_region_var(NllRegionVariableOrigin::Existential { from_forall: true }) .to_region_vid(); UniversalRegions { diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index fad949a3bc6a1..d566634a49203 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -4,7 +4,7 @@ //! and use that to decide when one free region outlives another, and so forth. use rustc_data_structures::transitive_relation::TransitiveRelation; -use rustc_middle::ty::{self, Lift, Region, TyCtxt}; +use rustc_middle::ty::{Lift, Region, TyCtxt}; /// Combines a `FreeRegionMap` and a `TyCtxt`. /// @@ -49,7 +49,7 @@ impl<'tcx> FreeRegionMap<'tcx> { // (with the exception that `'static: 'x` is not notable) pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) { debug!("relate_regions(sub={:?}, sup={:?})", sub, sup); - if self.is_free_or_static(sub) && self.is_free(sup) { + if sub.is_free_or_static() && sup.is_free() { self.relation.add(sub, sup) } } @@ -68,7 +68,7 @@ impl<'tcx> FreeRegionMap<'tcx> { r_a: Region<'tcx>, r_b: Region<'tcx>, ) -> bool { - assert!(self.is_free_or_static(r_a) && self.is_free_or_static(r_b)); + assert!(r_a.is_free_or_static() && r_b.is_free_or_static()); let re_static = tcx.lifetimes.re_static; if self.check_relation(re_static, r_b) { // `'a <= 'static` is always true, and not stored in the @@ -85,20 +85,6 @@ impl<'tcx> FreeRegionMap<'tcx> { r_a == r_b || self.relation.contains(r_a, r_b) } - /// True for free regions other than `'static`. - pub fn is_free(&self, r: Region<'_>) -> bool { - matches!(*r, ty::ReEarlyBound(_) | ty::ReFree(_)) - } - - /// True if `r` is a free region or static of the sort that this - /// free region map can be used with. - pub fn is_free_or_static(&self, r: Region<'_>) -> bool { - match *r { - ty::ReStatic => true, - _ => self.is_free(r), - } - } - /// Computes the least-upper-bound of two free regions. In some /// cases, this is more conservative than necessary, in order to /// avoid making arbitrary choices. See @@ -110,8 +96,8 @@ impl<'tcx> FreeRegionMap<'tcx> { r_b: Region<'tcx>, ) -> Region<'tcx> { debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b); - assert!(self.is_free(r_a)); - assert!(self.is_free(r_b)); + assert!(r_a.is_free()); + assert!(r_b.is_free()); let result = if r_a == r_b { r_a } else { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 87fa22b3835ef..3783cfb4cc5c8 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -47,7 +47,6 @@ pub(crate) fn resolve<'tcx>( #[derive(Clone)] pub struct LexicalRegionResolutions<'tcx> { pub(crate) values: IndexVec>, - pub(crate) error_region: ty::Region<'tcx>, } #[derive(Copy, Clone, Debug)] @@ -140,7 +139,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// empty region. The `expansion` phase will grow this larger. fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> { LexicalRegionResolutions { - error_region: tcx.lifetimes.re_static, values: IndexVec::from_fn_n( |vid| { let vid_universe = self.var_infos[vid].universe; @@ -310,7 +308,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // Check for the case where we know that `'b: 'static` -- in that case, // `a <= b` for all `a`. - let b_free_or_static = self.region_rels.free_regions.is_free_or_static(b); + let b_free_or_static = b.is_free_or_static(); if b_free_or_static && sub_free_regions(tcx.lifetimes.re_static, b) { return true; } @@ -320,7 +318,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // `lub` relationship defined below, since sometimes the "lub" // is actually the `postdom_upper_bound` (see // `TransitiveRelation` for more details). - let a_free_or_static = self.region_rels.free_regions.is_free_or_static(a); + let a_free_or_static = a.is_free_or_static(); if a_free_or_static && b_free_or_static { return sub_free_regions(a, b); } @@ -864,10 +862,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { where T: TypeFoldable<'tcx>, { - tcx.fold_regions(value, |r, _db| match *r { - ty::ReVar(rid) => self.resolve_var(rid), - _ => r, - }) + tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r)) } fn value(&self, rid: RegionVid) -> &VarValue<'tcx> { @@ -878,12 +873,19 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { &mut self.values[rid] } - pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> { - let result = match self.values[rid] { - VarValue::Value(r) => r, - VarValue::ErrorValue => self.error_region, + pub(crate) fn resolve_region( + &self, + tcx: TyCtxt<'tcx>, + r: ty::Region<'tcx>, + ) -> ty::Region<'tcx> { + let result = match *r { + ty::ReVar(rid) => match self.values[rid] { + VarValue::Value(r) => r, + VarValue::ErrorValue => tcx.lifetimes.re_static, + }, + _ => r, }; - debug!("resolve_var({:?}) = {:?}", rid, result); + debug!("resolve_region({:?}) = {:?}", r, result); result } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 991fd23ab4344..6e0f2d687437b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -466,9 +466,6 @@ pub enum NllRegionVariableOrigin { /// from a `for<'a> T` binder). Meant to represent "any region". Placeholder(ty::PlaceholderRegion), - /// The variable we create to represent `'empty(U0)`. - RootEmptyRegion, - Existential { /// If this is true, then this variable was created to represent a lifetime /// bound in a `for` binder. For example, it might have been created to @@ -1250,7 +1247,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let lexical_region_resolutions = LexicalRegionResolutions { - error_region: self.tcx.lifetimes.re_static, values: rustc_index::vec::IndexVec::from_elem_n( crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), var_infos.len(), diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index a614568742920..3d99f0958f7f9 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -206,13 +206,13 @@ impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { match *r { - ty::ReVar(rid) => Ok(self + ty::ReVar(_) => Ok(self .infcx .lexical_region_resolutions .borrow() .as_ref() .expect("region resolution not performed") - .resolve_var(rid)), + .resolve_region(self.infcx.tcx, r)), _ => Ok(r), } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 815e39aab5715..03e4319bbf1a8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1570,6 +1570,19 @@ impl<'tcx> Region<'tcx> { _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), } } + + /// True for free regions other than `'static`. + pub fn is_free(self) -> bool { + matches!(*self, ty::ReEarlyBound(_) | ty::ReFree(_)) + } + + /// True if `self` is a free region or static. + pub fn is_free_or_static(self) -> bool { + match *self { + ty::ReStatic => true, + _ => self.is_free(), + } + } } /// Type utilities From 31e1a777e7b055b240b507a7c04719c0563852e9 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Thu, 30 Jun 2022 21:27:13 -0400 Subject: [PATCH 9/9] Move code from rustc_trait_selection/opaque_types to better places --- .../src/region_infer/opaque_types.rs | 484 +++++++++++++++- compiler/rustc_trait_selection/src/lib.rs | 1 - .../rustc_trait_selection/src/opaque_types.rs | 545 ------------------ .../rustc_trait_selection/src/traits/wf.rs | 61 +- 4 files changed, 542 insertions(+), 549 deletions(-) delete mode 100644 compiler/rustc_trait_selection/src/opaque_types.rs diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index d129e8454265b..7c1fa28b8dfcc 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,11 +1,20 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::DefId; use rustc_hir::OpaqueTyOrigin; +use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::InferCtxt; +use rustc_infer::infer::TyCtxtInferExt as _; +use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; +use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; +use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ - self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable, TypeVisitable, + self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable, }; -use rustc_trait_selection::opaque_types::InferCtxtExt; +use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::TraitEngineExt as _; use super::RegionInferenceContext; @@ -173,3 +182,474 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) } } + +pub trait InferCtxtExt<'tcx> { + fn infer_opaque_definition_from_instantiation( + &self, + opaque_type_key: OpaqueTypeKey<'tcx>, + instantiated_ty: OpaqueHiddenType<'tcx>, + origin: OpaqueTyOrigin, + ) -> Ty<'tcx>; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { + /// Given the fully resolved, instantiated type for an opaque + /// type, i.e., the value of an inference variable like C1 or C2 + /// (*), computes the "definition type" for an opaque type + /// definition -- that is, the inferred value of `Foo1<'x>` or + /// `Foo2<'x>` that we would conceptually use in its definition: + /// ```ignore (illustrative) + /// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA + /// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB + /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } + /// ``` + /// Note that these values are defined in terms of a distinct set of + /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main + /// purpose of this function is to do that translation. + /// + /// (*) C1 and C2 were introduced in the comments on + /// `register_member_constraints`. Read that comment for more context. + /// + /// # Parameters + /// + /// - `def_id`, the `impl Trait` type + /// - `substs`, the substs used to instantiate this opaque type + /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of + /// `opaque_defn.concrete_ty` + #[instrument(level = "debug", skip(self))] + fn infer_opaque_definition_from_instantiation( + &self, + opaque_type_key: OpaqueTypeKey<'tcx>, + instantiated_ty: OpaqueHiddenType<'tcx>, + origin: OpaqueTyOrigin, + ) -> Ty<'tcx> { + if self.is_tainted_by_errors() { + return self.tcx.ty_error(); + } + + let OpaqueTypeKey { def_id, substs } = opaque_type_key; + + // Use substs to build up a reverse map from regions to their + // identity mappings. This is necessary because of `impl + // Trait` lifetimes are computed by replacing existing + // lifetimes with 'static and remapping only those used in the + // `impl Trait` return type, resulting in the parameters + // shifting. + let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); + debug!(?id_substs); + let map: FxHashMap, GenericArg<'tcx>> = + substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect(); + debug!("map = {:#?}", map); + + // Convert the type from the function into a type valid outside + // the function, by replacing invalid regions with 'static, + // after producing an error for each of them. + let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new( + self.tcx, + def_id, + map, + instantiated_ty.ty, + instantiated_ty.span, + )); + debug!(?definition_ty); + + if !check_opaque_type_parameter_valid( + self.tcx, + opaque_type_key, + origin, + instantiated_ty.span, + ) { + return self.tcx.ty_error(); + } + + // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` + // on stable and we'd break that. + if let OpaqueTyOrigin::TyAlias = origin { + // This logic duplicates most of `check_opaque_meets_bounds`. + // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. + let param_env = self.tcx.param_env(def_id); + let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()); + self.tcx.infer_ctxt().enter(move |infcx| { + // Require the hidden type to be well-formed with only the generics of the opaque type. + // Defining use functions may have more bounds than the opaque type, which is ok, as long as the + // hidden type is well formed even without those bounds. + let predicate = + ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) + .to_predicate(infcx.tcx); + let mut fulfillment_cx = >::new(infcx.tcx); + + // Require that the hidden type actually fulfills all the bounds of the opaque type, even without + // the bounds that the function supplies. + match infcx.register_hidden_type( + OpaqueTypeKey { def_id, substs: id_substs }, + ObligationCause::misc(instantiated_ty.span, body_id), + param_env, + definition_ty, + origin, + ) { + Ok(infer_ok) => { + for obligation in infer_ok.obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + } + } + Err(err) => { + infcx + .report_mismatched_types( + &ObligationCause::misc(instantiated_ty.span, body_id), + self.tcx.mk_opaque(def_id, id_substs), + definition_ty, + err, + ) + .emit(); + } + } + + fulfillment_cx.register_predicate_obligation( + &infcx, + Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), + ); + + // Check that all obligations are satisfied by the implementation's + // version. + let errors = fulfillment_cx.select_all_or_error(&infcx); + + let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + + if errors.is_empty() { + definition_ty + } else { + infcx.report_fulfillment_errors(&errors, None, false); + self.tcx.ty_error() + } + }) + } else { + definition_ty + } + } +} + +fn check_opaque_type_parameter_valid( + tcx: TyCtxt<'_>, + opaque_type_key: OpaqueTypeKey<'_>, + origin: OpaqueTyOrigin, + span: Span, +) -> bool { + match origin { + // No need to check return position impl trait (RPIT) + // because for type and const parameters they are correct + // by construction: we convert + // + // fn foo() -> impl Trait + // + // into + // + // type Foo + // fn foo() -> Foo. + // + // For lifetime parameters we convert + // + // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> + // + // into + // + // type foo::<'p0..'pn>::Foo<'q0..'qm> + // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. + // + // which would error here on all of the `'static` args. + OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, + // Check these + OpaqueTyOrigin::TyAlias => {} + } + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); + let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); + for (i, arg) in opaque_type_key.substs.iter().enumerate() { + let arg_is_param = match arg.unpack() { + GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), + GenericArgKind::Lifetime(lt) if lt.is_static() => { + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_label( + tcx.def_span(opaque_generics.param_at(i, tcx).def_id), + "cannot use static lifetime; use a bound lifetime \ + instead or remove the lifetime parameter from the \ + opaque type", + ) + .emit(); + return false; + } + GenericArgKind::Lifetime(lt) => { + matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) + } + GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), + }; + + if arg_is_param { + seen_params.entry(arg).or_default().push(i); + } else { + // Prevent `fn foo() -> Foo` from being defining. + let opaque_param = opaque_generics.param_at(i, tcx); + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_note( + tcx.def_span(opaque_param.def_id), + &format!( + "used non-generic {} `{}` for generic parameter", + opaque_param.kind.descr(), + arg, + ), + ) + .emit(); + return false; + } + } + + for (_, indices) in seen_params { + if indices.len() > 1 { + let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); + let spans: Vec<_> = indices + .into_iter() + .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) + .collect(); + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_note(spans, &format!("{} used multiple times", descr)) + .emit(); + return false; + } + } + true +} + +struct ReverseMapper<'tcx> { + tcx: TyCtxt<'tcx>, + + opaque_type_def_id: DefId, + map: FxHashMap, GenericArg<'tcx>>, + map_missing_regions_to_empty: bool, + + /// initially `Some`, set to `None` once error has been reported + hidden_ty: Option>, + + /// Span of function being checked. + span: Span, +} + +impl<'tcx> ReverseMapper<'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + opaque_type_def_id: DefId, + map: FxHashMap, GenericArg<'tcx>>, + hidden_ty: Ty<'tcx>, + span: Span, + ) -> Self { + Self { + tcx, + opaque_type_def_id, + map, + map_missing_regions_to_empty: false, + hidden_ty: Some(hidden_ty), + span, + } + } + + fn fold_kind_mapping_missing_regions_to_empty( + &mut self, + kind: GenericArg<'tcx>, + ) -> GenericArg<'tcx> { + assert!(!self.map_missing_regions_to_empty); + self.map_missing_regions_to_empty = true; + let kind = kind.fold_with(self); + self.map_missing_regions_to_empty = false; + kind + } + + fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { + assert!(!self.map_missing_regions_to_empty); + kind.fold_with(self) + } +} + +impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + #[instrument(skip(self), level = "debug")] + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + // Ignore bound regions and `'static` regions that appear in the + // type, we only need to remap regions that reference lifetimes + // from the function declaration. + // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReLateBound(..) | ty::ReStatic => return r, + + // If regions have been erased (by writeback), don't try to unerase + // them. + ty::ReErased => return r, + + // The regions that we expect from borrow checking. + ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} + + ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => { + // All of the regions in the type should either have been + // erased by writeback, or mapped back to named regions by + // borrow checking. + bug!("unexpected region kind in opaque type: {:?}", r); + } + } + + let generics = self.tcx().generics_of(self.opaque_type_def_id); + match self.map.get(&r.into()).map(|k| k.unpack()) { + Some(GenericArgKind::Lifetime(r1)) => r1, + Some(u) => panic!("region mapped to unexpected kind: {:?}", u), + None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty, + None if generics.parent.is_some() => { + if let Some(hidden_ty) = self.hidden_ty.take() { + unexpected_hidden_region_diagnostic( + self.tcx, + self.tcx.def_span(self.opaque_type_def_id), + hidden_ty, + r, + ) + .emit(); + } + self.tcx.lifetimes.re_root_empty + } + None => { + self.tcx + .sess + .struct_span_err(self.span, "non-defining opaque type use in defining scope") + .span_label( + self.span, + format!( + "lifetime `{}` is part of concrete type but not used in \ + parameter list of the `impl Trait` type alias", + r + ), + ) + .emit(); + + self.tcx().lifetimes.re_static + } + } + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match *ty.kind() { + ty::Closure(def_id, substs) => { + // I am a horrible monster and I pray for death. When + // we encounter a closure here, it is always a closure + // from within the function that we are currently + // type-checking -- one that is now being encapsulated + // in an opaque type. Ideally, we would + // go through the types/lifetimes that it references + // and treat them just like we would any other type, + // which means we would error out if we find any + // reference to a type/region that is not in the + // "reverse map". + // + // **However,** in the case of closures, there is a + // somewhat subtle (read: hacky) consideration. The + // problem is that our closure types currently include + // all the lifetime parameters declared on the + // enclosing function, even if they are unused by the + // closure itself. We can't readily filter them out, + // so here we replace those values with `'empty`. This + // can't really make a difference to the rest of the + // compiler; those regions are ignored for the + // outlives relation, and hence don't affect trait + // selection or auto traits, and they are erased + // during codegen. + + let generics = self.tcx.generics_of(def_id); + let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + })); + + self.tcx.mk_closure(def_id, substs) + } + + ty::Generator(def_id, substs, movability) => { + let generics = self.tcx.generics_of(def_id); + let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + })); + + self.tcx.mk_generator(def_id, substs, movability) + } + + ty::Param(param) => { + // Look it up in the substitution list. + match self.map.get(&ty.into()).map(|k| k.unpack()) { + // Found it in the substitution list; replace with the parameter from the + // opaque type. + Some(GenericArgKind::Type(t1)) => t1, + Some(u) => panic!("type mapped to unexpected kind: {:?}", u), + None => { + debug!(?param, ?self.map); + self.tcx + .sess + .struct_span_err( + self.span, + &format!( + "type parameter `{}` is part of concrete type but not \ + used in parameter list for the `impl Trait` type alias", + ty + ), + ) + .emit(); + + self.tcx().ty_error() + } + } + } + + _ => ty.super_fold_with(self), + } + } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + trace!("checking const {:?}", ct); + // Find a const parameter + match ct.kind() { + ty::ConstKind::Param(..) => { + // Look it up in the substitution list. + match self.map.get(&ct.into()).map(|k| k.unpack()) { + // Found it in the substitution list, replace with the parameter from the + // opaque type. + Some(GenericArgKind::Const(c1)) => c1, + Some(u) => panic!("const mapped to unexpected kind: {:?}", u), + None => { + self.tcx + .sess + .struct_span_err( + self.span, + &format!( + "const parameter `{}` is part of concrete type but not \ + used in parameter list for the `impl Trait` type alias", + ct + ), + ) + .emit(); + + self.tcx().const_error(ct.ty()) + } + } + } + + _ => ct, + } + } +} diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 44ff3fd73061e..282ee632ce581 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -37,5 +37,4 @@ extern crate smallvec; pub mod autoderef; pub mod infer; -pub mod opaque_types; pub mod traits; diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs deleted file mode 100644 index d290f7b074cb5..0000000000000 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ /dev/null @@ -1,545 +0,0 @@ -use crate::traits; -use crate::traits::error_reporting::InferCtxtExt as _; -use crate::traits::TraitEngineExt as _; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::DefId; -use rustc_hir::OpaqueTyOrigin; -use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt as _}; -use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; -use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt}; -use rustc_span::Span; - -pub trait InferCtxtExt<'tcx> { - fn infer_opaque_definition_from_instantiation( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - instantiated_ty: OpaqueHiddenType<'tcx>, - origin: OpaqueTyOrigin, - ) -> Ty<'tcx>; -} - -impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { - /// Given the fully resolved, instantiated type for an opaque - /// type, i.e., the value of an inference variable like C1 or C2 - /// (*), computes the "definition type" for an opaque type - /// definition -- that is, the inferred value of `Foo1<'x>` or - /// `Foo2<'x>` that we would conceptually use in its definition: - /// ```ignore (illustrative) - /// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA - /// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB - /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } - /// ``` - /// Note that these values are defined in terms of a distinct set of - /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main - /// purpose of this function is to do that translation. - /// - /// (*) C1 and C2 were introduced in the comments on - /// `register_member_constraints`. Read that comment for more context. - /// - /// # Parameters - /// - /// - `def_id`, the `impl Trait` type - /// - `substs`, the substs used to instantiate this opaque type - /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of - /// `opaque_defn.concrete_ty` - #[instrument(level = "debug", skip(self))] - fn infer_opaque_definition_from_instantiation( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - instantiated_ty: OpaqueHiddenType<'tcx>, - origin: OpaqueTyOrigin, - ) -> Ty<'tcx> { - if self.is_tainted_by_errors() { - return self.tcx.ty_error(); - } - - let OpaqueTypeKey { def_id, substs } = opaque_type_key; - - // Use substs to build up a reverse map from regions to their - // identity mappings. This is necessary because of `impl - // Trait` lifetimes are computed by replacing existing - // lifetimes with 'static and remapping only those used in the - // `impl Trait` return type, resulting in the parameters - // shifting. - let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); - debug!(?id_substs); - let map: FxHashMap, GenericArg<'tcx>> = - substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect(); - debug!("map = {:#?}", map); - - // Convert the type from the function into a type valid outside - // the function, by replacing invalid regions with 'static, - // after producing an error for each of them. - let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new( - self.tcx, - def_id, - map, - instantiated_ty.ty, - instantiated_ty.span, - )); - debug!(?definition_ty); - - if !check_opaque_type_parameter_valid( - self.tcx, - opaque_type_key, - origin, - instantiated_ty.span, - ) { - return self.tcx.ty_error(); - } - - // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` - // on stable and we'd break that. - if let OpaqueTyOrigin::TyAlias = origin { - // This logic duplicates most of `check_opaque_meets_bounds`. - // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. - let param_env = self.tcx.param_env(def_id); - let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()); - self.tcx.infer_ctxt().enter(move |infcx| { - // Require the hidden type to be well-formed with only the generics of the opaque type. - // Defining use functions may have more bounds than the opaque type, which is ok, as long as the - // hidden type is well formed even without those bounds. - let predicate = - ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) - .to_predicate(infcx.tcx); - let mut fulfillment_cx = >::new(infcx.tcx); - - // Require that the hidden type actually fulfills all the bounds of the opaque type, even without - // the bounds that the function supplies. - match infcx.register_hidden_type( - OpaqueTypeKey { def_id, substs: id_substs }, - ObligationCause::misc(instantiated_ty.span, body_id), - param_env, - definition_ty, - origin, - ) { - Ok(infer_ok) => { - for obligation in infer_ok.obligations { - fulfillment_cx.register_predicate_obligation(&infcx, obligation); - } - } - Err(err) => { - infcx - .report_mismatched_types( - &ObligationCause::misc(instantiated_ty.span, body_id), - self.tcx.mk_opaque(def_id, id_substs), - definition_ty, - err, - ) - .emit(); - } - } - - fulfillment_cx.register_predicate_obligation( - &infcx, - Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), - ); - - // Check that all obligations are satisfied by the implementation's - // version. - let errors = fulfillment_cx.select_all_or_error(&infcx); - - let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - - if errors.is_empty() { - definition_ty - } else { - infcx.report_fulfillment_errors(&errors, None, false); - self.tcx.ty_error() - } - }) - } else { - definition_ty - } - } -} - -fn check_opaque_type_parameter_valid( - tcx: TyCtxt<'_>, - opaque_type_key: OpaqueTypeKey<'_>, - origin: OpaqueTyOrigin, - span: Span, -) -> bool { - match origin { - // No need to check return position impl trait (RPIT) - // because for type and const parameters they are correct - // by construction: we convert - // - // fn foo() -> impl Trait - // - // into - // - // type Foo - // fn foo() -> Foo. - // - // For lifetime parameters we convert - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. - // - // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, - // Check these - OpaqueTyOrigin::TyAlias => {} - } - let opaque_generics = tcx.generics_of(opaque_type_key.def_id); - let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); - for (i, arg) in opaque_type_key.substs.iter().enumerate() { - let arg_is_param = match arg.unpack() { - GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - GenericArgKind::Lifetime(lt) if lt.is_static() => { - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_label( - tcx.def_span(opaque_generics.param_at(i, tcx).def_id), - "cannot use static lifetime; use a bound lifetime \ - instead or remove the lifetime parameter from the \ - opaque type", - ) - .emit(); - return false; - } - GenericArgKind::Lifetime(lt) => { - matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) - } - GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), - }; - - if arg_is_param { - seen_params.entry(arg).or_default().push(i); - } else { - // Prevent `fn foo() -> Foo` from being defining. - let opaque_param = opaque_generics.param_at(i, tcx); - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note( - tcx.def_span(opaque_param.def_id), - &format!( - "used non-generic {} `{}` for generic parameter", - opaque_param.kind.descr(), - arg, - ), - ) - .emit(); - return false; - } - } - - for (_, indices) in seen_params { - if indices.len() > 1 { - let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); - let spans: Vec<_> = indices - .into_iter() - .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) - .collect(); - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note(spans, &format!("{} used multiple times", descr)) - .emit(); - return false; - } - } - true -} - -struct ReverseMapper<'tcx> { - tcx: TyCtxt<'tcx>, - - opaque_type_def_id: DefId, - map: FxHashMap, GenericArg<'tcx>>, - map_missing_regions_to_empty: bool, - - /// initially `Some`, set to `None` once error has been reported - hidden_ty: Option>, - - /// Span of function being checked. - span: Span, -} - -impl<'tcx> ReverseMapper<'tcx> { - fn new( - tcx: TyCtxt<'tcx>, - opaque_type_def_id: DefId, - map: FxHashMap, GenericArg<'tcx>>, - hidden_ty: Ty<'tcx>, - span: Span, - ) -> Self { - Self { - tcx, - opaque_type_def_id, - map, - map_missing_regions_to_empty: false, - hidden_ty: Some(hidden_ty), - span, - } - } - - fn fold_kind_mapping_missing_regions_to_empty( - &mut self, - kind: GenericArg<'tcx>, - ) -> GenericArg<'tcx> { - assert!(!self.map_missing_regions_to_empty); - self.map_missing_regions_to_empty = true; - let kind = kind.fold_with(self); - self.map_missing_regions_to_empty = false; - kind - } - - fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { - assert!(!self.map_missing_regions_to_empty); - kind.fold_with(self) - } -} - -impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - #[instrument(skip(self), level = "debug")] - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - // Ignore bound regions and `'static` regions that appear in the - // type, we only need to remap regions that reference lifetimes - // from the function declaration. - // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | ty::ReStatic => return r, - - // If regions have been erased (by writeback), don't try to unerase - // them. - ty::ReErased => return r, - - // The regions that we expect from borrow checking. - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} - - ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => { - // All of the regions in the type should either have been - // erased by writeback, or mapped back to named regions by - // borrow checking. - bug!("unexpected region kind in opaque type: {:?}", r); - } - } - - let generics = self.tcx().generics_of(self.opaque_type_def_id); - match self.map.get(&r.into()).map(|k| k.unpack()) { - Some(GenericArgKind::Lifetime(r1)) => r1, - Some(u) => panic!("region mapped to unexpected kind: {:?}", u), - None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty, - None if generics.parent.is_some() => { - if let Some(hidden_ty) = self.hidden_ty.take() { - unexpected_hidden_region_diagnostic( - self.tcx, - self.tcx.def_span(self.opaque_type_def_id), - hidden_ty, - r, - ) - .emit(); - } - self.tcx.lifetimes.re_root_empty - } - None => { - self.tcx - .sess - .struct_span_err(self.span, "non-defining opaque type use in defining scope") - .span_label( - self.span, - format!( - "lifetime `{}` is part of concrete type but not used in \ - parameter list of the `impl Trait` type alias", - r - ), - ) - .emit(); - - self.tcx().lifetimes.re_static - } - } - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Closure(def_id, substs) => { - // I am a horrible monster and I pray for death. When - // we encounter a closure here, it is always a closure - // from within the function that we are currently - // type-checking -- one that is now being encapsulated - // in an opaque type. Ideally, we would - // go through the types/lifetimes that it references - // and treat them just like we would any other type, - // which means we would error out if we find any - // reference to a type/region that is not in the - // "reverse map". - // - // **However,** in the case of closures, there is a - // somewhat subtle (read: hacky) consideration. The - // problem is that our closure types currently include - // all the lifetime parameters declared on the - // enclosing function, even if they are unused by the - // closure itself. We can't readily filter them out, - // so here we replace those values with `'empty`. This - // can't really make a difference to the rest of the - // compiler; those regions are ignored for the - // outlives relation, and hence don't affect trait - // selection or auto traits, and they are erased - // during codegen. - - let generics = self.tcx.generics_of(def_id); - let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { - if index < generics.parent_count { - // Accommodate missing regions in the parent kinds... - self.fold_kind_mapping_missing_regions_to_empty(kind) - } else { - // ...but not elsewhere. - self.fold_kind_normally(kind) - } - })); - - self.tcx.mk_closure(def_id, substs) - } - - ty::Generator(def_id, substs, movability) => { - let generics = self.tcx.generics_of(def_id); - let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { - if index < generics.parent_count { - // Accommodate missing regions in the parent kinds... - self.fold_kind_mapping_missing_regions_to_empty(kind) - } else { - // ...but not elsewhere. - self.fold_kind_normally(kind) - } - })); - - self.tcx.mk_generator(def_id, substs, movability) - } - - ty::Param(param) => { - // Look it up in the substitution list. - match self.map.get(&ty.into()).map(|k| k.unpack()) { - // Found it in the substitution list; replace with the parameter from the - // opaque type. - Some(GenericArgKind::Type(t1)) => t1, - Some(u) => panic!("type mapped to unexpected kind: {:?}", u), - None => { - debug!(?param, ?self.map); - self.tcx - .sess - .struct_span_err( - self.span, - &format!( - "type parameter `{}` is part of concrete type but not \ - used in parameter list for the `impl Trait` type alias", - ty - ), - ) - .emit(); - - self.tcx().ty_error() - } - } - } - - _ => ty.super_fold_with(self), - } - } - - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - trace!("checking const {:?}", ct); - // Find a const parameter - match ct.kind() { - ty::ConstKind::Param(..) => { - // Look it up in the substitution list. - match self.map.get(&ct.into()).map(|k| k.unpack()) { - // Found it in the substitution list, replace with the parameter from the - // opaque type. - Some(GenericArgKind::Const(c1)) => c1, - Some(u) => panic!("const mapped to unexpected kind: {:?}", u), - None => { - self.tcx - .sess - .struct_span_err( - self.span, - &format!( - "const parameter `{}` is part of concrete type but not \ - used in parameter list for the `impl Trait` type alias", - ct - ), - ) - .emit(); - - self.tcx().const_error(ct.ty()) - } - } - } - - _ => ct, - } - } -} - -/// Given a set of predicates that apply to an object type, returns -/// the region bounds that the (erased) `Self` type must -/// outlive. Precisely *because* the `Self` type is erased, the -/// parameter `erased_self_ty` must be supplied to indicate what type -/// has been used to represent `Self` in the predicates -/// themselves. This should really be a unique type; `FreshTy(0)` is a -/// popular choice. -/// -/// N.B., in some cases, particularly around higher-ranked bounds, -/// this function returns a kind of conservative approximation. -/// That is, all regions returned by this function are definitely -/// required, but there may be other region bounds that are not -/// returned, as well as requirements like `for<'a> T: 'a`. -/// -/// Requires that trait definitions have been processed so that we can -/// elaborate predicates and walk supertraits. -#[instrument(skip(tcx, predicates), level = "debug")] -pub(crate) fn required_region_bounds<'tcx>( - tcx: TyCtxt<'tcx>, - erased_self_ty: Ty<'tcx>, - predicates: impl Iterator>, -) -> Vec> { - assert!(!erased_self_ty.has_escaping_bound_vars()); - - traits::elaborate_predicates(tcx, predicates) - .filter_map(|obligation| { - debug!(?obligation); - match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Projection(..) - | ty::PredicateKind::Trait(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::WellFormed(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::RegionOutlives(..) - | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { - // Search for a bound of the form `erased_self_ty - // : 'a`, but be wary of something like `for<'a> - // erased_self_ty : 'a` (we interpret a - // higher-ranked bound like that as 'static, - // though at present the code in `fulfill.rs` - // considers such bounds to be unsatisfiable, so - // it's kind of a moot point since you could never - // construct such an object, but this seems - // correct even if that code changes). - if t == &erased_self_ty && !r.has_escaping_bound_vars() { - Some(*r) - } else { - None - } - } - } - }) - .collect() -} diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d43b3c9091fc6..3dfc7a9cacd97 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1,5 +1,4 @@ use crate::infer::InferCtxt; -use crate::opaque_types::required_region_bounds; use crate::traits; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -810,3 +809,63 @@ pub fn object_region_bounds<'tcx>( required_region_bounds(tcx, open_ty, predicates) } + +/// Given a set of predicates that apply to an object type, returns +/// the region bounds that the (erased) `Self` type must +/// outlive. Precisely *because* the `Self` type is erased, the +/// parameter `erased_self_ty` must be supplied to indicate what type +/// has been used to represent `Self` in the predicates +/// themselves. This should really be a unique type; `FreshTy(0)` is a +/// popular choice. +/// +/// N.B., in some cases, particularly around higher-ranked bounds, +/// this function returns a kind of conservative approximation. +/// That is, all regions returned by this function are definitely +/// required, but there may be other region bounds that are not +/// returned, as well as requirements like `for<'a> T: 'a`. +/// +/// Requires that trait definitions have been processed so that we can +/// elaborate predicates and walk supertraits. +#[instrument(skip(tcx, predicates), level = "debug")] +pub(crate) fn required_region_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + erased_self_ty: Ty<'tcx>, + predicates: impl Iterator>, +) -> Vec> { + assert!(!erased_self_ty.has_escaping_bound_vars()); + + traits::elaborate_predicates(tcx, predicates) + .filter_map(|obligation| { + debug!(?obligation); + match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Projection(..) + | ty::PredicateKind::Trait(..) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::RegionOutlives(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { + // Search for a bound of the form `erased_self_ty + // : 'a`, but be wary of something like `for<'a> + // erased_self_ty : 'a` (we interpret a + // higher-ranked bound like that as 'static, + // though at present the code in `fulfill.rs` + // considers such bounds to be unsatisfiable, so + // it's kind of a moot point since you could never + // construct such an object, but this seems + // correct even if that code changes). + if t == &erased_self_ty && !r.has_escaping_bound_vars() { + Some(*r) + } else { + None + } + } + } + }) + .collect() +}