From 07988bb8a1ce5b6732d351c4299f0b0a4d51e192 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 9 Aug 2021 18:26:58 -0700 Subject: [PATCH 01/31] Reword description of automatic impls of `Unsize`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing documentation felt a little unhelpfully concise, so this change tries to improve it by using longer sentences, each of which specifies which kinds of types it applies to as early as possible. In particular, the third item starts with “Structs ...” instead of saying “Foo is a struct” later. Also, the previous list items “Only the last field has a type involving `T`” and “`T` is not part of the type of any other fields” are, as far as I see, redundant with each other, so I removed the latter. --- library/core/src/marker.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index fb957348bebd3..556b1a721d303 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -99,17 +99,15 @@ pub trait Sized { /// `Unsize`. /// /// All implementations of `Unsize` are provided automatically by the compiler. -/// -/// `Unsize` is implemented for: -/// -/// - `[T; N]` is `Unsize<[T]>` -/// - `T` is `Unsize` when `T: Trait` -/// - `Foo<..., T, ...>` is `Unsize>` if: -/// - `T: Unsize` -/// - Foo is a struct -/// - Only the last field of `Foo` has a type involving `T` -/// - `T` is not part of the type of any other fields -/// - `Bar: Unsize>`, if the last field of `Foo` has type `Bar` +/// Those implementations are: +/// +/// - Arrays `[T; N]` implement `Unsize<[T]>`. +/// - Types implementing a trait `Trait` also implement `Unsize`. +/// - Structs `Foo<..., T, ...>` implement `Unsize>` if all of these conditions +/// are met: +/// - `T: Unsize`. +/// - Only the last field of `Foo` has a type involving `T`. +/// - `Bar: Unsize>`, where `Bar` stands for the actual type of that last field. /// /// `Unsize` is used along with [`ops::CoerceUnsized`] to allow /// "user-defined" containers such as [`Rc`] to contain dynamically-sized From 2884a74d083cc6d601e5f1e53cc33b60e9655cfc Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Thu, 19 Aug 2021 01:01:49 +0200 Subject: [PATCH 02/31] Fix non-capturing closure return type coercion --- compiler/rustc_typeck/src/check/coercion.rs | 4 +++ src/test/ui/coercion/issue-88097.rs | 31 +++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/ui/coercion/issue-88097.rs diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 208eb27c84406..e3c43aa8b8482 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -941,6 +941,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { exprs.len() ); + if prev_ty == new_ty { + return Ok(prev_ty); + } + // Special-case that coercion alone cannot handle: // Function items or non-capturing closures of differing IDs or InternalSubsts. let (a_sig, b_sig) = { diff --git a/src/test/ui/coercion/issue-88097.rs b/src/test/ui/coercion/issue-88097.rs new file mode 100644 index 0000000000000..e543e1bae9239 --- /dev/null +++ b/src/test/ui/coercion/issue-88097.rs @@ -0,0 +1,31 @@ +// In #88097, the compiler attempted to coerce a closure type to itself via +// a function pointer, which caused an unnecessary error. Check that this +// behavior has been fixed. + +// check-pass + +fn peculiar() -> impl Fn(u8) -> u8 { + return |x| x + 1 +} + +fn peculiar2() -> impl Fn(u8) -> u8 { + return |x| x + 1; +} + +fn peculiar3() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + return f +} + +fn peculiar4() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + f +} + +fn peculiar5() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + let g = |x| x + 2; + return if true { f } else { g } +} + +fn main() {} From 4d6bfdec9e2b4f613fffca2dd92af4ad744d3f9e Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 21 Aug 2021 15:47:24 +0100 Subject: [PATCH 03/31] Improve error message when _ is used for in/inout asm operands --- compiler/rustc_builtin_macros/src/asm.rs | 12 +++++ src/test/ui/asm/parse-error.rs | 6 +++ src/test/ui/asm/parse-error.stderr | 68 +++++++++++++++--------- 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index cb0cfdcefdc22..fd5cff31587ff 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -117,6 +117,10 @@ fn parse_args<'a>( let mut explicit_reg = false; let op = if !is_global_asm && p.eat_keyword(kw::In) { let reg = parse_reg(&mut p, &mut explicit_reg)?; + if p.eat_keyword(kw::Underscore) { + let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + return Err(err); + } let expr = p.parse_expr()?; ast::InlineAsmOperand::In { reg, expr } } else if !is_global_asm && p.eat_keyword(sym::out) { @@ -129,6 +133,10 @@ fn parse_args<'a>( ast::InlineAsmOperand::Out { reg, expr, late: true } } else if !is_global_asm && p.eat_keyword(sym::inout) { let reg = parse_reg(&mut p, &mut explicit_reg)?; + if p.eat_keyword(kw::Underscore) { + let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + return Err(err); + } let expr = p.parse_expr()?; if p.eat(&token::FatArrow) { let out_expr = @@ -139,6 +147,10 @@ fn parse_args<'a>( } } else if !is_global_asm && p.eat_keyword(sym::inlateout) { let reg = parse_reg(&mut p, &mut explicit_reg)?; + if p.eat_keyword(kw::Underscore) { + let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + return Err(err); + } let expr = p.parse_expr()?; if p.eat(&token::FatArrow) { let out_expr = diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/parse-error.rs index 3ec3c72d38d72..fa14c52cf0ad7 100644 --- a/src/test/ui/asm/parse-error.rs +++ b/src/test/ui/asm/parse-error.rs @@ -76,6 +76,12 @@ fn main() { //~^ ERROR asm template must be a string literal asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); //~^ ERROR asm template must be a string literal + asm!("{}", in(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inout(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inlateout(reg) _); + //~^ ERROR _ cannot be used for input operands } } diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr index 423003c99d42c..78d342cc1daf7 100644 --- a/src/test/ui/asm/parse-error.stderr +++ b/src/test/ui/asm/parse-error.stderr @@ -214,62 +214,80 @@ LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:79:28 + | +LL | asm!("{}", in(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:81:31 + | +LL | asm!("{}", inout(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:83:35 + | +LL | asm!("{}", inlateout(reg) _); + | ^ + error: requires at least a template string argument - --> $DIR/parse-error.rs:84:1 + --> $DIR/parse-error.rs:90:1 | LL | global_asm!(); | ^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:86:13 + --> $DIR/parse-error.rs:92:13 | LL | global_asm!(FOO); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:88:18 + --> $DIR/parse-error.rs:94:18 | LL | global_asm!("{}" FOO); | ^^^ expected `,` error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:90:19 + --> $DIR/parse-error.rs:96:19 | LL | global_asm!("{}", FOO); | ^^^ expected operand, options, or additional template string error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:92:24 + --> $DIR/parse-error.rs:98:24 | LL | global_asm!("{}", const); | ^ expected expression error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:94:30 + --> $DIR/parse-error.rs:100:30 | LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:96:25 + --> $DIR/parse-error.rs:102:25 | LL | global_asm!("", options(FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:98:25 + --> $DIR/parse-error.rs:104:25 | LL | global_asm!("", options(nomem FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:100:25 + --> $DIR/parse-error.rs:106:25 | LL | global_asm!("", options(nomem, FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: arguments are not allowed after options - --> $DIR/parse-error.rs:102:30 + --> $DIR/parse-error.rs:108:30 | LL | global_asm!("{}", options(), const FOO); | --------- ^^^^^^^^^ argument @@ -277,25 +295,25 @@ LL | global_asm!("{}", options(), const FOO); | previous options error: expected string literal - --> $DIR/parse-error.rs:104:29 + --> $DIR/parse-error.rs:110:29 | LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal error: expected `)`, found `FOO` - --> $DIR/parse-error.rs:106:33 + --> $DIR/parse-error.rs:112:33 | LL | global_asm!("", clobber_abi("C" FOO)); | ^^^ expected `)` error: expected `)`, found `,` - --> $DIR/parse-error.rs:108:32 + --> $DIR/parse-error.rs:114:32 | LL | global_asm!("", clobber_abi("C", FOO)); | ^ expected `)` error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:110:37 + --> $DIR/parse-error.rs:116:37 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ---------------- ^^^^^^^^^ argument @@ -303,13 +321,13 @@ LL | global_asm!("{}", clobber_abi("C"), const FOO); | clobber_abi error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:110:19 + --> $DIR/parse-error.rs:116:19 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:113:28 + --> $DIR/parse-error.rs:119:28 | LL | global_asm!("", options(), clobber_abi("C")); | --------- ^^^^^^^^^^^^^^^^ @@ -317,7 +335,7 @@ LL | global_asm!("", options(), clobber_abi("C")); | options error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:115:30 + --> $DIR/parse-error.rs:121:30 | LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | --------- ^^^^^^^^^^^^^^^^ @@ -325,7 +343,7 @@ LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | options error: clobber_abi specified multiple times - --> $DIR/parse-error.rs:117:35 + --> $DIR/parse-error.rs:123:35 | LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); | ---------------- ^^^^^^^^^^^^^^^^ @@ -333,7 +351,7 @@ LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); | clobber_abi previously specified here error: duplicate argument named `a` - --> $DIR/parse-error.rs:119:35 + --> $DIR/parse-error.rs:125:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -341,7 +359,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); | previously here error: argument never used - --> $DIR/parse-error.rs:119:35 + --> $DIR/parse-error.rs:125:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ^^^^^^^^^^^^^ argument never used @@ -349,19 +367,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: expected one of `clobber_abi`, `const`, or `options`, found `""` - --> $DIR/parse-error.rs:122:28 + --> $DIR/parse-error.rs:128:28 | LL | global_asm!("", options(), ""); | ^^ expected one of `clobber_abi`, `const`, or `options` error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"` - --> $DIR/parse-error.rs:124:30 + --> $DIR/parse-error.rs:130:30 | LL | global_asm!("{}", const FOO, "{}", const FOO); | ^^^^ expected one of `clobber_abi`, `const`, or `options` error: asm template must be a string literal - --> $DIR/parse-error.rs:126:13 + --> $DIR/parse-error.rs:132:13 | LL | global_asm!(format!("{{{}}}", 0), const FOO); | ^^^^^^^^^^^^^^^^^^^^ @@ -369,7 +387,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:128:20 + --> $DIR/parse-error.rs:134:20 | LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | ^^^^^^^^^^^^^^^^^^^^ @@ -439,6 +457,6 @@ LL | let mut bar = 0; LL | asm!("{1}", in("eax") foo, const bar); | ^^^ non-constant value -error: aborting due to 63 previous errors +error: aborting due to 66 previous errors For more information about this error, try `rustc --explain E0435`. From bbe3be9bf8d8e8503b8effbe392d0e449224b406 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Tue, 31 Aug 2021 23:44:15 +0200 Subject: [PATCH 04/31] Add explanatory comment --- compiler/rustc_typeck/src/check/coercion.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index e3c43aa8b8482..e05d14289c348 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -941,6 +941,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { exprs.len() ); + // The following check fixes #88097, where the compiler erroneously + // attempted to coerce a closure type to itself via a function pointer. if prev_ty == new_ty { return Ok(prev_ty); } From cd75af25e036301d7971f6f302cf6a5593b0a6b5 Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Sun, 5 Sep 2021 16:42:36 +0100 Subject: [PATCH 05/31] Change more x64 size checks to not apply to x32. Commit 95e096d6 changed a bunch of size checks already, but more have been added, so this fixes the new ones the same way: the various size checks that are conditional on target_arch = "x86_64" were not intended to apply to x86_64-unknown-linux-gnux32, so add target_pointer_width = "64" to the conditions. --- compiler/rustc_middle/src/mir/mod.rs | 8 ++++---- compiler/rustc_parse/src/parser/attr_wrapper.rs | 2 +- src/librustdoc/html/render/context.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 83f6e79d5fcf6..36afbc6cbf171 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1708,7 +1708,7 @@ pub struct Place<'tcx> { pub projection: &'tcx List>, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Place<'_>, 16); #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -2034,7 +2034,7 @@ pub enum Operand<'tcx> { Constant(Box>), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Operand<'_>, 24); impl<'tcx> Debug for Operand<'tcx> { @@ -2172,7 +2172,7 @@ pub enum Rvalue<'tcx> { Aggregate(Box>, Vec>), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Rvalue<'_>, 40); #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -2198,7 +2198,7 @@ pub enum AggregateKind<'tcx> { Generator(DefId, SubstsRef<'tcx>, hir::Movability), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(AggregateKind<'_>, 48); #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 9f06bdcc135ba..568682cc3e4e0 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -34,7 +34,7 @@ pub struct AttrWrapper { // This struct is passed around very frequently, // so make sure it doesn't accidentally get larger -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(AttrWrapper, 16); impl AttrWrapper { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 733bedfdde9b4..34f9c0a8187a6 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -69,7 +69,7 @@ crate struct Context<'tcx> { } // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Context<'_>, 104); /// Shared mutable state used in [`Context`] and elsewhere. From 04db063b9034957c4d1c18ae95bd8ddc4eab1205 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 5 Sep 2021 20:07:57 +0000 Subject: [PATCH 06/31] Don't build the library and standard library before documenting them Rustdoc doesn't require the build artifacts to generate the docs, and especially in the case of rustc, it greatly increases the time needed to run the build. --- src/bootstrap/doc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index c871411793073..6eb8df1368944 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -446,7 +446,6 @@ impl Step for Std { t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, builder.config.build); - builder.ensure(compile::Std { compiler, target }); let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc"); t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); @@ -564,9 +563,10 @@ impl Step for Rustc { let out = builder.compiler_doc_out(target); t!(fs::create_dir_all(&out)); - // Build rustc. + // Build the standard library, so that proc-macros can use it. + // (Normally, only the metadata would be necessary, but proc-macros are special since they run at compile-time.) let compiler = builder.compiler(stage, builder.config.build); - builder.ensure(compile::Rustc { compiler, target }); + builder.ensure(compile::Std { compiler, target: builder.config.build }); // This uses a shared directory so that librustdoc documentation gets // correctly built and merged with the rustc documentation. This is From e2d01eddc3034aa3a418ce41247c129a342601f8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 Sep 2021 17:21:52 +0200 Subject: [PATCH 07/31] Simplify std::os module reexports to fix rustdoc linking issues --- library/std/src/os/mod.rs | 183 +++++++++++++++----------------------- 1 file changed, 74 insertions(+), 109 deletions(-) diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 79e6967300767..1a4d77e00bf07 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -10,117 +10,82 @@ pub mod raw; // of a macro that is not vendored by Rust and included in the toolchain. // See https://github.com/rust-analyzer/rust-analyzer/issues/6038. -#[cfg(all( - doc, - not(any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - )) -))] -#[path = "."] -mod doc { - // When documenting std we want to show the `unix`, `windows`, `linux` and `wasi` - // modules as these are the "main modules" that are used across platforms, - // so these modules are enabled when `cfg(doc)` is set. - // This should help show platform-specific functionality in a hopefully cross-platform - // way in the documentation. - - pub mod unix; - - pub mod linux; - - pub mod wasi; - - pub mod windows; -} -#[cfg(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -))] -mod doc { - // On certain platforms right now the "main modules" modules that are - // documented don't compile (missing things in `libc` which is empty), - // so just omit them with an empty module. - - #[unstable(issue = "none", feature = "std_internals")] - pub mod unix {} - - #[unstable(issue = "none", feature = "std_internals")] - pub mod linux {} - - #[unstable(issue = "none", feature = "std_internals")] - pub mod wasi {} - - #[unstable(issue = "none", feature = "std_internals")] - pub mod windows {} +// On certain platforms right now the "main modules" modules that are +// documented don't compile (missing things in `libc` which is empty), +// so just omit them with an empty module and add the "unstable" attribute. + +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] +pub mod fortanix_sgx; + +// Unix, linux, wasi and windows are handled a bit differently. +cfg_if::cfg_if! { + if #[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) + ))] + { + #[unstable(issue = "none", feature = "std_internals")] + pub mod unix {} + #[unstable(issue = "none", feature = "std_internals")] + pub mod linux {} + #[unstable(issue = "none", feature = "std_internals")] + pub mod wasi {} + #[unstable(issue = "none", feature = "std_internals")] + pub mod windows {} + } else { + #[cfg(target_os = "hermit")] + #[path = "hermit/mod.rs"] + pub mod unix; + + #[cfg(any(unix, doc))] + pub mod unix; + + #[cfg(any(target_os = "linux", target_os = "l4re", doc))] + pub mod linux; + + #[cfg(any(target_os = "wasi", doc))] + pub mod wasi; + + #[cfg(any(windows, doc))] + pub mod windows; + } } -#[cfg(doc)] -#[stable(feature = "os", since = "1.0.0")] -pub use doc::*; - -#[cfg(not(doc))] -#[path = "."] -mod imp { - // If we're not documenting std then we only expose modules appropriate for the - // current platform. - - #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] - pub mod fortanix_sgx; - - #[cfg(target_os = "hermit")] - #[path = "hermit/mod.rs"] - pub mod unix; - #[cfg(target_os = "android")] - pub mod android; - #[cfg(target_os = "dragonfly")] - pub mod dragonfly; - #[cfg(target_os = "emscripten")] - pub mod emscripten; - #[cfg(target_os = "espidf")] - pub mod espidf; - #[cfg(target_os = "freebsd")] - pub mod freebsd; - #[cfg(target_os = "fuchsia")] - pub mod fuchsia; - #[cfg(target_os = "haiku")] - pub mod haiku; - #[cfg(target_os = "illumos")] - pub mod illumos; - #[cfg(target_os = "ios")] - pub mod ios; - #[cfg(target_os = "l4re")] - pub mod linux; - #[cfg(target_os = "linux")] - pub mod linux; - #[cfg(target_os = "macos")] - pub mod macos; - #[cfg(target_os = "netbsd")] - pub mod netbsd; - #[cfg(target_os = "openbsd")] - pub mod openbsd; - #[cfg(target_os = "redox")] - pub mod redox; - #[cfg(target_os = "solaris")] - pub mod solaris; - #[cfg(unix)] - pub mod unix; - - #[cfg(target_os = "vxworks")] - pub mod vxworks; - - #[cfg(target_os = "wasi")] - pub mod wasi; - - #[cfg(windows)] - pub mod windows; -} -#[cfg(not(doc))] -#[stable(feature = "os", since = "1.0.0")] -pub use imp::*; +// Others. +#[cfg(target_os = "android")] +pub mod android; +#[cfg(target_os = "dragonfly")] +pub mod dragonfly; +#[cfg(target_os = "emscripten")] +pub mod emscripten; +#[cfg(target_os = "espidf")] +pub mod espidf; +#[cfg(target_os = "freebsd")] +pub mod freebsd; +#[cfg(target_os = "fuchsia")] +pub mod fuchsia; +#[cfg(target_os = "haiku")] +pub mod haiku; +#[cfg(target_os = "illumos")] +pub mod illumos; +#[cfg(target_os = "ios")] +pub mod ios; +#[cfg(target_os = "macos")] +pub mod macos; +#[cfg(target_os = "netbsd")] +pub mod netbsd; +#[cfg(target_os = "openbsd")] +pub mod openbsd; +#[cfg(target_os = "redox")] +pub mod redox; +#[cfg(target_os = "solaris")] +pub mod solaris; + +#[cfg(target_os = "vxworks")] +pub mod vxworks; #[cfg(any(unix, target_os = "wasi", doc))] mod fd; From 2987f4ba42b002c58ae485f7ae528cb29c3b1611 Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 6 Sep 2021 02:27:41 +0100 Subject: [PATCH 08/31] WIP state --- .../rustc_middle/src/mir/abstract_const.rs | 1 + compiler/rustc_mir_build/src/build/mod.rs | 8 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 + compiler/rustc_mir_build/src/thir/cx/mod.rs | 1 + compiler/rustc_privacy/src/lib.rs | 7 +- .../src/traits/const_evaluatable.rs | 360 +++++++----------- .../src/traits/object_safety.rs | 7 +- 7 files changed, 160 insertions(+), 227 deletions(-) diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs index 1ef10241143b8..e75f084e79e21 100644 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ b/compiler/rustc_middle/src/mir/abstract_const.rs @@ -17,6 +17,7 @@ pub enum Node<'tcx> { Binop(mir::BinOp, NodeId, NodeId), UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), + Block(&'tcx [NodeId], Option), Cast(CastKind, NodeId, Ty<'tcx>), } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 0a760a740dcae..390ce59cb489c 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -28,6 +28,7 @@ crate fn mir_built<'tcx>( if let Some(def) = def.try_upgrade(tcx) { return tcx.mir_built(def); } + debug!("mir_built: def={:?}", def); let mut body = mir_build(tcx, def); if def.const_param_did.is_some() { @@ -40,6 +41,7 @@ crate fn mir_built<'tcx>( /// Construct the MIR for a given `DefId`. fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_> { + debug!("mir_build: def={:?}", def); let id = tcx.hir().local_def_id_to_hir_id(def.did); let body_owner_kind = tcx.hir().body_owner_kind(id); let typeck_results = tcx.typeck_opt_const_arg(def); @@ -47,10 +49,12 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ // Ensure unsafeck is ran before we steal the THIR. match def { ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => { - tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)) + tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)); + tcx.ensure().mir_abstract_const_of_const_arg((did, const_param_did)); } ty::WithOptConstParam { did, const_param_did: None } => { - tcx.ensure().thir_check_unsafety(did) + tcx.ensure().thir_check_unsafety(did); + tcx.ensure().mir_abstract_const(did); } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 66005be05df75..70a5a9286b0b3 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -149,7 +149,9 @@ impl<'tcx> Cx<'tcx> { } fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { + debug!("Expr::make_mirror_unadjusted: expr={:?}", expr); let expr_ty = self.typeck_results().expr_ty(expr); + debug!("Expr::make_mirror_unadjusted: expr_ty={:?}", expr_ty); let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let kind = match expr.kind { @@ -762,6 +764,7 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Err => unreachable!(), }; + debug!("Expr::make_mirror_unadjusted: finish"); Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind } } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 5059dd939d92d..5310efbccd655 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -20,6 +20,7 @@ crate fn thir_body<'tcx>( tcx: TyCtxt<'tcx>, owner_def: ty::WithOptConstParam, ) -> (&'tcx Steal>, ExprId) { + debug!("thir_body: {:?}", owner_def); let hir = tcx.hir(); let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(owner_def.did))); let mut cx = Cx::new(tcx, owner_def); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 35e25e52dc5f9..26e1c3e7b8cf4 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -159,9 +159,10 @@ where self.visit_const(leaf) } ACNode::Cast(_, _, ty) => self.visit_ty(ty), - ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { - ControlFlow::CONTINUE - } + ACNode::Block(_, _) + | ACNode::Binop(..) + | ACNode::UnaryOp(..) + | ACNode::FunctionCall(_, _) => ControlFlow::CONTINUE, }) } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index ddabe5967d79c..4e11fefdc81f3 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -8,14 +8,15 @@ //! In this case we try to build an abstract representation of this constant using //! `mir_abstract_const` which can then be checked for structural equality with other //! generic constants mentioned in the `caller_bounds` of the current environment. +use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_hir::def::DefKind; -use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; +use rustc_middle::mir; use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable}; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind}; +use rustc_middle::thir; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_session::lint; @@ -101,9 +102,10 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } - Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => { - ControlFlow::CONTINUE - } + Node::Block(_, _) + | Node::Binop(_, _, _) + | Node::UnaryOp(_, _) + | Node::FunctionCall(_, _) => ControlFlow::CONTINUE, }); match failure_kind { @@ -232,7 +234,8 @@ struct WorkNode<'tcx> { struct AbstractConstBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + body_id: thir::ExprId, + body: Lrc<&'a thir::Thir<'tcx>>, /// The current WIP node tree. /// /// We require all nodes to be used in the final abstract const, @@ -240,18 +243,18 @@ struct AbstractConstBuilder<'a, 'tcx> { /// if they are mentioned in an assert, so some used nodes are never /// actually reachable by walking the [`AbstractConst`]. nodes: IndexVec>, - locals: IndexVec, - /// We only allow field accesses if they access - /// the result of a checked operation. - checked_op_locals: BitSet, } impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { + fn root_span(&self) -> Span { + self.body.exprs[self.body_id].span + } + fn error(&mut self, span: Option, msg: &str) -> Result { self.tcx .sess - .struct_span_err(self.body.span, "overly complex generic constant") - .span_label(span.unwrap_or(self.body.span), msg) + .struct_span_err(self.root_span(), "overly complex generic constant") + .span_label(span.unwrap_or(self.root_span()), msg) .help("consider moving this anonymous constant into a `const` function") .emit(); @@ -260,28 +263,12 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { fn new( tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + (body, body_id): (&'a thir::Thir<'tcx>, thir::ExprId), ) -> Result>, ErrorReported> { - let mut builder = AbstractConstBuilder { - tcx, - body, - nodes: IndexVec::new(), - locals: IndexVec::from_elem(NodeId::MAX, &body.local_decls), - checked_op_locals: BitSet::new_empty(body.local_decls.len()), - }; - - // We don't have to look at concrete constants, as we - // can just evaluate them. - if !body.is_polymorphic { - return Ok(None); - } + let builder = + AbstractConstBuilder { tcx, body_id, body: Lrc::new(body), nodes: IndexVec::new() }; - // We only allow consts without control flow, so - // we check for cycles here which simplifies the - // rest of this implementation. - if body.is_cfg_cyclic() { - builder.error(None, "cyclic anonymous constants are forbidden")?; - } + // FIXME non-constants should return Ok(None) Ok(Some(builder)) } @@ -301,6 +288,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.nodes[func].used = true; nodes.iter().for_each(|&n| self.nodes[n].used = true); } + Node::Block(stmts, opt_expr) => { + stmts.iter().for_each(|&id| self.nodes[id].used = true); + opt_expr.map(|e| self.nodes[e].used = true); + } Node::Cast(_, operand, _) => { self.nodes[operand].used = true; } @@ -310,50 +301,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.nodes.push(WorkNode { node, span, used: false }) } - fn place_to_local( - &mut self, - span: Span, - p: &mir::Place<'tcx>, - ) -> Result { - const ZERO_FIELD: mir::Field = mir::Field::from_usize(0); - // Do not allow any projections. - // - // One exception are field accesses on the result of checked operations, - // which are required to support things like `1 + 2`. - if let Some(p) = p.as_local() { - debug_assert!(!self.checked_op_locals.contains(p)); - Ok(p) - } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() { - // Only allow field accesses if the given local - // contains the result of a checked operation. - if self.checked_op_locals.contains(p.local) { - Ok(p.local) - } else { - self.error(Some(span), "unsupported projection")?; - } - } else { - self.error(Some(span), "unsupported projection")?; - } - } - - fn operand_to_node( - &mut self, - span: Span, - op: &mir::Operand<'tcx>, - ) -> Result { - debug!("operand_to_node: op={:?}", op); - match op { - mir::Operand::Copy(p) | mir::Operand::Move(p) => { - let local = self.place_to_local(span, p)?; - Ok(self.locals[local]) - } - mir::Operand::Constant(ct) => match ct.literal { - mir::ConstantKind::Ty(ct) => Ok(self.add_node(Node::Leaf(ct), span)), - mir::ConstantKind::Val(..) => self.error(Some(span), "unsupported constant")?, - }, - } - } - /// We do not allow all binary operations in abstract consts, so filter disallowed ones. fn check_binop(op: mir::BinOp) -> bool { use mir::BinOp::*; @@ -373,148 +320,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { } } - fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Result<(), ErrorReported> { - debug!("AbstractConstBuilder: stmt={:?}", stmt); - let span = stmt.source_info.span; - match stmt.kind { - StatementKind::Assign(box (ref place, ref rvalue)) => { - let local = self.place_to_local(span, place)?; - match *rvalue { - Rvalue::Use(ref operand) => { - self.locals[local] = self.operand_to_node(span, operand)?; - Ok(()) - } - Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) if Self::check_binop(op) => { - let lhs = self.operand_to_node(span, lhs)?; - let rhs = self.operand_to_node(span, rhs)?; - self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span); - if op.is_checkable() { - bug!("unexpected unchecked checkable binary operation"); - } else { - Ok(()) - } - } - Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) - if Self::check_binop(op) => - { - let lhs = self.operand_to_node(span, lhs)?; - let rhs = self.operand_to_node(span, rhs)?; - self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span); - self.checked_op_locals.insert(local); - Ok(()) - } - Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => { - let operand = self.operand_to_node(span, operand)?; - self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span); - Ok(()) - } - Rvalue::Cast(cast_kind, ref operand, ty) => { - let operand = self.operand_to_node(span, operand)?; - self.locals[local] = - self.add_node(Node::Cast(cast_kind, operand, ty), span); - Ok(()) - } - _ => self.error(Some(span), "unsupported rvalue")?, - } - } - // These are not actually relevant for us here, so we can ignore them. - StatementKind::AscribeUserType(..) - | StatementKind::StorageLive(_) - | StatementKind::StorageDead(_) => Ok(()), - _ => self.error(Some(stmt.source_info.span), "unsupported statement")?, - } - } - - /// Possible return values: - /// - /// - `None`: unsupported terminator, stop building - /// - `Some(None)`: supported terminator, finish building - /// - `Some(Some(block))`: support terminator, build `block` next - fn build_terminator( - &mut self, - terminator: &mir::Terminator<'tcx>, - ) -> Result, ErrorReported> { - debug!("AbstractConstBuilder: terminator={:?}", terminator); - match terminator.kind { - TerminatorKind::Goto { target } => Ok(Some(target)), - TerminatorKind::Return => Ok(None), - TerminatorKind::Call { - ref func, - ref args, - destination: Some((ref place, target)), - // We do not care about `cleanup` here. Any branch which - // uses `cleanup` will fail const-eval and they therefore - // do not matter when checking for const evaluatability. - // - // Do note that even if `panic::catch_unwind` is made const, - // we still do not have to care about this, as we do not look - // into functions. - cleanup: _, - // Do not allow overloaded operators for now, - // we probably do want to allow this in the future. - // - // This is currently fairly irrelevant as it requires `const Trait`s. - from_hir_call: true, - fn_span, - } => { - let local = self.place_to_local(fn_span, place)?; - let func = self.operand_to_node(fn_span, func)?; - let args = self.tcx.arena.alloc_from_iter( - args.iter() - .map(|arg| self.operand_to_node(terminator.source_info.span, arg)) - .collect::, _>>()?, - ); - self.locals[local] = self.add_node(Node::FunctionCall(func, args), fn_span); - Ok(Some(target)) - } - TerminatorKind::Assert { ref cond, expected: false, target, .. } => { - let p = match cond { - mir::Operand::Copy(p) | mir::Operand::Move(p) => p, - mir::Operand::Constant(_) => bug!("unexpected assert"), - }; - - const ONE_FIELD: mir::Field = mir::Field::from_usize(1); - debug!("proj: {:?}", p.projection); - if let Some(p) = p.as_local() { - debug_assert!(!self.checked_op_locals.contains(p)); - // Mark locals directly used in asserts as used. - // - // This is needed because division does not use `CheckedBinop` but instead - // adds an explicit assert for `divisor != 0`. - self.nodes[self.locals[p]].used = true; - return Ok(Some(target)); - } else if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() { - // Only allow asserts checking the result of a checked operation. - if self.checked_op_locals.contains(p.local) { - return Ok(Some(target)); - } - } - - self.error(Some(terminator.source_info.span), "unsupported assertion")?; - } - _ => self.error(Some(terminator.source_info.span), "unsupported terminator")?, - } - } - - /// Builds the abstract const by walking the mir from start to finish - /// and bailing out when encountering an unsupported operation. + /// Builds the abstract const by walking the thir and bailing out when + /// encountering an unspported operation. fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorReported> { - let mut block = &self.body.basic_blocks()[mir::START_BLOCK]; - // We checked for a cyclic cfg above, so this should terminate. - loop { - debug!("AbstractConstBuilder: block={:?}", block); - for stmt in block.statements.iter() { - self.build_statement(stmt)?; - } - - if let Some(next) = self.build_terminator(block.terminator())? { - block = &self.body.basic_blocks()[next]; - } else { - break; - } - } + debug!("Abstractconstbuilder::build: body={:?}", &*self.body); + let last = self.recurse_build(self.body_id)?; + self.nodes[last].used = true; - assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); for n in self.nodes.iter() { if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node { // `AbstractConst`s should not contain any promoteds as they require references which @@ -523,13 +335,108 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { } } - self.nodes[self.locals[mir::RETURN_PLACE]].used = true; if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { self.error(Some(unused.span), "dead code")?; } Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))) } + + fn recurse_build(&mut self, node: thir::ExprId) -> Result { + use thir::ExprKind; + let node = &self.body.clone().exprs[node]; + debug!("recurse_build: node={:?}", node); + Ok(match &node.kind { + // I dont know if handling of these 3 is correct + &ExprKind::Scope { value, .. } => self.recurse_build(value)?, + &ExprKind::PlaceTypeAscription { source, .. } | + &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?, + + &ExprKind::Literal { literal, .. } + | &ExprKind::StaticRef { literal, .. } => self.add_node(Node::Leaf(literal), node.span), + + // FIXME(generic_const_exprs) handle `from_hir_call` field + ExprKind::Call { fun, args, .. } => { + let fun = self.recurse_build(*fun)?; + + let mut new_args = Vec::::with_capacity(args.len()); + for &id in args.iter() { + new_args.push(self.recurse_build(id)?); + } + let new_args = self.tcx.arena.alloc_slice(&new_args); + self.add_node(Node::FunctionCall(fun, new_args), node.span) + }, + &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => { + let lhs = self.recurse_build(lhs)?; + let rhs = self.recurse_build(rhs)?; + self.add_node(Node::Binop(op, lhs, rhs), node.span) + } + &ExprKind::Unary { op, arg } if Self::check_unop(op) => { + let arg = self.recurse_build(arg)?; + self.add_node(Node::UnaryOp(op, arg), node.span) + }, + // HACK: without this arm the following doesn't compile: + // ``` + // fn foo(_: [(); N + 1]) { + // bar::<{ N + 1}>(); + // } + // ``` + // we ought to properly handle this in `try_unify` + ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?, + ExprKind::Block { body } => { + let mut stmts = Vec::with_capacity(body.stmts.len()); + for &id in body.stmts.iter() { + match &self.body.stmts[id].kind { + thir::StmtKind::Let { .. } => return self.error( + Some(node.span), + "let statements are not supported in generic constants", + ).map(|never| never), + thir::StmtKind::Expr { expr, .. } => stmts.push(self.recurse_build(*expr)?), + } + }; + let stmts = self.tcx.arena.alloc_slice(&stmts); + let opt_expr = body.expr.map(|e| self.recurse_build(e)).transpose()?; + self.add_node(Node::Block(stmts, opt_expr), node.span) + } + &ExprKind::Cast { source } => todo!(), + // never can arise even without panic/fail to terminate + &ExprKind::NeverToAny { source } => todo!(), + // i think this is a dummy usage of the expr to allow coercions + &ExprKind::Use { source } => todo!(), + + ExprKind::Return { .. } + | ExprKind::Box { .. } // allocations not allowed in constants + | ExprKind::AssignOp { .. } + | ExprKind::AddressOf { .. } // FIXME(generic_const_exprs) + | ExprKind::Borrow { .. } // FIXME(generic_const_exprs) + | ExprKind::Deref { .. } // FIXME(generic_const_exprs) + | ExprKind::Repeat { .. } // FIXME(generic_const_exprs) + | ExprKind::Array { .. } // FIXME(generic_const_exprs) + | ExprKind::Tuple { .. } // FIXME(generic_const_exprs) + | ExprKind::Index { .. } // FIXME(generic_const_exprs) + | ExprKind::Field { .. } // FIXME(generic_const_exprs) + | ExprKind::ConstBlock { .. } // FIXME(generic_const_exprs) + | ExprKind::Adt(_) // FIXME(generic_const_exprs) we *should* permit this but dont currently + | ExprKind::Match { .. } + | ExprKind::VarRef { .. } // + | ExprKind::UpvarRef { .. } // we dont permit let stmts so... + | ExprKind::Closure { .. } + | ExprKind::Let { .. } // let expressions imply control flow + | ExprKind::Loop { .. } + | ExprKind::Assign { .. } + | ExprKind::LogicalOp { .. } + | ExprKind::Unary { .. } // + | ExprKind::Binary { .. } // we handle valid unary/binary ops above + | ExprKind::Break { .. } + | ExprKind::Continue { .. } + | ExprKind::If { .. } + | ExprKind::Pointer { .. } // dont know if this is correct + | ExprKind::ThreadLocalRef(_) + | ExprKind::LlvmInlineAsm { .. } + | ExprKind::InlineAsm { .. } + | ExprKind::Yield { .. } => return self.error(Some(node.span), "unsupported operation in generic constant").map(|never| never), + }) + } } /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead. @@ -547,8 +454,17 @@ pub(super) fn mir_abstract_const<'tcx>( DefKind::AnonConst => (), _ => return Ok(None), } - let body = tcx.mir_const(def).borrow(); - AbstractConstBuilder::new(tcx, &body)?.map(AbstractConstBuilder::build).transpose() + debug!("mir_abstract_const: {:?}", def); + let body = tcx.thir_body(def); + + if body.0.borrow().exprs.is_empty() { + // type error in constant, there is no thir + return Err(ErrorReported); + } + + AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))? + .map(AbstractConstBuilder::build) + .transpose() } else { Ok(None) } @@ -599,6 +515,12 @@ where recurse(tcx, ct.subtree(func), f)?; args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f)) } + Node::Block(stmts, opt_expr) => { + for id in stmts.iter().copied().chain(opt_expr) { + recurse(tcx, ct.subtree(id), f)?; + } + ControlFlow::CONTINUE + } Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f), } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 57b8a84300ff9..e64cc9e4b8f28 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -844,9 +844,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( self.visit_const(leaf) } Node::Cast(_, _, ty) => self.visit_ty(ty), - Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { - ControlFlow::CONTINUE - } + Node::Block(_, _) + | Node::Binop(..) + | Node::UnaryOp(..) + | Node::FunctionCall(_, _) => ControlFlow::CONTINUE, }) } else { ControlFlow::CONTINUE From 9b2913814b95e1b8f123da59ddecb1bc6b3813af Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 6 Sep 2021 16:14:01 +0100 Subject: [PATCH 09/31] as casts and block exprs --- .../rustc_middle/src/mir/abstract_const.rs | 4 +- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/traits/const_evaluatable.rs | 84 ++++++++++++------- .../src/traits/object_safety.rs | 2 +- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs index e75f084e79e21..1158a9f4f8008 100644 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ b/compiler/rustc_middle/src/mir/abstract_const.rs @@ -1,5 +1,5 @@ //! A subset of a mir body used for const evaluatability checking. -use crate::mir::{self, CastKind}; +use crate::mir; use crate::ty::{self, Ty}; rustc_index::newtype_index! { @@ -18,7 +18,7 @@ pub enum Node<'tcx> { UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), Block(&'tcx [NodeId], Option), - Cast(CastKind, NodeId, Ty<'tcx>), + Cast(NodeId, Ty<'tcx>), } #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 26e1c3e7b8cf4..7d0f6767900a3 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -158,7 +158,7 @@ where let leaf = leaf.subst(tcx, ct.substs); self.visit_const(leaf) } - ACNode::Cast(_, _, ty) => self.visit_ty(ty), + ACNode::Cast(_, ty) => self.visit_ty(ty), ACNode::Block(_, _) | ACNode::Binop(..) | ACNode::UnaryOp(..) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 4e11fefdc81f3..461ebba58d985 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -92,7 +92,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } - Node::Cast(_, _, ty) => { + Node::Cast(_, ty) => { let ty = ty.subst(tcx, ct.substs); if ty.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; @@ -292,7 +292,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { stmts.iter().for_each(|&id| self.nodes[id].used = true); opt_expr.map(|e| self.nodes[e].used = true); } - Node::Cast(_, operand, _) => { + Node::Cast(operand, _) => { self.nodes[operand].used = true; } } @@ -335,6 +335,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { } } + // FIXME I dont even think we can get unused nodes anymore with thir abstract const if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { self.error(Some(unused.span), "dead code")?; } @@ -352,6 +353,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { &ExprKind::PlaceTypeAscription { source, .. } | &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?, + // subtle: associated consts are literals this arm handles + // `::ASSOC` as well as `12` &ExprKind::Literal { literal, .. } | &ExprKind::StaticRef { literal, .. } => self.add_node(Node::Leaf(literal), node.span), @@ -375,14 +378,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let arg = self.recurse_build(arg)?; self.add_node(Node::UnaryOp(op, arg), node.span) }, - // HACK: without this arm the following doesn't compile: - // ``` - // fn foo(_: [(); N + 1]) { - // bar::<{ N + 1}>(); - // } - // ``` - // we ought to properly handle this in `try_unify` - ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?, ExprKind::Block { body } => { let mut stmts = Vec::with_capacity(body.stmts.len()); for &id in body.stmts.iter() { @@ -398,26 +393,34 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let opt_expr = body.expr.map(|e| self.recurse_build(e)).transpose()?; self.add_node(Node::Block(stmts, opt_expr), node.span) } - &ExprKind::Cast { source } => todo!(), + + // ExprKind::Use happens when a `hir::ExprKind::Cast` is a + // "coercion cast" i.e. using a coercion or is a no-op. + // this is important so that `N as usize as usize` doesnt unify with `N as usize` + &ExprKind::Use { source} + | &ExprKind::Cast { source } => { + let arg = self.recurse_build(source)?; + self.add_node(Node::Cast(arg, node.ty), node.span) + }, // never can arise even without panic/fail to terminate &ExprKind::NeverToAny { source } => todo!(), - // i think this is a dummy usage of the expr to allow coercions - &ExprKind::Use { source } => todo!(), - ExprKind::Return { .. } - | ExprKind::Box { .. } // allocations not allowed in constants - | ExprKind::AssignOp { .. } - | ExprKind::AddressOf { .. } // FIXME(generic_const_exprs) - | ExprKind::Borrow { .. } // FIXME(generic_const_exprs) - | ExprKind::Deref { .. } // FIXME(generic_const_exprs) - | ExprKind::Repeat { .. } // FIXME(generic_const_exprs) - | ExprKind::Array { .. } // FIXME(generic_const_exprs) - | ExprKind::Tuple { .. } // FIXME(generic_const_exprs) - | ExprKind::Index { .. } // FIXME(generic_const_exprs) - | ExprKind::Field { .. } // FIXME(generic_const_exprs) - | ExprKind::ConstBlock { .. } // FIXME(generic_const_exprs) - | ExprKind::Adt(_) // FIXME(generic_const_exprs) we *should* permit this but dont currently - | ExprKind::Match { .. } + // FIXME(generic_const_exprs) we want to support these + ExprKind::AddressOf { .. } + | ExprKind::Borrow { .. } + | ExprKind::Deref { .. } + | ExprKind::Repeat { .. } + | ExprKind::Array { .. } + | ExprKind::Tuple { .. } + | ExprKind::Index { .. } + | ExprKind::Field { .. } + | ExprKind::ConstBlock { .. } + | ExprKind::Adt(_) => return self.error( + Some(node.span), + "unsupported operation in generic constant, this may be supported in the future", + ).map(|never| never), + + ExprKind::Match { .. } | ExprKind::VarRef { .. } // | ExprKind::UpvarRef { .. } // we dont permit let stmts so... | ExprKind::Closure { .. } @@ -433,6 +436,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Pointer { .. } // dont know if this is correct | ExprKind::ThreadLocalRef(_) | ExprKind::LlvmInlineAsm { .. } + | ExprKind::Return { .. } + | ExprKind::Box { .. } // allocations not allowed in constants + | ExprKind::AssignOp { .. } | ExprKind::InlineAsm { .. } | ExprKind::Yield { .. } => return self.error(Some(node.span), "unsupported operation in generic constant").map(|never| never), }) @@ -521,7 +527,7 @@ where } ControlFlow::CONTINUE } - Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f), + Node::Cast(operand, _) => recurse(tcx, ct.subtree(operand), f), } } @@ -604,11 +610,27 @@ pub(super) fn try_unify<'tcx>( && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } - (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty)) - if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) => + (Node::Cast(a_operand, a_ty), Node::Cast(b_operand, b_ty)) + if (a_ty == b_ty) => { try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) } - _ => false, + (Node::Block(a_stmts, a_opt_expr), Node::Block(b_stmts, b_opt_expr)) + if a_stmts.len() == b_stmts.len() => { + a_stmts.iter().zip(b_stmts.iter()).all(|(&a_stmt, &b_stmt)| { + try_unify(tcx, a.subtree(a_stmt), b.subtree(b_stmt)) + }) && match (a_opt_expr, b_opt_expr) { + (Some(a_expr), Some(b_expr)) => try_unify(tcx, a.subtree(a_expr), b.subtree(b_expr)), + (None, None) => true, + _ => false, + } + } + // use this over `_ => false` to make adding variants to `Node` less error prone + (Node::Block(..), _) + | (Node::Cast(..), _) + | (Node::FunctionCall(..), _) + | (Node::UnaryOp(..), _) + | (Node::Binop(..), _) + | (Node::Leaf(..), _) => false, } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index e64cc9e4b8f28..3527aede609a4 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -843,7 +843,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( let leaf = leaf.subst(self.tcx, ct.substs); self.visit_const(leaf) } - Node::Cast(_, _, ty) => self.visit_ty(ty), + Node::Cast(_, ty) => self.visit_ty(ty), Node::Block(_, _) | Node::Binop(..) | Node::UnaryOp(..) From 4483c2bdf64e213627998ac7e2340de7dafb3037 Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 6 Sep 2021 18:20:09 +0100 Subject: [PATCH 10/31] dont support blocks --- .../rustc_middle/src/mir/abstract_const.rs | 1 - compiler/rustc_privacy/src/lib.rs | 3 +- .../src/traits/const_evaluatable.rs | 51 ++++--------------- .../src/traits/object_safety.rs | 3 +- .../generic_const_exprs/unused_expr.stderr | 12 ++--- 5 files changed, 16 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs index 1158a9f4f8008..27849e4bdb0bf 100644 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ b/compiler/rustc_middle/src/mir/abstract_const.rs @@ -17,7 +17,6 @@ pub enum Node<'tcx> { Binop(mir::BinOp, NodeId, NodeId), UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), - Block(&'tcx [NodeId], Option), Cast(NodeId, Ty<'tcx>), } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 7d0f6767900a3..02ea34ea9743f 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -159,8 +159,7 @@ where self.visit_const(leaf) } ACNode::Cast(_, ty) => self.visit_ty(ty), - ACNode::Block(_, _) - | ACNode::Binop(..) + ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => ControlFlow::CONTINUE, }) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 461ebba58d985..77fe1f514d901 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -102,8 +102,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } - Node::Block(_, _) - | Node::Binop(_, _, _) + Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => ControlFlow::CONTINUE, }); @@ -288,10 +287,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.nodes[func].used = true; nodes.iter().for_each(|&n| self.nodes[n].used = true); } - Node::Block(stmts, opt_expr) => { - stmts.iter().for_each(|&id| self.nodes[id].used = true); - opt_expr.map(|e| self.nodes[e].used = true); - } Node::Cast(operand, _) => { self.nodes[operand].used = true; } @@ -378,22 +373,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let arg = self.recurse_build(arg)?; self.add_node(Node::UnaryOp(op, arg), node.span) }, - ExprKind::Block { body } => { - let mut stmts = Vec::with_capacity(body.stmts.len()); - for &id in body.stmts.iter() { - match &self.body.stmts[id].kind { - thir::StmtKind::Let { .. } => return self.error( - Some(node.span), - "let statements are not supported in generic constants", - ).map(|never| never), - thir::StmtKind::Expr { expr, .. } => stmts.push(self.recurse_build(*expr)?), - } - }; - let stmts = self.tcx.arena.alloc_slice(&stmts); - let opt_expr = body.expr.map(|e| self.recurse_build(e)).transpose()?; - self.add_node(Node::Block(stmts, opt_expr), node.span) - } - + // this is necessary so that the following compiles: + // + // ``` + // fn foo(a: [(); N + 1]) { + // bar::<{ N + 1 }>(); + // } + // ``` + ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?, // ExprKind::Use happens when a `hir::ExprKind::Cast` is a // "coercion cast" i.e. using a coercion or is a no-op. // this is important so that `N as usize as usize` doesnt unify with `N as usize` @@ -411,6 +398,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Deref { .. } | ExprKind::Repeat { .. } | ExprKind::Array { .. } + | ExprKind::Block { .. } | ExprKind::Tuple { .. } | ExprKind::Index { .. } | ExprKind::Field { .. } @@ -521,12 +509,6 @@ where recurse(tcx, ct.subtree(func), f)?; args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f)) } - Node::Block(stmts, opt_expr) => { - for id in stmts.iter().copied().chain(opt_expr) { - recurse(tcx, ct.subtree(id), f)?; - } - ControlFlow::CONTINUE - } Node::Cast(operand, _) => recurse(tcx, ct.subtree(operand), f), } } @@ -615,19 +597,8 @@ pub(super) fn try_unify<'tcx>( { try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) } - (Node::Block(a_stmts, a_opt_expr), Node::Block(b_stmts, b_opt_expr)) - if a_stmts.len() == b_stmts.len() => { - a_stmts.iter().zip(b_stmts.iter()).all(|(&a_stmt, &b_stmt)| { - try_unify(tcx, a.subtree(a_stmt), b.subtree(b_stmt)) - }) && match (a_opt_expr, b_opt_expr) { - (Some(a_expr), Some(b_expr)) => try_unify(tcx, a.subtree(a_expr), b.subtree(b_expr)), - (None, None) => true, - _ => false, - } - } // use this over `_ => false` to make adding variants to `Node` less error prone - (Node::Block(..), _) - | (Node::Cast(..), _) + (Node::Cast(..), _) | (Node::FunctionCall(..), _) | (Node::UnaryOp(..), _) | (Node::Binop(..), _) diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 3527aede609a4..d9ea259155358 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -844,8 +844,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( self.visit_const(leaf) } Node::Cast(_, ty) => self.visit_ty(ty), - Node::Block(_, _) - | Node::Binop(..) + Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => ControlFlow::CONTINUE, }) diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr index 1687dbbcbe3f8..3da91b19a5ed9 100644 --- a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr @@ -2,9 +2,7 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:4:34 | LL | fn add() -> [u8; { N + 1; 5 }] { - | ^^-----^^^^^ - | | - | dead code + | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function @@ -12,9 +10,7 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:9:34 | LL | fn div() -> [u8; { N / 1; 5 }] { - | ^^-----^^^^^ - | | - | dead code + | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function @@ -22,9 +18,7 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:16:38 | LL | fn fn_call() -> [u8; { foo(N); 5 }] { - | ^^------^^^^^ - | | - | dead code + | ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function From 47b16f4ac9145538e8375d2625181df281206be7 Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 6 Sep 2021 18:41:05 +0100 Subject: [PATCH 11/31] bless stderr --- .../array-size-in-generic-struct-param.full.stderr | 2 +- .../ui/const-generics/generic_const_exprs/closures.stderr | 2 +- .../generic_const_exprs/let-bindings.stderr | 8 ++------ src/test/ui/const-generics/issues/issue-67375.full.stderr | 6 +++--- .../ui/const-generics/issues/issue-67945-2.full.stderr | 3 +-- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr index deb6f3bd12c1d..9b3c32a939779 100644 --- a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr @@ -10,7 +10,7 @@ error: overly complex generic constant --> $DIR/array-size-in-generic-struct-param.rs:19:15 | LL | arr: [u8; CFG.arr_size], - | ^^^^^^^^^^^^ unsupported projection + | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr index 9f0b7252e8326..95dae4ecc0431 100644 --- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr @@ -4,7 +4,7 @@ error: overly complex generic constant LL | fn test() -> [u8; N + (|| 42)()] {} | ^^^^-------^^ | | - | unsupported rvalue + | unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr index 5749defb3e12c..c9f847995223a 100644 --- a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr @@ -2,9 +2,7 @@ error: overly complex generic constant --> $DIR/let-bindings.rs:6:68 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^-^^^^^^^^^^^^^ - | | - | unsupported statement + | ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function @@ -12,9 +10,7 @@ error: overly complex generic constant --> $DIR/let-bindings.rs:6:35 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^-^^^^^^^^^^^^^ - | | - | unsupported statement + | ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr index 5386ef56a245a..d7b52063dc4db 100644 --- a/src/test/ui/const-generics/issues/issue-67375.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr @@ -2,9 +2,9 @@ error: overly complex generic constant --> $DIR/issue-67375.rs:7:17 | LL | inner: [(); { [|_: &T| {}; 0].len() }], - | ^^^----------^^^^^^^^^^^^ - | | - | unsupported rvalue + | ^^---------------^^^^^^^^ + | | + | unsupported operation in generic constant | = help: consider moving this anonymous constant into a `const` function diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr index 118cf447c01e2..fe0351a829220 100644 --- a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr @@ -5,11 +5,10 @@ LL | A: [(); { | _____________^ LL | | LL | | let x: Option> = None; - | | ---- unsupported rvalue LL | | LL | | 0 LL | | }], - | |_____^ + | |_____^ unsupported operation in generic constant, this may be supported in the future | = help: consider moving this anonymous constant into a `const` function From c170dcf04c62ffd79cbf28f340aaf6824e70f493 Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 6 Sep 2021 23:18:25 +0100 Subject: [PATCH 12/31] tidy --- compiler/rustc_privacy/src/lib.rs | 6 ++-- .../src/traits/const_evaluatable.rs | 30 +++++++++---------- .../src/traits/object_safety.rs | 6 ++-- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 02ea34ea9743f..910249ecc479e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -159,9 +159,9 @@ where self.visit_const(leaf) } ACNode::Cast(_, ty) => self.visit_ty(ty), - ACNode::Binop(..) - | ACNode::UnaryOp(..) - | ACNode::FunctionCall(_, _) => ControlFlow::CONTINUE, + ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { + ControlFlow::CONTINUE + } }) } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 77fe1f514d901..7d69ec54bdf02 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -102,9 +102,9 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } - Node::Binop(_, _, _) - | Node::UnaryOp(_, _) - | Node::FunctionCall(_, _) => ControlFlow::CONTINUE, + Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => { + ControlFlow::CONTINUE + } }); match failure_kind { @@ -348,8 +348,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { &ExprKind::PlaceTypeAscription { source, .. } | &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?, - // subtle: associated consts are literals this arm handles - // `::ASSOC` as well as `12` + // subtle: associated consts are literals this arm handles + // `::ASSOC` as well as `12` &ExprKind::Literal { literal, .. } | &ExprKind::StaticRef { literal, .. } => self.add_node(Node::Leaf(literal), node.span), @@ -381,10 +381,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // } // ``` ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?, - // ExprKind::Use happens when a `hir::ExprKind::Cast` is a + // ExprKind::Use happens when a `hir::ExprKind::Cast` is a // "coercion cast" i.e. using a coercion or is a no-op. // this is important so that `N as usize as usize` doesnt unify with `N as usize` - &ExprKind::Use { source} + &ExprKind::Use { source} | &ExprKind::Cast { source } => { let arg = self.recurse_build(source)?; self.add_node(Node::Cast(arg, node.ty), node.span) @@ -404,7 +404,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Field { .. } | ExprKind::ConstBlock { .. } | ExprKind::Adt(_) => return self.error( - Some(node.span), + Some(node.span), "unsupported operation in generic constant, this may be supported in the future", ).map(|never| never), @@ -417,7 +417,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Assign { .. } | ExprKind::LogicalOp { .. } | ExprKind::Unary { .. } // - | ExprKind::Binary { .. } // we handle valid unary/binary ops above + | ExprKind::Binary { .. } // we handle valid unary/binary ops above | ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::If { .. } @@ -592,16 +592,14 @@ pub(super) fn try_unify<'tcx>( && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } - (Node::Cast(a_operand, a_ty), Node::Cast(b_operand, b_ty)) - if (a_ty == b_ty) => - { + (Node::Cast(a_operand, a_ty), Node::Cast(b_operand, b_ty)) if (a_ty == b_ty) => { try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) } // use this over `_ => false` to make adding variants to `Node` less error prone - (Node::Cast(..), _) - | (Node::FunctionCall(..), _) - | (Node::UnaryOp(..), _) - | (Node::Binop(..), _) + (Node::Cast(..), _) + | (Node::FunctionCall(..), _) + | (Node::UnaryOp(..), _) + | (Node::Binop(..), _) | (Node::Leaf(..), _) => false, } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index d9ea259155358..63bd10994b1ac 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -844,9 +844,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( self.visit_const(leaf) } Node::Cast(_, ty) => self.visit_ty(ty), - Node::Binop(..) - | Node::UnaryOp(..) - | Node::FunctionCall(_, _) => ControlFlow::CONTINUE, + Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { + ControlFlow::CONTINUE + } }) } else { ControlFlow::CONTINUE From 08e86440165619c57e0072eb742c7dad3cfd0950 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 00:05:24 +0100 Subject: [PATCH 13/31] move thir visitor to rustc_middle --- compiler/rustc_middle/src/thir.rs | 243 ++++++++++++++++++ .../rustc_mir_build/src/check_unsafety.rs | 2 +- compiler/rustc_mir_build/src/thir/mod.rs | 1 - compiler/rustc_mir_build/src/thir/visit.rs | 240 ----------------- 4 files changed, 244 insertions(+), 242 deletions(-) delete mode 100644 compiler/rustc_mir_build/src/thir/visit.rs diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 91a64e163e7c0..3012676c872bd 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -818,3 +818,246 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } } } + +pub mod visit { + use super::*; + pub trait Visitor<'a, 'tcx: 'a>: Sized { + fn thir(&self) -> &'a Thir<'tcx>; + + fn visit_expr(&mut self, expr: &Expr<'tcx>) { + walk_expr(self, expr); + } + + fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { + walk_stmt(self, stmt); + } + + fn visit_block(&mut self, block: &Block) { + walk_block(self, block); + } + + fn visit_arm(&mut self, arm: &Arm<'tcx>) { + walk_arm(self, arm); + } + + fn visit_pat(&mut self, pat: &Pat<'tcx>) { + walk_pat(self, pat); + } + + fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {} + } + + pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) { + use ExprKind::*; + match expr.kind { + Scope { value, region_scope: _, lint_level: _ } => { + visitor.visit_expr(&visitor.thir()[value]) + } + Box { value } => visitor.visit_expr(&visitor.thir()[value]), + If { cond, then, else_opt, if_then_scope: _ } => { + visitor.visit_expr(&visitor.thir()[cond]); + visitor.visit_expr(&visitor.thir()[then]); + if let Some(else_expr) = else_opt { + visitor.visit_expr(&visitor.thir()[else_expr]); + } + } + Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => { + visitor.visit_expr(&visitor.thir()[fun]); + for &arg in &**args { + visitor.visit_expr(&visitor.thir()[arg]); + } + } + Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]), + Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => { + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[rhs]); + } + Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]), + Cast { source } => visitor.visit_expr(&visitor.thir()[source]), + Use { source } => visitor.visit_expr(&visitor.thir()[source]), + NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), + Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), + Let { expr, .. } => { + visitor.visit_expr(&visitor.thir()[expr]); + } + Loop { body } => visitor.visit_expr(&visitor.thir()[body]), + Match { scrutinee, ref arms } => { + visitor.visit_expr(&visitor.thir()[scrutinee]); + for &arm in &**arms { + visitor.visit_arm(&visitor.thir()[arm]); + } + } + Block { ref body } => visitor.visit_block(body), + Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[rhs]); + } + Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]), + Index { lhs, index } => { + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[index]); + } + VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {} + Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]), + AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), + Break { value, label: _ } => { + if let Some(value) = value { + visitor.visit_expr(&visitor.thir()[value]) + } + } + Continue { label: _ } => {} + Return { value } => { + if let Some(value) = value { + visitor.visit_expr(&visitor.thir()[value]) + } + } + ConstBlock { value } => visitor.visit_const(value), + Repeat { value, count } => { + visitor.visit_expr(&visitor.thir()[value]); + visitor.visit_const(count); + } + Array { ref fields } | Tuple { ref fields } => { + for &field in &**fields { + visitor.visit_expr(&visitor.thir()[field]); + } + } + Adt(box crate::thir::Adt { + ref fields, + ref base, + adt_def: _, + variant_index: _, + substs: _, + user_ty: _, + }) => { + for field in &**fields { + visitor.visit_expr(&visitor.thir()[field.expr]); + } + if let Some(base) = base { + visitor.visit_expr(&visitor.thir()[base.base]); + } + } + PlaceTypeAscription { source, user_ty: _ } + | ValueTypeAscription { source, user_ty: _ } => { + visitor.visit_expr(&visitor.thir()[source]) + } + Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} + Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal), + StaticRef { literal, def_id: _ } => visitor.visit_const(literal), + InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { + for op in &**operands { + use InlineAsmOperand::*; + match op { + In { expr, reg: _ } + | Out { expr: Some(expr), reg: _, late: _ } + | InOut { expr, reg: _, late: _ } + | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]), + SplitInOut { in_expr, out_expr, reg: _, late: _ } => { + visitor.visit_expr(&visitor.thir()[*in_expr]); + if let Some(out_expr) = out_expr { + visitor.visit_expr(&visitor.thir()[*out_expr]); + } + } + Out { expr: None, reg: _, late: _ } + | Const { value: _, span: _ } + | SymStatic { def_id: _ } => {} + } + } + } + ThreadLocalRef(_) => {} + LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => { + for &out_expr in &**outputs { + visitor.visit_expr(&visitor.thir()[out_expr]); + } + for &in_expr in &**inputs { + visitor.visit_expr(&visitor.thir()[in_expr]); + } + } + Yield { value } => visitor.visit_expr(&visitor.thir()[value]), + } + } + + pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) { + match &stmt.kind { + StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]), + StmtKind::Let { + initializer, + remainder_scope: _, + init_scope: _, + ref pattern, + lint_level: _, + } => { + if let Some(init) = initializer { + visitor.visit_expr(&visitor.thir()[*init]); + } + visitor.visit_pat(pattern); + } + } + } + + pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) { + for &stmt in &*block.stmts { + visitor.visit_stmt(&visitor.thir()[stmt]); + } + if let Some(expr) = block.expr { + visitor.visit_expr(&visitor.thir()[expr]); + } + } + + pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) { + match arm.guard { + Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]), + Some(Guard::IfLet(ref pat, expr)) => { + visitor.visit_pat(pat); + visitor.visit_expr(&visitor.thir()[expr]); + } + None => {} + } + visitor.visit_pat(&arm.pattern); + visitor.visit_expr(&visitor.thir()[arm.body]); + } + + pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) { + use PatKind::*; + match pat.kind.as_ref() { + AscribeUserType { subpattern, ascription: _ } + | Deref { subpattern } + | Binding { + subpattern: Some(subpattern), + mutability: _, + mode: _, + var: _, + ty: _, + is_primary: _, + name: _, + } => visitor.visit_pat(&subpattern), + Binding { .. } | Wild => {} + Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } + | Leaf { subpatterns } => { + for subpattern in subpatterns { + visitor.visit_pat(&subpattern.pattern); + } + } + Constant { value } => visitor.visit_const(value), + Range(range) => { + visitor.visit_const(range.lo); + visitor.visit_const(range.hi); + } + Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { + for subpattern in prefix { + visitor.visit_pat(&subpattern); + } + if let Some(pat) = slice { + visitor.visit_pat(pat); + } + for subpattern in suffix { + visitor.visit_pat(&subpattern); + } + } + Or { pats } => { + for pat in pats { + visitor.visit_pat(&pat); + } + } + }; + } +} diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 05a5fcef16ae5..0e82b18720142 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,5 +1,5 @@ use crate::build::ExprCategory; -use crate::thir::visit::{self, Visitor}; +use rustc_middle::thir::visit::{self, Visitor}; use rustc_errors::struct_span_err; use rustc_hir as hir; diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index e5123d8ef0c99..ddbe1b0b69c1e 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -11,4 +11,3 @@ crate mod cx; crate mod pattern; mod util; -pub mod visit; diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_mir_build/src/thir/visit.rs deleted file mode 100644 index 51c371b872057..0000000000000 --- a/compiler/rustc_mir_build/src/thir/visit.rs +++ /dev/null @@ -1,240 +0,0 @@ -use rustc_middle::thir::{self, *}; -use rustc_middle::ty::Const; - -pub trait Visitor<'a, 'tcx: 'a>: Sized { - fn thir(&self) -> &'a Thir<'tcx>; - - fn visit_expr(&mut self, expr: &Expr<'tcx>) { - walk_expr(self, expr); - } - - fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { - walk_stmt(self, stmt); - } - - fn visit_block(&mut self, block: &Block) { - walk_block(self, block); - } - - fn visit_arm(&mut self, arm: &Arm<'tcx>) { - walk_arm(self, arm); - } - - fn visit_pat(&mut self, pat: &Pat<'tcx>) { - walk_pat(self, pat); - } - - fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {} -} - -pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) { - use ExprKind::*; - match expr.kind { - Scope { value, region_scope: _, lint_level: _ } => { - visitor.visit_expr(&visitor.thir()[value]) - } - Box { value } => visitor.visit_expr(&visitor.thir()[value]), - If { cond, then, else_opt, if_then_scope: _ } => { - visitor.visit_expr(&visitor.thir()[cond]); - visitor.visit_expr(&visitor.thir()[then]); - if let Some(else_expr) = else_opt { - visitor.visit_expr(&visitor.thir()[else_expr]); - } - } - Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => { - visitor.visit_expr(&visitor.thir()[fun]); - for &arg in &**args { - visitor.visit_expr(&visitor.thir()[arg]); - } - } - Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]), - Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => { - visitor.visit_expr(&visitor.thir()[lhs]); - visitor.visit_expr(&visitor.thir()[rhs]); - } - Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]), - Cast { source } => visitor.visit_expr(&visitor.thir()[source]), - Use { source } => visitor.visit_expr(&visitor.thir()[source]), - NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), - Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), - Let { expr, .. } => { - visitor.visit_expr(&visitor.thir()[expr]); - } - Loop { body } => visitor.visit_expr(&visitor.thir()[body]), - Match { scrutinee, ref arms } => { - visitor.visit_expr(&visitor.thir()[scrutinee]); - for &arm in &**arms { - visitor.visit_arm(&visitor.thir()[arm]); - } - } - Block { ref body } => visitor.visit_block(body), - Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { - visitor.visit_expr(&visitor.thir()[lhs]); - visitor.visit_expr(&visitor.thir()[rhs]); - } - Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]), - Index { lhs, index } => { - visitor.visit_expr(&visitor.thir()[lhs]); - visitor.visit_expr(&visitor.thir()[index]); - } - VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {} - Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]), - AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), - Break { value, label: _ } => { - if let Some(value) = value { - visitor.visit_expr(&visitor.thir()[value]) - } - } - Continue { label: _ } => {} - Return { value } => { - if let Some(value) = value { - visitor.visit_expr(&visitor.thir()[value]) - } - } - ConstBlock { value } => visitor.visit_const(value), - Repeat { value, count } => { - visitor.visit_expr(&visitor.thir()[value]); - visitor.visit_const(count); - } - Array { ref fields } | Tuple { ref fields } => { - for &field in &**fields { - visitor.visit_expr(&visitor.thir()[field]); - } - } - Adt(box thir::Adt { - ref fields, - ref base, - adt_def: _, - variant_index: _, - substs: _, - user_ty: _, - }) => { - for field in &**fields { - visitor.visit_expr(&visitor.thir()[field.expr]); - } - if let Some(base) = base { - visitor.visit_expr(&visitor.thir()[base.base]); - } - } - PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => { - visitor.visit_expr(&visitor.thir()[source]) - } - Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} - Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal), - StaticRef { literal, def_id: _ } => visitor.visit_const(literal), - InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { - for op in &**operands { - use InlineAsmOperand::*; - match op { - In { expr, reg: _ } - | Out { expr: Some(expr), reg: _, late: _ } - | InOut { expr, reg: _, late: _ } - | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]), - SplitInOut { in_expr, out_expr, reg: _, late: _ } => { - visitor.visit_expr(&visitor.thir()[*in_expr]); - if let Some(out_expr) = out_expr { - visitor.visit_expr(&visitor.thir()[*out_expr]); - } - } - Out { expr: None, reg: _, late: _ } - | Const { value: _, span: _ } - | SymStatic { def_id: _ } => {} - } - } - } - ThreadLocalRef(_) => {} - LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => { - for &out_expr in &**outputs { - visitor.visit_expr(&visitor.thir()[out_expr]); - } - for &in_expr in &**inputs { - visitor.visit_expr(&visitor.thir()[in_expr]); - } - } - Yield { value } => visitor.visit_expr(&visitor.thir()[value]), - } -} - -pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) { - match &stmt.kind { - StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]), - StmtKind::Let { - initializer, - remainder_scope: _, - init_scope: _, - ref pattern, - lint_level: _, - } => { - if let Some(init) = initializer { - visitor.visit_expr(&visitor.thir()[*init]); - } - visitor.visit_pat(pattern); - } - } -} - -pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) { - for &stmt in &*block.stmts { - visitor.visit_stmt(&visitor.thir()[stmt]); - } - if let Some(expr) = block.expr { - visitor.visit_expr(&visitor.thir()[expr]); - } -} - -pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) { - match arm.guard { - Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]), - Some(Guard::IfLet(ref pat, expr)) => { - visitor.visit_pat(pat); - visitor.visit_expr(&visitor.thir()[expr]); - } - None => {} - } - visitor.visit_pat(&arm.pattern); - visitor.visit_expr(&visitor.thir()[arm.body]); -} - -pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) { - use PatKind::*; - match pat.kind.as_ref() { - AscribeUserType { subpattern, ascription: _ } - | Deref { subpattern } - | Binding { - subpattern: Some(subpattern), - mutability: _, - mode: _, - var: _, - ty: _, - is_primary: _, - name: _, - } => visitor.visit_pat(&subpattern), - Binding { .. } | Wild => {} - Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => { - for subpattern in subpatterns { - visitor.visit_pat(&subpattern.pattern); - } - } - Constant { value } => visitor.visit_const(value), - Range(range) => { - visitor.visit_const(range.lo); - visitor.visit_const(range.hi); - } - Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { - for subpattern in prefix { - visitor.visit_pat(&subpattern); - } - if let Some(pat) = slice { - visitor.visit_pat(pat); - } - for subpattern in suffix { - visitor.visit_pat(&subpattern); - } - } - Or { pats } => { - for pat in pats { - visitor.visit_pat(&pat); - } - } - }; -} From fc63e9a8fb619ad79d2d24db06078652a2a6c1ba Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 00:05:59 +0100 Subject: [PATCH 14/31] dont build abstract const for monomorphic consts --- .../src/traits/const_evaluatable.rs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 7d69ec54bdf02..3e1719e08acfa 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -267,7 +267,36 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let builder = AbstractConstBuilder { tcx, body_id, body: Lrc::new(body), nodes: IndexVec::new() }; - // FIXME non-constants should return Ok(None) + struct IsThirPolymorphic<'a, 'tcx> { + is_poly: bool, + thir: &'a thir::Thir<'tcx>, + tcx: TyCtxt<'tcx>, + } + + use thir::visit; + impl<'a, 'tcx: 'a> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> { + fn thir(&self) -> &'a thir::Thir<'tcx> { + &self.thir + } + + fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) { + self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx); + if self.is_poly { + return; + } + visit::walk_expr(self, expr); + } + + fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) { + self.is_poly |= ct.definitely_has_param_types_or_consts(self.tcx); + } + } + + let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx }; + visit::walk_expr(&mut is_poly_vis, &body[body_id]); + if is_poly_vis.is_poly == false { + return Ok(None); + } Ok(Some(builder)) } From 4cbcb0936a3ae16a99f977427a6a01646a1ed8dd Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 00:06:44 +0100 Subject: [PATCH 15/31] handle `ExprKind::NeverToAny` --- compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 3e1719e08acfa..21423d415e3b9 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -418,8 +418,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let arg = self.recurse_build(source)?; self.add_node(Node::Cast(arg, node.ty), node.span) }, - // never can arise even without panic/fail to terminate - &ExprKind::NeverToAny { source } => todo!(), // FIXME(generic_const_exprs) we want to support these ExprKind::AddressOf { .. } @@ -428,6 +426,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Repeat { .. } | ExprKind::Array { .. } | ExprKind::Block { .. } + | ExprKind::NeverToAny { .. } // I dont think we can get this without adt construction | ExprKind::Tuple { .. } | ExprKind::Index { .. } | ExprKind::Field { .. } From 1f57f8b9032fa0f83aa59f634ac72f1e63a1cfa2 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 00:44:24 +0100 Subject: [PATCH 16/31] remove `WorkNode` --- .../src/traits/const_evaluatable.rs | 61 +++---------------- 1 file changed, 10 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 21423d415e3b9..c47b0c31ca01c 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -224,24 +224,13 @@ impl<'tcx> AbstractConst<'tcx> { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -struct WorkNode<'tcx> { - node: Node<'tcx>, - span: Span, - used: bool, -} - struct AbstractConstBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, body_id: thir::ExprId, + /// `Lrc` is used to avoid borrowck difficulties in `recurse_build` body: Lrc<&'a thir::Thir<'tcx>>, /// The current WIP node tree. - /// - /// We require all nodes to be used in the final abstract const, - /// so we store this here. Note that we also consider nodes as used - /// if they are mentioned in an assert, so some used nodes are never - /// actually reachable by walking the [`AbstractConst`]. - nodes: IndexVec>, + nodes: IndexVec>, } impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { @@ -301,30 +290,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { Ok(Some(builder)) } - fn add_node(&mut self, node: Node<'tcx>, span: Span) -> NodeId { - // Mark used nodes. - match node { - Node::Leaf(_) => (), - Node::Binop(_, lhs, rhs) => { - self.nodes[lhs].used = true; - self.nodes[rhs].used = true; - } - Node::UnaryOp(_, input) => { - self.nodes[input].used = true; - } - Node::FunctionCall(func, nodes) => { - self.nodes[func].used = true; - nodes.iter().for_each(|&n| self.nodes[n].used = true); - } - Node::Cast(operand, _) => { - self.nodes[operand].used = true; - } - } - - // Nodes start as unused. - self.nodes.push(WorkNode { node, span, used: false }) - } - /// We do not allow all binary operations in abstract consts, so filter disallowed ones. fn check_binop(op: mir::BinOp) -> bool { use mir::BinOp::*; @@ -348,23 +313,17 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { /// encountering an unspported operation. fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorReported> { debug!("Abstractconstbuilder::build: body={:?}", &*self.body); - let last = self.recurse_build(self.body_id)?; - self.nodes[last].used = true; + self.recurse_build(self.body_id)?; for n in self.nodes.iter() { - if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node { + if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n { // `AbstractConst`s should not contain any promoteds as they require references which // are not allowed. assert_eq!(ct.promoted, None); } } - // FIXME I dont even think we can get unused nodes anymore with thir abstract const - if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { - self.error(Some(unused.span), "dead code")?; - } - - Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))) + Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter())) } fn recurse_build(&mut self, node: thir::ExprId) -> Result { @@ -380,7 +339,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // subtle: associated consts are literals this arm handles // `::ASSOC` as well as `12` &ExprKind::Literal { literal, .. } - | &ExprKind::StaticRef { literal, .. } => self.add_node(Node::Leaf(literal), node.span), + | &ExprKind::StaticRef { literal, .. } => self.nodes.push(Node::Leaf(literal)), // FIXME(generic_const_exprs) handle `from_hir_call` field ExprKind::Call { fun, args, .. } => { @@ -391,16 +350,16 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { new_args.push(self.recurse_build(id)?); } let new_args = self.tcx.arena.alloc_slice(&new_args); - self.add_node(Node::FunctionCall(fun, new_args), node.span) + self.nodes.push(Node::FunctionCall(fun, new_args)) }, &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => { let lhs = self.recurse_build(lhs)?; let rhs = self.recurse_build(rhs)?; - self.add_node(Node::Binop(op, lhs, rhs), node.span) + self.nodes.push(Node::Binop(op, lhs, rhs)) } &ExprKind::Unary { op, arg } if Self::check_unop(op) => { let arg = self.recurse_build(arg)?; - self.add_node(Node::UnaryOp(op, arg), node.span) + self.nodes.push(Node::UnaryOp(op, arg)) }, // this is necessary so that the following compiles: // @@ -416,7 +375,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { &ExprKind::Use { source} | &ExprKind::Cast { source } => { let arg = self.recurse_build(source)?; - self.add_node(Node::Cast(arg, node.ty), node.span) + self.nodes.push(Node::Cast(arg, node.ty)) }, // FIXME(generic_const_exprs) we want to support these From 15101c8e95db6941f8c7d55fb301ad1b62748c7b Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 01:17:51 +0100 Subject: [PATCH 17/31] remove debug stmts --- compiler/rustc_mir_build/src/build/mod.rs | 2 -- compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 --- compiler/rustc_mir_build/src/thir/cx/mod.rs | 1 - compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 3 +-- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 390ce59cb489c..e931c686dde59 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -28,7 +28,6 @@ crate fn mir_built<'tcx>( if let Some(def) = def.try_upgrade(tcx) { return tcx.mir_built(def); } - debug!("mir_built: def={:?}", def); let mut body = mir_build(tcx, def); if def.const_param_did.is_some() { @@ -41,7 +40,6 @@ crate fn mir_built<'tcx>( /// Construct the MIR for a given `DefId`. fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_> { - debug!("mir_build: def={:?}", def); let id = tcx.hir().local_def_id_to_hir_id(def.did); let body_owner_kind = tcx.hir().body_owner_kind(id); let typeck_results = tcx.typeck_opt_const_arg(def); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 70a5a9286b0b3..66005be05df75 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -149,9 +149,7 @@ impl<'tcx> Cx<'tcx> { } fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { - debug!("Expr::make_mirror_unadjusted: expr={:?}", expr); let expr_ty = self.typeck_results().expr_ty(expr); - debug!("Expr::make_mirror_unadjusted: expr_ty={:?}", expr_ty); let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let kind = match expr.kind { @@ -764,7 +762,6 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Err => unreachable!(), }; - debug!("Expr::make_mirror_unadjusted: finish"); Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind } } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 5310efbccd655..5059dd939d92d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -20,7 +20,6 @@ crate fn thir_body<'tcx>( tcx: TyCtxt<'tcx>, owner_def: ty::WithOptConstParam, ) -> (&'tcx Steal>, ExprId) { - debug!("thir_body: {:?}", owner_def); let hir = tcx.hir(); let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(owner_def.did))); let mut cx = Cx::new(tcx, owner_def); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index c47b0c31ca01c..4251dc5e93904 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -435,9 +435,8 @@ pub(super) fn mir_abstract_const<'tcx>( DefKind::AnonConst => (), _ => return Ok(None), } - debug!("mir_abstract_const: {:?}", def); + let body = tcx.thir_body(def); - if body.0.borrow().exprs.is_empty() { // type error in constant, there is no thir return Err(ErrorReported); From 406d2ab95de0e90f45e00f6c1be1e4e7912aa153 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 01:56:29 +0100 Subject: [PATCH 18/31] rename mir -> thir around abstract consts --- compiler/rustc_metadata/src/rmeta/decoder.rs | 9 +- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 8 +- compiler/rustc_metadata/src/rmeta/mod.rs | 3 +- compiler/rustc_middle/src/mir/mod.rs | 1 - compiler/rustc_middle/src/mir/query.rs | 9 +- compiler/rustc_middle/src/query/mod.rs | 8 +- compiler/rustc_middle/src/thir.rs | 246 +----------------- .../src/{mir => thir}/abstract_const.rs | 0 compiler/rustc_middle/src/thir/visit.rs | 238 +++++++++++++++++ compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_middle/src/ty/codec.rs | 5 +- compiler/rustc_mir_build/src/build/mod.rs | 4 +- compiler/rustc_mir_transform/src/lib.rs | 1 - compiler/rustc_privacy/src/lib.rs | 2 +- .../rustc_query_impl/src/on_disk_cache.rs | 3 +- .../src/traits/const_evaluatable.rs | 12 +- .../src/traits/error_reporting/mod.rs | 2 +- .../src/traits/fulfill.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 10 +- .../src/traits/object_safety.rs | 2 +- .../src/traits/select/mod.rs | 2 +- 22 files changed, 287 insertions(+), 284 deletions(-) rename compiler/rustc_middle/src/{mir => thir}/abstract_const.rs (100%) create mode 100644 compiler/rustc_middle/src/thir/visit.rs diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index dd44e0cb1fa90..7ebea9ecc8ef2 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -26,6 +26,7 @@ use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, Body, Promoted}; +use rustc_middle::thir; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; @@ -540,7 +541,7 @@ impl<'a, 'tcx> Decodable> for Span { } } -impl<'a, 'tcx> Decodable> for &'tcx [mir::abstract_const::Node<'tcx>] { +impl<'a, 'tcx> Decodable> for &'tcx [thir::abstract_const::Node<'tcx>] { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result { ty::codec::RefDecodable::decode(d) } @@ -1198,14 +1199,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, tcx)) } - fn get_mir_abstract_const( + fn get_thir_abstract_const( &self, tcx: TyCtxt<'tcx>, id: DefIndex, - ) -> Result]>, ErrorReported> { + ) -> Result]>, ErrorReported> { self.root .tables - .mir_abstract_consts + .thir_abstract_consts .get(self, id) .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx))))) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 41839c58021ab..1a147242619a7 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -117,7 +117,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) } mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) } promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } - mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) } + thir_abstract_const => { cdata.get_thir_abstract_const(tcx, def_id.index) } unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) } mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d8b9a4799760e..60d7f0f85bb57 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -23,6 +23,7 @@ use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportLevel, }; use rustc_middle::mir::interpret; +use rustc_middle::thir; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; @@ -344,7 +345,7 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { } } -impl<'a, 'tcx> Encodable> for &'tcx [mir::abstract_const::Node<'tcx>] { +impl<'a, 'tcx> Encodable> for &'tcx [thir::abstract_const::Node<'tcx>] { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { (**self).encode(s) } @@ -1304,9 +1305,10 @@ impl EncodeContext<'a, 'tcx> { if encode_const { record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id)); - let abstract_const = self.tcx.mir_abstract_const(def_id); + // FIXME this feels wrong to have in `encode_mir` + let abstract_const = self.tcx.thir_abstract_const(def_id); if let Ok(Some(abstract_const)) = abstract_const { - record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const); + record!(self.tables.thir_abstract_consts[def_id.to_def_id()] <- abstract_const); } } record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id)); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a487753f4628a..e59e9ad5d15d6 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -15,6 +15,7 @@ use rustc_middle::hir::exports::Export; use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir; +use rustc_middle::thir; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; @@ -305,7 +306,7 @@ define_tables! { mir: Table)>, mir_for_ctfe: Table)>, promoted_mir: Table>)>, - mir_abstract_consts: Table])>, + thir_abstract_consts: Table])>, const_defaults: Table>>, unused_generic_params: Table>>, // `def_keys` and `def_path_hashes` represent a lazy version of a diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 38d4c5b4bd10e..ba8ccc71954ff 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -40,7 +40,6 @@ use self::graph_cyclic_cache::GraphIsCyclicCache; use self::predecessors::{PredecessorCache, Predecessors}; pub use self::query::*; -pub mod abstract_const; pub mod coverage; mod generic_graph; pub mod generic_graphviz; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 1bdb6ca012b4a..a1c6a8bf99e79 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,6 +1,7 @@ //! Values computed by queries that use MIR. -use crate::mir::{abstract_const, Body, Promoted}; +use crate::mir::{Body, Promoted}; +use crate::thir::abstract_const; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; @@ -433,14 +434,14 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mir_abstract_const_opt_const_arg( + pub fn thir_abstract_const_opt_const_arg( self, def: ty::WithOptConstParam, ) -> Result]>, ErrorReported> { if let Some((did, param_did)) = def.as_const_arg() { - self.mir_abstract_const_of_const_arg((did, param_did)) + self.thir_abstract_const_of_const_arg((did, param_did)) } else { - self.mir_abstract_const(def.did) + self.thir_abstract_const(def.did) } } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c93996162e3e3..19535195488b7 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -295,17 +295,17 @@ rustc_queries! { } /// Try to build an abstract representation of the given constant. - query mir_abstract_const( + query thir_abstract_const( key: DefId - ) -> Result]>, ErrorReported> { + ) -> Result]>, ErrorReported> { desc { |tcx| "building an abstract representation for {}", tcx.def_path_str(key), } } /// Try to build an abstract representation of the given constant. - query mir_abstract_const_of_const_arg( + query thir_abstract_const_of_const_arg( key: (LocalDefId, DefId) - ) -> Result]>, ErrorReported> { + ) -> Result]>, ErrorReported> { desc { |tcx| "building an abstract representation for the const argument {}", diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 3012676c872bd..8d6fd1e729d3b 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -33,6 +33,9 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use std::fmt; use std::ops::Index; +pub mod abstract_const; +pub mod visit; + newtype_index! { /// An index to an [`Arm`] stored in [`Thir::arms`] #[derive(HashStable)] @@ -818,246 +821,3 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } } } - -pub mod visit { - use super::*; - pub trait Visitor<'a, 'tcx: 'a>: Sized { - fn thir(&self) -> &'a Thir<'tcx>; - - fn visit_expr(&mut self, expr: &Expr<'tcx>) { - walk_expr(self, expr); - } - - fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { - walk_stmt(self, stmt); - } - - fn visit_block(&mut self, block: &Block) { - walk_block(self, block); - } - - fn visit_arm(&mut self, arm: &Arm<'tcx>) { - walk_arm(self, arm); - } - - fn visit_pat(&mut self, pat: &Pat<'tcx>) { - walk_pat(self, pat); - } - - fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {} - } - - pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) { - use ExprKind::*; - match expr.kind { - Scope { value, region_scope: _, lint_level: _ } => { - visitor.visit_expr(&visitor.thir()[value]) - } - Box { value } => visitor.visit_expr(&visitor.thir()[value]), - If { cond, then, else_opt, if_then_scope: _ } => { - visitor.visit_expr(&visitor.thir()[cond]); - visitor.visit_expr(&visitor.thir()[then]); - if let Some(else_expr) = else_opt { - visitor.visit_expr(&visitor.thir()[else_expr]); - } - } - Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => { - visitor.visit_expr(&visitor.thir()[fun]); - for &arg in &**args { - visitor.visit_expr(&visitor.thir()[arg]); - } - } - Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]), - Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => { - visitor.visit_expr(&visitor.thir()[lhs]); - visitor.visit_expr(&visitor.thir()[rhs]); - } - Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]), - Cast { source } => visitor.visit_expr(&visitor.thir()[source]), - Use { source } => visitor.visit_expr(&visitor.thir()[source]), - NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), - Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), - Let { expr, .. } => { - visitor.visit_expr(&visitor.thir()[expr]); - } - Loop { body } => visitor.visit_expr(&visitor.thir()[body]), - Match { scrutinee, ref arms } => { - visitor.visit_expr(&visitor.thir()[scrutinee]); - for &arm in &**arms { - visitor.visit_arm(&visitor.thir()[arm]); - } - } - Block { ref body } => visitor.visit_block(body), - Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { - visitor.visit_expr(&visitor.thir()[lhs]); - visitor.visit_expr(&visitor.thir()[rhs]); - } - Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]), - Index { lhs, index } => { - visitor.visit_expr(&visitor.thir()[lhs]); - visitor.visit_expr(&visitor.thir()[index]); - } - VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {} - Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]), - AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), - Break { value, label: _ } => { - if let Some(value) = value { - visitor.visit_expr(&visitor.thir()[value]) - } - } - Continue { label: _ } => {} - Return { value } => { - if let Some(value) = value { - visitor.visit_expr(&visitor.thir()[value]) - } - } - ConstBlock { value } => visitor.visit_const(value), - Repeat { value, count } => { - visitor.visit_expr(&visitor.thir()[value]); - visitor.visit_const(count); - } - Array { ref fields } | Tuple { ref fields } => { - for &field in &**fields { - visitor.visit_expr(&visitor.thir()[field]); - } - } - Adt(box crate::thir::Adt { - ref fields, - ref base, - adt_def: _, - variant_index: _, - substs: _, - user_ty: _, - }) => { - for field in &**fields { - visitor.visit_expr(&visitor.thir()[field.expr]); - } - if let Some(base) = base { - visitor.visit_expr(&visitor.thir()[base.base]); - } - } - PlaceTypeAscription { source, user_ty: _ } - | ValueTypeAscription { source, user_ty: _ } => { - visitor.visit_expr(&visitor.thir()[source]) - } - Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} - Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal), - StaticRef { literal, def_id: _ } => visitor.visit_const(literal), - InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { - for op in &**operands { - use InlineAsmOperand::*; - match op { - In { expr, reg: _ } - | Out { expr: Some(expr), reg: _, late: _ } - | InOut { expr, reg: _, late: _ } - | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]), - SplitInOut { in_expr, out_expr, reg: _, late: _ } => { - visitor.visit_expr(&visitor.thir()[*in_expr]); - if let Some(out_expr) = out_expr { - visitor.visit_expr(&visitor.thir()[*out_expr]); - } - } - Out { expr: None, reg: _, late: _ } - | Const { value: _, span: _ } - | SymStatic { def_id: _ } => {} - } - } - } - ThreadLocalRef(_) => {} - LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => { - for &out_expr in &**outputs { - visitor.visit_expr(&visitor.thir()[out_expr]); - } - for &in_expr in &**inputs { - visitor.visit_expr(&visitor.thir()[in_expr]); - } - } - Yield { value } => visitor.visit_expr(&visitor.thir()[value]), - } - } - - pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) { - match &stmt.kind { - StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]), - StmtKind::Let { - initializer, - remainder_scope: _, - init_scope: _, - ref pattern, - lint_level: _, - } => { - if let Some(init) = initializer { - visitor.visit_expr(&visitor.thir()[*init]); - } - visitor.visit_pat(pattern); - } - } - } - - pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) { - for &stmt in &*block.stmts { - visitor.visit_stmt(&visitor.thir()[stmt]); - } - if let Some(expr) = block.expr { - visitor.visit_expr(&visitor.thir()[expr]); - } - } - - pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) { - match arm.guard { - Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]), - Some(Guard::IfLet(ref pat, expr)) => { - visitor.visit_pat(pat); - visitor.visit_expr(&visitor.thir()[expr]); - } - None => {} - } - visitor.visit_pat(&arm.pattern); - visitor.visit_expr(&visitor.thir()[arm.body]); - } - - pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) { - use PatKind::*; - match pat.kind.as_ref() { - AscribeUserType { subpattern, ascription: _ } - | Deref { subpattern } - | Binding { - subpattern: Some(subpattern), - mutability: _, - mode: _, - var: _, - ty: _, - is_primary: _, - name: _, - } => visitor.visit_pat(&subpattern), - Binding { .. } | Wild => {} - Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } - | Leaf { subpatterns } => { - for subpattern in subpatterns { - visitor.visit_pat(&subpattern.pattern); - } - } - Constant { value } => visitor.visit_const(value), - Range(range) => { - visitor.visit_const(range.lo); - visitor.visit_const(range.hi); - } - Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { - for subpattern in prefix { - visitor.visit_pat(&subpattern); - } - if let Some(pat) = slice { - visitor.visit_pat(pat); - } - for subpattern in suffix { - visitor.visit_pat(&subpattern); - } - } - Or { pats } => { - for pat in pats { - visitor.visit_pat(&pat); - } - } - }; - } -} diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs similarity index 100% rename from compiler/rustc_middle/src/mir/abstract_const.rs rename to compiler/rustc_middle/src/thir/abstract_const.rs diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs new file mode 100644 index 0000000000000..21826ac89d3a9 --- /dev/null +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -0,0 +1,238 @@ +use super::*; +pub trait Visitor<'a, 'tcx: 'a>: Sized { + fn thir(&self) -> &'a Thir<'tcx>; + + fn visit_expr(&mut self, expr: &Expr<'tcx>) { + walk_expr(self, expr); + } + + fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { + walk_stmt(self, stmt); + } + + fn visit_block(&mut self, block: &Block) { + walk_block(self, block); + } + + fn visit_arm(&mut self, arm: &Arm<'tcx>) { + walk_arm(self, arm); + } + + fn visit_pat(&mut self, pat: &Pat<'tcx>) { + walk_pat(self, pat); + } + + fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {} +} + +pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) { + use ExprKind::*; + match expr.kind { + Scope { value, region_scope: _, lint_level: _ } => { + visitor.visit_expr(&visitor.thir()[value]) + } + Box { value } => visitor.visit_expr(&visitor.thir()[value]), + If { cond, then, else_opt, if_then_scope: _ } => { + visitor.visit_expr(&visitor.thir()[cond]); + visitor.visit_expr(&visitor.thir()[then]); + if let Some(else_expr) = else_opt { + visitor.visit_expr(&visitor.thir()[else_expr]); + } + } + Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => { + visitor.visit_expr(&visitor.thir()[fun]); + for &arg in &**args { + visitor.visit_expr(&visitor.thir()[arg]); + } + } + Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]), + Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => { + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[rhs]); + } + Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]), + Cast { source } => visitor.visit_expr(&visitor.thir()[source]), + Use { source } => visitor.visit_expr(&visitor.thir()[source]), + NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), + Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), + Let { expr, .. } => { + visitor.visit_expr(&visitor.thir()[expr]); + } + Loop { body } => visitor.visit_expr(&visitor.thir()[body]), + Match { scrutinee, ref arms } => { + visitor.visit_expr(&visitor.thir()[scrutinee]); + for &arm in &**arms { + visitor.visit_arm(&visitor.thir()[arm]); + } + } + Block { ref body } => visitor.visit_block(body), + Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[rhs]); + } + Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]), + Index { lhs, index } => { + visitor.visit_expr(&visitor.thir()[lhs]); + visitor.visit_expr(&visitor.thir()[index]); + } + VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {} + Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]), + AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), + Break { value, label: _ } => { + if let Some(value) = value { + visitor.visit_expr(&visitor.thir()[value]) + } + } + Continue { label: _ } => {} + Return { value } => { + if let Some(value) = value { + visitor.visit_expr(&visitor.thir()[value]) + } + } + ConstBlock { value } => visitor.visit_const(value), + Repeat { value, count } => { + visitor.visit_expr(&visitor.thir()[value]); + visitor.visit_const(count); + } + Array { ref fields } | Tuple { ref fields } => { + for &field in &**fields { + visitor.visit_expr(&visitor.thir()[field]); + } + } + Adt(box crate::thir::Adt { + ref fields, + ref base, + adt_def: _, + variant_index: _, + substs: _, + user_ty: _, + }) => { + for field in &**fields { + visitor.visit_expr(&visitor.thir()[field.expr]); + } + if let Some(base) = base { + visitor.visit_expr(&visitor.thir()[base.base]); + } + } + PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => { + visitor.visit_expr(&visitor.thir()[source]) + } + Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} + Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal), + StaticRef { literal, def_id: _ } => visitor.visit_const(literal), + InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { + for op in &**operands { + use InlineAsmOperand::*; + match op { + In { expr, reg: _ } + | Out { expr: Some(expr), reg: _, late: _ } + | InOut { expr, reg: _, late: _ } + | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]), + SplitInOut { in_expr, out_expr, reg: _, late: _ } => { + visitor.visit_expr(&visitor.thir()[*in_expr]); + if let Some(out_expr) = out_expr { + visitor.visit_expr(&visitor.thir()[*out_expr]); + } + } + Out { expr: None, reg: _, late: _ } + | Const { value: _, span: _ } + | SymStatic { def_id: _ } => {} + } + } + } + ThreadLocalRef(_) => {} + LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => { + for &out_expr in &**outputs { + visitor.visit_expr(&visitor.thir()[out_expr]); + } + for &in_expr in &**inputs { + visitor.visit_expr(&visitor.thir()[in_expr]); + } + } + Yield { value } => visitor.visit_expr(&visitor.thir()[value]), + } +} + +pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) { + match &stmt.kind { + StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]), + StmtKind::Let { + initializer, + remainder_scope: _, + init_scope: _, + ref pattern, + lint_level: _, + } => { + if let Some(init) = initializer { + visitor.visit_expr(&visitor.thir()[*init]); + } + visitor.visit_pat(pattern); + } + } +} + +pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) { + for &stmt in &*block.stmts { + visitor.visit_stmt(&visitor.thir()[stmt]); + } + if let Some(expr) = block.expr { + visitor.visit_expr(&visitor.thir()[expr]); + } +} + +pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) { + match arm.guard { + Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]), + Some(Guard::IfLet(ref pat, expr)) => { + visitor.visit_pat(pat); + visitor.visit_expr(&visitor.thir()[expr]); + } + None => {} + } + visitor.visit_pat(&arm.pattern); + visitor.visit_expr(&visitor.thir()[arm.body]); +} + +pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) { + use PatKind::*; + match pat.kind.as_ref() { + AscribeUserType { subpattern, ascription: _ } + | Deref { subpattern } + | Binding { + subpattern: Some(subpattern), + mutability: _, + mode: _, + var: _, + ty: _, + is_primary: _, + name: _, + } => visitor.visit_pat(&subpattern), + Binding { .. } | Wild => {} + Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => { + for subpattern in subpatterns { + visitor.visit_pat(&subpattern.pattern); + } + } + Constant { value } => visitor.visit_const(value), + Range(range) => { + visitor.visit_const(range.lo); + visitor.visit_const(range.hi); + } + Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { + for subpattern in prefix { + visitor.visit_pat(&subpattern); + } + if let Some(pat) = slice { + visitor.visit_pat(pat); + } + for subpattern in suffix { + visitor.visit_pat(&subpattern); + } + } + Or { pats } => { + for pat in pats { + visitor.visit_pat(&pat); + } + } + }; +} diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 74edb17fe32f1..e21a2d1034cdd 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -9,7 +9,7 @@ pub mod specialization_graph; mod structural_impls; use crate::infer::canonical::Canonical; -use crate::mir::abstract_const::NotConstEvaluatable; +use crate::thir::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 4edb6a327b035..8b70692960df9 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -12,6 +12,7 @@ use crate::mir::{ self, interpret::{AllocId, Allocation}, }; +use crate::thir; use crate::ty::subst::SubstsRef; use crate::ty::{self, List, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; @@ -362,7 +363,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::Node<'tcx>] { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { Ok(decoder.tcx().arena.alloc_from_iter( (0..decoder.read_usize()?) @@ -372,7 +373,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::NodeId] { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { Ok(decoder.tcx().arena.alloc_from_iter( (0..decoder.read_usize()?) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index e931c686dde59..0ee740a646359 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -48,11 +48,11 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ match def { ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => { tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)); - tcx.ensure().mir_abstract_const_of_const_arg((did, const_param_did)); + tcx.ensure().thir_abstract_const_of_const_arg((did, const_param_did)); } ty::WithOptConstParam { did, const_param_did: None } => { tcx.ensure().thir_check_unsafety(did); - tcx.ensure().mir_abstract_const(did); + tcx.ensure().thir_abstract_const(did); } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 22abce65a4b7d..20232e635a2b8 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -307,7 +307,6 @@ fn mir_promoted( // this point, before we steal the mir-const result. // Also this means promotion can rely on all const checks having been done. let _ = tcx.mir_const_qualif_opt_const_arg(def); - let _ = tcx.mir_abstract_const_opt_const_arg(def.to_global()); let mut body = tcx.mir_const(def).steal(); let mut required_consts = Vec::new(); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 910249ecc479e..4dcb98ae7e960 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -19,8 +19,8 @@ use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; use rustc_middle::bug; use rustc_middle::hir::map::Map; use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; -use rustc_middle::mir::abstract_const::Node as ACNode; use rustc_middle::span_bug; +use rustc_middle::thir::abstract_const::Node as ACNode; use rustc_middle::ty::fold::TypeVisitor; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{InternalSubsts, Subst}; diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 5c2803c67e73f..2903e220b3b07 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -9,6 +9,7 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, interpret}; +use rustc_middle::thir; use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_query_system::dep_graph::DepContext; @@ -906,7 +907,7 @@ impl<'a, 'tcx> Decodable> } } -impl<'a, 'tcx> Decodable> for &'tcx [mir::abstract_const::Node<'tcx>] { +impl<'a, 'tcx> Decodable> for &'tcx [thir::abstract_const::Node<'tcx>] { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result { RefDecodable::decode(d) } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 4251dc5e93904..8c2a3d4abf41b 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -6,7 +6,7 @@ //! this is not as easy. //! //! In this case we try to build an abstract representation of this constant using -//! `mir_abstract_const` which can then be checked for structural equality with other +//! `thir_abstract_const` which can then be checked for structural equality with other //! generic constants mentioned in the `caller_bounds` of the current environment. use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; @@ -14,9 +14,9 @@ use rustc_hir::def::DefKind; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; use rustc_middle::mir; -use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir; +use rustc_middle::thir::abstract_const::{Node, NodeId, NotConstEvaluatable}; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_session::lint; @@ -197,7 +197,7 @@ impl<'tcx> AbstractConst<'tcx> { tcx: TyCtxt<'tcx>, uv: ty::Unevaluated<'tcx, ()>, ) -> Result>, ErrorReported> { - let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?; + let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs(tcx) })) } @@ -421,10 +421,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { } /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead. -pub(super) fn mir_abstract_const<'tcx>( +pub(super) fn thir_abstract_const<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, -) -> Result]>, ErrorReported> { +) -> Result]>, ErrorReported> { if tcx.features().generic_const_exprs { match tcx.def_kind(def.did) { // FIXME(generic_const_exprs): We currently only do this for anonymous constants, @@ -435,7 +435,7 @@ pub(super) fn mir_abstract_const<'tcx>( DefKind::AnonConst => (), _ => return Ok(None), } - + let body = tcx.thir_body(def); if body.0.borrow().exprs.is_empty() { // type error in constant, there is no thir 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 9ce6c58a0f1df..4d3a8324d7987 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -19,7 +19,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::GenericParam; use rustc_hir::Item; use rustc_hir::Node; -use rustc_middle::mir::abstract_const::NotConstEvaluatable; +use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 18abcc72bcee8..b376f42929249 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -5,8 +5,8 @@ use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProce use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; -use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ToPredicate; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 44c675243838a..ef208c44471cb 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -827,16 +827,16 @@ pub fn provide(providers: &mut ty::query::Providers) { vtable_entries, vtable_trait_upcasting_coercion_new_vptr_slot, subst_and_check_impossible_predicates, - mir_abstract_const: |tcx, def_id| { + thir_abstract_const: |tcx, def_id| { let def_id = def_id.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) { - tcx.mir_abstract_const_of_const_arg(def) + tcx.thir_abstract_const_of_const_arg(def) } else { - const_evaluatable::mir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id)) + const_evaluatable::thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id)) } }, - mir_abstract_const_of_const_arg: |tcx, (did, param_did)| { - const_evaluatable::mir_abstract_const( + thir_abstract_const_of_const_arg: |tcx, (did, param_did)| { + const_evaluatable::thir_abstract_const( tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) }, ) diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 63bd10994b1ac..e001bb7445e8c 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -836,7 +836,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // // This shouldn't really matter though as we can't really use any // constants which are not considered const evaluatable. - use rustc_middle::mir::abstract_const::Node; + use rustc_middle::thir::abstract_const::Node; if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) { const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() { Node::Leaf(leaf) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 22013fb79cf79..01a38ffa7d0b2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -34,8 +34,8 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; -use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; From 79be0802557089b408776ba161d95f8f4b5d0683 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 03:02:12 +0100 Subject: [PATCH 19/31] remove comment --- compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 8c2a3d4abf41b..1aaed7cade281 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -385,7 +385,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Repeat { .. } | ExprKind::Array { .. } | ExprKind::Block { .. } - | ExprKind::NeverToAny { .. } // I dont think we can get this without adt construction + | ExprKind::NeverToAny { .. } | ExprKind::Tuple { .. } | ExprKind::Index { .. } | ExprKind::Field { .. } From 955e2b2da0ca29042206a56060baa820a2d961e7 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 12:05:11 +0100 Subject: [PATCH 20/31] nits --- compiler/rustc_middle/src/mir/query.rs | 13 ------- .../rustc_middle/src/thir/abstract_const.rs | 23 +++++++++-- compiler/rustc_middle/src/thir/visit.rs | 6 ++- .../src/traits/const_evaluatable.rs | 39 +++++++++---------- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index a1c6a8bf99e79..567f65e83d98c 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,7 +1,6 @@ //! Values computed by queries that use MIR. use crate::mir::{Body, Promoted}; -use crate::thir::abstract_const; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; @@ -432,16 +431,4 @@ impl<'tcx> TyCtxt<'tcx> { self.mir_for_ctfe(def.did) } } - - #[inline] - pub fn thir_abstract_const_opt_const_arg( - self, - def: ty::WithOptConstParam, - ) -> Result]>, ErrorReported> { - if let Some((did, param_did)) = def.as_const_arg() { - self.thir_abstract_const_of_const_arg((did, param_did)) - } else { - self.thir_abstract_const(def.did) - } - } } diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs index 27849e4bdb0bf..00f1390eb4d4e 100644 --- a/compiler/rustc_middle/src/thir/abstract_const.rs +++ b/compiler/rustc_middle/src/thir/abstract_const.rs @@ -1,6 +1,7 @@ //! A subset of a mir body used for const evaluatability checking. use crate::mir; -use crate::ty::{self, Ty}; +use crate::ty::{self, Ty, TyCtxt}; +use rustc_errors::ErrorReported; rustc_index::newtype_index! { /// An index into an `AbstractConst`. @@ -22,13 +23,13 @@ pub enum Node<'tcx> { #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub enum NotConstEvaluatable { - Error(rustc_errors::ErrorReported), + Error(ErrorReported), MentionsInfer, MentionsParam, } -impl From for NotConstEvaluatable { - fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable { +impl From for NotConstEvaluatable { + fn from(e: ErrorReported) -> NotConstEvaluatable { NotConstEvaluatable::Error(e) } } @@ -36,3 +37,17 @@ impl From for NotConstEvaluatable { TrivialTypeFoldableAndLiftImpls! { NotConstEvaluatable, } + +impl<'tcx> TyCtxt<'tcx> { + #[inline] + pub fn thir_abstract_const_opt_const_arg( + self, + def: ty::WithOptConstParam, + ) -> Result]>, ErrorReported> { + if let Some((did, param_did)) = def.as_const_arg() { + self.thir_abstract_const_of_const_arg((did, param_did)) + } else { + self.thir_abstract_const(def.did) + } + } +} diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 21826ac89d3a9..7fc15e02fcd30 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -1,4 +1,8 @@ -use super::*; +use super::{ + Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir, +}; +use rustc_middle::ty::Const; + pub trait Visitor<'a, 'tcx: 'a>: Sized { fn thir(&self) -> &'a Thir<'tcx>; diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 1aaed7cade281..1845b9d1314b1 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -8,7 +8,6 @@ //! In this case we try to build an abstract representation of this constant using //! `thir_abstract_const` which can then be checked for structural equality with other //! generic constants mentioned in the `caller_bounds` of the current environment. -use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_hir::def::DefKind; use rustc_index::vec::IndexVec; @@ -227,8 +226,7 @@ impl<'tcx> AbstractConst<'tcx> { struct AbstractConstBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, body_id: thir::ExprId, - /// `Lrc` is used to avoid borrowck difficulties in `recurse_build` - body: Lrc<&'a thir::Thir<'tcx>>, + body: &'a thir::Thir<'tcx>, /// The current WIP node tree. nodes: IndexVec>, } @@ -253,8 +251,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, (body, body_id): (&'a thir::Thir<'tcx>, thir::ExprId), ) -> Result>, ErrorReported> { - let builder = - AbstractConstBuilder { tcx, body_id, body: Lrc::new(body), nodes: IndexVec::new() }; + let builder = AbstractConstBuilder { tcx, body_id, body, nodes: IndexVec::new() }; struct IsThirPolymorphic<'a, 'tcx> { is_poly: bool, @@ -328,7 +325,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { fn recurse_build(&mut self, node: thir::ExprId) -> Result { use thir::ExprKind; - let node = &self.body.clone().exprs[node]; + let node = &self.body.exprs[node]; debug!("recurse_build: node={:?}", node); Ok(match &node.kind { // I dont know if handling of these 3 is correct @@ -338,10 +335,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // subtle: associated consts are literals this arm handles // `::ASSOC` as well as `12` - &ExprKind::Literal { literal, .. } - | &ExprKind::StaticRef { literal, .. } => self.nodes.push(Node::Leaf(literal)), + &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)), - // FIXME(generic_const_exprs) handle `from_hir_call` field + // FIXME(generic_const_exprs): Handle `from_hir_call` field ExprKind::Call { fun, args, .. } => { let fun = self.recurse_build(*fun)?; @@ -361,7 +357,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let arg = self.recurse_build(arg)?; self.nodes.push(Node::UnaryOp(op, arg)) }, - // this is necessary so that the following compiles: + // This is necessary so that the following compiles: // // ``` // fn foo(a: [(); N + 1]) { @@ -369,16 +365,16 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // } // ``` ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?, - // ExprKind::Use happens when a `hir::ExprKind::Cast` is a + // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a // "coercion cast" i.e. using a coercion or is a no-op. - // this is important so that `N as usize as usize` doesnt unify with `N as usize` + // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested) &ExprKind::Use { source} | &ExprKind::Cast { source } => { let arg = self.recurse_build(source)?; self.nodes.push(Node::Cast(arg, node.ty)) }, - // FIXME(generic_const_exprs) we want to support these + // FIXME(generic_const_exprs): We may want to support these. ExprKind::AddressOf { .. } | ExprKind::Borrow { .. } | ExprKind::Deref { .. } @@ -390,21 +386,24 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Index { .. } | ExprKind::Field { .. } | ExprKind::ConstBlock { .. } - | ExprKind::Adt(_) => return self.error( + | ExprKind::Adt(_) => self.error( Some(node.span), "unsupported operation in generic constant, this may be supported in the future", - ).map(|never| never), + )?, ExprKind::Match { .. } - | ExprKind::VarRef { .. } // - | ExprKind::UpvarRef { .. } // we dont permit let stmts so... + // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen + | ExprKind::VarRef { .. } + | ExprKind::UpvarRef { .. } | ExprKind::Closure { .. } | ExprKind::Let { .. } // let expressions imply control flow | ExprKind::Loop { .. } | ExprKind::Assign { .. } + | ExprKind::StaticRef { .. } | ExprKind::LogicalOp { .. } - | ExprKind::Unary { .. } // - | ExprKind::Binary { .. } // we handle valid unary/binary ops above + // we handle valid unary/binary ops above + | ExprKind::Unary { .. } + | ExprKind::Binary { .. } | ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::If { .. } @@ -415,7 +414,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | ExprKind::Box { .. } // allocations not allowed in constants | ExprKind::AssignOp { .. } | ExprKind::InlineAsm { .. } - | ExprKind::Yield { .. } => return self.error(Some(node.span), "unsupported operation in generic constant").map(|never| never), + | ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?, }) } } From 8c7954dc425e8c6ee4aaaf14be5015ad8982d540 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 13:24:04 +0100 Subject: [PATCH 21/31] add a `CastKind` to `Node::Cast` --- .../rustc_middle/src/thir/abstract_const.rs | 10 +++++++++- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/traits/const_evaluatable.rs | 17 ++++++++++------- .../src/traits/object_safety.rs | 2 +- .../abstract-consts-as-cast-5.rs | 11 +++++++++++ .../abstract-consts-as-cast-5.stderr | 10 ++++++++++ 6 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs index 00f1390eb4d4e..f80beadd6e551 100644 --- a/compiler/rustc_middle/src/thir/abstract_const.rs +++ b/compiler/rustc_middle/src/thir/abstract_const.rs @@ -11,6 +11,14 @@ rustc_index::newtype_index! { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum CastKind { + /// thir::ExprKind::As + As, + /// thir::ExprKind::Use + Use, +} + /// A node of an `AbstractConst`. #[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub enum Node<'tcx> { @@ -18,7 +26,7 @@ pub enum Node<'tcx> { Binop(mir::BinOp, NodeId, NodeId), UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), - Cast(NodeId, Ty<'tcx>), + Cast(CastKind, NodeId, Ty<'tcx>), } #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4dcb98ae7e960..391e43054239d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -158,7 +158,7 @@ where let leaf = leaf.subst(tcx, ct.substs); self.visit_const(leaf) } - ACNode::Cast(_, ty) => self.visit_ty(ty), + ACNode::Cast(_, _, ty) => self.visit_ty(ty), ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { ControlFlow::CONTINUE } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 1845b9d1314b1..26c71a0f53921 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -15,7 +15,7 @@ use rustc_infer::infer::InferCtxt; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir; -use rustc_middle::thir::abstract_const::{Node, NodeId, NotConstEvaluatable}; +use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable}; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_session::lint; @@ -91,7 +91,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } - Node::Cast(_, ty) => { + Node::Cast(_, _, ty) => { let ty = ty.subst(tcx, ct.substs); if ty.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; @@ -368,10 +368,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a // "coercion cast" i.e. using a coercion or is a no-op. // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested) - &ExprKind::Use { source} - | &ExprKind::Cast { source } => { + &ExprKind::Use { source } => { let arg = self.recurse_build(source)?; - self.nodes.push(Node::Cast(arg, node.ty)) + self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty)) + }, + &ExprKind::Cast { source } => { + let arg = self.recurse_build(source)?; + self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty)) }, // FIXME(generic_const_exprs): We may want to support these. @@ -494,7 +497,7 @@ where recurse(tcx, ct.subtree(func), f)?; args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f)) } - Node::Cast(operand, _) => recurse(tcx, ct.subtree(operand), f), + Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f), } } @@ -577,7 +580,7 @@ pub(super) fn try_unify<'tcx>( && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } - (Node::Cast(a_operand, a_ty), Node::Cast(b_operand, b_ty)) if (a_ty == b_ty) => { + (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty)) if (a_ty == b_ty) && (a_kind == b_kind) => { try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) } // use this over `_ => false` to make adding variants to `Node` less error prone diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index e001bb7445e8c..70cdbe4d5c7cb 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -843,7 +843,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( let leaf = leaf.subst(self.tcx, ct.substs); self.visit_const(leaf) } - Node::Cast(_, ty) => self.visit_ty(ty), + Node::Cast(_, _, ty) => self.visit_ty(ty), Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { ControlFlow::CONTINUE } diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs new file mode 100644 index 0000000000000..b3cde61f5e7f2 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo(a: [(); N as usize]) { + bar::<{ N as usize as usize }>(); + //~^ error: unconstrained generic constant +} + +fn bar() {} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr new file mode 100644 index 0000000000000..d48b639dbdee3 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/abstract-consts-as-cast-5.rs:5:11 + | +LL | bar::<{ N as usize as usize }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:` + +error: aborting due to previous error + From 3212734bd744719dc197a19902d083c591670ab1 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 13:36:50 +0100 Subject: [PATCH 22/31] resolve `from_hir_call` FIXME --- .../src/traits/const_evaluatable.rs | 1 - .../abstract-consts-as-cast-5.rs | 2 +- .../unify-op-with-fn-call.rs | 23 +++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 26c71a0f53921..702b5a508b744 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -337,7 +337,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // `::ASSOC` as well as `12` &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)), - // FIXME(generic_const_exprs): Handle `from_hir_call` field ExprKind::Call { fun, args, .. } => { let fun = self.recurse_build(*fun)?; diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs index b3cde61f5e7f2..916d60c0e0def 100644 --- a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs @@ -8,4 +8,4 @@ fn foo(a: [(); N as usize]) { fn bar() {} -fn main() {} \ No newline at end of file +fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs new file mode 100644 index 0000000000000..abbeb2c928ed4 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -0,0 +1,23 @@ +#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +struct Foo(u8); + +impl const std::ops::Add for Foo { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + self + } +} + +struct Evaluatable; + +fn foo(a: Evaluatable<{ N + N }>) { + bar::<{ std::ops::Add::add(N, N) }>(); +} + +fn bar() {} + +fn main() {} From cd2915eddb446df2d89922d3b68080d091dc247e Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 13:49:31 +0100 Subject: [PATCH 23/31] fmt --- .../rustc_trait_selection/src/traits/const_evaluatable.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 702b5a508b744..4f178f777afb2 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -579,7 +579,9 @@ pub(super) fn try_unify<'tcx>( && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } - (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty)) if (a_ty == b_ty) && (a_kind == b_kind) => { + (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty)) + if (a_ty == b_ty) && (a_kind == b_kind) => + { try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) } // use this over `_ => false` to make adding variants to `Node` less error prone From fd9bb30ab8fc65da735272f9cfd55d1368da9069 Mon Sep 17 00:00:00 2001 From: Ellen Date: Tue, 7 Sep 2021 14:27:07 +0100 Subject: [PATCH 24/31] CI please --- .../const-generics/generic_const_exprs/unify-op-with-fn-call.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs index abbeb2c928ed4..bb054bec6b6c2 100644 --- a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs +++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(generic_const_exprs, adt_const_params, const_trait_impl)] #![allow(incomplete_features)] From dc02b51382d5fea61d74624273d1d98263745243 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 9 Sep 2021 14:22:24 +0000 Subject: [PATCH 25/31] Use more accurate spans for "unused delimiter" lint --- compiler/rustc_lint/src/unused.rs | 120 +++++------ .../issues/issue-54752-async-block.stderr | 7 +- .../ui/const-generics/unused_braces.stderr | 7 +- .../ui/lint/lint-unnecessary-parens.stderr | 135 +++++++++++-- src/test/ui/lint/suggestions.stderr | 7 +- .../issue-54538-unused-parens-lint.stderr | 191 +++++++++++++++--- ...ssue-74883-unused-paren-baren-yield.stderr | 46 ++++- src/test/ui/lint/unused_braces.stderr | 38 +++- src/test/ui/lint/unused_braces_borrow.stderr | 7 +- .../lint/unused_parens_json_suggestion.stderr | 9 +- ...nused_parens_remove_json_suggestion.stderr | 89 ++++++-- src/test/ui/path-lookahead.stderr | 7 +- .../try-block/try-block-unused-delims.stderr | 38 +++- 13 files changed, 551 insertions(+), 150 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 7a42e8c1037ba..48b955e41ac69 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -3,7 +3,6 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext} use rustc_ast as ast; use rustc_ast::util::{classify, parser}; use rustc_ast::{ExprKind, StmtKind}; -use rustc_ast_pretty::pprust; use rustc_errors::{pluralize, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -12,7 +11,7 @@ use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; declare_lint! { /// The `unused_must_use` lint detects unused result of a type flagged as @@ -491,77 +490,60 @@ trait UnusedDelimLint { left_pos: Option, right_pos: Option, ) { - let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { - snippet - } else { - pprust::expr_to_string(value) + let spans = match value.kind { + ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => { + let start = block.stmts[0].span; + let end = block.stmts[block.stmts.len() - 1].span; + if value.span.from_expansion() || start.from_expansion() || end.from_expansion() { + ( + value.span.with_hi(value.span.lo() + BytePos(1)), + value.span.with_lo(value.span.hi() - BytePos(1)), + ) + } else { + (value.span.with_hi(start.lo()), value.span.with_lo(end.hi())) + } + } + ast::ExprKind::Paren(ref expr) => { + if value.span.from_expansion() || expr.span.from_expansion() { + ( + value.span.with_hi(value.span.lo() + BytePos(1)), + value.span.with_lo(value.span.hi() - BytePos(1)), + ) + } else { + (value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi())) + } + } + _ => return, }; let keep_space = ( left_pos.map_or(false, |s| s >= value.span.lo()), right_pos.map_or(false, |s| s <= value.span.hi()), ); - self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space); + self.emit_unused_delims(cx, spans, ctx.into(), keep_space); } fn emit_unused_delims( &self, cx: &EarlyContext<'_>, - span: Span, - pattern: &str, + spans: (Span, Span), msg: &str, keep_space: (bool, bool), ) { // FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc // properly. - if span == DUMMY_SP { + if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP { return; } - cx.struct_span_lint(self.lint(), span, |lint| { + cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| { let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg); let mut err = lint.build(&span_msg); - let mut ate_left_paren = false; - let mut ate_right_paren = false; - let parens_removed = pattern - .trim_matches(|c| match c { - '(' | '{' => { - if ate_left_paren { - false - } else { - ate_left_paren = true; - true - } - } - ')' | '}' => { - if ate_right_paren { - false - } else { - ate_right_paren = true; - true - } - } - _ => false, - }) - .trim(); - - let replace = { - let mut replace = if keep_space.0 { - let mut s = String::from(" "); - s.push_str(parens_removed); - s - } else { - String::from(parens_removed) - }; - - if keep_space.1 { - replace.push(' '); - } - replace - }; - + let replacement = vec![ + (spans.0, if keep_space.0 { " ".into() } else { "".into() }), + (spans.1, if keep_space.1 { " ".into() } else { "".into() }), + ]; let suggestion = format!("remove these {}", Self::DELIM_STR); - - err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable); + err.multipart_suggestion(&suggestion, replacement, Applicability::MachineApplicable); err.emit(); }); } @@ -770,14 +752,15 @@ impl UnusedParens { // Otherwise proceed with linting. _ => {} } - - let pattern_text = - if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { - snippet - } else { - pprust::pat_to_string(value) - }; - self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false)); + let spans = if value.span.from_expansion() || inner.span.from_expansion() { + ( + value.span.with_hi(value.span.lo() + BytePos(1)), + value.span.with_lo(value.span.hi() - BytePos(1)), + ) + } else { + (value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi())) + }; + self.emit_unused_delims(cx, spans, "pattern", (false, false)); } } } @@ -870,14 +853,15 @@ impl EarlyLintPass for UnusedParens { ); } _ => { - let pattern_text = - if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) { - snippet - } else { - pprust::ty_to_string(ty) - }; - - self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false)); + let spans = if ty.span.from_expansion() || r.span.from_expansion() { + ( + ty.span.with_hi(ty.span.lo() + BytePos(1)), + ty.span.with_lo(ty.span.hi() - BytePos(1)), + ) + } else { + (ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi())) + }; + self.emit_unused_delims(cx, spans, "type", (false, false)); } } } diff --git a/src/test/ui/async-await/issues/issue-54752-async-block.stderr b/src/test/ui/async-await/issues/issue-54752-async-block.stderr index e39a049e2d304..0aea56ddb702b 100644 --- a/src/test/ui/async-await/issues/issue-54752-async-block.stderr +++ b/src/test/ui/async-await/issues/issue-54752-async-block.stderr @@ -2,9 +2,14 @@ warning: unnecessary parentheses around assigned value --> $DIR/issue-54752-async-block.rs:6:22 | LL | fn main() { let _a = (async { }); } - | ^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | = note: `#[warn(unused_parens)]` on by default +help: remove these parentheses + | +LL - fn main() { let _a = (async { }); } +LL + fn main() { let _a = async { }; } + | warning: 1 warning emitted diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr index 5e1bace549241..533fcabd41822 100644 --- a/src/test/ui/const-generics/unused_braces.stderr +++ b/src/test/ui/const-generics/unused_braces.stderr @@ -2,13 +2,18 @@ warning: unnecessary braces around const expression --> $DIR/unused_braces.rs:9:14 | LL | let _: A<{ 7 }>; - | ^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/unused_braces.rs:3:9 | LL | #![warn(unused_braces)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - let _: A<{ 7 }>; +LL + let _: A<7>; + | warning: 1 warning emitted diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr index 9eae7da90047e..1d5f9ebb5e5c5 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.stderr +++ b/src/test/ui/lint/lint-unnecessary-parens.stderr @@ -2,109 +2,210 @@ error: unnecessary parentheses around `return` value --> $DIR/lint-unnecessary-parens.rs:13:12 | LL | return (1); - | ^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/lint-unnecessary-parens.rs:3:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - return (1); +LL + return 1; + | error: unnecessary parentheses around `return` value --> $DIR/lint-unnecessary-parens.rs:16:12 | LL | return (X { y }); - | ^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - return (X { y }); +LL + return X { y }; + | error: unnecessary parentheses around type --> $DIR/lint-unnecessary-parens.rs:19:46 | LL | pub fn unused_parens_around_return_type() -> (u32) { - | ^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn unused_parens_around_return_type() -> (u32) { +LL + pub fn unused_parens_around_return_type() -> u32 { + | error: unnecessary parentheses around block return value --> $DIR/lint-unnecessary-parens.rs:25:9 | LL | (5) - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | error: unnecessary parentheses around block return value --> $DIR/lint-unnecessary-parens.rs:27:5 | LL | (5) - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:44:31 | LL | pub const CONST_ITEM: usize = (10); - | ^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - pub const CONST_ITEM: usize = (10); +LL + pub const CONST_ITEM: usize = 10; + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:45:33 | LL | pub static STATIC_ITEM: usize = (10); - | ^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - pub static STATIC_ITEM: usize = (10); +LL + pub static STATIC_ITEM: usize = 10; + | error: unnecessary parentheses around function argument --> $DIR/lint-unnecessary-parens.rs:49:9 | LL | bar((true)); - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - bar((true)); +LL + bar(true); + | error: unnecessary parentheses around `if` condition --> $DIR/lint-unnecessary-parens.rs:51:8 | LL | if (true) {} - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if (true) {} +LL + if true {} + | error: unnecessary parentheses around `while` condition --> $DIR/lint-unnecessary-parens.rs:52:11 | LL | while (true) {} - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while (true) {} +LL + while true {} + | error: unnecessary parentheses around `match` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:53:11 | LL | match (true) { - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - match (true) { +LL + match true { + | error: unnecessary parentheses around `let` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:56:16 | LL | if let 1 = (1) {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let 1 = (1) {} +LL + if let 1 = 1 {} + | error: unnecessary parentheses around `let` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:57:19 | LL | while let 1 = (2) {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let 1 = (2) {} +LL + while let 1 = 2 {} + | error: unnecessary parentheses around method argument --> $DIR/lint-unnecessary-parens.rs:73:24 | LL | X { y: false }.foo((true)); - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - X { y: false }.foo((true)); +LL + X { y: false }.foo(true); + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:75:18 | LL | let mut _a = (0); - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - let mut _a = (0); +LL + let mut _a = 0; + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:76:10 | LL | _a = (0); - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - _a = (0); +LL + _a = 0; + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:77:11 | LL | _a += (1); - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - _a += (1); +LL + _a += 1; + | error: aborting due to 17 previous errors diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index cad2514625588..255772ff40261 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -10,13 +10,18 @@ warning: unnecessary parentheses around assigned value --> $DIR/suggestions.rs:48:31 | LL | let mut registry_no = (format!("NX-{}", 74205)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/suggestions.rs:4:21 | LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let mut registry_no = (format!("NX-{}", 74205)); +LL + let mut registry_no = format!("NX-{}", 74205); + | warning: variable does not need to be mutable --> $DIR/suggestions.rs:48:13 diff --git a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr index e6d0a359c5ca7..677b96d3f32f0 100644 --- a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr @@ -2,151 +2,294 @@ error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:16:9 | LL | let (a) = 0; - | ^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/issue-54538-unused-parens-lint.rs:13:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let (a) = 0; +LL + let a = 0; + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:17:9 | LL | for (a) in 0..1 {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - for (a) in 0..1 {} +LL + for a in 0..1 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:18:12 | LL | if let (a) = 0 {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let (a) = 0 {} +LL + if let a = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:19:15 | LL | while let (a) = 0 {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let (a) = 0 {} +LL + while let a = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:20:12 | LL | fn foo((a): u8) {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - fn foo((a): u8) {} +LL + fn foo(a: u8) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:21:14 | LL | let _ = |(a): u8| 0; - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - let _ = |(a): u8| 0; +LL + let _ = |a: u8| 0; + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:49:12 | LL | if let (0 | 1) = 0 {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let (0 | 1) = 0 {} +LL + if let 0 | 1 = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:50:13 | LL | if let ((0 | 1),) = (0,) {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let ((0 | 1),) = (0,) {} +LL + if let (0 | 1,) = (0,) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:51:13 | LL | if let [(0 | 1)] = [0] {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let [(0 | 1)] = [0] {} +LL + if let [0 | 1] = [0] {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:52:16 | LL | if let 0 | (1 | 2) = 0 {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let 0 | (1 | 2) = 0 {} +LL + if let 0 | 1 | 2 = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:54:15 | LL | if let TS((0 | 1)) = TS(0) {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let TS((0 | 1)) = TS(0) {} +LL + if let TS(0 | 1) = TS(0) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:56:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let NS { f: (0 | 1) } = (NS { f: 0 }) {} +LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:66:9 | LL | (_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:67:9 | LL | (y) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:68:9 | LL | (ref r) => {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:69:9 | LL | (e @ 1...2) => {} - | ^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1...2) => {} +LL + e @ 1...2 => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:75:9 | LL | (e @ &(1...2)) => {} - | ^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1...2)) => {} +LL + e @ &(1...2) => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:76:10 | LL | &(_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:87:9 | LL | (_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:88:9 | LL | (y) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:89:9 | LL | (ref r) => {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (e @ 1..=2) => {} - | ^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1..=2) => {} +LL + e @ 1..=2 => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:96:9 | LL | (e @ &(1..=2)) => {} - | ^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1..=2)) => {} +LL + e @ &(1..=2) => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:97:10 | LL | &(_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | error: aborting due to 24 previous errors diff --git a/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr b/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr index 3f6260dc6e19e..a715093df4c32 100644 --- a/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr +++ b/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr @@ -2,49 +2,83 @@ error: unnecessary parentheses around `let` scrutinee expression --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29 | LL | while let Some(_) = ({yield}) {} - | ^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24 | LL | #![deny(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - while let Some(_) = ({yield}) {} +LL + while let Some(_) = {yield} {} + | error: unnecessary parentheses around `let` scrutinee expression --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29 | LL | while let Some(_) = ((yield)) {} - | ^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = ((yield)) {} +LL + while let Some(_) = (yield) {} + | error: unnecessary braces around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10 | LL | {{yield}}; - | ^^^^^^^ help: remove these braces + | ^ ^ | note: the lint level is defined here --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9 | LL | #![deny(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - {{yield}}; +LL + {yield}; + | error: unnecessary parentheses around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10 | LL | {( yield )}; - | ^^^^^^^^^ help: remove these parentheses + | ^^ ^^ + | +help: remove these parentheses + | +LL - {( yield )}; +LL + {yield}; + | error: unnecessary parentheses around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30 | LL | while let Some(_) = {(yield)} {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = {(yield)} {} +LL + while let Some(_) = {yield} {} + | error: unnecessary braces around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30 | LL | while let Some(_) = {{yield}} {} - | ^^^^^^^ help: remove these braces + | ^ ^ + | +help: remove these braces + | +LL - while let Some(_) = {{yield}} {} +LL + while let Some(_) = {yield} {} + | error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/unused_braces.stderr b/src/test/ui/lint/unused_braces.stderr index 8fa5dfde61db0..7d6fef00ac1a4 100644 --- a/src/test/ui/lint/unused_braces.stderr +++ b/src/test/ui/lint/unused_braces.stderr @@ -2,43 +2,71 @@ warning: unnecessary parentheses around assigned value --> $DIR/unused_braces.rs:10:13 | LL | let _ = (7); - | ^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/unused_braces.rs:4:24 | LL | #![warn(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _ = (7); +LL + let _ = 7; + | warning: unnecessary braces around `if` condition --> $DIR/unused_braces.rs:26:8 | LL | if { true } { - | ^^^^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/unused_braces.rs:4:9 | LL | #![warn(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - if { true } { +LL + if true { + | warning: unnecessary braces around `while` condition --> $DIR/unused_braces.rs:30:11 | LL | while { false } { - | ^^^^^^^^^ help: remove these braces + | ^^ ^^ + | +help: remove these braces + | +LL - while { false } { +LL + while false { + | warning: unnecessary braces around const expression --> $DIR/unused_braces.rs:34:17 | LL | let _: [u8; { 3 }]; - | ^^^^^ help: remove these braces + | ^^ ^^ + | +help: remove these braces + | +LL - let _: [u8; { 3 }]; +LL + let _: [u8; 3]; + | warning: unnecessary braces around function argument --> $DIR/unused_braces.rs:37:13 | LL | consume({ 7 }); - | ^^^^^ help: remove these braces + | ^^ ^^ + | +help: remove these braces + | +LL - consume({ 7 }); +LL + consume(7); + | warning: 5 warnings emitted diff --git a/src/test/ui/lint/unused_braces_borrow.stderr b/src/test/ui/lint/unused_braces_borrow.stderr index f018c46fcd3c6..5a5326cab3b1d 100644 --- a/src/test/ui/lint/unused_braces_borrow.stderr +++ b/src/test/ui/lint/unused_braces_borrow.stderr @@ -2,13 +2,18 @@ warning: unnecessary braces around function argument --> $DIR/unused_braces_borrow.rs:24:13 | LL | consume({ a.b }); - | ^^^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/unused_braces_borrow.rs:4:9 | LL | #![warn(unused_braces)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ a.b }); +LL + consume(a.b); + | warning: 1 warning emitted diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr index 09f0fc90032dc..498c25d2e1c44 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr @@ -1,14 +1,19 @@ -{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); +{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); --> $DIR/unused_parens_json_suggestion.rs:16:14 | LL | let _a = (1 / (2 + 3)); - | ^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/unused_parens_json_suggestion.rs:10:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _a = (1 / (2 + 3)); +LL + let _a = 1 / (2 + 3); + | "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr index 5fb67fd7c95a3..08291b10fcc20 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -1,70 +1,123 @@ -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) { +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) { --> $DIR/unused_parens_remove_json_suggestion.rs:17:8 | LL | if (_b) { - | ^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/unused_parens_remove_json_suggestion.rs:10:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - if (_b) { +LL + if _b { + | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"is_primary":true,"text":[{"text":" if(c) { +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) { --> $DIR/unused_parens_remove_json_suggestion.rs:28:7 | LL | if(c) { - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if(c) { +LL + if c { + | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"is_primary":true,"text":[{"text":" if (c){ +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){ --> $DIR/unused_parens_remove_json_suggestion.rs:32:8 | LL | if (c){ - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if (c){ +LL + if c { + | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 | LL | while (false && true){ - | ^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while (false && true){ +LL + while false && true { + | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"is_primary":true,"text":[{"text":" if (c) { +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) { --> $DIR/unused_parens_remove_json_suggestion.rs:37:12 | LL | if (c) { - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if (c) { +LL + if c { + | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) { +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) { --> $DIR/unused_parens_remove_json_suggestion.rs:43:10 | LL | while(true && false) { - | ^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while(true && false) { +LL + while true && false { + | "} -{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 | LL | for _ in (0 .. 3){ - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3){ +LL + for _ in 0 .. 3 { + | "} -{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 | LL | for _ in (0 .. 3) { - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3) { +LL + for _ in 0 .. 3 { + | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) { +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) { --> $DIR/unused_parens_remove_json_suggestion.rs:50:15 | LL | while (true && false) { - | ^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while (true && false) { +LL + while true && false { + | "} {"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index dcf235a9e2774..8adf02b150b87 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -2,13 +2,18 @@ warning: unnecessary parentheses around `return` value --> $DIR/path-lookahead.rs:10:12 | LL | return (::to_string(&arg)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/path-lookahead.rs:5:9 | LL | #![warn(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - return (::to_string(&arg)); +LL + return ::to_string(&arg); + | warning: 1 warning emitted diff --git a/src/test/ui/try-block/try-block-unused-delims.stderr b/src/test/ui/try-block/try-block-unused-delims.stderr index c5a2405462932..d8dd31645e061 100644 --- a/src/test/ui/try-block/try-block-unused-delims.stderr +++ b/src/test/ui/try-block/try-block-unused-delims.stderr @@ -2,43 +2,71 @@ warning: unnecessary parentheses around function argument --> $DIR/try-block-unused-delims.rs:11:13 | LL | consume((try {})); - | ^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/try-block-unused-delims.rs:6:9 | LL | #![warn(unused_parens, unused_braces)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - consume((try {})); +LL + consume(try {}); + | warning: unnecessary braces around function argument --> $DIR/try-block-unused-delims.rs:14:13 | LL | consume({ try {} }); - | ^^^^^^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/try-block-unused-delims.rs:6:24 | LL | #![warn(unused_parens, unused_braces)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ try {} }); +LL + consume(try {}); + | warning: unnecessary parentheses around `match` scrutinee expression --> $DIR/try-block-unused-delims.rs:17:11 | LL | match (try {}) { - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | warning: unnecessary parentheses around `let` scrutinee expression --> $DIR/try-block-unused-delims.rs:22:22 | LL | if let Err(()) = (try {}) {} - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let Err(()) = (try {}) {} +LL + if let Err(()) = try {} {} + | warning: unnecessary parentheses around `match` scrutinee expression --> $DIR/try-block-unused-delims.rs:25:11 | LL | match (try {}) { - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | warning: 5 warnings emitted From 8295e4a6cfb12ce74c480172c2854f76d1428b8b Mon Sep 17 00:00:00 2001 From: Ellen Date: Thu, 9 Sep 2021 15:43:59 +0100 Subject: [PATCH 26/31] add test for builtin types N + N unifying with fn call --- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- .../src/traits/const_evaluatable.rs | 13 ++++++++++--- .../generic_const_exprs/unify-op-with-fn-call.rs | 13 ++++++++++++- .../unify-op-with-fn-call.stderr | 10 ++++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 60d7f0f85bb57..97c0bca5d911c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1305,7 +1305,7 @@ impl EncodeContext<'a, 'tcx> { if encode_const { record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id)); - // FIXME this feels wrong to have in `encode_mir` + // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir` let abstract_const = self.tcx.thir_abstract_const(def_id); if let Ok(Some(abstract_const)) = abstract_const { record!(self.tables.thir_abstract_consts[def_id.to_def_id()] <- abstract_const); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 4f178f777afb2..24fa5007f1ecd 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -267,10 +267,16 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) { self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx); - if self.is_poly { - return; + if self.is_poly == false { + visit::walk_expr(self, expr) + } + } + + fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) { + self.is_poly |= pat.ty.definitely_has_param_types_or_consts(self.tcx); + if self.is_poly == false { + visit::walk_pat(self, pat); } - visit::walk_expr(self, expr); } fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) { @@ -280,6 +286,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx }; visit::walk_expr(&mut is_poly_vis, &body[body_id]); + debug!("AbstractConstBuilder: is_poly={}", is_poly_vis.is_poly); if is_poly_vis.is_poly == false { return Ok(None); } diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs index bb054bec6b6c2..c0404d35b0887 100644 --- a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs +++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -1,7 +1,7 @@ -// check-pass #![feature(generic_const_exprs, adt_const_params, const_trait_impl)] #![allow(incomplete_features)] +// test `N + N` unifies with explicit function calls for non-builtin-types #[derive(PartialEq, Eq)] struct Foo(u8); @@ -21,4 +21,15 @@ fn foo(a: Evaluatable<{ N + N }>) { fn bar() {} +// test that `N + N` unifies with explicit function calls for builin-types +struct Evaluatable2; + +fn foo2(a: Evaluatable2<{ N + N }>) { + bar2::<{ std::ops::Add::add(N, N) }>(); + //~^ error: unconstrained generic constant + // FIXME(generic_const_exprs) make this not an error +} + +fn bar2() {} + fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr new file mode 100644 index 0000000000000..d18c7916f5f6f --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/unify-op-with-fn-call.rs:28:12 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` + +error: aborting due to previous error + From 64354a9ea27b62edb8db9e6eddfc413ec58ca183 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 Sep 2021 21:13:52 +0200 Subject: [PATCH 27/31] Remove usage of cfg_if in std/src/os/mod.rs --- library/std/src/os/mod.rs | 102 ++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 1a4d77e00bf07..3f02a650e3541 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -18,41 +18,81 @@ pub mod raw; pub mod fortanix_sgx; // Unix, linux, wasi and windows are handled a bit differently. -cfg_if::cfg_if! { - if #[cfg(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) - ))] - { - #[unstable(issue = "none", feature = "std_internals")] - pub mod unix {} - #[unstable(issue = "none", feature = "std_internals")] - pub mod linux {} - #[unstable(issue = "none", feature = "std_internals")] - pub mod wasi {} - #[unstable(issue = "none", feature = "std_internals")] - pub mod windows {} - } else { - #[cfg(target_os = "hermit")] - #[path = "hermit/mod.rs"] - pub mod unix; +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod unix {} +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod linux {} +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod wasi {} +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod windows {} - #[cfg(any(unix, doc))] - pub mod unix; +// unix +#[cfg(not(any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") +)))] +#[cfg(all(not(doc), target_os = "hermit"))] +#[path = "hermit/mod.rs"] +pub mod unix; +#[cfg(not(any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") +)))] +#[cfg(any(unix, doc))] +pub mod unix; - #[cfg(any(target_os = "linux", target_os = "l4re", doc))] - pub mod linux; +// linux +#[cfg(not(any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") +)))] +#[cfg(any(target_os = "linux", target_os = "l4re", doc))] +pub mod linux; - #[cfg(any(target_os = "wasi", doc))] - pub mod wasi; +// wasi +#[cfg(not(any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") +)))] +#[cfg(any(target_os = "wasi", doc))] +pub mod wasi; - #[cfg(any(windows, doc))] - pub mod windows; - } -} +// windows +#[cfg(not(any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") +)))] +#[cfg(any(windows, doc))] +pub mod windows; // Others. #[cfg(target_os = "android")] From 88d5aa62dc6e30e6b48e2c280e914752ea26937e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 7 Sep 2021 15:44:08 +0200 Subject: [PATCH 28/31] Move fortanix module position in std::os reexports for alpha sort --- library/std/src/os/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 3f02a650e3541..eb9967a8a7ab3 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -14,9 +14,6 @@ pub mod raw; // documented don't compile (missing things in `libc` which is empty), // so just omit them with an empty module and add the "unstable" attribute. -#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] -pub mod fortanix_sgx; - // Unix, linux, wasi and windows are handled a bit differently. #[cfg(all( doc, @@ -103,6 +100,8 @@ pub mod dragonfly; pub mod emscripten; #[cfg(target_os = "espidf")] pub mod espidf; +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] +pub mod fortanix_sgx; #[cfg(target_os = "freebsd")] pub mod freebsd; #[cfg(target_os = "fuchsia")] From c9a56cdc58bbb51ece4510f4e54ef2fe26b7b771 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Sep 2021 20:20:10 +0200 Subject: [PATCH 29/31] Add help for E0463 --- compiler/rustc_metadata/src/locator.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index d3512b6cf579e..b6922e0d72a06 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1095,6 +1095,11 @@ impl CrateError { == Symbol::intern(&sess.opts.debugging_opts.profiler_runtime) { err.note(&"the compiler may have been built without the profiler runtime"); + } else if crate_name.as_str().starts_with("rustc_") { + err.help( + "maybe you need to install the missing components with: \ + `rustup component add rust-src rustc-dev llvm-tools-preview`", + ); } err.span_label(span, "can't find crate"); err From 294510e1bb7e03bd462f6a6db2fab5f56fae1c8c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 Sep 2021 23:37:15 +0300 Subject: [PATCH 30/31] rustc: Remove local variable IDs from `Export`s Local variables can never be exported. --- compiler/rustc_data_structures/src/lib.rs | 1 + .../src/stable_hasher.rs | 6 +++ compiler/rustc_hir/src/def.rs | 5 +++ compiler/rustc_metadata/src/rmeta/decoder.rs | 5 +-- .../src/rmeta/decoder/cstore_impl.rs | 40 ++++++++----------- compiler/rustc_metadata/src/rmeta/encoder.rs | 9 +---- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/hir/exports.rs | 13 ++---- compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- .../rustc_resolve/src/build_reduced_graph.rs | 4 +- compiler/rustc_resolve/src/imports.rs | 5 +-- compiler/rustc_resolve/src/lib.rs | 3 +- compiler/rustc_serialize/src/serialize.rs | 12 ++++++ .../rustc_typeck/src/check/method/suggest.rs | 2 +- src/librustdoc/clean/inline.rs | 11 +++-- src/librustdoc/clean/types.rs | 9 +++-- src/librustdoc/visit_lib.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +- 19 files changed, 71 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index d128a688e751f..dd6a17b92aef3 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -21,6 +21,7 @@ #![feature(iter_map_while)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] +#![feature(never_type)] #![feature(type_alias_impl_trait)] #![feature(new_uninit)] #![feature(nll)] diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 18b352cf3b0b9..354f9dd93cc4d 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -209,6 +209,12 @@ impl_stable_hash_via_hash!(i128); impl_stable_hash_via_hash!(char); impl_stable_hash_via_hash!(()); +impl HashStable for ! { + fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { + unreachable!() + } +} + impl HashStable for ::std::num::NonZeroU32 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.get().hash_stable(ctx, hasher) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 853415c4173b5..cb668eb35e093 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -598,6 +598,11 @@ impl Res { } } + #[track_caller] + pub fn expect_non_local(self) -> Res { + self.map_id(|_| panic!("unexpected `Res::Local`")) + } + pub fn macro_kind(self) -> Option { match self { Res::Def(DefKind::Macro(kind), _) => Some(kind), diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index dd44e0cb1fa90..0c284269c2fe3 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1019,10 +1019,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over each child of the given item. - fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) - where - F: FnMut(Export), - { + fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) { if let Some(data) = &self.root.proc_macro_data { /* If we are loading as a proc macro, we want to return the view of this crate * as a proc macro crate. diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 41839c58021ab..80341b16e1412 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -5,7 +5,6 @@ use crate::rmeta::encoder; use rustc_ast as ast; use rustc_data_structures::stable_map::FxHashMap; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; @@ -326,28 +325,27 @@ pub fn provide(providers: &mut Providers) { // (restrict scope of mutable-borrow of `visible_parent_map`) { let visible_parent_map = &mut visible_parent_map; - let mut add_child = - |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { - if child.vis != ty::Visibility::Public { - return; - } + let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { + if child.vis != ty::Visibility::Public { + return; + } - if let Some(child) = child.res.opt_def_id() { - match visible_parent_map.entry(child) { - Entry::Occupied(mut entry) => { - // If `child` is defined in crate `cnum`, ensure - // that it is mapped to a parent in `cnum`. - if child.is_local() && entry.get().is_local() { - entry.insert(parent); - } - } - Entry::Vacant(entry) => { + if let Some(child) = child.res.opt_def_id() { + match visible_parent_map.entry(child) { + Entry::Occupied(mut entry) => { + // If `child` is defined in crate `cnum`, ensure + // that it is mapped to a parent in `cnum`. + if child.is_local() && entry.get().is_local() { entry.insert(parent); - bfs_queue.push_back(child); } } + Entry::Vacant(entry) => { + entry.insert(parent); + bfs_queue.push_back(child); + } } - }; + } + }; while let Some(def) = bfs_queue.pop_front() { for child in tcx.item_children(def).iter() { @@ -393,11 +391,7 @@ impl CStore { self.get_crate_data(def.krate).get_visibility(def.index) } - pub fn item_children_untracked( - &self, - def_id: DefId, - sess: &Session, - ) -> Vec> { + pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec { let mut result = vec![]; self.get_crate_data(def_id.krate).each_child_of_item( def_id.index, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d8b9a4799760e..52c6193940dbc 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1065,14 +1065,7 @@ impl EncodeContext<'a, 'tcx> { // items - we encode information about proc-macros later on. let reexports = if !self.is_proc_macro { match tcx.module_exports(local_def_id) { - Some(exports) => { - let hir = self.tcx.hir(); - self.lazy( - exports - .iter() - .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))), - ) - } + Some(exports) => self.lazy(exports), _ => Lazy::empty(), } } else { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a487753f4628a..fe0bf5b64ba09 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -359,7 +359,7 @@ struct RenderedConst(String); #[derive(MetadataEncodable, MetadataDecodable)] struct ModData { - reexports: Lazy<[Export]>, + reexports: Lazy<[Export]>, expansion: ExpnId, } diff --git a/compiler/rustc_middle/src/hir/exports.rs b/compiler/rustc_middle/src/hir/exports.rs index be9e38aca65d1..f37b976fba68d 100644 --- a/compiler/rustc_middle/src/hir/exports.rs +++ b/compiler/rustc_middle/src/hir/exports.rs @@ -11,23 +11,18 @@ use std::fmt::Debug; /// This is the replacement export map. It maps a module to all of the exports /// within. -pub type ExportMap = FxHashMap>>; +pub type ExportMap = FxHashMap>; #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub struct Export { +pub struct Export { /// The name of the target. pub ident: Ident, /// The resolution of the target. - pub res: Res, + /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. + pub res: Res, /// The span of the target. pub span: Span, /// The visibility of the export. /// We include non-`pub` exports for hygienic macros that get used from extern crates. pub vis: ty::Visibility, } - -impl Export { - pub fn map_id(self, map: impl FnMut(Id) -> R) -> Export { - Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis } - } -} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c93996162e3e3..3b07be460db9b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1181,7 +1181,7 @@ rustc_queries! { desc { "traits in scope at a block" } } - query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { + query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) } } @@ -1393,7 +1393,7 @@ rustc_queries! { eval_always desc { "fetching what a crate is named" } } - query item_children(def_id: DefId) -> &'tcx [Export] { + query item_children(def_id: DefId) -> &'tcx [Export] { desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) } } query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index fddfd6e435c05..cd1e38445ae8c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -127,7 +127,7 @@ pub struct ResolverOutputs { pub extern_crate_map: FxHashMap, pub maybe_unused_trait_imports: FxHashSet, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, - pub export_map: ExportMap, + pub export_map: ExportMap, pub glob_map: FxHashMap>, /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2ee483d850e7b..55f2b04c4f1c1 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -228,7 +228,6 @@ impl<'a> Resolver<'a> { crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { let def_id = module.def_id().expect("unpopulated module without a def-id"); for child in self.cstore().item_children_untracked(def_id, self.session) { - let child = child.map_id(|_| panic!("unexpected id")); let parent_scope = ParentScope::module(module, self); BuildReducedGraphVisitor { r: self, parent_scope } .build_reduced_graph_for_external_crate_res(child); @@ -946,9 +945,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { + fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { let parent = self.parent_scope.module; let Export { ident, res, vis, span } = child; + let res = res.expect_non_local(); let expansion = self.parent_scope.expansion; // Record primary definitions. match res { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index dfb6d89a0d126..d4782edbc1346 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -11,7 +11,6 @@ use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBindin use rustc_ast::unwrap_or; use rustc_ast::NodeId; -use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_errors::{pluralize, struct_span_err, Applicability}; @@ -1387,13 +1386,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); - module.for_each_child(self.r, |this, ident, _, binding| { + module.for_each_child(self.r, |_, ident, _, binding| { // Filter away ambiguous imports and anything that has def-site hygiene. // FIXME: Implement actual cross-crate hygiene. let is_good_import = binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion(); if is_good_import || binding.is_macro_def() { - let res = binding.res().map_id(|id| this.local_def_id(id)); + let res = binding.res().expect_non_local(); if res != def::Res::Err { reexports.push(Export { ident, res, span: binding.span, vis: binding.vis }); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6d2961db9e3da..912f0bf13fe1a 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -14,6 +14,7 @@ #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] #![feature(iter_zip)] +#![feature(never_type)] #![feature(nll)] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] @@ -911,7 +912,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap, - export_map: ExportMap, + export_map: ExportMap, trait_map: Option>>, /// A map from nodes to anonymous modules. diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index ecc8dae04800a..e32e4493726db 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -366,6 +366,18 @@ direct_serialize_impls! { char emit_char read_char } +impl Encodable for ! { + fn encode(&self, _s: &mut S) -> Result<(), S::Error> { + unreachable!() + } +} + +impl Decodable for ! { + fn decode(_d: &mut D) -> Result { + unreachable!() + } +} + impl Encodable for ::std::num::NonZeroU32 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u32(self.get()) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index a746ad7ad4bc7..9744f4f6483c7 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1655,7 +1655,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { tcx: TyCtxt<'_>, traits: &mut Vec, external_mods: &mut FxHashSet, - res: Res, + res: Res, ) { match res { Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0c81a55843013..b8633f0dcfd29 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -482,12 +482,13 @@ fn build_module( // visit each node at most once. for &item in cx.tcx.item_children(did).iter() { if item.vis == ty::Visibility::Public { - if let Some(def_id) = item.res.mod_def_id() { + let res = item.res.expect_non_local(); + if let Some(def_id) = res.mod_def_id() { if did == def_id || !visited.insert(def_id) { continue; } } - if let Res::PrimTy(p) = item.res { + if let Res::PrimTy(p) = res { // Primitive types can't be inlined so generate an import instead. let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { @@ -500,7 +501,7 @@ fn build_module( clean::ImportSource { path: clean::Path { global: false, - res: item.res, + res, segments: vec![clean::PathSegment { name: prim_ty.as_sym(), args: clean::GenericArgs::AngleBracketed { @@ -515,9 +516,7 @@ fn build_module( ))), cfg: None, }); - } else if let Some(i) = - try_inline(cx, did, None, item.res, item.ident.name, None, visited) - { + } else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) { items.extend(i) } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5eff56a2200e1..8f31a42e1a2a3 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -212,7 +212,7 @@ impl ExternalCrate { crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> { let root = self.def_id(); - let as_keyword = |res: Res| { + let as_keyword = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = tcx.get_attrs(def_id); let mut keyword = None; @@ -243,7 +243,8 @@ impl ExternalCrate { hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { - as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim)) + as_keyword(path.res.expect_non_local()) + .map(|(_, prim)| (id.def_id.to_def_id(), prim)) } _ => None, } @@ -274,7 +275,7 @@ impl ExternalCrate { // Also note that this does not attempt to deal with modules tagged // duplicately for the same primitive. This is handled later on when // rendering by delegating everything to a hash map. - let as_primitive = |res: Res| { + let as_primitive = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = tcx.get_attrs(def_id); let mut prim = None; @@ -309,7 +310,7 @@ impl ExternalCrate { hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { - as_primitive(path.res).map(|(_, prim)| { + as_primitive(path.res.expect_non_local()).map(|(_, prim)| { // Pretend the primitive is local. (id.def_id.to_def_id(), prim) }) diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 3e06b4173144c..3e98ba08fb9ca 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { } } - fn visit_item(&mut self, res: Res) { + fn visit_item(&mut self, res: Res) { let def_id = res.def_id(); let vis = self.tcx.visibility(def_id); let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None }; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index da259511fe0b9..3a94f47298390 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -520,7 +520,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res { } }; } - fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> { + fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> { tcx.item_children(def_id) .iter() .find(|item| item.ident.name.as_str() == name) @@ -557,7 +557,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res { None } }); - try_res!(last).res + try_res!(last).res.expect_non_local() } /// Convenience function to get the `DefId` of a trait by path. From c1e96085d36af614ac9bb1c36dde9a5706eef6ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 11 Sep 2021 10:18:56 +0200 Subject: [PATCH 31/31] don't clone types that are Copy (clippy::clone_on_copy) --- compiler/rustc_borrowck/src/region_infer/mod.rs | 8 ++++---- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 6 +++--- compiler/rustc_macros/src/session_diagnostic.rs | 8 ++++---- compiler/rustc_mir_build/src/build/matches/mod.rs | 2 +- compiler/rustc_mir_transform/src/lower_slice_len.rs | 8 +++----- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 4 +--- .../src/traits/error_reporting/mod.rs | 8 ++++---- compiler/rustc_trait_selection/src/traits/project.rs | 6 +++--- compiler/rustc_trait_selection/src/traits/select/mod.rs | 2 +- compiler/rustc_typeck/src/check/method/probe.rs | 2 +- library/test/src/formatters/junit.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/doctest.rs | 2 +- src/librustdoc/passes/collect_intra_doc_links.rs | 2 +- 15 files changed, 30 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 48e45a9b1ce72..b28f8ce1d8b3a 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1739,7 +1739,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { category: constraint.category, from_closure: false, span, - variance_info: constraint.variance_info.clone(), + variance_info: constraint.variance_info, }; } Locations::Single(loc) => loc, @@ -1752,13 +1752,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { category, from_closure: true, span: span, - variance_info: constraint.variance_info.clone(), + variance_info: constraint.variance_info, }) .unwrap_or(BlameConstraint { category: constraint.category, from_closure: false, span: body.source_info(loc).span, - variance_info: constraint.variance_info.clone(), + variance_info: constraint.variance_info, }) } @@ -2001,7 +2001,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { category: constraint.category, from_closure: false, span: constraint.locations.span(body), - variance_info: constraint.variance_info.clone(), + variance_info: constraint.variance_info, } } }) diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index c211d8e94a68b..e88c6608aca33 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -519,7 +519,7 @@ where let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.ambient_variance.xform(variance); - self.ambient_variance_info = self.ambient_variance_info.clone().xform(info); + self.ambient_variance_info = self.ambient_variance_info.xform(info); debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance); @@ -597,12 +597,12 @@ where if self.ambient_covariance() { // Covariance: a <= b. Hence, `b: a`. - self.push_outlives(v_b, v_a, self.ambient_variance_info.clone()); + self.push_outlives(v_b, v_a, self.ambient_variance_info); } if self.ambient_contravariance() { // Contravariant: b <= a. Hence, `a: b`. - self.push_outlives(v_a, v_b, self.ambient_variance_info.clone()); + self.push_outlives(v_a, v_b, self.ambient_variance_info); } Ok(a) diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index 8a0fce209b7fb..80dcf99da6224 100644 --- a/compiler/rustc_macros/src/session_diagnostic.rs +++ b/compiler/rustc_macros/src/session_diagnostic.rs @@ -448,7 +448,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { span_idx = Some(syn::Index::from(idx)); } else { throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "type of field annotated with `#[suggestion(...)]` contains more than one Span" ); } @@ -460,7 +460,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { applicability_idx = Some(syn::Index::from(idx)); } else { throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "type of field annotated with `#[suggestion(...)]` contains more than one Applicability" ); } @@ -479,7 +479,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { return Ok((span, applicability)); } throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "wrong types for suggestion", |diag| { diag.help("#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)") @@ -487,7 +487,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { ); } _ => throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "wrong field type for suggestion", |diag| { diag.help("#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)") diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 0ff3fc60995bf..4df073c40e22c 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2060,7 +2060,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info.span, ascription.source, ascription.user_ty, ); - let user_ty = ascription.user_ty.clone().user_ty( + let user_ty = ascription.user_ty.user_ty( &mut self.canonical_user_type_annotations, ascription.source.ty(&self.local_decls, self.tcx).ty, source_info.span, diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 30de374a2d822..a2cce9f1eda07 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -75,13 +75,11 @@ fn lower_slice_len_call<'tcx>( let deref_arg = tcx.mk_place_deref(arg); let r_value = Rvalue::Len(deref_arg); let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value))); - let add_statement = Statement { - kind: len_statement_kind, - source_info: terminator.source_info.clone(), - }; + let add_statement = + Statement { kind: len_statement_kind, source_info: terminator.source_info }; // modify terminator into simple Goto - let new_terminator_kind = TerminatorKind::Goto { target: bb.clone() }; + let new_terminator_kind = TerminatorKind::Goto { target: *bb }; let patch = SliceLenPatchInformation { add_statement, new_terminator_kind }; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6d2961db9e3da..392d618995af4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1487,7 +1487,7 @@ impl<'a> Resolver<'a> { .iter() .map(|(ident, entry)| (ident.name, entry.introduced_by_item)) .collect(), - main_def: self.main_def.clone(), + main_def: self.main_def, trait_impls: self.trait_impls.clone(), proc_macros, confused_type_with_std_module: self.confused_type_with_std_module.clone(), diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index c22093c5a4288..ef60608a27c8b 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1357,9 +1357,7 @@ fn for_all_expns_in( mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>, ) -> Result<(), E> { let all_data: Vec<_> = HygieneData::with(|data| { - expns - .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone())) - .collect() + expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect() }); for (expn, data, hash) in all_data.into_iter() { f(expn, &data, hash)?; 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 9ce6c58a0f1df..52367661a4c00 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -249,10 +249,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let ObligationCauseCode::WellFormed(Some(wf_loc)) = root_obligation.cause.code.peel_derives() { - if let Some(cause) = self.tcx.diagnostic_hir_wf_check(( - tcx.erase_regions(obligation.predicate), - wf_loc.clone(), - )) { + if let Some(cause) = self + .tcx + .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc)) + { obligation.cause = cause; span = obligation.cause.span; } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 7038f16a2c9c4..92db0ca2a7c40 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -595,7 +595,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); let p = ty::PlaceholderRegion { universe, name: br.kind }; - self.mapped_regions.insert(p.clone(), br); + self.mapped_regions.insert(p, br); self.infcx.tcx.mk_region(ty::RePlaceholder(p)) } _ => r, @@ -613,7 +613,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); let p = ty::PlaceholderType { universe, name: bound_ty.var }; - self.mapped_types.insert(p.clone(), bound_ty); + self.mapped_types.insert(p, bound_ty); self.infcx.tcx.mk_ty(ty::Placeholder(p)) } _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), @@ -637,7 +637,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { universe, name: ty::BoundConst { var: bound_const, ty }, }; - self.mapped_consts.insert(p.clone(), bound_const); + self.mapped_consts.insert(p, bound_const); self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty }) } _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 22013fb79cf79..9824b644c3ebe 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2445,7 +2445,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { "get_provisional = {:#?}", self.map.borrow().get(&fresh_trait_ref), ); - Some(self.map.borrow().get(&fresh_trait_ref)?.clone()) + Some(*self.map.borrow().get(&fresh_trait_ref)?) } /// Insert a provisional result into the cache. The result came diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 1c7d68a3d57d4..cbfdce96bc57b 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -186,7 +186,7 @@ pub enum AutorefOrPtrAdjustment<'tcx> { impl<'tcx> AutorefOrPtrAdjustment<'tcx> { fn get_unsize(&self) -> Option> { match self { - AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => unsize.clone(), + AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize, AutorefOrPtrAdjustment::ToConstPtr => None, } } diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index c4b0e1e5c2339..aa24480751419 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -53,7 +53,7 @@ impl OutputFormatter for JunitFormatter { // Because the testsuit node holds some of the information as attributes, we can't write it // until all of the tests has ran. Instead of writting every result as they come in, we add // them to a Vec and write them all at once when run is complete. - let duration = exec_time.map(|t| t.0.clone()).unwrap_or_default(); + let duration = exec_time.map(|t| t.0).unwrap_or_default(); self.results.push((desc.clone(), result.clone(), duration)); Ok(()) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5f09e6ced96d4..4f4952d0afb9d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -463,7 +463,7 @@ impl Item { .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| { match did { Some(did) => { - if let Ok((mut href, ..)) = href(did.clone(), cx) { + if let Ok((mut href, ..)) = href(*did, cx) { if let Some(ref fragment) = *fragment { href.push('#'); href.push_str(fragment); diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index e6097f5cad7f3..9222a0338ae6f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -73,7 +73,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { search_paths: options.libs.clone(), crate_types, lint_opts: if !options.display_warnings { lint_opts } else { vec![] }, - lint_cap: Some(options.lint_cap.clone().unwrap_or_else(|| lint::Forbid)), + lint_cap: Some(options.lint_cap.unwrap_or_else(|| lint::Forbid)), cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: options.render_options.unstable_features, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 178c8c15a1588..61f6b4e01c18c 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1323,7 +1323,7 @@ impl LinkCollector<'_, '_> { if let Some(ref cached) = self.visited_links.get(&key) { match cached { Some(cached) => { - self.kind_side_channel.set(cached.side_channel.clone()); + self.kind_side_channel.set(cached.side_channel); return Some(cached.res.clone()); } None if cache_resolution_failure => return None,