From f427698c03a74b961dbc5f28bc7a9801a77d0d44 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 15 Mar 2022 17:20:21 -0700 Subject: [PATCH 01/24] Parse inner attributes on inline const block --- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/expr.rs | 17 ++++++++++++++--- compiler/rustc_parse/src/parser/mod.rs | 4 ++-- src/test/pretty/stmt_expr_attributes.rs | 9 +++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index b2c62383fb69a..dc610da5dd089 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -960,7 +960,7 @@ impl<'a> State<'a> { self.word_space("="); match term { Term::Ty(ty) => self.print_type(ty), - Term::Const(c) => self.print_expr_anon_const(c), + Term::Const(c) => self.print_expr_anon_const(c, &[]), } } ast::AssocConstraintKind::Bound { bounds } => self.print_type_bounds(":", &*bounds), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 6435f1b6141e3..9de4cbbee13f0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -88,10 +88,21 @@ impl<'a> State<'a> { self.end(); } - pub(super) fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) { + pub(super) fn print_expr_anon_const( + &mut self, + expr: &ast::AnonConst, + attrs: &[ast::Attribute], + ) { self.ibox(INDENT_UNIT); self.word("const"); - self.print_expr(&expr.value); + self.nbsp(); + if let ast::ExprKind::Block(block, None) = &expr.value.kind { + self.cbox(0); + self.ibox(0); + self.print_block_with_attrs(block, attrs); + } else { + self.print_expr(&expr.value); + } self.end(); } @@ -275,7 +286,7 @@ impl<'a> State<'a> { self.print_expr_vec(exprs); } ast::ExprKind::ConstBlock(ref anon_const) => { - self.print_expr_anon_const(anon_const); + self.print_expr_anon_const(anon_const, attrs); } ast::ExprKind::Repeat(ref element, ref count) => { self.print_expr_repeat(element, count); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4e229918b6362..ffa4f7fed2dc8 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1105,13 +1105,13 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::inline_const, span); } self.eat_keyword(kw::Const); - let blk = self.parse_block()?; + let (attrs, blk) = self.parse_inner_attrs_and_block()?; let anon_const = AnonConst { id: DUMMY_NODE_ID, value: self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()), }; let blk_span = anon_const.value.span; - Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::new())) + Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::from(attrs))) } /// Parses mutability (`mut` or nothing). diff --git a/src/test/pretty/stmt_expr_attributes.rs b/src/test/pretty/stmt_expr_attributes.rs index 7ab22f1960c2d..c01379065d1cd 100644 --- a/src/test/pretty/stmt_expr_attributes.rs +++ b/src/test/pretty/stmt_expr_attributes.rs @@ -1,6 +1,8 @@ // pp-exact #![feature(box_syntax)] +#![feature(inline_const)] +#![feature(inline_const_pat)] #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] @@ -16,6 +18,7 @@ fn _1() { #[rustc_dummy] unsafe { + #![rustc_dummy] // code } } @@ -206,6 +209,12 @@ fn _11() { let _ = (); () }; + let const { + #![rustc_dummy] + } = + #[rustc_dummy] const { + #![rustc_dummy] + }; let mut x = 0; let _ = #[rustc_dummy] x = 15; let _ = #[rustc_dummy] x += 15; From 3f7f5e8a2e3c9bb134d160241a6695bb379db647 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Tue, 22 Mar 2022 20:21:56 -0600 Subject: [PATCH 02/24] Optimize RcInnerPtr::inc_strong instruction count Inspired by this internals thread: https://internals.rust-lang.org/t/rc-optimization-on-64-bit-targets/16362 [The generated assembly is a bit smaller](https://rust.godbolt.org/z/TeTnf6144) and is a more efficient usage of the CPU's instruction cache. `unlikely` doesn't impact any of the small artificial tests I've done, but I've included it in case it might help more complex scenarios when this is inlined. --- library/alloc/src/rc.rs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index ea651c075d968..8e7946dfd971e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2512,14 +2512,21 @@ trait RcInnerPtr { fn inc_strong(&self) { let strong = self.strong(); + // We insert an `assume` here to hint LLVM at an otherwise + // missed optimization. + // SAFETY: The reference count will never be zero when this is + // called. + unsafe { core::intrinsics::assume(strong != 0); } + + let strong = strong.wrapping_add(1); + self.strong_ref().set(strong); + // We want to abort on overflow instead of dropping the value. - // The reference count will never be zero when this is called; - // nevertheless, we insert an abort here to hint LLVM at - // an otherwise missed optimization. - if strong == 0 || strong == usize::MAX { + // Checking after the store instead of before allows for + // slightly better code generation. + if core::intrinsics::unlikely(strong == 0) { abort(); } - self.strong_ref().set(strong + 1); } #[inline] @@ -2536,14 +2543,21 @@ trait RcInnerPtr { fn inc_weak(&self) { let weak = self.weak(); + // We insert an `assume` here to hint LLVM at an otherwise + // missed optimization. + // SAFETY: The reference count will never be zero when this is + // called. + unsafe { core::intrinsics::assume(weak != 0); } + + let weak = weak.wrapping_add(1); + self.weak_ref().set(weak); + // We want to abort on overflow instead of dropping the value. - // The reference count will never be zero when this is called; - // nevertheless, we insert an abort here to hint LLVM at - // an otherwise missed optimization. - if weak == 0 || weak == usize::MAX { + // Checking after the store instead of before allows for + // slightly better code generation. + if core::intrinsics::unlikely(weak == 0) { abort(); } - self.weak_ref().set(weak + 1); } #[inline] From f5dd42bce59bdd8ce5def70e2c87349434eb90a9 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Tue, 22 Mar 2022 20:42:03 -0600 Subject: [PATCH 03/24] Format unsafe {} blocks --- library/alloc/src/rc.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 8e7946dfd971e..858bbeb6bf3fa 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2516,7 +2516,9 @@ trait RcInnerPtr { // missed optimization. // SAFETY: The reference count will never be zero when this is // called. - unsafe { core::intrinsics::assume(strong != 0); } + unsafe { + core::intrinsics::assume(strong != 0); + } let strong = strong.wrapping_add(1); self.strong_ref().set(strong); @@ -2547,7 +2549,9 @@ trait RcInnerPtr { // missed optimization. // SAFETY: The reference count will never be zero when this is // called. - unsafe { core::intrinsics::assume(weak != 0); } + unsafe { + core::intrinsics::assume(weak != 0); + } let weak = weak.wrapping_add(1); self.weak_ref().set(weak); From 8d14c03568d0ec99c586e17ce19a93cc0684ab9e Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Wed, 23 Mar 2022 08:14:53 -0600 Subject: [PATCH 04/24] Explicitly mention overflow is what we're checking --- library/alloc/src/rc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 858bbeb6bf3fa..6ec86047fe4de 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2524,8 +2524,8 @@ trait RcInnerPtr { self.strong_ref().set(strong); // We want to abort on overflow instead of dropping the value. - // Checking after the store instead of before allows for - // slightly better code generation. + // Checking for overflow after the store instead of before + // allows for slightly better code generation. if core::intrinsics::unlikely(strong == 0) { abort(); } @@ -2557,8 +2557,8 @@ trait RcInnerPtr { self.weak_ref().set(weak); // We want to abort on overflow instead of dropping the value. - // Checking after the store instead of before allows for - // slightly better code generation. + // Checking for overflow after the store instead of before + // allows for slightly better code generation. if core::intrinsics::unlikely(weak == 0) { abort(); } From 9cfdb89999d3bdefc6c45047bbacb48c2416b5e8 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Feb 2022 19:21:33 +0100 Subject: [PATCH 05/24] Only add codegen backend to dep info if -Zbinary-dep-depinfo is used --- compiler/rustc_interface/src/passes.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 4f30e78f5e2aa..7640b9a7413d4 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -646,11 +646,11 @@ fn write_out_deps( }); files.extend(extra_tracked_files); - if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend { - files.push(backend.to_string()); - } - if sess.binary_dep_depinfo() { + if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend { + files.push(backend.to_string()); + } + boxed_resolver.borrow_mut().access(|resolver| { for cnum in resolver.cstore().crates_untracked() { let source = resolver.cstore().crate_source_untracked(cnum); From c681a884efa99cd14301553aacc42b702eac8b00 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Feb 2022 19:24:15 +0100 Subject: [PATCH 06/24] Don't include invalid paths in the depinfo for builtin backends --- compiler/rustc_interface/src/passes.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7640b9a7413d4..5a4b4df67723b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -648,7 +648,11 @@ fn write_out_deps( if sess.binary_dep_depinfo() { if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend { - files.push(backend.to_string()); + if backend.contains('.') { + // If the backend name contain a `.`, it is the path to an external dynamic + // library. If not, it is not a path. + files.push(backend.to_string()); + } } boxed_resolver.borrow_mut().access(|resolver| { From 147e5da9e34b86cd213900748a9da12bceb33de2 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 24 Mar 2022 16:23:51 +0100 Subject: [PATCH 07/24] Add test --- .../hotplug_codegen_backend/Makefile | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile b/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile index d8ceace7fff25..4cda243ffb5a3 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile @@ -2,10 +2,25 @@ include ../tools.mk # ignore-stage1 +# This test both exists as a check that -Zcodegen-backend is capable of loading external codegen +# backends and that this external codegen backend is only included in the dep info if +# -Zbinary-dep-depinfo is used. + all: /bin/echo || exit 0 # This test requires /bin/echo to exist $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \ -o $(TMPDIR)/the_backend.dylib + + $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \ + -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \ + --emit link,dep-info + grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib + # don't declare a dependency on the codegen backend if -Zbinary-dep-depinfo isn't used. + grep -v "the_backend.dylib" $(TMPDIR)/some_crate.d + $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \ - -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options - grep -x "This has been \"compiled\" successfully." $(TMPDIR)/some_crate + -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \ + --emit link,dep-info -Zbinary-dep-depinfo + grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib + # but declare a dependency on the codegen backend if -Zbinary-dep-depinfo it used. + grep "the_backend.dylib" $(TMPDIR)/some_crate.d From 8035796b9aabf1aa2a711694e40f00fe8a822f40 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 26 Mar 2022 18:23:32 -0400 Subject: [PATCH 08/24] Stablize `const_extern_fn` for "Rust" and "C" All other ABIs are left unstable for now. cc #64926 --- compiler/rustc_ast_passes/src/feature_gate.rs | 37 +++++++------ compiler/rustc_parse/src/parser/ty.rs | 3 ++ .../feature-gate-const_extern_fn.rs | 17 +++--- .../feature-gate-const_extern_fn.stderr | 54 ++++--------------- 4 files changed, 42 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 5b6147c72230d..5b2716b2dd088 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -58,9 +58,22 @@ struct PostExpansionVisitor<'a> { } impl<'a> PostExpansionVisitor<'a> { - fn check_abi(&self, abi: ast::StrLit) { + fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) { let ast::StrLit { symbol_unescaped, span, .. } = abi; + if let ast::Const::Yes(_) = constness { + match symbol_unescaped.as_str() { + // Stable + "Rust" | "C" => {} + abi => gate_feature_post!( + &self, + const_extern_fn, + span, + &format!("`{}` as a `const fn` ABI is unstable", abi) + ), + } + } + match symbol_unescaped.as_str() { // Stable "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64" @@ -261,9 +274,9 @@ impl<'a> PostExpansionVisitor<'a> { } } - fn check_extern(&self, ext: ast::Extern) { + fn check_extern(&self, ext: ast::Extern, constness: ast::Const) { if let ast::Extern::Explicit(abi) = ext { - self.check_abi(abi); + self.check_abi(abi, constness); } } @@ -445,7 +458,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match i.kind { ast::ItemKind::ForeignMod(ref foreign_module) => { if let Some(abi) = foreign_module.abi { - self.check_abi(abi); + self.check_abi(abi, ast::Const::No); } } @@ -568,7 +581,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, ty: &'a ast::Ty) { match ty.kind { ast::TyKind::BareFn(ref bare_fn_ty) => { - self.check_extern(bare_fn_ty.ext); + // Function pointers cannot be `const` + self.check_extern(bare_fn_ty.ext, ast::Const::No); } ast::TyKind::Never => { gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental"); @@ -668,18 +682,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { if let Some(header) = fn_kind.header() { // Stability of const fn methods are covered in `visit_assoc_item` below. - self.check_extern(header.ext); - - if let (ast::Const::Yes(_), ast::Extern::Implicit) - | (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext) - { - gate_feature_post!( - &self, - const_extern_fn, - span, - "`const extern fn` definitions are unstable" - ); - } + self.check_extern(header.ext, header.constness); } if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 436c5bd4fcac2..bb387064e27fe 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -523,6 +523,9 @@ impl<'a> Parser<'a> { let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let whole_span = lo.to(self.prev_token.span); if let ast::Const::Yes(span) = constness { + // If we ever start to allow `const fn()`, then update + // feature gating for `#![feature(const_extern_fn)]` to + // cover it. self.error_fn_ptr_bad_qualifier(whole_span, span, "const"); } if let ast::Async::Yes { span, .. } = asyncness { diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs index 5667d5535274d..f7bed91b03787 100644 --- a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs +++ b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs @@ -1,10 +1,13 @@ -// Check that `const extern fn` and `const unsafe extern fn` are feature-gated. +// Check that `const extern fn` and `const unsafe extern fn` are feature-gated +// for certain ABIs. -const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable -const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable -const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable -const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable -const unsafe extern "C" fn bar2() {} //~ ERROR `const extern fn` definitions are unstable -const unsafe extern "Rust" fn bar3() {} //~ ERROR `const extern fn` definitions are unstable +const extern fn foo1() {} +const extern "C" fn foo2() {} +const extern "Rust" fn foo3() {} +const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable +const unsafe extern fn bar1() {} +const unsafe extern "C" fn bar2() {} +const unsafe extern "Rust" fn bar3() {} +const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr index bd5940a3fd60c..f8c3107bd221a 100644 --- a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr +++ b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr @@ -1,57 +1,21 @@ -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:3:1 +error[E0658]: `cdecl` as a `const fn` ABI is unstable + --> $DIR/feature-gate-const_extern_fn.rs:7:14 | -LL | const extern fn foo1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const extern "cdecl" fn foo4() {} + | ^^^^^^^ | = note: see issue #64926 for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:4:1 +error[E0658]: `cdecl` as a `const fn` ABI is unstable + --> $DIR/feature-gate-const_extern_fn.rs:11:21 | -LL | const extern "C" fn foo2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const unsafe extern "cdecl" fn bar4() {} + | ^^^^^^^ | = note: see issue #64926 for more information = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:5:1 - | -LL | const extern "Rust" fn foo3() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #64926 for more information - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:6:1 - | -LL | const unsafe extern fn bar1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #64926 for more information - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:7:1 - | -LL | const unsafe extern "C" fn bar2() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #64926 for more information - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error[E0658]: `const extern fn` definitions are unstable - --> $DIR/feature-gate-const_extern_fn.rs:8:1 - | -LL | const unsafe extern "Rust" fn bar3() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #64926 for more information - = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. From 6b75406f5a7b006f7c724c08c6a00d7696a3620d Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 28 Feb 2022 18:13:24 -0500 Subject: [PATCH 09/24] Create 2024 edition --- compiler/rustc_ast/src/token.rs | 2 +- .../src/standard_library_imports.rs | 1 + compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_session/src/session.rs | 5 ++++ compiler/rustc_span/src/edition.rs | 30 +++++++++++++++++-- compiler/rustc_span/src/lib.rs | 5 ++++ compiler/rustc_span/src/symbol.rs | 2 ++ library/core/src/prelude/mod.rs | 10 +++++++ library/std/src/lib.rs | 1 + library/std/src/prelude/mod.rs | 14 +++++++++ src/test/ui/hello.rs | 11 +++++-- src/test/ui/hello2021.rs | 6 ---- src/tools/rustfmt/src/bin/main.rs | 1 + src/tools/rustfmt/src/config/options.rs | 5 ++++ 14 files changed, 83 insertions(+), 12 deletions(-) delete mode 100644 src/test/ui/hello2021.rs diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 2132cdfc001b6..3e274107e7fb6 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -722,7 +722,7 @@ impl NonterminalKind { Edition::Edition2015 | Edition::Edition2018 => { NonterminalKind::PatParam { inferred: true } } - Edition::Edition2021 => NonterminalKind::PatWithOr, + Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr, }, sym::pat_param => NonterminalKind::PatParam { inferred: false }, sym::expr => NonterminalKind::Expr, diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 3571517d2b258..09ad5f9b3eaa9 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -70,6 +70,7 @@ pub fn inject( Edition2015 => sym::rust_2015, Edition2018 => sym::rust_2018, Edition2021 => sym::rust_2021, + Edition2024 => sym::rust_2024, }]) .map(|&symbol| Ident::new(symbol, span)) .collect(); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 10b2b9f07e2a5..058b03530a39f 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1033,7 +1033,7 @@ fn check_matcher_core( err.span_label(sp, format!("not allowed after `{}` fragments", kind)); if kind == NonterminalKind::PatWithOr - && sess.edition == Edition::Edition2021 + && sess.edition.rust_2021() && next_token.is_token(&BinOp(token::BinOpToken::Or)) { let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index eed0f1e09fffe..8ba859bed4d08 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -945,6 +945,11 @@ impl Session { self.opts.edition >= Edition::Edition2021 } + /// Are we allowed to use features from the Rust 2024 edition? + pub fn rust_2024(&self) -> bool { + self.opts.edition >= Edition::Edition2024 + } + pub fn edition(&self) -> Edition { self.opts.edition } diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index 511c2e8662697..065d3660e5008 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -22,13 +22,15 @@ pub enum Edition { Edition2018, /// The 2021 edition Edition2021, + /// The 2024 edition + Edition2024, } // Must be in order from oldest to newest. pub const ALL_EDITIONS: &[Edition] = - &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021]; + &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021, Edition::Edition2024]; -pub const EDITION_NAME_LIST: &str = "2015|2018|2021"; +pub const EDITION_NAME_LIST: &str = "2015|2018|2021|2024"; pub const DEFAULT_EDITION: Edition = Edition::Edition2015; @@ -40,6 +42,7 @@ impl fmt::Display for Edition { Edition::Edition2015 => "2015", Edition::Edition2018 => "2018", Edition::Edition2021 => "2021", + Edition::Edition2024 => "2024", }; write!(f, "{}", s) } @@ -51,6 +54,7 @@ impl Edition { Edition::Edition2015 => "rust_2015_compatibility", Edition::Edition2018 => "rust_2018_compatibility", Edition::Edition2021 => "rust_2021_compatibility", + Edition::Edition2024 => "rust_2024_compatibility", } } @@ -59,6 +63,7 @@ impl Edition { Edition::Edition2015 => sym::rust_2015_preview, Edition::Edition2018 => sym::rust_2018_preview, Edition::Edition2021 => sym::rust_2021_preview, + Edition::Edition2024 => sym::rust_2024_preview, } } @@ -67,8 +72,28 @@ impl Edition { Edition::Edition2015 => true, Edition::Edition2018 => true, Edition::Edition2021 => true, + Edition::Edition2024 => false, } } + + pub fn rust_2015(&self) -> bool { + *self == Edition::Edition2015 + } + + /// Are we allowed to use features from the Rust 2018 edition? + pub fn rust_2018(&self) -> bool { + *self >= Edition::Edition2018 + } + + /// Are we allowed to use features from the Rust 2021 edition? + pub fn rust_2021(&self) -> bool { + *self >= Edition::Edition2021 + } + + /// Are we allowed to use features from the Rust 2024 edition? + pub fn rust_2024(&self) -> bool { + *self >= Edition::Edition2024 + } } impl FromStr for Edition { @@ -78,6 +103,7 @@ impl FromStr for Edition { "2015" => Ok(Edition::Edition2015), "2018" => Ok(Edition::Edition2018), "2021" => Ok(Edition::Edition2021), + "2024" => Ok(Edition::Edition2024), _ => Err(()), } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 6d7377927c291..9ae366a5fe811 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -698,6 +698,11 @@ impl Span { self.edition() >= edition::Edition::Edition2021 } + #[inline] + pub fn rust_2024(self) -> bool { + self.edition() >= edition::Edition::Edition2024 + } + /// Returns the source callee. /// /// Returns `None` if the supplied span has no expansion trace, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2737c26708bc4..443f0a6db89ce 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1145,6 +1145,8 @@ symbols! { rust_2018_preview, rust_2021, rust_2021_preview, + rust_2024, + rust_2024_preview, rust_begin_unwind, rust_eh_catch_typeinfo, rust_eh_personality, diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index ccd36a428e296..3cd3a3b780e9c 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -45,3 +45,13 @@ pub mod rust_2021 { #[doc(no_inline)] pub use crate::convert::{TryFrom, TryInto}; } + +/// The 2024 edition of the core prelude. +/// +/// See the [module-level documentation](self) for more. +#[unstable(feature = "prelude_2024", issue = "none")] +pub mod rust_2024 { + #[unstable(feature = "prelude_2024", issue = "none")] + #[doc(no_inline)] + pub use super::rust_2021::*; +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 819ec10a4b4b6..a5cdc89c5b60e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -279,6 +279,7 @@ #![feature(panic_info_message)] #![feature(panic_internals)] #![feature(portable_simd)] +#![feature(prelude_2024)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] #![feature(slice_internals)] diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index d4bf6aeefee57..c314bbbb68e57 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -132,3 +132,17 @@ pub mod rust_2021 { #[doc(no_inline)] pub use core::prelude::rust_2021::*; } + +/// The 2024 version of the prelude of The Rust Standard Library. +/// +/// See the [module-level documentation](self) for more. +#[unstable(feature = "prelude_2024", issue = "none")] +pub mod rust_2024 { + #[unstable(feature = "prelude_2024", issue = "none")] + #[doc(no_inline)] + pub use super::v1::*; + + #[unstable(feature = "prelude_2024", issue = "none")] + #[doc(no_inline)] + pub use core::prelude::rust_2024::*; +} diff --git a/src/test/ui/hello.rs b/src/test/ui/hello.rs index c207c25545eca..c66b7c60fb4ea 100644 --- a/src/test/ui/hello.rs +++ b/src/test/ui/hello.rs @@ -1,5 +1,12 @@ // run-pass +// revisions: e2015 e2018 e2021 e2024 -pub fn main() { - println!("hello, world"); +//[e2018] edition:2018 +//[e2021] edition:2021 +//[e2024] edition:2024 + +//[e2024] compile-flags: -Zunstable-options + +fn main() { + println!("hello"); } diff --git a/src/test/ui/hello2021.rs b/src/test/ui/hello2021.rs deleted file mode 100644 index 134d8af5bfb8a..0000000000000 --- a/src/test/ui/hello2021.rs +++ /dev/null @@ -1,6 +0,0 @@ -// run-pass -// edition:2021 - -fn main() { - println!("hello, 2021"); -} diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index ad10b9ede608f..8e871e61f2683 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -693,6 +693,7 @@ fn edition_from_edition_str(edition_str: &str) -> Result { "2015" => Ok(Edition::Edition2015), "2018" => Ok(Edition::Edition2018), "2021" => Ok(Edition::Edition2021), + "2024" => Ok(Edition::Edition2024), _ => Err(format_err!("Invalid value for `--edition`")), } } diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs index d857c29be29c6..257a17b2703a9 100644 --- a/src/tools/rustfmt/src/config/options.rs +++ b/src/tools/rustfmt/src/config/options.rs @@ -423,6 +423,10 @@ pub enum Edition { #[doc_hint = "2021"] /// Edition 2021. Edition2021, + #[value = "2024"] + #[doc_hint = "2024"] + /// Edition 2024. + Edition2024, } impl Default for Edition { @@ -437,6 +441,7 @@ impl From for rustc_span::edition::Edition { Edition::Edition2015 => Self::Edition2015, Edition::Edition2018 => Self::Edition2018, Edition::Edition2021 => Self::Edition2021, + Edition::Edition2024 => Self::Edition2024, } } } From 98190b716829fd4edbf1b364a1a662de9a9ca7bb Mon Sep 17 00:00:00 2001 From: "Cliff L. Biffle" Date: Mon, 4 Apr 2022 11:03:03 -0700 Subject: [PATCH 10/24] Revert "Work around invalid DWARF bugs for fat LTO" Since September, the toolchain has not been generating reliable DWARF information for static variables when LTO is on. This has affected projects in the embedded space where the use of LTO is typical. In our case, it has kept us from bumping past the 2021-09-22 nightly toolchain lest our debugger break. This has been a pretty dramatic regression for people using debuggers and static variables. See #90357 for more info and a repro case. This commit is a mechanical revert of d5de680e20def848751cb3c11e1182408112b1d3 from PR #89041, which caused the issue. (Note on that PR that the commit's author has requested it be reverted.) I have locally verified that this fixes #90357 by restoring the functionality of both the repro case I posted on that bug, and debugger behavior on real programs. There do not appear to be test cases for this in the toolchain; if I've missed them, point me at 'em and I'll update them. --- compiler/rustc_codegen_llvm/src/back/lto.rs | 18 ++---------------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 8 ++++++-- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 4 ++-- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 0f5b1c08ec2dc..266ed6d8b6f30 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -325,20 +325,6 @@ fn fat_lto( drop(linker); save_temp_bitcode(cgcx, &module, "lto.input"); - // Fat LTO also suffers from the invalid DWARF issue similar to Thin LTO. - // Here we rewrite all `DICompileUnit` pointers if there is only one `DICompileUnit`. - // This only works around the problem when codegen-units = 1. - // Refer to the comments in the `optimize_thin_module` function for more details. - let mut cu1 = ptr::null_mut(); - let mut cu2 = ptr::null_mut(); - unsafe { llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2) }; - if !cu2.is_null() { - let _timer = - cgcx.prof.generic_activity_with_arg("LLVM_fat_lto_patch_debuginfo", &*module.name); - unsafe { llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1) }; - save_temp_bitcode(cgcx, &module, "fat-lto-after-patch"); - } - // Internalize everything below threshold to help strip out more modules and such. unsafe { let ptr = symbols_below_threshold.as_ptr(); @@ -757,7 +743,7 @@ pub unsafe fn optimize_thin_module( // an error. let mut cu1 = ptr::null_mut(); let mut cu2 = ptr::null_mut(); - llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); + llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); if !cu2.is_null() { let msg = "multiple source DICompileUnits found"; return Err(write::llvm_err(&diag_handler, msg)); @@ -846,7 +832,7 @@ pub unsafe fn optimize_thin_module( let _timer = cgcx .prof .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name()); - llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1); + llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); save_temp_bitcode(cgcx, &module, "thin-lto-after-patch"); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 375b9927c8672..db018aeac1385 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2506,8 +2506,12 @@ extern "C" { len: usize, out_len: &mut usize, ) -> *const u8; - pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void); - pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); + pub fn LLVMRustThinLTOGetDICompileUnit( + M: &Module, + CU1: &mut *mut c_void, + CU2: &mut *mut c_void, + ); + pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>; pub fn LLVMRustLinkerAdd( diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 7030fd53704dd..e3ee21c80859e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1611,7 +1611,7 @@ LLVMRustGetBitcodeSliceFromObjectData(const char *data, // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void -LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod, +LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, DICompileUnit **A, DICompileUnit **B) { Module *M = unwrap(Mod); @@ -1629,7 +1629,7 @@ LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod, // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void -LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { +LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { Module *M = unwrap(Mod); // If the original source module didn't have a `DICompileUnit` then try to From 42af197431fd3185767b6f3064336d65b0e62869 Mon Sep 17 00:00:00 2001 From: "Cliff L. Biffle" Date: Tue, 5 Apr 2022 10:35:52 -0700 Subject: [PATCH 11/24] Improve debuginfo test coverage for simple statics. - Re-enabled basic-types-globals which has been disabled since 2018 - Updated its now-rotted assertions about GDB's output to pass - Rewrote header comment describing some previous state of GDB behavior that didn't match either the checked-in assertions _or_ the current behavior, and so I assume has just been wrong for some time. - Copy-pasta'd the test into a version that uses LTO to check for regression on #90357, because I don't see a way to matrix the same test into several build configurations. --- src/test/debuginfo/basic-types-globals-lto.rs | 80 +++++++++++++++++++ src/test/debuginfo/basic-types-globals.rs | 10 +-- 2 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 src/test/debuginfo/basic-types-globals-lto.rs diff --git a/src/test/debuginfo/basic-types-globals-lto.rs b/src/test/debuginfo/basic-types-globals-lto.rs new file mode 100644 index 0000000000000..03770eb6f01c7 --- /dev/null +++ b/src/test/debuginfo/basic-types-globals-lto.rs @@ -0,0 +1,80 @@ +// Caveat - gdb doesn't know about UTF-32 character encoding and will print a +// rust char as only its numerical value. + +// min-lldb-version: 310 + +// no-prefer-dynamic +// compile-flags:-g -C lto +// gdb-command:run +// gdbg-command:print 'basic_types_globals::B' +// gdbr-command:print B +// gdb-check:$1 = false +// gdbg-command:print 'basic_types_globals::I' +// gdbr-command:print I +// gdb-check:$2 = -1 +// gdbg-command:print 'basic_types_globals::C' +// gdbr-command:print C +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 +// gdbg-command:print/d 'basic_types_globals::I8' +// gdbr-command:print I8 +// gdb-check:$4 = 68 +// gdbg-command:print 'basic_types_globals::I16' +// gdbr-command:print I16 +// gdb-check:$5 = -16 +// gdbg-command:print 'basic_types_globals::I32' +// gdbr-command:print I32 +// gdb-check:$6 = -32 +// gdbg-command:print 'basic_types_globals::I64' +// gdbr-command:print I64 +// gdb-check:$7 = -64 +// gdbg-command:print 'basic_types_globals::U' +// gdbr-command:print U +// gdb-check:$8 = 1 +// gdbg-command:print/d 'basic_types_globals::U8' +// gdbr-command:print U8 +// gdb-check:$9 = 100 +// gdbg-command:print 'basic_types_globals::U16' +// gdbr-command:print U16 +// gdb-check:$10 = 16 +// gdbg-command:print 'basic_types_globals::U32' +// gdbr-command:print U32 +// gdb-check:$11 = 32 +// gdbg-command:print 'basic_types_globals::U64' +// gdbr-command:print U64 +// gdb-check:$12 = 64 +// gdbg-command:print 'basic_types_globals::F32' +// gdbr-command:print F32 +// gdb-check:$13 = 2.5 +// gdbg-command:print 'basic_types_globals::F64' +// gdbr-command:print F64 +// gdb-check:$14 = 3.5 +// gdb-command:continue + +#![allow(unused_variables)] +#![feature(omit_gdb_pretty_printer_section)] +#![omit_gdb_pretty_printer_section] + +// N.B. These are `mut` only so they don't constant fold away. +static mut B: bool = false; +static mut I: isize = -1; +static mut C: char = 'a'; +static mut I8: i8 = 68; +static mut I16: i16 = -16; +static mut I32: i32 = -32; +static mut I64: i64 = -64; +static mut U: usize = 1; +static mut U8: u8 = 100; +static mut U16: u16 = 16; +static mut U32: u32 = 32; +static mut U64: u64 = 64; +static mut F32: f32 = 2.5; +static mut F64: f64 = 3.5; + +fn main() { + _zzz(); // #break + + let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; +} + +fn _zzz() {()} diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs index 389b2cf015cac..11637d2294a83 100644 --- a/src/test/debuginfo/basic-types-globals.rs +++ b/src/test/debuginfo/basic-types-globals.rs @@ -1,11 +1,7 @@ -// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values) -// as its numerical value along with its associated ASCII char, there -// doesn't seem to be any way around this. Also, gdb doesn't know -// about UTF-32 character encoding and will print a rust char as only -// its numerical value. +// Caveat - gdb doesn't know about UTF-32 character encoding and will print a +// rust char as only its numerical value. // min-lldb-version: 310 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-g // gdb-command:run @@ -18,7 +14,7 @@ // gdbg-command:print 'basic_types_globals::C' // gdbr-command:print C // gdbg-check:$3 = 97 -// gdbr-check:$3 = 97 'a' +// gdbr-check:$3 = 97 // gdbg-command:print/d 'basic_types_globals::I8' // gdbr-command:print I8 // gdb-check:$4 = 68 From 7bd22e29d0d604e594ba03b51bd8c3fc82959215 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 6 Apr 2022 21:10:43 -0700 Subject: [PATCH 12/24] only downgrade Error -> Ambiguous if type error is in predicate --- .../src/traits/select/candidate_assembly.rs | 4 ++-- ...n-help-with-err-generic-is-not-function.rs | 8 -------- ...lp-with-err-generic-is-not-function.stderr | 19 ++----------------- .../typeck/autoderef-with-param-env-error.rs | 9 +++++++++ .../autoderef-with-param-env-error.stderr | 12 ++++++++++++ 5 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/typeck/autoderef-with-param-env-error.rs create mode 100644 src/test/ui/typeck/autoderef-with-param-env-error.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cf472813e9e32..4bb0ce29b637b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -231,8 +231,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `Err(Unimplemented)` to `Ok(None)`. This helps us avoid // emitting additional spurious errors, since we're guaranteed // to have emitted at least one. - if stack.obligation.references_error() { - debug!("no results for error type, treating as ambiguous"); + if stack.obligation.predicate.references_error() { + debug!(?stack.obligation.predicate, "found error type in predicate, treating as ambiguous"); return Ok(None); } return Err(Unimplemented); diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs index 26deb59876268..e48ab4aa96fb9 100644 --- a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs +++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs @@ -8,15 +8,7 @@ where //~^ ERROR cannot find type `T` in this scope //~| NOTE not found in this scope { - // The part where it claims that there is no method named `len` is a bug. Feel free to fix it. - // This test is intended to ensure that a different bug, where it claimed - // that `v` was a function, does not regress. fn method(v: Vec) { v.len(); } - //~^ ERROR type annotations needed - //~| NOTE cannot infer type - //~| NOTE type must be known at this point - //~| ERROR no method named `len` - //~| NOTE private field, not a method } fn main() {} diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr index 958ce3c25d027..26bdf460f5e4d 100644 --- a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr +++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr @@ -12,21 +12,6 @@ error[E0412]: cannot find type `T` in this scope LL | T: Copy, | ^ not found in this scope -error[E0282]: type annotations needed - --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31 - | -LL | fn method(v: Vec) { v.len(); } - | ^^^ cannot infer type - | - = note: type must be known at this point - -error[E0599]: no method named `len` found for struct `Vec` in the current scope - --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31 - | -LL | fn method(v: Vec) { v.len(); } - | ^^^ private field, not a method - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0412, E0599. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/typeck/autoderef-with-param-env-error.rs b/src/test/ui/typeck/autoderef-with-param-env-error.rs new file mode 100644 index 0000000000000..ec96c61c63e3a --- /dev/null +++ b/src/test/ui/typeck/autoderef-with-param-env-error.rs @@ -0,0 +1,9 @@ +fn foo() +where + T: Send, + //~^ cannot find type `T` in this scope +{ + let s = "abc".to_string(); +} + +fn main() {} diff --git a/src/test/ui/typeck/autoderef-with-param-env-error.stderr b/src/test/ui/typeck/autoderef-with-param-env-error.stderr new file mode 100644 index 0000000000000..cde800336dd3d --- /dev/null +++ b/src/test/ui/typeck/autoderef-with-param-env-error.stderr @@ -0,0 +1,12 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/autoderef-with-param-env-error.rs:3:5 + | +LL | fn foo() + | - help: you might be missing a type parameter: `` +LL | where +LL | T: Send, + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. From edeb826d0a6c157f389f94b8525794b52362e174 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Apr 2022 12:23:42 -0700 Subject: [PATCH 13/24] Inline shallow_resolve_ty into ShallowResolver --- compiler/rustc_infer/src/infer/mod.rs | 83 +++++++++++++-------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2524bd78355a1..e1cad1a4f6cef 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1659,49 +1659,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.const_eval_resolve(param_env_erased, unevaluated, span) } - /// If `typ` is a type variable of some kind, resolve it one level - /// (but do not resolve types found in the result). If `typ` is - /// not a type variable, just return it unmodified. - // FIXME(eddyb) inline into `ShallowResolver::visit_ty`. - fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> { - match *typ.kind() { - ty::Infer(ty::TyVar(v)) => { - // Not entirely obvious: if `typ` is a type variable, - // it can be resolved to an int/float variable, which - // can then be recursively resolved, hence the - // recursion. Note though that we prevent type - // variables from unifying to other type variables - // directly (though they may be embedded - // structurally), and we prevent cycles in any case, - // so this recursion should always be of very limited - // depth. - // - // Note: if these two lines are combined into one we get - // dynamic borrow errors on `self.inner`. - let known = self.inner.borrow_mut().type_variables().probe(v).known(); - known.map_or(typ, |t| self.shallow_resolve_ty(t)) - } - - ty::Infer(ty::IntVar(v)) => self - .inner - .borrow_mut() - .int_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.tcx)) - .unwrap_or(typ), - - ty::Infer(ty::FloatVar(v)) => self - .inner - .borrow_mut() - .float_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.tcx)) - .unwrap_or(typ), - - _ => typ, - } - } - /// `ty_or_const_infer_var_changed` is equivalent to one of these two: /// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`) /// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`) @@ -1831,8 +1788,46 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { self.infcx.tcx } + /// If `ty` is a type variable of some kind, resolve it one level + /// (but do not resolve types found in the result). If `typ` is + /// not a type variable, just return it unmodified. fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.shallow_resolve_ty(ty) + match *ty.kind() { + ty::Infer(ty::TyVar(v)) => { + // Not entirely obvious: if `typ` is a type variable, + // it can be resolved to an int/float variable, which + // can then be recursively resolved, hence the + // recursion. Note though that we prevent type + // variables from unifying to other type variables + // directly (though they may be embedded + // structurally), and we prevent cycles in any case, + // so this recursion should always be of very limited + // depth. + // + // Note: if these two lines are combined into one we get + // dynamic borrow errors on `self.inner`. + let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); + known.map_or(ty, |t| self.fold_ty(t)) + } + + ty::Infer(ty::IntVar(v)) => self + .infcx + .inner + .borrow_mut() + .int_unification_table() + .probe_value(v) + .map_or(ty, |v| v.to_type(self.infcx.tcx)), + + ty::Infer(ty::FloatVar(v)) => self + .infcx + .inner + .borrow_mut() + .float_unification_table() + .probe_value(v) + .map_or(ty, |v| v.to_type(self.infcx.tcx)), + + _ => ty, + } } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { From 7f945b2b5b0d8123d6031bb655d2a9fe5c71ee01 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 Apr 2022 11:00:55 -0400 Subject: [PATCH 14/24] add simd_arith_offset intrinsics --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 21 ++++++++++++++++++++ compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_typeck/src/check/intrinsic.rs | 1 + 3 files changed, 23 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 48840c76cac8b..cf9cf1b70aaa7 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1839,6 +1839,27 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, simd_neg: Int => neg, Float => fneg; } + if name == sym::simd_arith_offset { + // This also checks that the first operand is a ptr type. + let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| { + span_bug!(span, "must be called with a vector of pointer types as first argument") + }); + let layout = bx.layout_of(pointee.ty); + let ptrs = args[0].immediate(); + // The second argument must be a ptr-sized integer. + // (We don't care about the signedness, this is wrapping anyway.) + let (_offsets_len, offsets_elem) = arg_tys[1].simd_size_and_type(bx.tcx()); + if !matches!(offsets_elem.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) { + span_bug!( + span, + "must be called with a vector of pointer-sized integers as second argument" + ); + } + let offsets = args[1].immediate(); + + return Ok(bx.gep(bx.backend_type(layout), ptrs, &[offsets])); + } + if name == sym::simd_saturating_add || name == sym::simd_saturating_sub { let lhs = args[0].immediate(); let rhs = args[1].immediate(); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index dc4d10f699c75..1070cb1cd9ed8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1245,6 +1245,7 @@ symbols! { simd, simd_add, simd_and, + simd_arith_offset, simd_as, simd_bitmask, simd_cast, diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index cd6b1115ed806..8bad238f5976d 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -437,6 +437,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_fpow | sym::simd_saturating_add | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), + sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)), sym::simd_neg | sym::simd_fsqrt | sym::simd_fsin From e886dc52eedf3d074c6cc66f0518a996f7bbe735 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 Apr 2022 11:01:22 -0400 Subject: [PATCH 15/24] portable-simd: use simd_arith_offset to avoid ptr-int transmutation --- .../portable-simd/crates/core_simd/src/intrinsics.rs | 4 ++++ .../portable-simd/crates/core_simd/src/vector/ptr.rs | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/library/portable-simd/crates/core_simd/src/intrinsics.rs b/library/portable-simd/crates/core_simd/src/intrinsics.rs index 426c4de6ab1ea..82508c6882dab 100644 --- a/library/portable-simd/crates/core_simd/src/intrinsics.rs +++ b/library/portable-simd/crates/core_simd/src/intrinsics.rs @@ -61,6 +61,10 @@ extern "platform-intrinsic" { /// xor pub(crate) fn simd_xor(x: T, y: T) -> T; + /// getelementptr (without inbounds) + #[cfg(not(bootstrap))] + pub(crate) fn simd_arith_offset(ptrs: T, offsets: U) -> T; + /// fptoui/fptosi/uitofp/sitofp /// casting floats to integers is truncating, so it is safe to convert values like e.g. 1.5 /// but the truncated value must fit in the target type or the result is poison. diff --git a/library/portable-simd/crates/core_simd/src/vector/ptr.rs b/library/portable-simd/crates/core_simd/src/vector/ptr.rs index 417d255c28d63..68a9c67f795af 100644 --- a/library/portable-simd/crates/core_simd/src/vector/ptr.rs +++ b/library/portable-simd/crates/core_simd/src/vector/ptr.rs @@ -1,5 +1,8 @@ //! Private implementation details of public gather/scatter APIs. +#[cfg(not(bootstrap))] +use crate::simd::intrinsics; use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +#[cfg(bootstrap)] use core::mem; /// A vector of *const T. @@ -21,12 +24,16 @@ where #[inline] #[must_use] pub fn wrapping_add(self, addend: Simd) -> Self { + #[cfg(bootstrap)] // Safety: converting pointers to usize and vice-versa is safe // (even if using that pointer is not) unsafe { let x: Simd = mem::transmute_copy(&self); mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::())) }) } + #[cfg(not(bootstrap))] + // Safety: this intrinsic doesn't have a precondition + unsafe { intrinsics::simd_arith_offset(self, addend) } } } @@ -49,11 +56,15 @@ where #[inline] #[must_use] pub fn wrapping_add(self, addend: Simd) -> Self { + #[cfg(bootstrap)] // Safety: converting pointers to usize and vice-versa is safe // (even if using that pointer is not) unsafe { let x: Simd = mem::transmute_copy(&self); mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::())) }) } + #[cfg(not(bootstrap))] + // Safety: this intrinsic doesn't have a precondition + unsafe { intrinsics::simd_arith_offset(self, addend) } } } From 69de21385e90d58c226ab688d04806a5c82259e3 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 12 Apr 2022 20:11:10 -0500 Subject: [PATCH 16/24] Fix `x test --doc --stage 0 library/std` I managed to break this in https://github.com/rust-lang/rust/pull/95449. I am not quite sure why this is the correct fix, but it doesn't break `doc --stage 0` and is strictly closer to the previous behavior. Previously, rustdoc would error with strange issues because of the mismatched sysroot: ``` error[E0460]: found possibly newer version of crate `std` which `rustc_span` depends on --> /home/jnelson/rust-lang/rust/compiler/rustc_lint_defs/src/lib.rs:14:5 | 14 | use rustc_span::{sym, symbol::Ident, Span, Symbol}; | ^^^^^^^^^^ | = note: perhaps that crate needs to be recompiled? = note: the following crate versions were found: crate `std`: /home/jnelson/rust-lang/rust/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-ff9290e971253a38.rlib crate `std`: /home/jnelson/rust-lang/rust/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-ff9290e971253a38.so crate `rustc_span`: /home/jnelson/rust-lang/rust/build/x86_64-unknown-linux-gnu/stage0-rustc/x86_64-unknown-linux-gnu/release/deps/librustc_span-ed11dce30c1766f9.rlib ``` --- src/bootstrap/bin/rustdoc.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 4bba2eb450744..0349277a36b90 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -31,7 +31,9 @@ fn main() { let mut cmd = Command::new(rustdoc); - if target.is_some() { + // I am not actually sure why it's necessary to pass the sysroot for `--test`, + // but `test --doc --stage 0` is broken without it :( + if target.is_some() || args.iter().any(|x| x == "--test") { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, // unless one is already set. From eb905c08c90e7d1c09f4ad73e7e10fe9bd4534e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 Apr 2022 22:25:52 -0400 Subject: [PATCH 17/24] add codegen smoke test --- src/test/codegen/simd_arith_offset.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/codegen/simd_arith_offset.rs diff --git a/src/test/codegen/simd_arith_offset.rs b/src/test/codegen/simd_arith_offset.rs new file mode 100644 index 0000000000000..cb885ac6c3516 --- /dev/null +++ b/src/test/codegen/simd_arith_offset.rs @@ -0,0 +1,25 @@ +// compile-flags: -C no-prepopulate-passes +// + +#![crate_type = "lib"] +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + pub(crate) fn simd_arith_offset(ptrs: T, offsets: U) -> T; +} + +/// A vector of *const T. +#[derive(Debug, Copy, Clone)] +#[repr(simd)] +pub struct SimdConstPtr([*const T; LANES]); + +#[derive(Debug, Copy, Clone)] +#[repr(simd)] +pub struct Simd([T; LANES]); + +// CHECK-LABEL: smoke +#[no_mangle] +pub fn smoke(ptrs: SimdConstPtr, offsets: Simd) -> SimdConstPtr { + // CHECK: getelementptr i8, <8 x i8*> %_3, <8 x i64> %_4 + unsafe { simd_arith_offset(ptrs, offsets) } +} From 7c2d57e0fa1615d993a4b4166163fb0b3ec7d395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 13 Apr 2022 22:51:34 +0200 Subject: [PATCH 18/24] couple of clippy::complexity fixes --- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_expand/src/mbe/macro_check.rs | 2 +- compiler/rustc_infer/src/infer/at.rs | 6 +++--- compiler/rustc_macros/src/lib.rs | 2 +- compiler/rustc_middle/src/ty/inhabitedness/mod.rs | 2 +- compiler/rustc_mir_build/src/build/expr/as_constant.rs | 2 +- compiler/rustc_mir_build/src/build/expr/into.rs | 6 +----- compiler/rustc_mir_build/src/build/matches/test.rs | 2 +- compiler/rustc_mir_transform/src/check_unsafety.rs | 4 ++-- compiler/rustc_parse/src/lexer/mod.rs | 6 +++--- compiler/rustc_passes/src/stability.rs | 4 ++-- compiler/rustc_session/src/session.rs | 2 +- compiler/rustc_target/src/abi/call/sparc64.rs | 6 +++--- .../rustc_trait_selection/src/traits/on_unimplemented.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 4 ++-- compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs | 2 +- 16 files changed, 25 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index ecb3cdd627cec..9cd072c8b4cdf 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -832,7 +832,7 @@ impl Diagnostic { name: impl Into>, arg: DiagnosticArgValue<'static>, ) -> &mut Self { - self.args.push((name.into(), arg.into())); + self.args.push((name.into(), arg)); self } diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 4298475767e6f..c6a6e3d125f70 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -270,7 +270,7 @@ fn check_binders( MISSING_FRAGMENT_SPECIFIER, span, node_id, - &format!("missing fragment specifier"), + "missing fragment specifier", ); } if !macros.is_empty() { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 09b02ba74a8de..58c309a5c52ea 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -63,9 +63,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// common state. Used in coherence. pub fn fork(&self) -> Self { Self { - tcx: self.tcx.clone(), - defining_use_anchor: self.defining_use_anchor.clone(), - in_progress_typeck_results: self.in_progress_typeck_results.clone(), + tcx: self.tcx, + defining_use_anchor: self.defining_use_anchor, + in_progress_typeck_results: self.in_progress_typeck_results, inner: self.inner.clone(), skip_leak_check: self.skip_leak_check.clone(), lexical_region_resolutions: self.lexical_region_resolutions.clone(), diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 3589860eb0eac..b53ef8161359a 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -44,7 +44,7 @@ pub fn symbols(input: TokenStream) -> TokenStream { #[proc_macro] #[allow_internal_unstable(step_trait, rustc_attrs, trusted_step)] pub fn newtype_index(input: TokenStream) -> TokenStream { - newtype::newtype(input).into() + newtype::newtype(input) } decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 2c78c1f63d8ff..226456588e75d 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -191,7 +191,7 @@ impl<'tcx> Ty<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> DefIdForest<'tcx> { - tcx.type_uninhabited_from(param_env.and(self)).clone() + tcx.type_uninhabited_from(param_env.and(self)) } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 8b9b1847e7f0e..3a6e59db90b91 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } }; - Constant { span, user_ty: None, literal: literal.into() } + Constant { span, user_ty: None, literal } } ExprKind::NonHirLiteral { lit, user_ty } => { let user_ty = user_ty.map(|user_ty| { diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index a8f623dbe4693..823f5f4cf12c4 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -423,11 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } thir::InlineAsmOperand::Const { value, span } => { mir::InlineAsmOperand::Const { - value: Box::new(Constant { - span, - user_ty: None, - literal: value.into(), - }), + value: Box::new(Constant { span, user_ty: None, literal: value }), } } thir::InlineAsmOperand::SymFn { expr } => mir::InlineAsmOperand::SymFn { diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 806c260d110ea..0e9e986937660 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -441,7 +441,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Need to experiment. user_ty: None, - literal: method.into(), + literal: method, })), args: vec![val, expect], destination: Some((eq_result, eq_block)), diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index d1d6e7cfe2fed..1b4510b622068 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -539,13 +539,13 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { UnusedUnsafe::InUnsafeBlock(id) => { db.span_label( tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), - format!("because it's nested under this `unsafe` block"), + "because it's nested under this `unsafe` block", ); } UnusedUnsafe::InUnsafeFn(id, usage_lint_root) => { db.span_label( tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), - format!("because it's nested under this `unsafe` fn"), + "because it's nested under this `unsafe` fn", ) .note( "this `unsafe` block does contain unsafe operations, \ diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 5ab412dc777de..79f0237fd9b74 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -234,13 +234,13 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::InvalidIdent // Do not recover an identifier with emoji if the codepoint is a confusable // with a recoverable substitution token, like `➖`. - if UNICODE_ARRAY + if !UNICODE_ARRAY .iter() - .find(|&&(c, _, _)| { + .any(|&(c, _, _)| { let sym = self.str_from(start); sym.chars().count() == 1 && c == sym.chars().next().unwrap() }) - .is_none() => + => { let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index ff033cbb57299..01ba9e35c24dc 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -133,9 +133,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } // `Deprecation` is just two pointers, no need to intern it - let depr_entry = DeprecationEntry::local(depr.clone(), def_id); + let depr_entry = DeprecationEntry::local(*depr, def_id); self.index.depr_map.insert(def_id, depr_entry); - } else if let Some(parent_depr) = self.parent_depr.clone() { + } else if let Some(parent_depr) = self.parent_depr { if inherit_deprecation.yes() { is_deprecated = true; info!("tagging child {:?} as deprecated from parent", def_id); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d70f89760a1ff..3fdceadf1919a 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -238,7 +238,7 @@ impl Session { } diag.emit(); // If we should err, make sure we did. - if must_err && !self.has_errors().is_some() { + if must_err && self.has_errors().is_none() { // We have skipped a feature gate, and not run into other errors... reject. self.err( "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \ diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 5a92ebdd9e843..cc3a0a69999b0 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -113,11 +113,11 @@ where data = arg_scalar(cx, &scalar, offset, data); } abi::Abi::Aggregate { .. } => { - for i in 0..layout.fields.count().clone() { + for i in 0..layout.fields.count() { if offset < layout.fields.offset(i) { offset = layout.fields.offset(i); } - data = parse_structure(cx, layout.field(cx, i).clone(), data.clone(), offset); + data = parse_structure(cx, layout.field(cx, i), data.clone(), offset); } } _ => { @@ -161,7 +161,7 @@ where let mut data = parse_structure( cx, - arg.layout.clone(), + arg.layout, Sdata { prefix: [None; 8], prefix_index: 0, diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 38be28c07ff18..ce0e0a21ff516 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -258,7 +258,7 @@ impl<'tcx> OnUnimplementedDirective { enclosing_scope = Some(enclosing_scope_.clone()); } - append_const_msg = command.append_const_msg.clone(); + append_const_msg = command.append_const_msg; } OnUnimplementedNote { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index f6a5243274cd2..9c70261088880 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -415,8 +415,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get_if_local(def_id) .and_then(|node| node.body_id()) .into_iter() - .map(|id| tcx.hir().body(id).params) - .flatten(); + .flat_map(|id| tcx.hir().body(id).params) + ; for param in params { spans.push_span_label(param.span, String::new()); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 93a0900c7e80d..62518408b8b30 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -646,7 +646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // now get all predicates in the same types as the where bounds, so we can chain them let predicates_from_where = - where_predicates.iter().flatten().map(|bounds| bounds.iter()).flatten(); + where_predicates.iter().flatten().flat_map(|bounds| bounds.iter()); // extract all bounds from the source code using their spans let all_matching_bounds_strs = expected_generic_param From 21d3f8444ab21c7bfc4a2b78d429f1ab161708c9 Mon Sep 17 00:00:00 2001 From: Keita Nonaka Date: Wed, 13 Apr 2022 22:09:03 -0700 Subject: [PATCH 19/24] test: add is_superset test cases for BTreeSet --- .../alloc/src/collections/btree/set/tests.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 00a2a0aaa14ce..a56916081b748 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -319,6 +319,42 @@ fn test_is_subset() { assert_eq!(is_subset(&[99, 100], &large), false); } +#[test] +fn test_is_superset() { + fn is_superset(a: &[i32], b: &[i32]) -> bool { + let set_a = BTreeSet::from_iter(a.iter()); + let set_b = BTreeSet::from_iter(b.iter()); + set_a.is_superset(&set_b) + } + + assert_eq!(is_superset(&[], &[]), true); + assert_eq!(is_superset(&[], &[1, 2]), false); + assert_eq!(is_superset(&[0], &[1, 2]), false); + assert_eq!(is_superset(&[1], &[1, 2]), false); + assert_eq!(is_superset(&[4], &[1, 2]), false); + assert_eq!(is_superset(&[1, 4], &[1, 2]), false); + assert_eq!(is_superset(&[1, 2], &[1, 2]), true); + assert_eq!(is_superset(&[1, 2, 3], &[1, 3]), true); + assert_eq!(is_superset(&[1, 2, 3], &[]), true); + assert_eq!(is_superset(&[-1, 1, 2, 3], &[-1, 3]), true); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = Vec::from_iter(0..100); + assert_eq!(is_superset(&[], &large), false); + assert_eq!(is_superset(&large, &[]), true); + assert_eq!(is_superset(&large, &[1]), true); + assert_eq!(is_superset(&large, &[50, 99]), true); + assert_eq!(is_superset(&large, &[100]), false); + assert_eq!(is_superset(&large, &[0, 99]), true); + assert_eq!(is_superset(&[-1], &large), false); + assert_eq!(is_superset(&[0], &large), false); + assert_eq!(is_superset(&[99, 100], &large), false); +} + #[test] fn test_retain() { let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]); From 50c339e8f5e5516c9ba4938979e787c0a0a8e081 Mon Sep 17 00:00:00 2001 From: Keita Nonaka Date: Wed, 13 Apr 2022 22:19:08 -0700 Subject: [PATCH 20/24] test: add remove() test cases for BTreeSet --- .../alloc/src/collections/btree/set/tests.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index a56916081b748..429b1644976c7 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -427,6 +427,26 @@ fn test_clear() { x.clear(); assert!(x.is_empty()); } +#[test] +fn test_remove() { + let mut x = BTreeSet::new(); + assert!(x.is_empty()); + + x.insert(1); + x.insert(2); + x.insert(3); + x.insert(4); + + assert_eq!(x.remove(&2), true); + assert_eq!(x.remove(&0), false); + assert_eq!(x.remove(&5), false); + assert_eq!(x.remove(&1), true); + assert_eq!(x.remove(&2), false); + assert_eq!(x.remove(&3), true); + assert_eq!(x.remove(&4), true); + assert_eq!(x.remove(&4), false); + assert!(x.is_empty()); +} #[test] fn test_zip() { From 1e78a47faec4c45af8f99bfda091d17b3b668a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 14 Apr 2022 15:42:13 +0300 Subject: [PATCH 21/24] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 46d7ee68f2628..24cf957627d5e 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 46d7ee68f26285db26b2640f2c07d6332380c756 +Subproject commit 24cf957627d5ede1b395f92ff871fd7a281d49a4 From 9d319f370134afc9c46965f2b9af23dc5d625124 Mon Sep 17 00:00:00 2001 From: Keita Nonaka Date: Wed, 13 Apr 2022 22:37:41 -0700 Subject: [PATCH 22/24] update: actions/checkout@v2 to actions/checkout@v3 update: actions/checkout@v2 to actions/checkout@v3 for all yaml files Revert "update: actions/checkout@v2 to actions/checkout@v3 for all yaml files" This reverts commit 7445e582b900f0f56f5f2bd9036aacab97ef28e9. change GitHub Actions version v2 to v3 change GitHub Actions --- .github/workflows/ci.yml | 8 ++++---- src/ci/github-actions/ci.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff3a832631530..451116f320d64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: - name: disable git crlf conversion run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: configure the PR in which the error message will be posted @@ -454,7 +454,7 @@ jobs: - name: disable git crlf conversion run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: configure the PR in which the error message will be posted @@ -567,7 +567,7 @@ jobs: - name: disable git crlf conversion run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: configure the PR in which the error message will be posted @@ -670,7 +670,7 @@ jobs: if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'" steps: - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: publish toolstate diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 5622422d50f52..173ee170c9f58 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -99,7 +99,7 @@ x--expand-yaml-anchors--remove: run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 @@ -703,7 +703,7 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust' steps: - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 From c20bb1d59f17c6329ea922c4bb2ccec5d46e7e00 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Thu, 14 Apr 2022 23:42:15 +0300 Subject: [PATCH 23/24] Update issue-92893.stderr --- compiler/rustc_middle/src/middle/region.rs | 9 +++------ .../rustc_mir_build/src/build/matches/mod.rs | 10 ++++++---- .../src/check/generator_interior.rs | 2 +- src/test/ui/mir/issue-92893.rs | 7 +++++++ src/test/ui/mir/issue-92893.stderr | 20 +++++++++++++++++++ .../src/loops/needless_range_loop.rs | 4 ++-- src/tools/clippy/clippy_lints/src/shadow.rs | 4 ++-- 7 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/mir/issue-92893.rs create mode 100644 src/test/ui/mir/issue-92893.stderr diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 98da20baf026b..af16e5e3fc871 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -362,12 +362,9 @@ impl ScopeTree { self.parent_map.get(&id).cloned().map(|(p, _)| p) } - /// Returns the lifetime of the local variable `var_id` - pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Scope { - self.var_map - .get(&var_id) - .cloned() - .unwrap_or_else(|| bug!("no enclosing scope for id {:?}", var_id)) + /// Returns the lifetime of the local variable `var_id`, if any. + pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Option { + self.var_map.get(&var_id).cloned() } /// Returns the scope when the temp created by `expr_id` will be cleaned up. diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 219d101aa7ccf..d45ae19752e8c 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -701,8 +701,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) }); - let region_scope = self.region_scope_tree.var_scope(var.local_id); - if schedule_drop { + // Altough there is almost always scope for given variable in corner cases + // like #92893 we might get variable with no scope. + if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) && schedule_drop{ self.schedule_drop(span, region_scope, local_id, DropKind::Storage); } Place::from(local_id) @@ -710,8 +711,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) { let local_id = self.var_local_id(var, for_guard); - let region_scope = self.region_scope_tree.var_scope(var.local_id); - self.schedule_drop(span, region_scope, local_id, DropKind::Value); + if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) { + self.schedule_drop(span, region_scope, local_id, DropKind::Value); + } } /// Visit all of the primary bindings in a patterns, that is, visit the diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index e584c9ad201f7..a4ae89ecada08 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -319,7 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { self.expr_count += 1; if let PatKind::Binding(..) = pat.kind { - let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id); + let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id).unwrap(); let ty = self.fcx.typeck_results.borrow().pat_ty(pat); self.record(ty, pat.hir_id, Some(scope), None, pat.span, false); } diff --git a/src/test/ui/mir/issue-92893.rs b/src/test/ui/mir/issue-92893.rs new file mode 100644 index 0000000000000..d2bbb4f110114 --- /dev/null +++ b/src/test/ui/mir/issue-92893.rs @@ -0,0 +1,7 @@ +struct Bug { + //~^ `let` expressions are not supported here + //~^^ `let` expressions in this position are unstable [E0658] + a: A +} + +fn main() {} diff --git a/src/test/ui/mir/issue-92893.stderr b/src/test/ui/mir/issue-92893.stderr new file mode 100644 index 0000000000000..063b5d66feb45 --- /dev/null +++ b/src/test/ui/mir/issue-92893.stderr @@ -0,0 +1,20 @@ +error: `let` expressions are not supported here + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 72e86804ed2c3..6ed141fa4a5a6 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -59,7 +59,7 @@ pub(super) fn check<'tcx>( if let Some(indexed_extent) = indexed_extent { let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id); let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id); - let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id); + let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap(); if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) { return; } @@ -262,7 +262,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { match res { Res::Local(hir_id) => { let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); - let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); + let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id).unwrap(); if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 1188258504461..1ab7f52110ce7 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -160,8 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool { let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id()); - let first_scope = scope_tree.var_scope(first); - let second_scope = scope_tree.var_scope(second); + let first_scope = scope_tree.var_scope(first).unwrap(); + let second_scope = scope_tree.var_scope(second).unwrap(); scope_tree.is_subscope_of(second_scope, first_scope) } From 5459e6637ae4cd86367927753df6e7fbe1c503e1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 14 Apr 2022 16:42:49 -0700 Subject: [PATCH 24/24] docs: Update tests chapter for Termination stabilization --- src/doc/rustc/src/tests/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md index 0e0eb85db746a..32baed9c94498 100644 --- a/src/doc/rustc/src/tests/index.md +++ b/src/doc/rustc/src/tests/index.md @@ -15,7 +15,8 @@ fn it_works() { ``` Tests "pass" if they return without an error. They "fail" if they [panic], or -return a [`Result`] with an error. +return a type such as [`Result`] that implements the [`Termination`] trait +with a non-zero value. By passing the [`--test` option] to `rustc`, the compiler will build the crate in a special mode to construct an executable that will run the tests in the @@ -304,6 +305,7 @@ Experimental support for using custom test harnesses is available on the [`libtest`]: ../../test/index.html [`main` function]: ../../reference/crates-and-source-files.html#main-functions [`Result`]: ../../std/result/index.html +[`Termination`]: ../../std/process/trait.Termination.html [`test` cfg option]: ../../reference/conditional-compilation.html#test [attribute-ignore]: ../../reference/attributes/testing.html#the-ignore-attribute [attribute-should_panic]: ../../reference/attributes/testing.html#the-should_panic-attribute