From 1e95cddc74f88c1bb86f80103d0d7128f779f544 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Wed, 1 Mar 2023 22:17:08 +1300 Subject: [PATCH 01/13] feat: implement basic suggest-tests tool --- Cargo.lock | 13 ++- Cargo.toml | 1 + src/bootstrap/builder.rs | 22 ++++- src/bootstrap/config.rs | 24 ++--- src/bootstrap/flags.rs | 14 ++- src/bootstrap/lib.rs | 19 +++- src/bootstrap/suggest.rs | 72 ++++++++++++++ src/bootstrap/test.rs | 36 +++++++ src/bootstrap/tool.rs | 1 + src/tools/suggest-tests/Cargo.toml | 9 ++ .../suggest-tests/src/dynamic_suggestions.rs | 23 +++++ src/tools/suggest-tests/src/lib.rs | 96 +++++++++++++++++++ src/tools/suggest-tests/src/main.rs | 27 ++++++ .../suggest-tests/src/static_suggestions.rs | 24 +++++ src/tools/suggest-tests/src/tests.rs | 21 ++++ 15 files changed, 377 insertions(+), 25 deletions(-) create mode 100644 src/bootstrap/suggest.rs create mode 100644 src/tools/suggest-tests/Cargo.toml create mode 100644 src/tools/suggest-tests/src/dynamic_suggestions.rs create mode 100644 src/tools/suggest-tests/src/lib.rs create mode 100644 src/tools/suggest-tests/src/main.rs create mode 100644 src/tools/suggest-tests/src/static_suggestions.rs create mode 100644 src/tools/suggest-tests/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index d4fca32d750f6..4167fd7de9ae0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3459,9 +3459,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "opener" @@ -6097,6 +6097,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "suggest-tests" +version = "0.1.0" +dependencies = [ + "build_helper", + "glob", + "once_cell", +] + [[package]] name = "syn" version = "1.0.102" diff --git a/Cargo.toml b/Cargo.toml index 15cbb2659c9b3..1fcaaf6ddc4d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ members = [ "src/tools/lld-wrapper", "src/tools/collect-license-metadata", "src/tools/generate-copyright", + "src/tools/suggest-tests", ] exclude = [ diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ade8fa4c74dcb..e959ea06f8b69 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -591,6 +591,7 @@ pub enum Kind { Install, Run, Setup, + Suggest, } impl Kind { @@ -610,6 +611,7 @@ impl Kind { "install" => Kind::Install, "run" | "r" => Kind::Run, "setup" => Kind::Setup, + "suggest" => Kind::Suggest, _ => return None, }) } @@ -629,6 +631,7 @@ impl Kind { Kind::Install => "install", Kind::Run => "run", Kind::Setup => "setup", + Kind::Suggest => "suggest", } } } @@ -709,6 +712,7 @@ impl<'a> Builder<'a> { test::CrateRustdoc, test::CrateRustdocJsonTypes, test::CrateJsonDocLint, + test::SuggestTestsCrate, test::Linkcheck, test::TierCheck, test::ReplacePlaceholderTest, @@ -827,7 +831,7 @@ impl<'a> Builder<'a> { Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode), Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std), // special-cased in Build::build() - Kind::Format => vec![], + Kind::Format | Kind::Suggest => vec![], } } @@ -891,6 +895,7 @@ impl<'a> Builder<'a> { Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]), Subcommand::Clean { ref paths, .. } => (Kind::Clean, &paths[..]), Subcommand::Format { .. } => (Kind::Format, &[][..]), + Subcommand::Suggest { .. } => (Kind::Suggest, &[][..]), Subcommand::Setup { profile: ref path } => ( Kind::Setup, path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)), @@ -900,6 +905,21 @@ impl<'a> Builder<'a> { Self::new_internal(build, kind, paths.to_owned()) } + /// Creates a new standalone builder for use outside of the normal process + pub fn new_standalone( + build: &mut Build, + kind: Kind, + paths: Vec, + stage: Option, + ) -> Builder<'_> { + // FIXME: don't mutate `build` + if let Some(stage) = stage { + build.config.stage = stage; + } + + Self::new_internal(build, kind, paths.to_owned()) + } + pub fn execute_cli(&self) { self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths); } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index dd65dc91c0cd3..cc3b3bc25f3d5 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -56,8 +56,7 @@ pub enum DryRun { /// filled out from the decoded forms of the structs below. For documentation /// each field, see the corresponding fields in /// `config.example.toml`. -#[derive(Default)] -#[cfg_attr(test, derive(Clone))] +#[derive(Default, Clone)] pub struct Config { pub changelog_seen: Option, pub ccache: Option, @@ -240,23 +239,20 @@ pub struct Config { pub initial_rustfmt: RefCell, } -#[derive(Default, Deserialize)] -#[cfg_attr(test, derive(Clone))] +#[derive(Default, Deserialize, Clone)] pub struct Stage0Metadata { pub compiler: CompilerMetadata, pub config: Stage0Config, pub checksums_sha256: HashMap, pub rustfmt: Option, } -#[derive(Default, Deserialize)] -#[cfg_attr(test, derive(Clone))] +#[derive(Default, Deserialize, Clone)] pub struct CompilerMetadata { pub date: String, pub version: String, } -#[derive(Default, Deserialize)] -#[cfg_attr(test, derive(Clone))] +#[derive(Default, Deserialize, Clone)] pub struct Stage0Config { pub dist_server: String, pub artifacts_server: String, @@ -264,8 +260,7 @@ pub struct Stage0Config { pub git_merge_commit_email: String, pub nightly_branch: String, } -#[derive(Default, Deserialize)] -#[cfg_attr(test, derive(Clone))] +#[derive(Default, Deserialize, Clone)] pub struct RustfmtMetadata { pub date: String, pub version: String, @@ -443,8 +438,7 @@ impl PartialEq<&str> for TargetSelection { } /// Per-target configuration stored in the global configuration structure. -#[derive(Default)] -#[cfg_attr(test, derive(Clone))] +#[derive(Default, Clone)] pub struct Target { /// Some(path to llvm-config) if using an external LLVM. pub llvm_config: Option, @@ -1396,7 +1390,8 @@ impl Config { | Subcommand::Fix { .. } | Subcommand::Run { .. } | Subcommand::Setup { .. } - | Subcommand::Format { .. } => flags.stage.unwrap_or(0), + | Subcommand::Format { .. } + | Subcommand::Suggest { .. } => flags.stage.unwrap_or(0), }; // CI should always run stage 2 builds, unless it specifically states otherwise @@ -1421,7 +1416,8 @@ impl Config { | Subcommand::Fix { .. } | Subcommand::Run { .. } | Subcommand::Setup { .. } - | Subcommand::Format { .. } => {} + | Subcommand::Format { .. } + | Subcommand::Suggest { .. } => {} } } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 2b0b772a61817..b6f5f31039838 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -84,8 +84,7 @@ pub struct Flags { pub free_args: Option>, } -#[derive(Debug)] -#[cfg_attr(test, derive(Clone))] +#[derive(Debug, Clone)] pub enum Subcommand { Build { paths: Vec, @@ -149,6 +148,9 @@ pub enum Subcommand { Setup { profile: Option, }, + Suggest { + run: bool, + }, } impl Default for Subcommand { @@ -183,6 +185,7 @@ Subcommands: install Install distribution artifacts run, r Run tools contained in this repository setup Create a config.toml (making it easier to use `x.py` itself) + suggest Suggest a subset of tests to run, based on modified files To learn more about a subcommand, run `./x.py -h`", ); @@ -349,6 +352,9 @@ To learn more about a subcommand, run `./x.py -h`", Kind::Run => { opts.optmulti("", "args", "arguments for the tool", "ARGS"); } + Kind::Suggest => { + opts.optflag("", "run", "run suggested tests"); + } _ => {} }; @@ -565,7 +571,7 @@ Arguments: Profile::all_for_help(" ").trim_end() )); } - Kind::Bench | Kind::Clean | Kind::Dist | Kind::Install => {} + Kind::Bench | Kind::Clean | Kind::Dist | Kind::Install | Kind::Suggest => {} }; // Get any optional paths which occur after the subcommand let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::>(); @@ -626,6 +632,7 @@ Arguments: Kind::Format => Subcommand::Format { check: matches.opt_present("check"), paths }, Kind::Dist => Subcommand::Dist { paths }, Kind::Install => Subcommand::Install { paths }, + Kind::Suggest => Subcommand::Suggest { run: matches.opt_present("run") }, Kind::Run => { if paths.is_empty() { println!("\nrun requires at least a path!\n"); @@ -734,6 +741,7 @@ impl Subcommand { Subcommand::Install { .. } => Kind::Install, Subcommand::Run { .. } => Kind::Run, Subcommand::Setup { .. } => Kind::Setup, + Subcommand::Suggest { .. } => Kind::Suggest, } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 5ee18cf641104..2ce9ddd2a680e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -58,6 +58,7 @@ mod render_tests; mod run; mod sanity; mod setup; +mod suggest; mod tarball; mod test; mod tool; @@ -189,6 +190,7 @@ pub enum GitRepo { /// although most functions are implemented as free functions rather than /// methods specifically on this structure itself (to make it easier to /// organize). +#[derive(Clone)] pub struct Build { /// User-specified configuration from `config.toml`. config: Config, @@ -242,7 +244,7 @@ pub struct Build { metrics: metrics::BuildMetrics, } -#[derive(Debug)] +#[derive(Debug, Clone)] struct Crate { name: Interned, deps: HashSet>, @@ -656,13 +658,20 @@ impl Build { job::setup(self); } - if let Subcommand::Format { check, paths } = &self.config.cmd { - return format::format(&builder::Builder::new(&self), *check, &paths); - } - // Download rustfmt early so that it can be used in rust-analyzer configs. let _ = &builder::Builder::new(&self).initial_rustfmt(); + // hardcoded subcommands + match &self.config.cmd { + Subcommand::Format { check, paths } => { + return format::format(&builder::Builder::new(&self), *check, &paths); + } + Subcommand::Suggest { run } => { + return suggest::suggest(&builder::Builder::new(&self), *run); + } + _ => (), + } + { let builder = builder::Builder::new(&self); if let Some(path) = builder.paths.get(0) { diff --git a/src/bootstrap/suggest.rs b/src/bootstrap/suggest.rs new file mode 100644 index 0000000000000..1a482e4165944 --- /dev/null +++ b/src/bootstrap/suggest.rs @@ -0,0 +1,72 @@ +use std::str::FromStr; + +use std::path::PathBuf; + +use crate::{ + builder::{Builder, Kind}, + tool::Tool, +}; + +/// Suggests a list of possible `x.py` commands to run based on modified files in branch. +pub fn suggest(builder: &Builder<'_>, run: bool) { + let suggestions = + builder.tool_cmd(Tool::SuggestTests).output().expect("failed to run `suggest-tests` tool"); + + if !suggestions.status.success() { + println!("failed to run `suggest-tests` tool ({})", suggestions.status); + println!( + "`suggest_tests` stdout:\n{}`suggest_tests` stderr:\n{}", + String::from_utf8(suggestions.stdout).unwrap(), + String::from_utf8(suggestions.stderr).unwrap() + ); + panic!("failed to run `suggest-tests`"); + } + + let suggestions = String::from_utf8(suggestions.stdout).unwrap(); + let suggestions = suggestions + .lines() + .map(|line| { + let mut sections = line.split_ascii_whitespace(); + + // this code expects one suggestion per line in the following format: + // {some number of flags} [optional stage number] + let cmd = sections.next().unwrap(); + let stage = sections.next_back().map(|s| str::parse(s).ok()).flatten(); + let paths: Vec = sections.map(|p| PathBuf::from_str(p).unwrap()).collect(); + + (cmd, stage, paths) + }) + .collect::>(); + + if !suggestions.is_empty() { + println!("==== SUGGESTIONS ===="); + for sug in &suggestions { + print!("x {} ", sug.0); + if let Some(stage) = sug.1 { + print!("--stage {stage} "); + } + + for path in &sug.2 { + print!("{} ", path.display()); + } + println!(); + } + println!("====================="); + } else { + println!("No suggestions found!"); + return; + } + + if run { + for sug in suggestions { + let mut build = builder.build.clone(); + + let builder = + Builder::new_standalone(&mut build, Kind::parse(&sug.0).unwrap(), sug.2, sug.1); + + builder.execute_cli() + } + } else { + println!("help: consider using the `--run` flag to automatically run suggested tests"); + } +} diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 058ff429e80f1..1d55992446eb4 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -128,6 +128,42 @@ impl Step for CrateJsonDocLint { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct SuggestTestsCrate { + host: TargetSelection, +} + +impl Step for SuggestTestsCrate { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/suggest-tests") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(SuggestTestsCrate { host: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + let bootstrap_host = builder.config.build; + let compiler = builder.compiler(0, bootstrap_host); + + let suggest_tests = tool::prepare_tool_cargo( + builder, + compiler, + Mode::ToolBootstrap, + bootstrap_host, + "test", + "src/tools/suggest-tests", + SourceType::InTree, + &[], + ); + add_flags_and_try_run_tests(builder, &mut suggest_tests.into()); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Linkcheck { host: TargetSelection, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 6a687a7903e0f..d1fd2e8c42cb0 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -433,6 +433,7 @@ bootstrap_tool!( ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder"; CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata"; GenerateCopyright, "src/tools/generate-copyright", "generate-copyright"; + SuggestTests, "src/tools/suggest-tests", "suggest-tests"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/tools/suggest-tests/Cargo.toml b/src/tools/suggest-tests/Cargo.toml new file mode 100644 index 0000000000000..f4f4d548bb79e --- /dev/null +++ b/src/tools/suggest-tests/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "suggest-tests" +version = "0.1.0" +edition = "2021" + +[dependencies] +glob = "0.3.0" +build_helper = { version = "0.1.0", path = "../build_helper" } +once_cell = "1.17.1" diff --git a/src/tools/suggest-tests/src/dynamic_suggestions.rs b/src/tools/suggest-tests/src/dynamic_suggestions.rs new file mode 100644 index 0000000000000..2b0213cdc223c --- /dev/null +++ b/src/tools/suggest-tests/src/dynamic_suggestions.rs @@ -0,0 +1,23 @@ +use std::path::Path; + +use crate::Suggestion; + +type DynamicSuggestion = fn(&Path) -> Vec; + +pub(crate) const DYNAMIC_SUGGESTIONS: &[DynamicSuggestion] = &[|path: &Path| -> Vec { + if path.starts_with("compiler/") || path.starts_with("library/") { + let path = path.components().take(2).collect::>(); + + vec![Suggestion::with_single_path( + "test", + None, + &format!( + "{}/{}", + path[0].as_os_str().to_str().unwrap(), + path[1].as_os_str().to_str().unwrap() + ), + )] + } else { + Vec::new() + } +}]; diff --git a/src/tools/suggest-tests/src/lib.rs b/src/tools/suggest-tests/src/lib.rs new file mode 100644 index 0000000000000..44cd3c7f6a84d --- /dev/null +++ b/src/tools/suggest-tests/src/lib.rs @@ -0,0 +1,96 @@ +use std::{ + fmt::{self, Display}, + path::Path, +}; + +use dynamic_suggestions::DYNAMIC_SUGGESTIONS; +use glob::Pattern; +use static_suggestions::STATIC_SUGGESTIONS; + +mod dynamic_suggestions; +mod static_suggestions; + +#[cfg(test)] +mod tests; + +macro_rules! sug { + ($cmd:expr) => { + Suggestion::new($cmd, None, &[]) + }; + + ($cmd:expr, $paths:expr) => { + Suggestion::new($cmd, None, $paths.as_slice()) + }; + + ($cmd:expr, $stage:expr, $paths:expr) => { + Suggestion::new($cmd, Some($stage), $paths.as_slice()) + }; +} + +pub(crate) use sug; + +pub fn get_suggestions>(modified_files: &[T]) -> Vec { + let mut suggestions = Vec::new(); + + // static suggestions + for sug in STATIC_SUGGESTIONS.iter() { + let glob = Pattern::new(&sug.0).expect("Found invalid glob pattern!"); + + for file in modified_files { + if glob.matches(file.as_ref()) { + suggestions.extend_from_slice(&sug.1); + } + } + } + + // dynamic suggestions + for sug in DYNAMIC_SUGGESTIONS { + for file in modified_files { + let sugs = sug(Path::new(file.as_ref())); + + suggestions.extend_from_slice(&sugs); + } + } + + suggestions.sort(); + suggestions.dedup(); + + suggestions +} + +#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Debug)] +pub struct Suggestion { + pub cmd: String, + pub stage: Option, + pub paths: Vec, +} + +impl Suggestion { + pub fn new(cmd: &str, stage: Option, paths: &[&str]) -> Self { + Self { cmd: cmd.to_owned(), stage, paths: paths.iter().map(|p| p.to_string()).collect() } + } + + pub fn with_single_path(cmd: &str, stage: Option, path: &str) -> Self { + Self::new(cmd, stage, &[path]) + } +} + +impl Display for Suggestion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{} ", self.cmd)?; + + for path in &self.paths { + write!(f, "{} ", path)?; + } + + if let Some(stage) = self.stage { + write!(f, "{}", stage)?; + } else { + // write a sentinel value here (in place of a stage) to be consumed + // by the shim in bootstrap, it will be read and ignored. + write!(f, "N/A")?; + } + + Ok(()) + } +} diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs new file mode 100644 index 0000000000000..0b541b60cba98 --- /dev/null +++ b/src/tools/suggest-tests/src/main.rs @@ -0,0 +1,27 @@ +use std::process::ExitCode; + +use build_helper::git::get_git_modified_files; +use suggest_tests::get_suggestions; + +fn main() -> ExitCode { + let modified_files = get_git_modified_files(None, &Vec::new()); + let modified_files = match modified_files { + Ok(Some(files)) => files, + Ok(None) => { + eprintln!("git error"); + return ExitCode::FAILURE; + } + Err(err) => { + eprintln!("Could not get modified files from git: \"{err}\""); + return ExitCode::FAILURE; + } + }; + + let suggestions = get_suggestions(&modified_files); + + for sug in &suggestions { + println!("{sug}"); + } + + ExitCode::SUCCESS +} diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs new file mode 100644 index 0000000000000..d8166ead8c49d --- /dev/null +++ b/src/tools/suggest-tests/src/static_suggestions.rs @@ -0,0 +1,24 @@ +use crate::{sug, Suggestion}; + +// FIXME: perhaps this could use `std::lazy` when it is stablizied +macro_rules! static_suggestions { + ($( $glob:expr => [ $( $suggestion:expr ),* ] ),*) => { + pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy)>> + = ::once_cell::unsync::Lazy::new(|| vec![ $( ($glob, vec![ $($suggestion),* ]) ),*]); + } +} + +static_suggestions! { + "*.md" => [ + sug!("test", 0, ["linkchecker"]) + ], + + "compiler/*" => [ + sug!("check"), + sug!("test", 1, ["src/test/ui", "src/test/run-make"]) + ], + + "src/librustdoc/*" => [ + sug!("test", 1, ["rustdoc"]) + ] +} diff --git a/src/tools/suggest-tests/src/tests.rs b/src/tools/suggest-tests/src/tests.rs new file mode 100644 index 0000000000000..5bc1a7df7ca15 --- /dev/null +++ b/src/tools/suggest-tests/src/tests.rs @@ -0,0 +1,21 @@ +macro_rules! sugg_test { + ( $( $name:ident: $paths:expr => $suggestions:expr ),* ) => { + $( + #[test] + fn $name() { + let suggestions = crate::get_suggestions(&$paths).into_iter().map(|s| s.to_string()).collect::>(); + assert_eq!(suggestions, $suggestions); + } + )* + }; +} + +sugg_test! { + test_error_code_docs: ["compiler/rustc_error_codes/src/error_codes/E0000.md"] => + ["check N/A", "test compiler/rustc_error_codes N/A", "test linkchecker 0", "test src/test/ui src/test/run-make 1"], + + test_rustdoc: ["src/librustdoc/src/lib.rs"] => ["test rustdoc 1"], + + test_rustdoc_and_libstd: ["src/librustdoc/src/lib.rs", "library/std/src/lib.rs"] => + ["test library/std N/A", "test rustdoc 1"] +} From afd45c2e10d9a5dbb277852384bb3d2245239f63 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 8 Apr 2023 14:24:16 +0900 Subject: [PATCH 02/13] Stabilize IsTerminal closes: https://github.com/rust-lang/rust/issues/98070 --- compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_errors/src/lib.rs | 1 - compiler/rustc_log/src/lib.rs | 1 - library/std/src/io/mod.rs | 2 +- library/std/src/io/stdio.rs | 5 +++-- library/std/src/lib.rs | 1 - library/std/src/os/fd/owned.rs | 2 +- library/std/src/os/windows/io/handle.rs | 2 +- library/test/src/lib.rs | 1 - src/librustdoc/lib.rs | 1 - src/tools/miri/src/lib.rs | 1 - src/tools/miri/tests/pass/shims/fs.rs | 1 - src/tools/miri/tests/pass/shims/io.rs | 2 -- 13 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 730d41ab962f8..ba5873d79a299 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(is_terminal)] #![feature(lazy_cell)] #![feature(decl_macro)] #![recursion_limit = "256"] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9866a9bffe0e1..cee62d2375441 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,7 +6,6 @@ #![feature(array_windows)] #![feature(drain_filter)] #![feature(if_let_guard)] -#![feature(is_terminal)] #![feature(adt_const_params)] #![feature(let_chains)] #![feature(never_type)] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 21f6a404a0153..3cbb2c21e289e 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -40,7 +40,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![feature(is_terminal)] use std::env::{self, VarError}; use std::fmt::{self, Display}; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 4b31c552eedd2..020c723925aeb 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -268,7 +268,7 @@ pub(crate) use self::stdio::attempt_print_to_stderr; #[unstable(feature = "internal_output_capture", issue = "none")] #[doc(no_inline, hidden)] pub use self::stdio::set_output_capture; -#[unstable(feature = "is_terminal", issue = "98070")] +#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] pub use self::stdio::IsTerminal; #[unstable(feature = "print_internals", issue = "none")] pub use self::stdio::{_eprint, _print}; diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 1a3200a5c62b8..b2c57b8ddc78e 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1047,7 +1047,7 @@ pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) { } /// Trait to determine if a descriptor/handle refers to a terminal/tty. -#[unstable(feature = "is_terminal", issue = "98070")] +#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] pub trait IsTerminal: crate::sealed::Sealed { /// Returns `true` if the descriptor/handle refers to a terminal/tty. /// @@ -1063,6 +1063,7 @@ pub trait IsTerminal: crate::sealed::Sealed { /// Note that this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] fn is_terminal(&self) -> bool; } @@ -1071,7 +1072,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] impl IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 736b3c0497c46..71f3576c93d4b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -254,7 +254,6 @@ #![feature(exhaustive_patterns)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] -#![feature(is_terminal)] #![feature(lang_items)] #![feature(let_chains)] #![feature(linkage)] diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index a40d39c5e44f5..6a6e6f33158fc 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -201,7 +201,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 1dfecc57338a7..f6622874625fc 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -389,7 +389,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[unstable(feature = "is_terminal", issue = "98070")] + #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 88d8e5fe97ad7..9fb31ed7663d0 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -17,7 +17,6 @@ #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] #![feature(internal_output_capture)] -#![feature(is_terminal)] #![feature(staged_api)] #![feature(process_exitcode_internals)] #![feature(panic_can_unwind)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 79f53ee57cc9d..8ab212099e344 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -7,7 +7,6 @@ #![feature(assert_matches)] #![feature(box_patterns)] #![feature(drain_filter)] -#![feature(is_terminal)] #![feature(let_chains)] #![feature(test)] #![feature(never_type)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index fb4e59acd001d..dcdec0627b709 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -7,7 +7,6 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(local_key_cell_methods)] -#![feature(is_terminal)] #![feature(round_ties_even)] // Configure clippy and other lints #![allow( diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 7a9974f393895..e379288de01cb 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -3,7 +3,6 @@ #![feature(io_error_more)] #![feature(io_error_uncategorized)] -#![feature(is_terminal)] use std::collections::HashMap; use std::ffi::{c_char, OsString}; diff --git a/src/tools/miri/tests/pass/shims/io.rs b/src/tools/miri/tests/pass/shims/io.rs index 4d43549a930be..295723957a426 100644 --- a/src/tools/miri/tests/pass/shims/io.rs +++ b/src/tools/miri/tests/pass/shims/io.rs @@ -1,5 +1,3 @@ -#![feature(is_terminal)] - use std::io::IsTerminal; fn main() { From 5eb0528483ddb7614578fe5ef4b1104047b10ce6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 11 Apr 2023 17:17:25 +0000 Subject: [PATCH 03/13] Erase lifetimes above ty::INNERMOST when probing ambiguous types --- .../rustc_hir_analysis/src/astconv/mod.rs | 20 ++++++------------- .../missing-assoc-item.stderr | 7 ++++++- tests/ui/typeck/issue-110052.rs | 12 +++++++++++ tests/ui/typeck/issue-110052.stderr | 9 +++++++++ 4 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 tests/ui/typeck/issue-110052.rs create mode 100644 tests/ui/typeck/issue-110052.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index acca3fa264187..96a7acc3c27bf 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2514,24 +2514,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx, infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id), ); - // I guess we don't need to make a universe unless we need it, - // but also we're on the error path, so it doesn't matter here. - let universe = infcx.create_next_universe(); + let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); + // FIXME: Don't bother dealing with non-lifetime binders here... + if value.has_escaping_bound_vars() { + return false; + } infcx .can_eq( ty::ParamEnv::empty(), impl_.self_ty(), - tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate { - regions: &mut |_| tcx.lifetimes.re_erased, - types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType { - universe, - bound: bv, - }), - consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst { - universe, - bound: bv, - }, ty), - }) + value, ) }) && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr index be6955c111e83..d985386423d29 100644 --- a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr +++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr @@ -11,7 +11,12 @@ error[E0223]: ambiguous associated type --> $DIR/missing-assoc-item.rs:6:12 | LL | for B::Item: Send, - | ^^^^^^^ help: use the fully-qualified path: `::Item` + | ^^^^^^^ + | +help: if there were a trait named `Example` with associated type `Item` implemented for `B`, you could use the fully-qualified path + | +LL | for ::Item: Send, + | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/typeck/issue-110052.rs b/tests/ui/typeck/issue-110052.rs new file mode 100644 index 0000000000000..f124b58b5b605 --- /dev/null +++ b/tests/ui/typeck/issue-110052.rs @@ -0,0 +1,12 @@ +// Makes sure we deal with escaping lifetimes *above* INNERMOST when +// suggesting trait for ambiguous associated type. + +impl Validator for () +where + for<'iter> dyn Validator<<&'iter I>::Item>:, + //~^ ERROR ambiguous associated type +{} + +pub trait Validator {} + +fn main() {} diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr new file mode 100644 index 0000000000000..0c15c03a7408d --- /dev/null +++ b/tests/ui/typeck/issue-110052.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-110052.rs:6:30 + | +LL | for<'iter> dyn Validator<<&'iter I>::Item>:, + | ^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'iter I as IntoIterator>::Item` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. From 44fbf0c7870d67b8032b5fbcdc225f56f2aa67c1 Mon Sep 17 00:00:00 2001 From: beetrees Date: Thu, 30 Mar 2023 15:16:06 +0100 Subject: [PATCH 04/13] Add creation time support to `FileTimes` on apple and windows --- library/std/src/fs.rs | 11 ++++++ library/std/src/os/ios/fs.rs | 22 ++++++++++-- library/std/src/os/macos/fs.rs | 22 ++++++++++-- library/std/src/os/watchos/fs.rs | 22 ++++++++++-- library/std/src/os/windows/fs.rs | 19 ++++++++++- library/std/src/sys/unix/fs.rs | 56 +++++++++++++++++++++---------- library/std/src/sys/windows/fs.rs | 22 ++++++++++-- 7 files changed, 147 insertions(+), 27 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c550378e7d6b7..ddaabe216351e 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -15,6 +15,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; +use crate::sealed::Sealed; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::time::SystemTime; @@ -1383,6 +1384,16 @@ impl FileTimes { } } +impl AsInnerMut for FileTimes { + fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes { + &mut self.0 + } +} + +// For implementing OS extension traits in `std::os` +#[unstable(feature = "file_set_times", issue = "98245")] +impl Sealed for FileTimes {} + impl Permissions { /// Returns `true` if these permissions describe a readonly (unwritable) file. /// diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs index 4a4637ce0722d..6d4d54b7c78c5 100644 --- a/library/std/src/os/ios/fs.rs +++ b/library/std/src/os/ios/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::ios::raw; @@ -140,3 +142,19 @@ impl MetadataExt for Metadata { self.as_inner().as_inner().st_lspare as u32 } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs index 91915da6a432c..fe82d03d86980 100644 --- a/library/std/src/os/macos/fs.rs +++ b/library/std/src/os/macos/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::macos::raw; @@ -146,3 +148,19 @@ impl MetadataExt for Metadata { [qspare[0] as u64, qspare[1] as u64] } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs index a14fe35a77c10..2ecc4c68a962f 100644 --- a/library/std/src/os/watchos/fs.rs +++ b/library/std/src/os/watchos/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::watchos::raw; @@ -140,3 +142,19 @@ impl MetadataExt for Metadata { self.as_inner().as_inner().st_lspare as u32 } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index a091f06dd532c..94509e547964b 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -9,7 +9,8 @@ use crate::io; use crate::path::Path; use crate::sealed::Sealed; use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut}; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; /// Windows-specific extensions to [`fs::File`]. #[stable(feature = "file_offset", since = "1.15.0")] @@ -526,6 +527,22 @@ impl FileTypeExt for fs::FileType { } } +/// Windows-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} + /// Creates a new symlink to a non-directory file on the filesystem. /// /// The `link` path will be a file symbolic link pointing to the `original` diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 7566fafda24a9..0cc9c65a3fe8d 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -348,6 +348,8 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option, modified: Option, + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + created: Option, } #[derive(Copy, Clone, Eq, Debug)] @@ -579,6 +581,11 @@ impl FileTimes { pub fn set_modified(&mut self, t: SystemTime) { self.modified = Some(t); } + + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + pub fn set_created(&mut self, t: SystemTime) { + self.created = Some(t); + } } impl FileType { @@ -1192,8 +1199,6 @@ impl File { None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), } }; - #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))] - let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; cfg_if::cfg_if! { if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] { // Redox doesn't appear to support `UTIME_OMIT`. @@ -1204,25 +1209,41 @@ impl File { io::ErrorKind::Unsupported, "setting file times not supported", )) - } else if #[cfg(any(target_os = "android", target_os = "macos"))] { - // futimens requires macOS 10.13, and Android API level 19 + } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] { + let mut buf = [mem::MaybeUninit::::uninit(); 3]; + let mut num_times = 0; + let mut attrlist: libc::attrlist = unsafe { mem::zeroed() }; + attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT; + if times.created.is_some() { + buf[num_times].write(to_timespec(times.created)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_CRTIME; + } + if times.modified.is_some() { + buf[num_times].write(to_timespec(times.modified)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_MODTIME; + } + if times.accessed.is_some() { + buf[num_times].write(to_timespec(times.accessed)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_ACCTIME; + } + cvt(unsafe { libc::fsetattrlist( + self.as_raw_fd(), + (&attrlist as *const libc::attrlist).cast::().cast_mut(), + buf.as_ptr().cast::().cast_mut(), + num_times * mem::size_of::(), + 0 + ) })?; + Ok(()) + } else if #[cfg(target_os = "android")] { + let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; + // futimens requires Android API level 19 cvt(unsafe { weak!(fn futimens(c_int, *const libc::timespec) -> c_int); match futimens.get() { Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()), - #[cfg(target_os = "macos")] - None => { - fn ts_to_tv(ts: &libc::timespec) -> libc::timeval { - libc::timeval { - tv_sec: ts.tv_sec, - tv_usec: (ts.tv_nsec / 1000) as _ - } - } - let timevals = [ts_to_tv(×[0]), ts_to_tv(×[1])]; - libc::futimes(self.as_raw_fd(), timevals.as_ptr()) - } - // futimes requires even newer Android. - #[cfg(target_os = "android")] None => return Err(io::const_io_error!( io::ErrorKind::Unsupported, "setting file times requires Android API level >= 19", @@ -1231,6 +1252,7 @@ impl File { })?; Ok(()) } else { + let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; cvt(unsafe { libc::futimens(self.as_raw_fd(), times.as_ptr()) })?; Ok(()) } diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 956db577d5371..4f5b361d124d7 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -88,6 +88,7 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option, modified: Option, + created: Option, } #[derive(Debug)] @@ -567,7 +568,10 @@ impl File { pub fn set_times(&self, times: FileTimes) -> io::Result<()> { let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0; - if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) { + if times.accessed.map_or(false, is_zero) + || times.modified.map_or(false, is_zero) + || times.created.map_or(false, is_zero) + { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "Cannot set file timestamp to 0", @@ -575,14 +579,22 @@ impl File { } let is_max = |t: c::FILETIME| t.dwLowDateTime == c::DWORD::MAX && t.dwHighDateTime == c::DWORD::MAX; - if times.accessed.map_or(false, is_max) || times.modified.map_or(false, is_max) { + if times.accessed.map_or(false, is_max) + || times.modified.map_or(false, is_max) + || times.created.map_or(false, is_max) + { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "Cannot set file timestamp to 0xFFFF_FFFF_FFFF_FFFF", )); } cvt(unsafe { - c::SetFileTime(self.as_handle(), None, times.accessed.as_ref(), times.modified.as_ref()) + c::SetFileTime( + self.as_handle(), + times.created.as_ref(), + times.accessed.as_ref(), + times.modified.as_ref(), + ) })?; Ok(()) } @@ -985,6 +997,10 @@ impl FileTimes { pub fn set_modified(&mut self, t: SystemTime) { self.modified = Some(t.into_inner()); } + + pub fn set_created(&mut self, t: SystemTime) { + self.created = Some(t.into_inner()); + } } impl FileType { From f31c34c79cc45328ad92510586abfa7b42532c80 Mon Sep 17 00:00:00 2001 From: beetrees Date: Sat, 8 Apr 2023 21:47:21 +0100 Subject: [PATCH 05/13] Add test for `FileTimes` --- library/std/src/fs/tests.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 401def1845827..a376e2ecd42c3 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1,7 +1,7 @@ use crate::io::prelude::*; use crate::env; -use crate::fs::{self, File, OpenOptions}; +use crate::fs::{self, File, FileTimes, OpenOptions}; use crate::io::{BorrowedBuf, ErrorKind, SeekFrom}; use crate::mem::MaybeUninit; use crate::path::Path; @@ -9,7 +9,7 @@ use crate::str; use crate::sync::Arc; use crate::sys_common::io::test::{tmpdir, TempDir}; use crate::thread; -use crate::time::{Duration, Instant}; +use crate::time::{Duration, Instant, SystemTime}; use rand::RngCore; @@ -1629,3 +1629,36 @@ fn rename_directory() { assert!(new_path.join("newdir").is_dir()); assert!(new_path.join("newdir/temp.txt").exists()); } + +#[test] +fn test_file_times() { + #[cfg(target_os = "ios")] + use crate::os::ios::fs::FileTimesExt; + #[cfg(target_os = "macos")] + use crate::os::macos::fs::FileTimesExt; + #[cfg(target_os = "watchos")] + use crate::os::watchos::fs::FileTimesExt; + #[cfg(windows)] + use crate::os::windows::fs::FileTimesExt; + + let tmp = tmpdir(); + let file = File::create(tmp.join("foo")).unwrap(); + let mut times = FileTimes::new(); + let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); + let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); + times = times.set_accessed(accessed).set_modified(modified); + #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); + #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + { + times = times.set_created(created); + } + file.set_times(times).unwrap(); + let metadata = file.metadata().unwrap(); + assert_eq!(metadata.accessed().unwrap(), accessed); + assert_eq!(metadata.modified().unwrap(), modified); + #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + { + assert_eq!(metadata.created().unwrap(), created); + } +} From a159dcda6292c03faf3adb37f0a176ca7a35f0dc Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Wed, 12 Apr 2023 14:01:59 +1200 Subject: [PATCH 06/13] fix: disable `x suggest` when using `build-metrics` --- src/bootstrap/lib.rs | 2 +- src/bootstrap/suggest.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2ce9ddd2a680e..1f2fa3df98e1e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -190,7 +190,7 @@ pub enum GitRepo { /// although most functions are implemented as free functions rather than /// methods specifically on this structure itself (to make it easier to /// organize). -#[derive(Clone)] +#[cfg_attr(not(feature = "build-metrics"), derive(Clone))] pub struct Build { /// User-specified configuration from `config.toml`. config: Config, diff --git a/src/bootstrap/suggest.rs b/src/bootstrap/suggest.rs index 1a482e4165944..ff20ebec26772 100644 --- a/src/bootstrap/suggest.rs +++ b/src/bootstrap/suggest.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "build-metrics", allow(unused))] + use std::str::FromStr; use std::path::PathBuf; @@ -7,7 +9,13 @@ use crate::{ tool::Tool, }; +#[cfg(feature = "build-metrics")] +pub fn suggest(builder: &Builder<'_>, run: bool) { + panic!("`x suggest` is not supported with `build-metrics`") +} + /// Suggests a list of possible `x.py` commands to run based on modified files in branch. +#[cfg(not(feature = "build-metrics"))] pub fn suggest(builder: &Builder<'_>, run: bool) { let suggestions = builder.tool_cmd(Tool::SuggestTests).output().expect("failed to run `suggest-tests` tool"); From a19adefa0e5aca0aabca2430530577ee140e4efa Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 12 Apr 2023 10:24:36 +0200 Subject: [PATCH 07/13] region error cleanup - require `TypeErrCtxt` to always result in an error - move `resolve_regions_and_report_errors` to the `ObligationCtxt` - merge `process_registered_region_obligations` into `resolve_regions` --- .../rustc_hir_analysis/src/check/check.rs | 7 +- .../src/check/compare_impl_item.rs | 40 ++--- .../rustc_hir_analysis/src/check/wfcheck.rs | 11 +- .../src/coherence/builtin.rs | 6 +- .../src/impl_wf_check/min_specialization.rs | 3 +- .../src/infer/error_reporting/mod.rs | 30 +++- compiler/rustc_infer/src/infer/mod.rs | 142 +----------------- .../rustc_infer/src/infer/outlives/mod.rs | 104 ++++++++++++- .../src/infer/outlives/obligations.rs | 47 ++---- .../src/traits/auto_trait.rs | 3 +- .../src/traits/coherence.rs | 3 - .../src/traits/engine.rs | 19 +++ .../rustc_trait_selection/src/traits/misc.rs | 4 - 13 files changed, 183 insertions(+), 236 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8617bca082589..0bb98fdf2a23e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -452,11 +452,8 @@ fn check_opaque_meets_bounds<'tcx>( hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {} // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { - let outlives_environment = OutlivesEnvironment::new(param_env); - let _ = infcx.err_ctxt().check_region_obligations_and_report_errors( - defining_use_anchor, - &outlives_environment, - ); + let outlives_env = OutlivesEnvironment::new(param_env); + let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env); } } // Clean up after ourselves diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index f6c2004c4a672..5d119a7737a4c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -332,10 +332,6 @@ fn compare_method_predicate_entailment<'tcx>( param_env, infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()), ); - infcx.process_registered_region_obligations( - outlives_env.region_bound_pairs(), - outlives_env.param_env, - ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { // FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT @@ -722,18 +718,18 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( return Err(reported); } + let collected_types = collector.types; + // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let outlives_environment = OutlivesEnvironment::with_bounds( + let outlives_env = OutlivesEnvironment::with_bounds( param_env, infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), ); - infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?; + ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; let mut collected_tys = FxHashMap::default(); - for (def_id, (ty, substs)) in collector.types { + for (def_id, (ty, substs)) in collected_types { match infcx.fully_resolve(ty) { Ok(ty) => { // `ty` contains free regions that we created earlier while liberating the @@ -1742,11 +1738,8 @@ pub(super) fn compare_impl_const_raw( return Err(infcx.err_ctxt().report_fulfillment_errors(&errors)); } - let outlives_environment = OutlivesEnvironment::new(param_env); - infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; - Ok(()) + let outlives_env = OutlivesEnvironment::new(param_env); + ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env) } pub(super) fn compare_impl_ty<'tcx>( @@ -1845,13 +1838,8 @@ fn compare_type_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.err_ctxt().check_region_obligations_and_report_errors( - impl_ty.def_id.expect_local(), - &outlives_environment, - )?; - - Ok(()) + let outlives_env = OutlivesEnvironment::new(param_env); + ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } /// Validate that `ProjectionCandidate`s created for this associated type will @@ -2063,14 +2051,8 @@ pub(super) fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types); - let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - - infcx.err_ctxt().check_region_obligations_and_report_errors( - impl_ty.def_id.expect_local(), - &outlives_environment, - )?; - - Ok(()) + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c03621fcfb224..53197bc849106 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -114,11 +114,9 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( return; } - let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let _ = infcx - .err_ctxt() - .check_region_obligations_and_report_errors(body_def_id, &outlives_environment); + let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env); } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { @@ -680,12 +678,7 @@ fn resolve_regions_with_wf_tys<'tcx>( add_constraints(&infcx, region_bound_pairs); - infcx.process_registered_region_obligations( - outlives_environment.region_bound_pairs(), - param_env, - ); let errors = infcx.resolve_regions(&outlives_environment); - debug!(?errors, "errors"); // If we were able to prove that the type outlives the region without diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index ac7c68d9c4b30..0f40cca9427b4 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -354,9 +354,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx - .err_ctxt() - .check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -592,7 +590,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 35785e81ff497..eb2fc395223ed 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -180,8 +180,7 @@ fn get_impl_substs( let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - let _ = - infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let span = tcx.def_span(impl1_def_id); tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 7901bc9402122..f6bed12ee2d43 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -74,6 +74,7 @@ use rustc_middle::ty::{ self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; +use rustc_span::DUMMY_SP; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::{ControlFlow, Deref}; @@ -113,7 +114,11 @@ fn escape_literal(s: &str) -> String { /// A helper for building type related errors. The `typeck_results` /// field is only populated during an in-progress typeck. -/// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`. +/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`. +/// +/// You must only create this if you intend to actually emit an error. +/// This provides a lot of utility methods which should not be used +/// during the happy path. pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub typeck_results: Option>>, @@ -125,6 +130,19 @@ pub struct TypeErrCtxt<'a, 'tcx> { Box) -> Vec<(Ty<'tcx>, Vec>)> + 'a>, } +impl Drop for TypeErrCtxt<'_, '_> { + fn drop(&mut self) { + if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() { + // ok, emitted an error. + } else { + self.infcx + .tcx + .sess + .delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation"); + } + } +} + impl TypeErrCtxt<'_, '_> { /// This is just to avoid a potential footgun of accidentally /// dropping `typeck_results` by calling `InferCtxt::err_ctxt` @@ -419,7 +437,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, generic_param_scope: LocalDefId, errors: &[RegionResolutionError<'tcx>], - ) { + ) -> ErrorGuaranteed { + if let Some(guaranteed) = self.infcx.tainted_by_errors() { + return guaranteed; + } + debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them @@ -499,6 +521,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } } + + self.tcx + .sess + .delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors") } // This method goes through all the errors and try to group certain types diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b4f2ad0bb3433..66f51328bbe7c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -45,8 +45,7 @@ use self::combine::CombineFields; use self::error_reporting::TypeErrCtxt; use self::free_regions::RegionRelations; use self::lexical_region_resolve::LexicalRegionResolutions; -use self::outlives::env::OutlivesEnvironment; -use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound}; +use self::region_constraints::{GenericKind, VarInfos, VerifyBound}; use self::region_constraints::{ RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot, }; @@ -1213,95 +1212,6 @@ impl<'tcx> InferCtxt<'tcx> { self.tainted_by_errors.set(Some(e)); } - pub fn skip_region_resolution(&self) { - let (var_infos, _) = { - let mut inner = self.inner.borrow_mut(); - let inner = &mut *inner; - // Note: `inner.region_obligations` may not be empty, because we - // didn't necessarily call `process_registered_region_obligations`. - // This is okay, because that doesn't introduce new vars. - inner - .region_constraint_storage - .take() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data() - }; - - let lexical_region_resolutions = LexicalRegionResolutions { - values: rustc_index::vec::IndexVec::from_elem_n( - crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), - var_infos.len(), - ), - }; - - let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); - assert!(old_value.is_none()); - } - - /// Process the region constraints and return any errors that - /// result. After this, no more unification operations should be - /// done -- or the compiler will panic -- but it is legal to use - /// `resolve_vars_if_possible` as well as `fully_resolve`. - pub fn resolve_regions( - &self, - outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Vec> { - let (var_infos, data) = { - let mut inner = self.inner.borrow_mut(); - let inner = &mut *inner; - assert!( - self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(), - "region_obligations not empty: {:#?}", - inner.region_obligations - ); - inner - .region_constraint_storage - .take() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data() - }; - - let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); - - let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); - - let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); - assert!(old_value.is_none()); - - errors - } - /// Obtains (and clears) the current set of region - /// constraints. The inference context is still usable: further - /// unifications will simply add new constraints. - /// - /// This method is not meant to be used with normal lexical region - /// resolution. Rather, it is used in the NLL mode as a kind of - /// interim hack: basically we run normal type-check and generate - /// region constraints as normal, but then we take them and - /// translate them into the form that the NLL solver - /// understands. See the NLL module for mode details. - pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> { - assert!( - self.inner.borrow().region_obligations.is_empty(), - "region_obligations not empty: {:#?}", - self.inner.borrow().region_obligations - ); - - self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data() - } - - /// Gives temporary access to the region constraint data. - pub fn with_region_constraints( - &self, - op: impl FnOnce(&RegionConstraintData<'tcx>) -> R, - ) -> R { - let mut inner = self.inner.borrow_mut(); - op(inner.unwrap_region_constraints().data()) - } - pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin { let mut inner = self.inner.borrow_mut(); let inner = &mut *inner; @@ -1754,56 +1664,6 @@ impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> { } impl<'tcx> TypeErrCtxt<'_, 'tcx> { - /// Processes registered region obliations and resolves regions, reporting - /// any errors if any were raised. Prefer using this function over manually - /// calling `resolve_regions_and_report_errors`. - pub fn check_region_obligations_and_report_errors( - &self, - generic_param_scope: LocalDefId, - outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Result<(), ErrorGuaranteed> { - self.process_registered_region_obligations( - outlives_env.region_bound_pairs(), - outlives_env.param_env, - ); - - self.resolve_regions_and_report_errors(generic_param_scope, outlives_env) - } - - /// Process the region constraints and report any errors that - /// result. After this, no more unification operations should be - /// done -- or the compiler will panic -- but it is legal to use - /// `resolve_vars_if_possible` as well as `fully_resolve`. - /// - /// Make sure to call [`InferCtxt::process_registered_region_obligations`] - /// first, or preferably use [`TypeErrCtxt::check_region_obligations_and_report_errors`] - /// to do both of these operations together. - pub fn resolve_regions_and_report_errors( - &self, - generic_param_scope: LocalDefId, - outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Result<(), ErrorGuaranteed> { - let errors = self.resolve_regions(outlives_env); - - if let None = self.tainted_by_errors() { - // As a heuristic, just skip reporting region errors - // altogether if other errors have been reported while - // this infcx was in use. This is totally hokey but - // otherwise we have a hard time separating legit region - // errors from silly ones. - self.report_region_errors(generic_param_scope, &errors); - } - - if errors.is_empty() { - Ok(()) - } else { - Err(self - .tcx - .sess - .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")) - } - } - // [Note-Type-error-reporting] // An invariant is that anytime the expected or actual type is Error (the special // error type, meaning that an error occurred when typechecking this expression), diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 048dad3a48bc2..21907c4b42340 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,4 +1,11 @@ //! Various code related to computing outlives relations. +use self::env::OutlivesEnvironment; +use super::region_constraints::RegionConstraintData; +use super::{InferCtxt, RegionResolutionError}; +use crate::infer::free_regions::RegionRelations; +use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions}; +use rustc_middle::traits::query::OutlivesBound; +use rustc_middle::ty; pub mod components; pub mod env; @@ -6,9 +13,6 @@ pub mod obligations; pub mod test_type_match; pub mod verify; -use rustc_middle::traits::query::OutlivesBound; -use rustc_middle::ty; - #[instrument(level = "debug", skip(param_env), ret)] pub fn explicit_outlives_bounds<'tcx>( param_env: ty::ParamEnv<'tcx>, @@ -39,3 +43,97 @@ pub fn explicit_outlives_bounds<'tcx>( ))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)), }) } + +impl<'tcx> InferCtxt<'tcx> { + pub fn skip_region_resolution(&self) { + let (var_infos, _) = { + let mut inner = self.inner.borrow_mut(); + let inner = &mut *inner; + // Note: `inner.region_obligations` may not be empty, because we + // didn't necessarily call `process_registered_region_obligations`. + // This is okay, because that doesn't introduce new vars. + inner + .region_constraint_storage + .take() + .expect("regions already resolved") + .with_log(&mut inner.undo_log) + .into_infos_and_data() + }; + + let lexical_region_resolutions = LexicalRegionResolutions { + values: rustc_index::vec::IndexVec::from_elem_n( + crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), + var_infos.len(), + ), + }; + + let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); + assert!(old_value.is_none()); + } + + /// Process the region constraints and return any errors that + /// result. After this, no more unification operations should be + /// done -- or the compiler will panic -- but it is legal to use + /// `resolve_vars_if_possible` as well as `fully_resolve`. + pub fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec> { + self.process_registered_region_obligations(outlives_env); + + let (var_infos, data) = { + let mut inner = self.inner.borrow_mut(); + let inner = &mut *inner; + assert!( + self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(), + "region_obligations not empty: {:#?}", + inner.region_obligations + ); + inner + .region_constraint_storage + .take() + .expect("regions already resolved") + .with_log(&mut inner.undo_log) + .into_infos_and_data() + }; + + let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); + + let (lexical_region_resolutions, errors) = + lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); + + let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); + assert!(old_value.is_none()); + + errors + } + + /// Obtains (and clears) the current set of region + /// constraints. The inference context is still usable: further + /// unifications will simply add new constraints. + /// + /// This method is not meant to be used with normal lexical region + /// resolution. Rather, it is used in the NLL mode as a kind of + /// interim hack: basically we run normal type-check and generate + /// region constraints as normal, but then we take them and + /// translate them into the form that the NLL solver + /// understands. See the NLL module for mode details. + pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> { + assert!( + self.inner.borrow().region_obligations.is_empty(), + "region_obligations not empty: {:#?}", + self.inner.borrow().region_obligations + ); + + self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data() + } + + /// Gives temporary access to the region constraint data. + pub fn with_region_constraints( + &self, + op: impl FnOnce(&RegionConstraintData<'tcx>) -> R, + ) -> R { + let mut inner = self.inner.borrow_mut(); + op(inner.unwrap_region_constraints().data()) + } +} diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index bbe7d4c63f794..ccf11c61b573b 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -72,6 +72,8 @@ use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitableExt}; use smallvec::smallvec; +use super::env::OutlivesEnvironment; + impl<'tcx> InferCtxt<'tcx> { /// Registers that the given region obligation must be resolved /// from within the scope of `body_id`. These regions are enqueued @@ -112,39 +114,17 @@ impl<'tcx> InferCtxt<'tcx> { std::mem::take(&mut self.inner.borrow_mut().region_obligations) } - /// NOTE: Prefer using `TypeErrCtxt::check_region_obligations_and_report_errors` - /// instead of calling this directly. - /// /// Process the region obligations that must be proven (during /// `regionck`) for the given `body_id`, given information about - /// the region bounds in scope and so forth. This function must be - /// invoked for all relevant body-ids before region inference is - /// done (or else an assert will fire). + /// the region bounds in scope and so forth. /// /// See the `region_obligations` field of `InferCtxt` for some /// comments about how this function fits into the overall expected /// flow of the inferencer. The key point is that it is /// invoked after all type-inference variables have been bound -- - /// towards the end of regionck. This also ensures that the - /// region-bound-pairs are available (see comments above regarding - /// closures). - /// - /// # Parameters - /// - /// - `region_bound_pairs_map`: the set of region bounds implied by - /// the parameters and where-clauses. In particular, each pair - /// `('a, K)` in this list tells us that the bounds in scope - /// indicate that `K: 'a`, where `K` is either a generic - /// parameter like `T` or a projection like `T::Item`. - /// - `param_env` is the parameter environment for the enclosing function. - /// - `body_id` is the body-id whose region obligations are being - /// processed. - #[instrument(level = "debug", skip(self, region_bound_pairs))] - pub fn process_registered_region_obligations( - &self, - region_bound_pairs: &RegionBoundPairs<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) { + /// right before lexical region resolution. + #[instrument(level = "debug", skip(self, outlives_env))] + pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) { assert!( !self.in_snapshot.get(), "cannot process registered region obligations in a snapshot" @@ -153,15 +133,16 @@ impl<'tcx> InferCtxt<'tcx> { let my_region_obligations = self.take_registered_region_obligations(); for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - debug!( - "process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}", - sup_type, sub_region, origin - ); - + debug!(?sup_type, ?sub_region, ?origin); let sup_type = self.resolve_vars_if_possible(sup_type); - let outlives = - &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); + let outlives = &mut TypeOutlives::new( + self, + self.tcx, + &outlives_env.region_bound_pairs(), + None, + outlives_env.param_env, + ); let category = origin.to_constraint_category(); outlives.type_must_outlive(origin, sup_type, sub_region, category); } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index a53d414be9e7a..fd45ef99aa9d0 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -187,7 +187,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors); } - infcx.process_registered_region_obligations(&Default::default(), full_env); + let outlives_env = OutlivesEnvironment::new(full_env); + infcx.process_registered_region_obligations(&outlives_env); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 53d4f95e9e30f..3c918b6028d47 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -405,9 +405,6 @@ fn resolve_negative_obligation<'tcx>( param_env, infcx.implied_bounds_tys(param_env, body_def_id, wf_tys), ); - - infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env); - infcx.resolve_regions(&outlives_env).is_empty() } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 8acc31cd410bd..d2b39ed226f04 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -6,11 +6,13 @@ use super::{ChalkFulfillmentContext, FulfillmentContext}; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::NormalizeExt; use rustc_data_structures::fx::FxIndexSet; +use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse, }; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::query::Fallible; use rustc_infer::traits::{ @@ -181,6 +183,23 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.engine.borrow_mut().select_all_or_error(self.infcx) } + /// Resolves regions and reports errors. + /// + /// Takes ownership of the context as doing trait solving afterwards + /// will result in region constraints getting ignored. + pub fn resolve_regions_and_report_errors( + self, + generic_param_scope: LocalDefId, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Result<(), ErrorGuaranteed> { + let errors = self.infcx.resolve_regions(&outlives_env); + if errors.is_empty() { + Ok(()) + } else { + Err(self.infcx.err_ctxt().report_region_errors(generic_param_scope, &errors)) + } + } + pub fn assumed_wf_types( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 0bde43c54df99..af567c074384e 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -117,10 +117,6 @@ pub fn type_allowed_to_implement_copy<'tcx>( FxIndexSet::from_iter([self_type]), ), ); - infcx.process_registered_region_obligations( - outlives_env.region_bound_pairs(), - param_env, - ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { infringing.push((field, ty, InfringingFieldsReason::Regions(errors))); From cc82ccb145f2056854b499d5033be1a06ddfa29c Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 12 Apr 2023 10:31:41 +0200 Subject: [PATCH 08/13] `#[must_use]` for fns returning a list of errors --- compiler/rustc_infer/src/infer/outlives/mod.rs | 1 + compiler/rustc_infer/src/traits/engine.rs | 2 ++ compiler/rustc_trait_selection/src/traits/engine.rs | 2 ++ .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 4 +++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 21907c4b42340..9a9a1696b0063 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -75,6 +75,7 @@ impl<'tcx> InferCtxt<'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. + #[must_use] pub fn resolve_regions( &self, outlives_env: &OutlivesEnvironment<'tcx>, diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index f75344f20b6d9..a188bb2388271 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -36,6 +36,7 @@ pub trait TraitEngine<'tcx>: 'tcx { obligation: PredicateObligation<'tcx>, ); + #[must_use] fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; fn collect_remaining_errors(&mut self) -> Vec>; @@ -58,6 +59,7 @@ pub trait TraitEngineExt<'tcx> { obligations: impl IntoIterator>, ); + #[must_use] fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index d2b39ed226f04..2beebe94b6d1d 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -175,10 +175,12 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + #[must_use] pub fn select_where_possible(&self) -> Vec> { self.engine.borrow_mut().select_where_possible(self.infcx) } + #[must_use] pub fn select_all_or_error(&self) -> Vec> { self.engine.borrow_mut().select_all_or_error(self.infcx) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 6ebf056f0e837..6790d7b76a3ad 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1763,7 +1763,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // constrain inference variables a bit more to nested obligations from normalize so // we can have more helpful errors. - ocx.select_where_possible(); + // + // we intentionally errors from normalization here. + let _ = ocx.select_where_possible(); if let Err(new_err) = ocx.eq_exp( &obligation.cause, From c0d3d32922d308088dd176d216d6c7409374c70b Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 12 Apr 2023 22:07:07 +0200 Subject: [PATCH 09/13] fix comment --- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 6790d7b76a3ad..81ab5b9f05769 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1764,7 +1764,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // constrain inference variables a bit more to nested obligations from normalize so // we can have more helpful errors. // - // we intentionally errors from normalization here. + // we intentionally drop errors from normalization here, + // since the normalization is just done to improve the error message. let _ = ocx.select_where_possible(); if let Err(new_err) = ocx.eq_exp( From c802694bdaded1ee655a08c3ecf03cf57bc4d60f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 15:36:03 +1000 Subject: [PATCH 10/13] Make `Region::as_var` infallible. It's what all the call sites require. --- compiler/rustc_borrowck/src/lib.rs | 8 ++------ compiler/rustc_borrowck/src/type_check/relate_tys.rs | 11 ++--------- compiler/rustc_middle/src/ty/sty.rs | 6 +++--- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3d876155fc952..043ccaa027156 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -507,9 +507,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { F: Fn() -> RegionCtxt, { let next_region = self.infcx.next_region_var(origin); - let vid = next_region - .as_var() - .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); + let vid = next_region.as_var(); if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); @@ -531,9 +529,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { F: Fn() -> RegionCtxt, { let next_region = self.infcx.next_nll_region_var(origin.clone()); - let vid = next_region - .as_var() - .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); + let vid = next_region.as_var(); if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 6b64e65518f5b..7e6d17ec3437e 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -131,13 +131,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env), }; - let reg_var = - reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg)); - if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - debug!(?reg_var); - var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info)); + var_to_origin.insert(reg.as_var(), RegionCtxt::Placeholder(reg_info)); } reg @@ -150,12 +146,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> universe, ); - let reg_var = - reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg)); - if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() { let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - var_to_origin.insert(reg_var, RegionCtxt::Existential(None)); + var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None)); } reg diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 086ceebd24d60..bbf6430a5ae70 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1772,10 +1772,10 @@ impl<'tcx> Region<'tcx> { matches!(self.kind(), ty::ReVar(_)) } - pub fn as_var(self) -> Option { + pub fn as_var(self) -> RegionVid { match self.kind() { - ty::ReVar(vid) => Some(vid), - _ => None, + ty::ReVar(vid) => vid, + _ => bug!("expected region {:?} to be of kind ReVar", self), } } } From 411422f2b9b0861f416d18f1ab9ca079ac01bb08 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 15:26:05 +1000 Subject: [PATCH 11/13] Remove `impl ToRegionVid for RegionVid`. It's weird and unnecessary. --- compiler/rustc_borrowck/src/dataflow.rs | 6 ++---- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_borrowck/src/nll.rs | 6 ------ .../rustc_borrowck/src/region_infer/mod.rs | 21 ++++++++----------- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 2cbd2e3bc0d86..94939c7e4cd72 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -11,9 +11,7 @@ use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill} use rustc_mir_dataflow::{Analysis, Direction, Results}; use std::fmt; -use crate::{ - places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid, -}; +use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext}; /// A tuple with named fields that can hold either the results or the transient state of the /// dataflow analyses used by the borrow checker. @@ -242,7 +240,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { ) -> Self { let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx); for (borrow_index, borrow_data) in borrow_set.iter_enumerated() { - let borrow_region = borrow_data.region.to_region_vid(); + let borrow_region = borrow_data.region; let location = borrow_data.reserve_location; prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 043ccaa027156..a4b285a34fa46 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -94,7 +94,7 @@ pub mod consumers; use borrow_set::{BorrowData, BorrowSet}; use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows}; -use nll::{PoloniusOutput, ToRegionVid}; +use nll::PoloniusOutput; use place_ext::PlaceExt; use places_conflict::{places_conflict, PlaceConflictBias}; use region_infer::RegionInferenceContext; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 06ecbdb1707c5..8b5ff999e9b3d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -459,12 +459,6 @@ impl<'tcx> ToRegionVid for Region<'tcx> { } } -impl ToRegionVid for RegionVid { - fn to_region_vid(self) -> RegionVid { - self - } -} - pub(crate) trait ConstraintDescription { fn description(&self) -> &'static str; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index f67af4584a4a5..ce6f3690e1904 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -27,7 +27,7 @@ use crate::{ }, diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}, member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, - nll::{PoloniusOutput, ToRegionVid}, + nll::PoloniusOutput, region_infer::reverse_sccs::ReverseSccGraph, region_infer::values::{ LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, @@ -593,14 +593,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Returns `true` if the region `r` contains the point `p`. /// /// Panics if called before `solve()` executes, - pub(crate) fn region_contains(&self, r: impl ToRegionVid, p: impl ToElementIndex) -> bool { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + pub(crate) fn region_contains(&self, r: RegionVid, p: impl ToElementIndex) -> bool { + let scc = self.constraint_sccs.scc(r); self.scc_values.contains(scc, p) } /// Returns access to the value of `r` for debugging purposes. pub(crate) fn region_value_str(&self, r: RegionVid) -> String { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); self.scc_values.region_value_str(scc) } @@ -608,24 +608,21 @@ impl<'tcx> RegionInferenceContext<'tcx> { &'a self, r: RegionVid, ) -> impl Iterator + 'a { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); self.scc_values.placeholders_contained_in(scc) } /// Returns access to the value of `r` for debugging purposes. pub(crate) fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); self.scc_universes[scc] } /// Once region solving has completed, this function will return /// the member constraints that were applied to the value of a given /// region `r`. See `AppliedMemberConstraint`. - pub(crate) fn applied_member_constraints( - &self, - r: impl ToRegionVid, - ) -> &[AppliedMemberConstraint] { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + pub(crate) fn applied_member_constraints(&self, r: RegionVid) -> &[AppliedMemberConstraint] { + let scc = self.constraint_sccs.scc(r); binary_search_util::binary_search_slice( &self.member_constraints_applied, |applied| applied.member_region_scc, @@ -2234,7 +2231,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { r: RegionVid, body: &Body<'_>, ) -> Option { - let scc = self.constraint_sccs.scc(r.to_region_vid()); + let scc = self.constraint_sccs.scc(r); let locations = self.scc_values.locations_outlived_by(scc); for location in locations { let bb = &body[location.block]; From bbc400993eadea8a927cc5f96a15cc7c493c7a88 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 15:31:57 +1000 Subject: [PATCH 12/13] Remove `ToRegionVid`. It is only implemented for `Region`, where it is equivalent to the inherent `as_var` method. --- compiler/rustc_borrowck/src/borrow_set.rs | 5 ++-- .../src/constraint_generation.rs | 6 ++--- .../src/diagnostics/find_use.rs | 3 +-- .../src/diagnostics/region_name.rs | 10 ++++---- .../src/diagnostics/var_name.rs | 6 ++--- compiler/rustc_borrowck/src/nll.rs | 17 +------------- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- .../src/type_check/constraint_conversion.rs | 3 +-- .../src/type_check/liveness/mod.rs | 5 +--- compiler/rustc_borrowck/src/type_check/mod.rs | 7 +++--- .../rustc_borrowck/src/universal_regions.rs | 23 +++++++++---------- 11 files changed, 32 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index fa0552e012de1..4824f6346d4c8 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -1,6 +1,5 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use crate::nll::ToRegionVid; use crate::path_utils::allow_two_phase_borrow; use crate::place_ext::PlaceExt; use crate::BorrowIndex; @@ -204,7 +203,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { return; } - let region = region.to_region_vid(); + let region = region.as_var(); let borrow = BorrowData { kind, @@ -279,7 +278,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { let borrow_data = &self.location_map[&location]; assert_eq!(borrow_data.reserve_location, location); assert_eq!(borrow_data.kind, kind); - assert_eq!(borrow_data.region, region.to_region_vid()); + assert_eq!(borrow_data.region, region.as_var()); assert_eq!(borrow_data.borrowed_place, place); } diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index 1427f5cb31d9c..2aa09a3f26c17 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -12,8 +12,8 @@ use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use crate::{ - borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid, - places_conflict, region_infer::values::LivenessValues, + borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict, + region_infer::values::LivenessValues, }; pub(super) fn generate_constraints<'tcx>( @@ -170,7 +170,7 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> { debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location); self.infcx.tcx.for_each_free_region(&live_ty, |live_region| { - let vid = live_region.to_region_vid(); + let vid = live_region.as_var(); self.liveness_constraints.add_element(vid, location); }); } diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index e2d04324f3b62..2495613fea1d2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -6,7 +6,6 @@ use std::rc::Rc; use crate::{ def_use::{self, DefUse}, - nll::ToRegionVid, region_infer::{Cause, RegionInferenceContext}, }; use rustc_data_structures::fx::FxIndexSet; @@ -117,7 +116,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> { let mut found_it = false; self.tcx.for_each_free_region(&local_ty, |r| { - if r.to_region_vid() == self.region_vid { + if r.as_var() == self.region_vid { found_it = true; } }); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index cc5a1f5ab122d..f69c4829ae299 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use crate::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt}; +use crate::{universal_regions::DefiningTy, MirBorrowckCtxt}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. @@ -497,7 +497,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // & // - let's call the lifetime of this reference `'1` (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => { - if region.to_region_vid() == needle_fr { + if region.as_var() == needle_fr { // Just grab the first character, the `&`. let source_map = self.infcx.tcx.sess.source_map(); let ampersand_span = source_map.start_point(hir_ty.span); @@ -598,7 +598,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { for (kind, hir_arg) in iter::zip(substs, args.args) { match (kind.unpack(), hir_arg) { (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => { - if r.to_region_vid() == needle_fr { + if r.as_var() == needle_fr { return Some(lt); } } @@ -666,7 +666,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); - if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { + if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) { return None; } @@ -803,7 +803,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let tcx = self.infcx.tcx; - if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) { + if !tcx.any_free_region_meets(&yield_ty, |r| r.as_var() == fr) { return None; } diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 80b2787ce0c42..376415e3d3208 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,8 +1,8 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +use crate::region_infer::RegionInferenceContext; use crate::Upvar; -use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext}; use rustc_index::vec::{Idx, IndexSlice}; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; @@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}"); tcx.any_free_region_meets(&upvar_ty, |r| { - let r = r.to_region_vid(); + let r = r.as_var(); debug!("get_upvar_index_for_region: r={r:?} fr={fr:?}"); r == fr }) @@ -96,7 +96,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position( |arg_ty| { debug!("get_argument_index_for_region: arg_ty = {arg_ty:?}"); - tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) + tcx.any_free_region_meets(arg_ty, |r| r.as_var() == fr) }, )?; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 8b5ff999e9b3d..59a3ab3189d75 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, }; -use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid, TyCtxt}; +use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; use rustc_span::symbol::sym; use std::env; use std::io; @@ -444,21 +444,6 @@ fn for_each_region_constraint<'tcx>( Ok(()) } -/// Right now, we piggy back on the `ReVar` to store our NLL inference -/// regions. These are indexed with `RegionVid`. This method will -/// assert that the region is a `ReVar` and extract its internal index. -/// This is reasonable because in our MIR we replace all universal regions -/// with inference variables. -pub trait ToRegionVid { - fn to_region_vid(self) -> RegionVid; -} - -impl<'tcx> ToRegionVid for Region<'tcx> { - fn to_region_vid(self) -> RegionVid { - if let ty::ReVar(vid) = *self { vid } else { bug!("region is not an ReVar: {:?}", self) } - } -} - pub(crate) trait ConstraintDescription { fn description(&self) -> &'static str; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index ce6f3690e1904..729f3dbff3b46 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1130,7 +1130,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let r_vid = self.to_region_vid(r); let r_scc = self.constraint_sccs.scc(r_vid); - // The challenge if this. We have some region variable `r` + // The challenge is this. We have some region variable `r` // whose value is a set of CFG points and universal // regions. We want to find if that set is *equivalent* to // any of the named regions found in the closure. diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index a93561350062c..71eae7b27d1db 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -12,7 +12,6 @@ use rustc_span::{Span, DUMMY_SP}; use crate::{ constraints::OutlivesConstraint, - nll::ToRegionVid, region_infer::TypeTest, type_check::{Locations, MirTypeckRegionConstraints}, universal_regions::UniversalRegions, @@ -198,7 +197,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid { if let ty::RePlaceholder(placeholder) = *r { - self.constraints.placeholder_region(self.infcx, placeholder).to_region_vid() + self.constraints.placeholder_region(self.infcx, placeholder).as_var() } else { self.universal_regions.to_region_vid(r) } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index a411aec518e93..f1ad0ca55ccfd 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -11,7 +11,6 @@ use crate::{ constraints::OutlivesConstraintSet, facts::{AllFacts, AllFactsExt}, location::LocationTable, - nll::ToRegionVid, region_infer::values::RegionValueElements, universal_regions::UniversalRegions, }; @@ -80,9 +79,7 @@ fn compute_relevant_live_locals<'tcx>( ) -> (Vec, Vec) { let (boring_locals, relevant_live_locals): (Vec<_>, Vec<_>) = body.local_decls.iter_enumerated().partition_map(|(local, local_decl)| { - if tcx.all_free_regions_meet(&local_decl.ty, |r| { - free_regions.contains(&r.to_region_vid()) - }) { + if tcx.all_free_regions_meet(&local_decl.ty, |r| free_regions.contains(&r.as_var())) { Either::Left(local) } else { Either::Right(local) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6d8305b7d471b..375eca1b29d3d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -56,7 +56,6 @@ use crate::{ facts::AllFacts, location::LocationTable, member_constraints::MemberConstraintSet, - nll::ToRegionVid, path_utils, region_infer::values::{ LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, @@ -2419,7 +2418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Some(all_facts) = all_facts { let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); if let Some(borrow_index) = borrow_set.get_index_of(&location) { - let region_vid = borrow_region.to_region_vid(); + let region_vid = borrow_region.as_var(); all_facts.loan_issued_at.push(( region_vid, borrow_index, @@ -2465,8 +2464,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match base_ty.kind() { ty::Ref(ref_region, _, mutbl) => { constraints.outlives_constraints.push(OutlivesConstraint { - sup: ref_region.to_region_vid(), - sub: borrow_region.to_region_vid(), + sup: ref_region.as_var(), + sub: borrow_region.as_var(), locations: location.to_locations(), span: location.to_locations().span(body), category, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 35dfc1f7d129a..70fddb1057c09 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -28,7 +28,6 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::Symbol; use std::iter; -use crate::nll::ToRegionVid; use crate::renumber::{BoundRegionInfo, RegionCtxt}; use crate::BorrowckInferCtxt; @@ -406,7 +405,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // Create the "global" region that is always free in all contexts: 'static. let fr_static = - self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).to_region_vid(); + self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).as_var(); // We've now added all the global regions. The next ones we // add will be external. @@ -446,7 +445,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { }; debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }, ); @@ -480,7 +479,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { }; debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }); @@ -499,7 +498,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let reg_vid = self .infcx .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic"))) - .to_region_vid(); + .as_var(); let region = self.infcx.tcx.mk_re_var(reg_vid); let va_list_ty = @@ -514,7 +513,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let fr_fn_body = self .infcx .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body"))) - .to_region_vid(); + .as_var(); let num_universals = self.infcx.num_region_vars(); @@ -635,7 +634,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); let subst_mapping = - iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid())); + iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.as_var())); UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static } } @@ -789,7 +788,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { self.next_nll_region_var(origin, || RegionCtxt::Bound(BoundRegionInfo::Name(name))) }; - indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid()); + indices.insert_late_bound_region(liberated_region, region_vid.as_var()); debug!(?liberated_region, ?region_vid); region_vid }); @@ -822,7 +821,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { }; debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }); } @@ -843,7 +842,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { }) }; - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + indices.insert_late_bound_region(r, region_vid.as_var()); } }); } @@ -861,7 +860,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { } /// Converts `r` into a local inference variable: `r` can either - /// by a `ReVar` (i.e., already a reference to an inference + /// be a `ReVar` (i.e., already a reference to an inference /// variable) or it can be `'static` or some early-bound /// region. This is useful when taking the results from /// type-checking and trait-matching, which may sometimes @@ -870,7 +869,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// fully initialized. pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { if let ty::ReVar(..) = *r { - r.to_region_vid() + r.as_var() } else if r.is_error() { // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if From 72605cd267fa0a812e74ad8412738b4db37aca9d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Apr 2023 16:49:13 +1000 Subject: [PATCH 13/13] Remove some unused type folders. I'm surprised the compiler doesn't warn about these. It appears having an `impl` on a struct is enough to avoid a warning about it never being constructed. --- .../rustc_hir_analysis/src/collect/type_of.rs | 27 +------ compiler/rustc_hir_typeck/src/op.rs | 22 +----- compiler/rustc_middle/src/ty/sty.rs | 79 +------------------ .../src/traits/auto_trait.rs | 21 ----- 4 files changed, 4 insertions(+), 145 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 225b155058076..c173bd913a84c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -8,10 +8,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{ - self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, -}; +use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -874,28 +871,6 @@ fn infer_placeholder_type<'a>( item_ident: Ident, kind: &'static str, ) -> Ty<'a> { - // Attempts to make the type nameable by turning FnDefs into FnPtrs. - struct MakeNameable<'tcx> { - tcx: TyCtxt<'tcx>, - } - - impl<'tcx> TypeFolder> for MakeNameable<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty = match *ty.kind() { - ty::FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) - } - _ => ty, - }; - - ty.super_fold_with(self) - } - } - let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id); // If this came from a free `const` or `static mut?` item, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 0ab6af127c096..a52c94cb00c53 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -12,9 +12,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{ - self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt, -}; +use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; @@ -965,21 +963,3 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool } } } - -struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span); - -impl<'tcx> TypeFolder> for TypeParamEraser<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.0.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.kind() { - ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: self.1, - }), - _ => ty.super_fold_with(self), - } - } -} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index bbf6430a5ae70..96c1577d52bcb 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, }; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; @@ -1156,81 +1156,6 @@ where } } -struct SkipBindersAt<'tcx> { - tcx: TyCtxt<'tcx>, - index: ty::DebruijnIndex, -} - -impl<'tcx> FallibleTypeFolder> for SkipBindersAt<'tcx> { - type Error = (); - - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> - where - T: ty::TypeFoldable>, - { - self.index.shift_in(1); - let value = t.try_map_bound(|t| t.try_fold_with(self)); - self.index.shift_out(1); - value - } - - fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { - if !ty.has_escaping_bound_vars() { - Ok(ty) - } else if let ty::Bound(index, bv) = *ty.kind() { - if index == self.index { - Err(()) - } else { - Ok(self.interner().mk_bound(index.shifted_out(1), bv)) - } - } else { - ty.try_super_fold_with(self) - } - } - - fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { - if !r.has_escaping_bound_vars() { - Ok(r) - } else if let ty::ReLateBound(index, bv) = r.kind() { - if index == self.index { - Err(()) - } else { - Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv)) - } - } else { - r.try_super_fold_with(self) - } - } - - fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result, Self::Error> { - if !ct.has_escaping_bound_vars() { - Ok(ct) - } else if let ty::ConstKind::Bound(index, bv) = ct.kind() { - if index == self.index { - Err(()) - } else { - Ok(self.interner().mk_const( - ty::ConstKind::Bound(index.shifted_out(1), bv), - ct.ty().try_fold_with(self)?, - )) - } - } else { - ct.try_super_fold_with(self) - } - } - - fn try_fold_predicate( - &mut self, - p: ty::Predicate<'tcx>, - ) -> Result, Self::Error> { - if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) } - } -} - /// Represents the projection of an associated type. /// /// For a projection, this would be `>::N`. diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index a53d414be9e7a..686631e5369fb 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -9,7 +9,6 @@ use crate::infer::InferCtxt; use crate::traits::project::ProjectAndUnifyResult; use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ImplPolarity, Region, RegionVid}; @@ -851,23 +850,3 @@ impl<'tcx> AutoTraitFinder<'tcx> { infcx.freshen(p) } } - -/// Replaces all ReVars in a type with ty::Region's, using the provided map -pub struct RegionReplacer<'a, 'tcx> { - vid_to_region: &'a FxHashMap>, - tcx: TyCtxt<'tcx>, -} - -impl<'a, 'tcx> TypeFolder> for RegionReplacer<'a, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - (match *r { - ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), - _ => None, - }) - .unwrap_or_else(|| r.super_fold_with(self)) - } -}