From 7874976762bc531fa6330854e35ec4db2182164d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 29 Sep 2022 17:27:03 +0900 Subject: [PATCH 001/221] Stabilize the `instruction_set` feature Signed-off-by: Yuki Okushi --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/active.rs | 2 -- compiler/rustc_feature/src/builtin_attrs.rs | 6 +---- src/test/ui/asm/issue-92378.rs | 2 +- src/test/ui/error-codes/E0778.rs | 8 ++---- src/test/ui/error-codes/E0778.stderr | 2 +- src/test/ui/error-codes/E0779.rs | 6 +---- src/test/ui/error-codes/E0779.stderr | 2 +- .../feature-gate-isa_attribute.rs | 6 ----- .../feature-gate-isa_attribute.stderr | 25 ------------------- 10 files changed, 9 insertions(+), 52 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-isa_attribute.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-isa_attribute.stderr diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 8efb7ccc1c71..4f58e42b6ace 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -185,6 +185,8 @@ declare_features! ( (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), + /// Allows `#[instruction_set(_)]` attribute. + (accepted, isa_attribute, "CURRENT_RUSTC_VERSION", Some(74727), None), /// Allows some increased flexibility in the name resolution rules, /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 71ad54291b28..e9b948bfe4da 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -426,8 +426,6 @@ declare_features! ( (incomplete, inline_const_pat, "1.58.0", Some(76001), None), /// Allows using `pointer` and `reference` in intra-doc links (active, intra_doc_pointers, "1.51.0", Some(80896), None), - /// Allows `#[instruction_set(_)]` attribute - (active, isa_attribute, "1.48.0", Some(74727), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), /// Allows `if/while p && let q = r && ...` chains. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 5ee6c9f23877..3c62bdcaadbd 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -384,6 +384,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing), ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk), ungated!(track_caller, Normal, template!(Word), WarnFollowing), + ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding), gated!( no_sanitize, Normal, template!(List: "address, memory, thread"), DuplicatesOk, @@ -445,11 +446,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute, experimental!(optimize), ), - // RFC 2867 - gated!( - instruction_set, Normal, template!(List: "set"), ErrorPreceding, - isa_attribute, experimental!(instruction_set) - ), gated!( ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) diff --git a/src/test/ui/asm/issue-92378.rs b/src/test/ui/asm/issue-92378.rs index 6e3c26e98c3f..809b0d1555ae 100644 --- a/src/test/ui/asm/issue-92378.rs +++ b/src/test/ui/asm/issue-92378.rs @@ -3,7 +3,7 @@ // needs-asm-support // build-pass -#![feature(no_core, lang_items, rustc_attrs, isa_attribute)] +#![feature(no_core, lang_items, rustc_attrs)] #![no_core] #![crate_type = "rlib"] diff --git a/src/test/ui/error-codes/E0778.rs b/src/test/ui/error-codes/E0778.rs index 60e5c2598f1e..74653886d415 100644 --- a/src/test/ui/error-codes/E0778.rs +++ b/src/test/ui/error-codes/E0778.rs @@ -1,8 +1,4 @@ -#![feature(isa_attribute)] - #[instruction_set()] //~ ERROR -fn no_isa_defined() { -} +fn no_isa_defined() {} -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0778.stderr b/src/test/ui/error-codes/E0778.stderr index 6ecae7924237..42647e5c6a1b 100644 --- a/src/test/ui/error-codes/E0778.stderr +++ b/src/test/ui/error-codes/E0778.stderr @@ -1,5 +1,5 @@ error[E0778]: `#[instruction_set]` requires an argument - --> $DIR/E0778.rs:3:1 + --> $DIR/E0778.rs:1:1 | LL | #[instruction_set()] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/error-codes/E0779.rs b/src/test/ui/error-codes/E0779.rs index 1b4dbce20360..c32dae12c9cb 100644 --- a/src/test/ui/error-codes/E0779.rs +++ b/src/test/ui/error-codes/E0779.rs @@ -1,6 +1,2 @@ -#![feature(isa_attribute)] - #[instruction_set(arm::magic)] //~ ERROR -fn main() { - -} +fn main() {} diff --git a/src/test/ui/error-codes/E0779.stderr b/src/test/ui/error-codes/E0779.stderr index da787260d4f6..7c6a119a0961 100644 --- a/src/test/ui/error-codes/E0779.stderr +++ b/src/test/ui/error-codes/E0779.stderr @@ -1,5 +1,5 @@ error[E0779]: invalid instruction set specified - --> $DIR/E0779.rs:3:1 + --> $DIR/E0779.rs:1:1 | LL | #[instruction_set(arm::magic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-isa_attribute.rs b/src/test/ui/feature-gates/feature-gate-isa_attribute.rs deleted file mode 100644 index cb02a0955e91..000000000000 --- a/src/test/ui/feature-gates/feature-gate-isa_attribute.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[instruction_set] -//~^ ERROR the `#[instruction_set]` attribute is an experimental feature [E0658] -//~| ERROR malformed `instruction_set` attribute input -//~| ERROR must specify an instruction set [E0778] -fn main() { -} diff --git a/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr b/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr deleted file mode 100644 index 2a95a80ca617..000000000000 --- a/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: malformed `instruction_set` attribute input - --> $DIR/feature-gate-isa_attribute.rs:1:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` - -error[E0658]: the `#[instruction_set]` attribute is an experimental feature - --> $DIR/feature-gate-isa_attribute.rs:1:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #74727 for more information - = help: add `#![feature(isa_attribute)]` to the crate attributes to enable - -error[E0778]: must specify an instruction set - --> $DIR/feature-gate-isa_attribute.rs:1:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0658, E0778. -For more information about an error, try `rustc --explain E0658`. From c87567cbfacae2f55983c2749b147391061530a0 Mon Sep 17 00:00:00 2001 From: b4den Date: Thu, 20 Oct 2022 15:44:25 +0100 Subject: [PATCH 002/221] Add context to compiler error message Changed `creates a temporary which is freed while still in use` to `creates a temporary value which is freed while still in use` --- compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 314119b6e814..d632dd843fab 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1549,7 +1549,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let mut err = self.temporary_value_borrowed_for_too_long(proper_span); - err.span_label(proper_span, "creates a temporary which is freed while still in use"); + err.span_label(proper_span, "creates a temporary value which is freed while still in use"); err.span_label(drop_span, "temporary value is freed at the end of this statement"); match explanation { From 6cb65646b83cc7d79d0b88453cc20ce1a475d693 Mon Sep 17 00:00:00 2001 From: b4den Date: Thu, 20 Oct 2022 16:43:27 +0100 Subject: [PATCH 003/221] Update tests to match error message changes --- library/core/src/pin.rs | 2 +- .../borrowck-borrowed-uniq-rvalue-2.stderr | 2 +- .../borrowck-borrowed-uniq-rvalue.stderr | 2 +- src/test/ui/borrowck/issue-11493.stderr | 2 +- src/test/ui/borrowck/issue-17545.stderr | 2 +- src/test/ui/borrowck/issue-36082.fixed | 2 +- src/test/ui/borrowck/issue-36082.rs | 2 +- src/test/ui/borrowck/issue-36082.stderr | 2 +- src/test/ui/cleanup-rvalue-scopes-cf.stderr | 14 +++---- .../const-eval-intrinsic-promotion.stderr | 2 +- .../dont_promote_unstable_const_fn.stderr | 6 +-- ...omote_unstable_const_fn_cross_crate.stderr | 4 +- .../const-eval/promoted_const_fn_fail.stderr | 2 +- ...omoted_const_fn_fail_deny_const_err.stderr | 2 +- .../const-eval/promoted_raw_ptr_ops.stderr | 8 ++-- .../transmute-const-promotion.stderr | 2 +- .../consts/const-eval/union_promotion.stderr | 2 +- .../ui/consts/const-int-conversion.stderr | 14 +++---- .../ui/consts/const-int-overflowing.stderr | 6 +-- src/test/ui/consts/const-int-rotate.stderr | 4 +- src/test/ui/consts/const-int-sign.stderr | 4 +- src/test/ui/consts/const-int-wrapping.stderr | 10 ++--- .../const-mut-refs/mut_ref_in_final.stderr | 10 ++--- src/test/ui/consts/const-ptr-nonnull.stderr | 4 +- src/test/ui/consts/const-ptr-unique.stderr | 2 +- .../control-flow/interior-mutability.stderr | 6 +-- src/test/ui/consts/issue-54224.stderr | 4 +- .../ui/consts/min_const_fn/promotion.stderr | 12 +++--- src/test/ui/consts/promote-not.stderr | 40 +++++++++---------- src/test/ui/consts/promote_const_let.stderr | 2 +- src/test/ui/consts/promoted-const-drop.stderr | 4 +- src/test/ui/consts/qualif-union.stderr | 10 ++--- .../ui/generator/auto-trait-regions.stderr | 4 +- .../bugs/hrtb-implied-1.stderr | 2 +- src/test/ui/issues/issue-47184.stderr | 2 +- src/test/ui/issues/issue-52049.stderr | 2 +- .../lifetimes/borrowck-let-suggestion.stderr | 2 +- .../ui/nll/borrowed-temporary-error.stderr | 2 +- .../issue-57265-return-type-wf-check.stderr | 2 +- .../ui/nll/user-annotations/patterns.stderr | 6 +-- ...fetime_errors_on_promotion_misusage.stderr | 4 +- ...egions-free-region-ordering-caller1.stderr | 2 +- .../regions-var-type-out-of-scope.stderr | 2 +- .../span/borrowck-let-suggestion-suffixes.rs | 6 +-- .../borrowck-let-suggestion-suffixes.stderr | 6 +-- .../ui/span/borrowck-ref-into-rvalue.stderr | 2 +- src/test/ui/span/issue-15480.stderr | 2 +- ...ions-close-over-borrowed-ref-in-obj.stderr | 2 +- src/test/ui/span/slice-borrow.stderr | 2 +- src/test/ui/static/static-drop-scope.stderr | 4 +- .../ui/static/static-reference-to-fn-2.stderr | 6 +-- src/test/ui/static/static-region-bound.stderr | 2 +- src/test/ui/statics/issue-44373.stderr | 2 +- 53 files changed, 127 insertions(+), 127 deletions(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index ccef35b45325..f0258640e2ae 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1059,7 +1059,7 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// 8 | let x: Pin<&mut Foo> = { /// | - borrow later stored here /// 9 | let x: Pin<&mut Foo> = pin!(Foo { /* … */ }); -/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use +/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use /// 10 | x /// 11 | }; // <- Foo is dropped /// | - temporary value is freed at the end of this statement diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr index a6af129bf39f..4eeec09b9104 100644 --- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr +++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x = defer(&vec!["Goodbye", "world!"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | x.x[0]; | ------ borrow later used here | diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr index dea8ac90bec2..c62d5f903c8d 100644 --- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr +++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | buggy_map.insert(42, &*Box::new(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | buggy_map.insert(43, &*tmp); | --------------------------- borrow later used here diff --git a/src/test/ui/borrowck/issue-11493.stderr b/src/test/ui/borrowck/issue-11493.stderr index a5d1f2816f1c..2720b09b0fc5 100644 --- a/src/test/ui/borrowck/issue-11493.stderr +++ b/src/test/ui/borrowck/issue-11493.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let y = x.as_ref().unwrap_or(&id(5)); | ^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | let _ = &y; | -- borrow later used here | diff --git a/src/test/ui/borrowck/issue-17545.stderr b/src/test/ui/borrowck/issue-17545.stderr index 79a1e09bd7cc..3ae7e64d202b 100644 --- a/src/test/ui/borrowck/issue-17545.stderr +++ b/src/test/ui/borrowck/issue-17545.stderr @@ -5,7 +5,7 @@ LL | pub fn foo<'a, F: Fn(&'a ())>(bar: F) { | -- lifetime `'a` defined here LL | / bar.call(( LL | | &id(()), - | | ^^^^^^ creates a temporary which is freed while still in use + | | ^^^^^^ creates a temporary value which is freed while still in use LL | | )); | | -- temporary value is freed at the end of this statement | |______| diff --git a/src/test/ui/borrowck/issue-36082.fixed b/src/test/ui/borrowck/issue-36082.fixed index 8640ca7a5096..8fc963a85664 100644 --- a/src/test/ui/borrowck/issue-36082.fixed +++ b/src/test/ui/borrowck/issue-36082.fixed @@ -10,7 +10,7 @@ fn main() { let val: &_ = binding.0; //~^ ERROR temporary value dropped while borrowed [E0716] //~| NOTE temporary value is freed at the end of this statement - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| HELP consider using a `let` binding to create a longer lived value println!("{}", val); //~^ borrow later used here diff --git a/src/test/ui/borrowck/issue-36082.rs b/src/test/ui/borrowck/issue-36082.rs index 877d372fb848..20f66b4d45de 100644 --- a/src/test/ui/borrowck/issue-36082.rs +++ b/src/test/ui/borrowck/issue-36082.rs @@ -9,7 +9,7 @@ fn main() { let val: &_ = x.borrow().0; //~^ ERROR temporary value dropped while borrowed [E0716] //~| NOTE temporary value is freed at the end of this statement - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| HELP consider using a `let` binding to create a longer lived value println!("{}", val); //~^ borrow later used here diff --git a/src/test/ui/borrowck/issue-36082.stderr b/src/test/ui/borrowck/issue-36082.stderr index 4bd586db1cdc..a6357f8182fc 100644 --- a/src/test/ui/borrowck/issue-36082.stderr +++ b/src/test/ui/borrowck/issue-36082.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let val: &_ = x.borrow().0; | ^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | println!("{}", val); | --- borrow later used here diff --git a/src/test/ui/cleanup-rvalue-scopes-cf.stderr b/src/test/ui/cleanup-rvalue-scopes-cf.stderr index 40f14c389842..425cd75141ce 100644 --- a/src/test/ui/cleanup-rvalue-scopes-cf.stderr +++ b/src/test/ui/cleanup-rvalue-scopes-cf.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x1 = arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -21,7 +21,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x2 = AddFlags(1).get(); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -38,7 +38,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x3 = &*arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -55,7 +55,7 @@ error[E0716]: temporary value dropped while borrowed LL | let ref x4 = *arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -72,7 +72,7 @@ error[E0716]: temporary value dropped while borrowed LL | let &ref x5 = arg(&AddFlags(1)); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -89,7 +89,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x6 = AddFlags(1).get(); | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here @@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed LL | let StackBox { f: x7 } = StackBox { f: AddFlags(1).get() }; | ^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | LL | (x1, x2, x3, x4, x5, x6, x7); | -- borrow later used here diff --git a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr index 78143042ece7..ed6a6ee6e0fd 100644 --- a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr +++ b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let x: &'static usize = | -------------- type annotation requires that borrow lasts for `'static` LL | &std::intrinsics::size_of::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr index 69e3ca716a90..2e697b219c5a 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -10,7 +10,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:17:28 | LL | let _: &'static u32 = &foo(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } @@ -20,7 +20,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:21:28 | LL | let _: &'static u32 = &meh(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -31,7 +31,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:22:26 | LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr index 129f06151074..aa742d784e03 100644 --- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr +++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28 | LL | let _: &'static u32 = &foo(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let _x: &'static u32 = &foo(); @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29 | LL | let _x: &'static u32 = &foo(); - | ------------ ^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr index 596fa090d976..2d4e7c83d3e4 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_fn_fail.rs:17:27 | LL | let x: &'static u8 = &(bar() + 1); - | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr index 63dc43a41a8f..9ebae3a18a32 100644 --- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr +++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_fn_fail_deny_const_err.rs:18:27 | LL | let x: &'static u8 = &(bar() + 1); - | ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr index 8ac60da38634..01fcf2ec2134 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:2:29 | LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:4:30 | LL | let y: &'static usize = &(&1 as *const i32 as usize + 1); - | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:6:28 | LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_raw_ptr_ops.rs:8:29 | LL | let a: &'static bool = &(main as fn() == main as fn()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr index 15b9b56ea660..434a957f6484 100644 --- a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr +++ b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/transmute-const-promotion.rs:4:37 | LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) }; - | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr index 70808c520d3f..42f17de20034 100644 --- a/src/test/ui/consts/const-eval/union_promotion.stderr +++ b/src/test/ui/consts/const-eval/union_promotion.stderr @@ -7,7 +7,7 @@ LL | let x: &'static bool = &unsafe { | | type annotation requires that borrow lasts for `'static` LL | | Foo { a: &1 }.b == Foo { a: &2 }.b LL | | }; - | |_____^ creates a temporary which is freed while still in use + | |_____^ creates a temporary value which is freed while still in use LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/consts/const-int-conversion.stderr b/src/test/ui/consts/const-int-conversion.stderr index 61162a792262..5dd757e3f5ee 100644 --- a/src/test/ui/consts/const-int-conversion.stderr +++ b/src/test/ui/consts/const-int-conversion.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:2:28 | LL | let x: &'static i32 = &(5_i32.reverse_bits()); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:4:28 | LL | let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78])); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:6:28 | LL | let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78])); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:8:28 | LL | let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]))); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:10:29 | LL | let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:12:29 | LL | let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -68,7 +68,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-conversion.rs:14:29 | LL | let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-overflowing.stderr b/src/test/ui/consts/const-int-overflowing.stderr index 56c7f7f092d6..7d3689e6ec7d 100644 --- a/src/test/ui/consts/const-int-overflowing.stderr +++ b/src/test/ui/consts/const-int-overflowing.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-overflowing.rs:2:36 | LL | let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); - | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-overflowing.rs:4:36 | LL | let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); - | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-overflowing.rs:6:36 | LL | let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); - | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-rotate.stderr b/src/test/ui/consts/const-int-rotate.stderr index ed265804bbc6..039da1c31c57 100644 --- a/src/test/ui/consts/const-int-rotate.stderr +++ b/src/test/ui/consts/const-int-rotate.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-rotate.rs:2:28 | LL | let x: &'static i32 = &(5_i32.rotate_left(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-rotate.rs:4:28 | LL | let y: &'static i32 = &(5_i32.rotate_right(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-sign.stderr b/src/test/ui/consts/const-int-sign.stderr index 5f8fd4141804..fc23d9d2b294 100644 --- a/src/test/ui/consts/const-int-sign.stderr +++ b/src/test/ui/consts/const-int-sign.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-sign.rs:2:29 | LL | let x: &'static bool = &(5_i32.is_negative()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-sign.rs:4:29 | LL | let y: &'static bool = &(5_i32.is_positive()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-int-wrapping.stderr b/src/test/ui/consts/const-int-wrapping.stderr index 5174b72659cd..1342fadc4055 100644 --- a/src/test/ui/consts/const-int-wrapping.stderr +++ b/src/test/ui/consts/const-int-wrapping.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:2:28 | LL | let x: &'static i32 = &(5_i32.wrapping_add(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:4:28 | LL | let y: &'static i32 = &(5_i32.wrapping_sub(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:6:28 | LL | let z: &'static i32 = &(5_i32.wrapping_mul(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:8:28 | LL | let a: &'static i32 = &(5_i32.wrapping_shl(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-int-wrapping.rs:10:28 | LL | let b: &'static i32 = &(5_i32.wrapping_shr(3)); - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr index 3a9ce79f10ef..78c58b5ab092 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -11,7 +11,7 @@ LL | const B3: Option<&mut i32> = Some(&mut 42); | ----------^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -21,7 +21,7 @@ LL | const B4: Option<&mut i32> = helper(&mut 42); | ------------^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -31,7 +31,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -41,7 +41,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -51,7 +51,7 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error: aborting due to 6 previous errors diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr index 26946fb99024..dbcb0c86052e 100644 --- a/src/test/ui/consts/const-ptr-nonnull.stderr +++ b/src/test/ui/consts/const-ptr-nonnull.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-ptr-nonnull.rs:4:37 | LL | let x: &'static NonNull = &(NonNull::dangling()); - | --------------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | --------------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-ptr-nonnull.rs:9:37 | LL | let x: &'static NonNull = &(non_null.cast()); - | --------------------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | --------------------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr index 3644cf4cec7d..83448c3e8d87 100644 --- a/src/test/ui/consts/const-ptr-unique.stderr +++ b/src/test/ui/consts/const-ptr-unique.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/const-ptr-unique.rs:8:33 | LL | let x: &'static *mut u32 = &(unique.as_ptr()); - | ----------------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ----------------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | diff --git a/src/test/ui/consts/control-flow/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr index 4f9c7d34c35f..db2ffb91b988 100644 --- a/src/test/ui/consts/control-flow/interior-mutability.stderr +++ b/src/test/ui/consts/control-flow/interior-mutability.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/interior-mutability.rs:40:26 | LL | let x: &'static _ = &X; - | ---------- ^ creates a temporary which is freed while still in use + | ---------- ^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/interior-mutability.rs:41:26 | LL | let y: &'static _ = &Y; - | ---------- ^ creates a temporary which is freed while still in use + | ---------- ^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let z: &'static _ = &Z; @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/interior-mutability.rs:42:26 | LL | let z: &'static _ = &Z; - | ---------- ^ creates a temporary which is freed while still in use + | ---------- ^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/issue-54224.stderr b/src/test/ui/consts/issue-54224.stderr index 8dcb4daca3b7..55fe55759df5 100644 --- a/src/test/ui/consts/issue-54224.stderr +++ b/src/test/ui/consts/issue-54224.stderr @@ -5,7 +5,7 @@ LL | const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); | ------^^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -15,7 +15,7 @@ LL | pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]); | ---------------^^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/min_const_fn/promotion.stderr b/src/test/ui/consts/min_const_fn/promotion.stderr index 550423c2d933..0b8dc0ce0e90 100644 --- a/src/test/ui/consts/min_const_fn/promotion.stderr +++ b/src/test/ui/consts/min_const_fn/promotion.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:11:27 | LL | let x: &'static () = &foo1(); - | ----------- ^^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:12:28 | LL | let y: &'static i32 = &foo2(42); - | ------------ ^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:13:28 | LL | let z: &'static i32 = &foo3(); - | ------------ ^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:14:34 | LL | let a: &'static Cell = &foo4(); - | ------------------ ^^^^^^ creates a temporary which is freed while still in use + | ------------------ ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:15:42 | LL | let a: &'static Option> = &foo5(); - | -------------------------- ^^^^^^ creates a temporary which is freed while still in use + | -------------------------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let a: &'static Option> = &foo6(); @@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promotion.rs:16:42 | LL | let a: &'static Option> = &foo6(); - | -------------------------- ^^^^^^ creates a temporary which is freed while still in use + | -------------------------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/promote-not.stderr b/src/test/ui/consts/promote-not.stderr index 0d0b0f9c689b..b93358e8dcce 100644 --- a/src/test/ui/consts/promote-not.stderr +++ b/src/test/ui/consts/promote-not.stderr @@ -5,14 +5,14 @@ LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); | ----------^^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:11:18 | LL | let x = &mut [1,2,3]; - | ^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^ creates a temporary value which is freed while still in use LL | x | - using this value as a static requires that borrow lasts for `'static` LL | }; @@ -22,7 +22,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:20:32 | LL | let _x: &'static () = &foo(); - | ----------- ^^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } @@ -32,7 +32,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:28:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } @@ -42,7 +42,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:33:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | }; @@ -52,7 +52,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:39:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).1; - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | }; @@ -62,7 +62,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:46:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).0; - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -73,7 +73,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:47:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).1; - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -84,7 +84,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:50:29 | LL | let _val: &'static _ = &(1/0); - | ---------- ^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -95,7 +95,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:51:29 | LL | let _val: &'static _ = &(1/(1-1)); - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:52:29 | LL | let _val: &'static _ = &(1%0); - | ---------- ^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -117,7 +117,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:53:29 | LL | let _val: &'static _ = &(1%(1-1)); - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -128,7 +128,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:54:29 | LL | let _val: &'static _ = &([1,2,3][4]+1); - | ---------- ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -139,7 +139,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:57:29 | LL | let _val: &'static _ = &TEST_DROP; - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -150,7 +150,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:59:29 | LL | let _val: &'static _ = &&TEST_DROP; - | ---------- ^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -161,7 +161,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:59:30 | LL | let _val: &'static _ = &&TEST_DROP; - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -172,7 +172,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:62:29 | LL | let _val: &'static _ = &(&TEST_DROP,); - | ---------- ^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -183,7 +183,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:62:31 | LL | let _val: &'static _ = &(&TEST_DROP,); - | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -194,7 +194,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:65:29 | LL | let _val: &'static _ = &[&TEST_DROP; 1]; - | ---------- ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ---------- ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -207,7 +207,7 @@ error[E0716]: temporary value dropped while borrowed LL | let _val: &'static _ = &[&TEST_DROP; 1]; | ---------- ^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error: aborting due to 20 previous errors diff --git a/src/test/ui/consts/promote_const_let.stderr b/src/test/ui/consts/promote_const_let.stderr index c47d297c9040..975a235a6495 100644 --- a/src/test/ui/consts/promote_const_let.stderr +++ b/src/test/ui/consts/promote_const_let.stderr @@ -19,7 +19,7 @@ LL | let x: &'static u32 = &{ LL | | let y = 42; LL | | y LL | | }; - | |_____^ creates a temporary which is freed while still in use + | |_____^ creates a temporary value which is freed while still in use LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/consts/promoted-const-drop.stderr b/src/test/ui/consts/promoted-const-drop.stderr index 184ba0ea3b37..4802834173fc 100644 --- a/src/test/ui/consts/promoted-const-drop.stderr +++ b/src/test/ui/consts/promoted-const-drop.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted-const-drop.rs:13:26 | LL | let _: &'static A = &A(); - | ---------- ^^^ creates a temporary which is freed while still in use + | ---------- ^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let _: &'static [A] = &[C]; @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/promoted-const-drop.rs:14:28 | LL | let _: &'static [A] = &[C]; - | ------------ ^^^ creates a temporary which is freed while still in use + | ------------ ^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/consts/qualif-union.stderr b/src/test/ui/consts/qualif-union.stderr index 8ec68ada048a..d847cf88f505 100644 --- a/src/test/ui/consts/qualif-union.stderr +++ b/src/test/ui/consts/qualif-union.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:28:26 | LL | let _: &'static _ = &C1; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:29:26 | LL | let _: &'static _ = &C2; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:30:26 | LL | let _: &'static _ = &C3; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` ... @@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:31:26 | LL | let _: &'static _ = &C4; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | let _: &'static _ = &C5; @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/qualif-union.rs:32:26 | LL | let _: &'static _ = &C5; - | ---------- ^^ creates a temporary which is freed while still in use + | ---------- ^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 23324af6171a..0b1f34aeb96b 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | assert_foo(a); | - borrow later used here @@ -17,7 +17,7 @@ error[E0716]: temporary value dropped while borrowed LL | let a = A(&mut true, &mut true, No); | ^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | assert_foo(a); | - borrow later used here diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr index 414999881d47..1c9abc4e837c 100644 --- a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/hrtb-implied-1.rs:31:22 | LL | let slice = &mut (); - | ^^ creates a temporary which is freed while still in use + | ^^ creates a temporary value which is freed while still in use ... LL | print_items::>(windows); | -------------------------------------- argument requires that borrow lasts for `'static` diff --git a/src/test/ui/issues/issue-47184.stderr b/src/test/ui/issues/issue-47184.stderr index f97713b4ac43..c2c7df7a333a 100644 --- a/src/test/ui/issues/issue-47184.stderr +++ b/src/test/ui/issues/issue-47184.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let _vec: Vec<&'static String> = vec![&String::new()]; | -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-52049.stderr b/src/test/ui/issues/issue-52049.stderr index 55929d85da45..b25dbd1cb8b1 100644 --- a/src/test/ui/issues/issue-52049.stderr +++ b/src/test/ui/issues/issue-52049.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | foo(&unpromotable(5u32)); | -----^^^^^^^^^^^^^^^^^^- | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | argument requires that borrow lasts for `'static` LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index bbf04c98436e..987b051b1110 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let mut x = vec![1].iter(); | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | LL | x.use_mut(); | ----------- borrow later used here diff --git a/src/test/ui/nll/borrowed-temporary-error.stderr b/src/test/ui/nll/borrowed-temporary-error.stderr index 2c6bd92641f6..89781d96fab2 100644 --- a/src/test/ui/nll/borrowed-temporary-error.stderr +++ b/src/test/ui/nll/borrowed-temporary-error.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/borrowed-temporary-error.rs:8:10 | LL | &(v,) - | ^^^^ creates a temporary which is freed while still in use + | ^^^^ creates a temporary value which is freed while still in use LL | LL | }); | - temporary value is freed at the end of this statement diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr index 20add62b91dd..bb45575fa64c 100644 --- a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr +++ b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let (_, z) = foo(&"hello".to_string()); | -----^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | argument requires that borrow lasts for `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr index 60d6e6db3632..de6f8f80fe25 100644 --- a/src/test/ui/nll/user-annotations/patterns.stderr +++ b/src/test/ui/nll/user-annotations/patterns.stderr @@ -76,7 +76,7 @@ error[E0716]: temporary value dropped while borrowed LL | let _: Vec<&'static String> = vec![&String::new()]; | -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -85,7 +85,7 @@ error[E0716]: temporary value dropped while borrowed LL | let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44); | ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed @@ -94,7 +94,7 @@ error[E0716]: temporary value dropped while borrowed LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44); | ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` error[E0597]: `x` does not live long enough diff --git a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr index 4971263af08a..fc1be052fb79 100644 --- a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr +++ b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | let phantom_pinned = identity(pin!(PhantomPinned)); | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | LL | stuff(phantom_pinned) | -------------- borrow later used here @@ -18,7 +18,7 @@ error[E0716]: temporary value dropped while borrowed LL | let phantom_pinned = { | -------------- borrow later stored here LL | let phantom_pinned = pin!(PhantomPinned); - | ^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use ... LL | }; | - temporary value is freed at the end of this statement diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr index 8042b1740b14..8ef7e22536bf 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr @@ -5,7 +5,7 @@ LL | fn call1<'a>(x: &'a usize) { | -- lifetime `'a` defined here ... LL | let z: &'a & usize = &(&y); - | ----------- ^^^^ creates a temporary which is freed while still in use + | ----------- ^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'a` ... diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.stderr b/src/test/ui/regions/regions-var-type-out-of-scope.stderr index 476e82f046f0..c32bbe0ee1fb 100644 --- a/src/test/ui/regions/regions-var-type-out-of-scope.stderr +++ b/src/test/ui/regions/regions-var-type-out-of-scope.stderr @@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed LL | x = &id(3); | ^^^^^- temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use LL | assert_eq!(*x, 3); | ----------------- borrow later used here | diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs index 6240f103c99b..18abfb5c3fbe 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs @@ -18,7 +18,7 @@ fn f() { v3.push(&id('x')); // statement 6 //~^ ERROR temporary value dropped while borrowed - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| NOTE temporary value is freed at the end of this statement //~| HELP consider using a `let` binding to create a longer lived value @@ -28,7 +28,7 @@ fn f() { v4.push(&id('y')); //~^ ERROR temporary value dropped while borrowed - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| NOTE temporary value is freed at the end of this statement //~| NOTE consider using a `let` binding to create a longer lived value v4.use_ref(); @@ -39,7 +39,7 @@ fn f() { v5.push(&id('z')); //~^ ERROR temporary value dropped while borrowed - //~| NOTE creates a temporary which is freed while still in use + //~| NOTE creates a temporary value which is freed while still in use //~| NOTE temporary value is freed at the end of this statement //~| HELP consider using a `let` binding to create a longer lived value diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index a236dab3ae56..2dc29a78d204 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -16,7 +16,7 @@ error[E0716]: temporary value dropped while borrowed LL | v3.push(&id('x')); // statement 6 | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); | -- borrow later used here @@ -33,7 +33,7 @@ error[E0716]: temporary value dropped while borrowed LL | v4.push(&id('y')); | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | v4.use_ref(); | ------------ borrow later used here @@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed LL | v5.push(&id('z')); | ^^^^^^^ - temporary value is freed at the end of this statement | | - | creates a temporary which is freed while still in use + | creates a temporary value which is freed while still in use ... LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); | -- borrow later used here diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr index cb5289d24b4f..25e344fedfb2 100644 --- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr +++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/borrowck-ref-into-rvalue.rs:4:11 | LL | match Some("Hello".to_string()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use ... LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr index 460ad9ac7444..d9cce2254dd9 100644 --- a/src/test/ui/span/issue-15480.stderr +++ b/src/test/ui/span/issue-15480.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/issue-15480.rs:6:10 | LL | &id(3) - | ^^^^^ creates a temporary which is freed while still in use + | ^^^^^ creates a temporary value which is freed while still in use LL | ]; | - temporary value is freed at the end of this statement ... diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index ba0c45acf237..81e858fa0ce0 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:12:27 | LL | let ss: &isize = &id(1); - | ^^^^^ creates a temporary which is freed while still in use + | ^^^^^ creates a temporary value which is freed while still in use ... LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index 27df25be3fa0..b70bf69d688a 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/slice-borrow.rs:6:28 | LL | let x: &[isize] = &vec![1, 2, 3, 4, 5]; - | ^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use ... LL | } | - temporary value is freed at the end of this statement diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index 112bfc003048..cedcb7367949 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -13,7 +13,7 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | ------^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a static requires that borrow lasts for `'static` error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time @@ -31,7 +31,7 @@ LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | ------^^^^^^^^- | | | | | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time diff --git a/src/test/ui/static/static-reference-to-fn-2.stderr b/src/test/ui/static/static-reference-to-fn-2.stderr index ff15884bd445..133d8ec2e1e5 100644 --- a/src/test/ui/static/static-reference-to-fn-2.stderr +++ b/src/test/ui/static/static-reference-to-fn-2.stderr @@ -6,7 +6,7 @@ LL | fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { LL | self_.statefn = &id(state2 as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | assignment requires that borrow lasts for `'1` error[E0716]: temporary value dropped while borrowed @@ -17,7 +17,7 @@ LL | fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { LL | self_.statefn = &id(state3 as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | assignment requires that borrow lasts for `'1` error[E0716]: temporary value dropped while borrowed @@ -28,7 +28,7 @@ LL | fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { LL | self_.statefn = &id(finished as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | - | | creates a temporary which is freed while still in use + | | creates a temporary value which is freed while still in use | assignment requires that borrow lasts for `'1` error[E0515]: cannot return value referencing temporary value diff --git a/src/test/ui/static/static-region-bound.stderr b/src/test/ui/static/static-region-bound.stderr index 15261259ed41..1a607e3c014a 100644 --- a/src/test/ui/static/static-region-bound.stderr +++ b/src/test/ui/static/static-region-bound.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/static-region-bound.rs:10:14 | LL | let x = &id(3); - | ^^^^^ creates a temporary which is freed while still in use + | ^^^^^ creates a temporary value which is freed while still in use LL | f(x); | ---- argument requires that borrow lasts for `'static` LL | } diff --git a/src/test/ui/statics/issue-44373.stderr b/src/test/ui/statics/issue-44373.stderr index 6f92fbb1eb68..2d29dec888e8 100644 --- a/src/test/ui/statics/issue-44373.stderr +++ b/src/test/ui/statics/issue-44373.stderr @@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/issue-44373.rs:4:42 | LL | let _val: &'static [&'static u32] = &[&FOO]; - | ----------------------- ^^^^^^ creates a temporary which is freed while still in use + | ----------------------- ^^^^^^ creates a temporary value which is freed while still in use | | | type annotation requires that borrow lasts for `'static` LL | } From 6d455296fde6ff0d5154d39513259a60eb73f302 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 25 Oct 2022 20:47:19 +0800 Subject: [PATCH 004/221] Fix #103451, find_width_of_character_at_span return width with 1 when reaching end --- compiler/rustc_span/src/source_map.rs | 8 ++---- compiler/rustc_span/src/source_map/tests.rs | 11 +++---- src/test/ui/parser/issue-103451.rs | 5 ++++ src/test/ui/parser/issue-103451.stderr | 32 +++++++++++++++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/parser/issue-103451.rs create mode 100644 src/test/ui/parser/issue-103451.stderr diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f9566eeee946..3baa2e03cbad 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -855,7 +855,8 @@ impl SourceMap { /// Returns a new span representing the next character after the end-point of this span. /// Special cases: /// - if span is a dummy one, returns the same span - /// - if next_point reached the end of source, return span with lo = hi + /// - if next_point reached the end of source, return a span exceeding the end of source, + /// which means sm.span_to_snippet(next_point) will get `Err` /// - respect multi-byte characters pub fn next_point(&self, sp: Span) -> Span { if sp.is_dummy() { @@ -864,9 +865,6 @@ impl SourceMap { let start_of_next_point = sp.hi().0; let width = self.find_width_of_character_at_span(sp, true); - if width == 0 { - return Span::new(sp.hi(), sp.hi(), sp.ctxt(), None); - } // If the width is 1, then the next span should only contain the next char besides current ending. // However, in the case of a multibyte character, where the width != 1, the next span should // span multiple bytes to include the whole character. @@ -938,7 +936,7 @@ impl SourceMap { // Ensure indexes are also not malformed. if start_index > end_index || end_index > source_len - 1 { debug!("find_width_of_character_at_span: source indexes are malformed"); - return 0; + return 1; } let src = local_begin.sf.external_src.borrow(); diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 1fd81018fa05..3cab59e8dbe6 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -511,16 +511,17 @@ fn test_next_point() { assert_eq!(span.lo().0, 4); assert_eq!(span.hi().0, 5); - // A non-empty span at the last byte should advance to create an empty - // span pointing at the end of the file. + // Reaching to the end of file, return a span that will get error with `span_to_snippet` let span = Span::with_root_ctxt(BytePos(4), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); - assert_eq!(span.hi().0, 5); + assert_eq!(span.hi().0, 6); + assert!(sm.span_to_snippet(span).is_err()); - // Empty span pointing just past the last byte. + // Reaching to the end of file, return a span that will get error with `span_to_snippet` let span = Span::with_root_ctxt(BytePos(5), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); - assert_eq!(span.hi().0, 5); + assert_eq!(span.hi().0, 6); + assert!(sm.span_to_snippet(span).is_err()); } diff --git a/src/test/ui/parser/issue-103451.rs b/src/test/ui/parser/issue-103451.rs new file mode 100644 index 000000000000..1fdb00148815 --- /dev/null +++ b/src/test/ui/parser/issue-103451.rs @@ -0,0 +1,5 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected value, found struct `R` +struct R { } +struct S { + x: [u8; R diff --git a/src/test/ui/parser/issue-103451.stderr b/src/test/ui/parser/issue-103451.stderr new file mode 100644 index 000000000000..eb3c92fb43d9 --- /dev/null +++ b/src/test/ui/parser/issue-103451.stderr @@ -0,0 +1,32 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error[E0423]: expected value, found struct `R` + --> $DIR/issue-103451.rs:5:13 + | +LL | struct R { } + | ------------ `R` defined here +LL | struct S { +LL | x: [u8; R + | ^ help: use struct literal syntax instead: `R {}` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. From 9e36fd926c80dc096d580b762658f07cb976da86 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Wed, 26 Oct 2022 11:58:33 +0200 Subject: [PATCH 005/221] stabilize `int_log` --- library/core/benches/lib.rs | 1 - library/core/src/num/int_macros.rs | 29 +++++++++++++----------- library/core/src/num/nonzero.rs | 8 +++---- library/core/src/num/uint_macros.rs | 29 +++++++++++++----------- library/core/tests/lib.rs | 1 - src/tools/miri/src/lib.rs | 1 - src/tools/miri/tests/pass/integer-ops.rs | 1 - 7 files changed, 36 insertions(+), 34 deletions(-) diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index 1e462e3fc3f8..5beb9a775900 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -1,7 +1,6 @@ // wasm32 does not support benches (no time). #![cfg(not(target_arch = "wasm32"))] #![feature(flt2dec)] -#![feature(int_log)] #![feature(test)] #![feature(trusted_random_access)] #![feature(iter_array_chunks)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 81f050cb283d..404ddff4f9da 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2271,15 +2271,16 @@ macro_rules! int_impl { /// # Panics /// /// This function will panic if `self` is less than or equal to zero, - /// or if `base` is less then 2. + /// or if `base` is less than 2. /// /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2298,10 +2299,11 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2319,10 +2321,11 @@ macro_rules! int_impl { /// # Example /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2343,10 +2346,10 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2379,10 +2382,10 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2403,10 +2406,10 @@ macro_rules! int_impl { /// # Example /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index da402d66502a..03e78329deb4 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -457,14 +457,14 @@ macro_rules! nonzero_unsigned_operations { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("# use std::num::", stringify!($Ty), ";")] /// #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -482,14 +482,14 @@ macro_rules! nonzero_unsigned_operations { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("# use std::num::", stringify!($Ty), ";")] /// #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 93f65c5c7aaf..0563f28278d3 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -692,15 +692,16 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `self` is zero, or if `base` is less then 2. + /// This function will panic if `self` is zero, or if `base` is less than 2. /// /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -719,10 +720,11 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -740,10 +742,11 @@ macro_rules! uint_impl { /// # Example /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -764,10 +767,10 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -800,10 +803,10 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -822,10 +825,10 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(int_log)] #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[unstable(feature = "int_log", issue = "70887")] + #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index b1f492381b13..cbc71d0ed1ae 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -62,7 +62,6 @@ #![feature(try_trait_v2)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] -#![feature(int_log)] #![feature(iter_advance_by)] #![feature(iter_array_chunks)] #![feature(iter_collect_into)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 8d754bad1b3c..e9c5c67e7f58 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -3,7 +3,6 @@ #![feature(never_type)] #![feature(try_blocks)] #![feature(io_error_more)] -#![feature(int_log)] #![feature(variant_count)] #![feature(yeet_expr)] #![feature(is_some_and)] diff --git a/src/tools/miri/tests/pass/integer-ops.rs b/src/tools/miri/tests/pass/integer-ops.rs index 724be9efc9f8..0ec1f8e9c693 100644 --- a/src/tools/miri/tests/pass/integer-ops.rs +++ b/src/tools/miri/tests/pass/integer-ops.rs @@ -1,5 +1,4 @@ //@compile-flags: -Coverflow-checks=off -#![feature(int_log)] #![allow(arithmetic_overflow)] pub fn main() { From 79e86e3ea067cf531d728fb15652e4fa76f54b63 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 1 Oct 2022 23:05:32 -0500 Subject: [PATCH 006/221] More build-manifest docs --- src/tools/build-manifest/README.md | 32 +++++++++++++++++----------- src/tools/build-manifest/src/main.rs | 6 +----- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md index 44c96f31d0ba..b5c6371e553a 100644 --- a/src/tools/build-manifest/README.md +++ b/src/tools/build-manifest/README.md @@ -1,7 +1,16 @@ # build-manifest -This tool generates the manifests uploaded to static.rust-lang.org and used by -rustup. The tool is invoked by the bootstrap tool. +This tool generates the manifests uploaded to static.rust-lang.org and used by rustup. +You can see a full list of all manifests at . + +This gets called by `promote-release` via `x.py dist hash-and-sign`. + +## Adding a new component + +There are several steps involved here. +1. Add a new `Step` to `dist.rs`. This should usually be named after the filename of the uploaded tarball. See https://github.com/rust-lang/rust/pull/101799/files#diff-2c56335faa24486df09ba392d8900c57e2fac4633e1f7038469bcf9ed3feb871 for an example. + a. If appropriate, call `tarball.is_preview(true)` for the component. +3. Add a new `PkgType` to build-manifest. Fix all the compile errors as appropriate. ## Testing changes locally @@ -9,19 +18,16 @@ In order to test the changes locally you need to have a valid dist directory available locally. If you don't want to build all the compiler, you can easily create one from the nightly artifacts with: -``` -#!/bin/bash -for cmpn in rust rustc rust-std rust-docs cargo; do - wget https://static.rust-lang.org/dist/${cmpn}-nightly-x86_64-unknown-linux-gnu.tar.gz +```sh +for component in rust rustc rust-std rust-docs cargo; do + wget -P build/dist https://static.rust-lang.org/dist/${component}-nightly-x86_64-unknown-linux-gnu.tar.gz done ``` -Then, you can generate the manifest and all the packages from `path/to/dist` to -`path/to/output` with: +Then, you can generate the manifest and all the packages from `build/dist` to +`build/manifest` with: +```sh +mkdir -p build/manifest +cargo +nightly run -p build-manifest build/dist build/manifest 1970-01-01 http://example.com nightly ``` -$ cargo +nightly run path/to/dist path/to/output 1970-01-01 http://example.com CHANNEL -``` - -Remember to replace `CHANNEL` with the channel you produced dist artifacts of -and `VERSION` with the current Rust version. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index b0006cb90bdd..983f4ca71388 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -1,8 +1,4 @@ -//! Build a dist manifest, hash and sign everything. -//! This gets called by `promote-release` -//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release) -//! via `x.py dist hash-and-sign`; the cmdline arguments are set up -//! by rustbuild (in `src/bootstrap/dist.rs`). +#![doc = include_str!("../README.md")] mod checksum; mod manifest; From 494cb47852ef7bb2cc14f1f440d77722bf0f759b Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 1 Oct 2022 23:42:21 -0500 Subject: [PATCH 007/221] build-manifest: Add a macro that makes it impossible to typo `-preview`, or have a mismatch between parsing and stringifying --- src/tools/build-manifest/src/versions.rs | 88 +++++++++++------------- 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index 0186194a41f5..61e8825753c5 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -8,58 +8,48 @@ use tar::Archive; const DEFAULT_TARGET: &str = "x86_64-unknown-linux-gnu"; -#[derive(Debug, Hash, Eq, PartialEq, Clone)] -pub(crate) enum PkgType { - Rust, - RustSrc, - Rustc, - Cargo, - Rls, - RustAnalyzer, - Clippy, - Rustfmt, - LlvmTools, - Miri, - JsonDocs, - Other(String), +macro_rules! pkg_type { + ( $($variant:ident = $component:literal $(; preview = true $(@$is_preview:tt)? )? ),+ $(,)? ) => { + #[derive(Debug, Hash, Eq, PartialEq, Clone)] + pub(crate) enum PkgType { + $($variant,)+ + Other(String), + } + + impl PkgType { + pub(crate) fn from_component(component: &str) -> Self { + match component { + $( $component $( | concat!($($is_preview)? $component, "-preview") )? => PkgType::$variant,)+ + _ => PkgType::Other(component.into()), + } + } + + /// First part of the tarball name. + fn tarball_component_name(&self) -> &str { + match self { + $( PkgType::$variant => $component,)+ + PkgType::Other(component) => component, + } + } + } + } +} + +pkg_type! { + Rust = "rust", + RustSrc = "rust-src", + Rustc = "rustc", + Cargo = "cargo", + Rls = "rls"; preview = true, + RustAnalyzer = "rust-analyzer"; preview = true, + Clippy = "clippy"; preview = true, + Rustfmt = "rustfmt"; preview = true, + LlvmTools = "llvm-tools"; preview = true, + Miri = "miri"; preview = true, + JsonDocs = "rust-docs-json"; preview = true, } impl PkgType { - pub(crate) fn from_component(component: &str) -> Self { - match component { - "rust" => PkgType::Rust, - "rust-src" => PkgType::RustSrc, - "rustc" => PkgType::Rustc, - "cargo" => PkgType::Cargo, - "rls" | "rls-preview" => PkgType::Rls, - "rust-analyzer" | "rust-analyzer-preview" => PkgType::RustAnalyzer, - "clippy" | "clippy-preview" => PkgType::Clippy, - "rustfmt" | "rustfmt-preview" => PkgType::Rustfmt, - "llvm-tools" | "llvm-tools-preview" => PkgType::LlvmTools, - "miri" | "miri-preview" => PkgType::Miri, - "rust-docs-json" | "rust-docs-json-preview" => PkgType::JsonDocs, - other => PkgType::Other(other.into()), - } - } - - /// First part of the tarball name. - fn tarball_component_name(&self) -> &str { - match self { - PkgType::Rust => "rust", - PkgType::RustSrc => "rust-src", - PkgType::Rustc => "rustc", - PkgType::Cargo => "cargo", - PkgType::Rls => "rls", - PkgType::RustAnalyzer => "rust-analyzer", - PkgType::Clippy => "clippy", - PkgType::Rustfmt => "rustfmt", - PkgType::LlvmTools => "llvm-tools", - PkgType::Miri => "miri", - PkgType::JsonDocs => "rust-docs-json", - PkgType::Other(component) => component, - } - } - /// Whether this package has the same version as Rust itself, or has its own `version` and /// `git-commit-hash` files inside the tarball. fn should_use_rust_version(&self) -> bool { From 69a74955fd9dfd28647b8a4c18abc3dcecb5696d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 2 Oct 2022 00:25:08 -0500 Subject: [PATCH 008/221] Use `PkgType` to determine which packages to add to the manifest Previously, these had to be hard-coded (i.e. specified in both `PkgType` and `fn package`). Now they only have to be specified in `PkgType`. --- src/tools/build-manifest/src/main.rs | 35 +++++------- src/tools/build-manifest/src/versions.rs | 70 ++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 983f4ca71388..726275988e09 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -283,28 +283,15 @@ impl Builder { } fn add_packages_to(&mut self, manifest: &mut Manifest) { - macro_rules! package { - ($name:expr, $targets:expr) => { - self.package($name, &mut manifest.pkg, $targets, &[]) - }; + for pkg in PkgType::all() { + let fallback = if pkg.use_docs_fallback() { DOCS_FALLBACK } else { &[] }; + self.package( + &pkg.manifest_component_name(), + &mut manifest.pkg, + pkg.targets(), + fallback, + ); } - package!("rustc", HOSTS); - package!("rustc-dev", HOSTS); - package!("reproducible-artifacts", HOSTS); - package!("rustc-docs", HOSTS); - package!("cargo", HOSTS); - package!("rust-mingw", MINGW); - package!("rust-std", TARGETS); - self.package("rust-docs", &mut manifest.pkg, HOSTS, DOCS_FALLBACK); - self.package("rust-docs-json-preview", &mut manifest.pkg, HOSTS, DOCS_FALLBACK); - package!("rust-src", &["*"]); - package!("rls-preview", HOSTS); - package!("rust-analyzer-preview", HOSTS); - package!("clippy-preview", HOSTS); - package!("miri-preview", HOSTS); - package!("rustfmt-preview", HOSTS); - package!("rust-analysis", TARGETS); - package!("llvm-tools-preview", TARGETS); } fn add_artifacts_to(&mut self, manifest: &mut Manifest) { @@ -500,6 +487,12 @@ impl Builder { targets: &[&str], fallback: &[(&str, &str)], ) { + if pkgname == "rust" { + // This is handled specially by `rust_package` later. + // Order is important, so don't call `rust_package` here. + return; + } + let version_info = self .versions .version(&PkgType::from_component(pkgname)) diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index 61e8825753c5..5aef232d7abf 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -17,6 +17,13 @@ macro_rules! pkg_type { } impl PkgType { + fn is_preview(&self) -> bool { + match self { + $( $( $($is_preview)? PkgType::$variant => true, )? )+ + _ => false, + } + } + pub(crate) fn from_component(component: &str) -> Self { match component { $( $component $( | concat!($($is_preview)? $component, "-preview") )? => PkgType::$variant,)+ @@ -31,6 +38,11 @@ macro_rules! pkg_type { PkgType::Other(component) => component, } } + + /// Component name in the manifest. In particular, this includes the `-preview` suffix where appropriate. + pub(crate) fn all() -> &'static [PkgType] { + &[ $(PkgType::$variant),+ ] + } } } } @@ -39,7 +51,14 @@ pkg_type! { Rust = "rust", RustSrc = "rust-src", Rustc = "rustc", + RustcDev = "rustc-dev", + RustcDocs = "rustc-docs", + ReproducibleArtifacts = "reproducible-artifacts", + RustMingw = "rust-mingw", + RustStd = "rust-std", Cargo = "cargo", + HtmlDocs = "rust-docs", + RustAnalysis = "rust-analysis", Rls = "rls"; preview = true, RustAnalyzer = "rust-analyzer"; preview = true, Clippy = "clippy"; preview = true, @@ -50,6 +69,15 @@ pkg_type! { } impl PkgType { + // / Component name in the manifest. In particular, this includes the `-preview` suffix where appropriate. + pub(crate) fn manifest_component_name(&self) -> String { + if self.is_preview() { + format!("{}-preview", self.tarball_component_name()) + } else { + self.tarball_component_name().to_string() + } + } + /// Whether this package has the same version as Rust itself, or has its own `version` and /// `git-commit-hash` files inside the tarball. fn should_use_rust_version(&self) -> bool { @@ -63,17 +91,59 @@ impl PkgType { PkgType::Miri => false, PkgType::Rust => true, + PkgType::RustStd => true, PkgType::RustSrc => true, PkgType::Rustc => true, PkgType::JsonDocs => true, + PkgType::HtmlDocs => true, + PkgType::RustcDev => true, + PkgType::RustcDocs => true, + PkgType::ReproducibleArtifacts => true, + PkgType::RustMingw => true, + PkgType::RustAnalysis => true, PkgType::Other(_) => true, } } + pub(crate) fn targets(&self) -> &[&str] { + use crate::{HOSTS, MINGW, TARGETS}; + use PkgType::*; + + match self { + Rust => HOSTS, // doesn't matter in practice, but return something to avoid panicking + Rustc => HOSTS, + RustcDev => HOSTS, + ReproducibleArtifacts => HOSTS, + RustcDocs => HOSTS, + Cargo => HOSTS, + RustMingw => MINGW, + RustStd => TARGETS, + HtmlDocs => HOSTS, + JsonDocs => HOSTS, + RustSrc => &["*"], + Rls => HOSTS, + RustAnalyzer => HOSTS, + Clippy => HOSTS, + Miri => HOSTS, + Rustfmt => HOSTS, + RustAnalysis => TARGETS, + LlvmTools => TARGETS, + Other(pkg) => panic!("add {pkg} to the list of known `PkgType`s"), + } + } + /// Whether this package is target-independent or not. fn target_independent(&self) -> bool { *self == PkgType::RustSrc } + + /// Whether to package these target-specific docs for another similar target. + pub(crate) fn use_docs_fallback(&self) -> bool { + match self { + PkgType::JsonDocs | PkgType::HtmlDocs => true, + _ => false, + } + } } #[derive(Debug, Default, Clone)] From a3dd94e702f2d640f5f84f9f43f25fd79dfeae95 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 2 Oct 2022 00:28:25 -0500 Subject: [PATCH 009/221] Use `PkgType::is_preview` to determine whether to add a rename to the manifest This caught a missing preview rename for `llvm-tools`. --- src/tools/build-manifest/src/main.rs | 11 +++++------ src/tools/build-manifest/src/versions.rs | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 726275988e09..f09e1e5718ee 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -365,12 +365,11 @@ impl Builder { let mut rename = |from: &str, to: &str| { manifest.renames.insert(from.to_owned(), Rename { to: to.to_owned() }) }; - rename("rls", "rls-preview"); - rename("rustfmt", "rustfmt-preview"); - rename("clippy", "clippy-preview"); - rename("miri", "miri-preview"); - rename("rust-docs-json", "rust-docs-json-preview"); - rename("rust-analyzer", "rust-analyzer-preview"); + for pkg in PkgType::all() { + if pkg.is_preview() { + rename(pkg.tarball_component_name(), &pkg.manifest_component_name()); + } + } } fn rust_package(&mut self, manifest: &Manifest) -> Package { diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index 5aef232d7abf..967433a86ad3 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -17,7 +17,7 @@ macro_rules! pkg_type { } impl PkgType { - fn is_preview(&self) -> bool { + pub(crate) fn is_preview(&self) -> bool { match self { $( $( $($is_preview)? PkgType::$variant => true, )? )+ _ => false, @@ -32,7 +32,7 @@ macro_rules! pkg_type { } /// First part of the tarball name. - fn tarball_component_name(&self) -> &str { + pub(crate) fn tarball_component_name(&self) -> &str { match self { $( PkgType::$variant => $component,)+ PkgType::Other(component) => component, From 6cbf07959692c662126d0971f767ba14fd175ce5 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 2 Oct 2022 00:48:50 -0500 Subject: [PATCH 010/221] Use an exhaustive match in `target_host_combination`. This avoids bugs where components are added to one part of the manifest but not another. --- src/tools/build-manifest/src/main.rs | 81 ++++++++++++++---------- src/tools/build-manifest/src/versions.rs | 3 +- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index f09e1e5718ee..efe4412726a9 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -401,43 +401,56 @@ impl Builder { let mut components = Vec::new(); let mut extensions = Vec::new(); - let host_component = |pkg| Component::from_str(pkg, host); + let host_component = |pkg: &_| Component::from_str(pkg, host); - // rustc/rust-std/cargo/docs are all required, - // and so is rust-mingw if it's available for the target. - components.extend(vec![ - host_component("rustc"), - host_component("rust-std"), - host_component("cargo"), - host_component("rust-docs"), - ]); - if host.contains("pc-windows-gnu") { - components.push(host_component("rust-mingw")); + for pkg in PkgType::all() { + match pkg { + // rustc/rust-std/cargo/docs are all required + PkgType::Rustc | PkgType::Cargo | PkgType::HtmlDocs => { + components.push(host_component(&pkg.manifest_component_name())); + } + PkgType::RustStd => { + components.push(host_component(&pkg.manifest_component_name())); + extensions.extend( + TARGETS.iter().filter(|&&target| target != host).map(|target| { + Component::from_str(&pkg.manifest_component_name(), target) + }), + ); + } + // so is rust-mingw if it's available for the target + PkgType::RustMingw => { + if host.contains("pc-windows-gnu") { + components.push(host_component("rust-mingw")); + } + } + // Tools are always present in the manifest, + // but might be marked as unavailable if they weren't built. + PkgType::Clippy + | PkgType::Miri + | PkgType::Rls + | PkgType::RustAnalyzer + | PkgType::Rustfmt + | PkgType::LlvmTools + | PkgType::RustAnalysis + | PkgType::JsonDocs => { + extensions.push(host_component(&pkg.manifest_component_name())); + } + PkgType::RustcDev | PkgType::RustcDocs => { + extensions.extend( + HOSTS.iter().map(|target| { + Component::from_str(&pkg.manifest_component_name(), target) + }), + ); + } + PkgType::RustSrc => { + extensions.push(Component::from_str(&pkg.manifest_component_name(), "*")); + } + PkgType::Rust | PkgType::Other(_) => {} + // FIXME: is this correct? maybe we should add it so rustup knows about it ... + PkgType::ReproducibleArtifacts => {} + } } - // Tools are always present in the manifest, - // but might be marked as unavailable if they weren't built. - extensions.extend(vec![ - host_component("clippy-preview"), - host_component("miri-preview"), - host_component("rls-preview"), - host_component("rust-analyzer-preview"), - host_component("rustfmt-preview"), - host_component("llvm-tools-preview"), - host_component("rust-analysis"), - host_component("rust-docs-json-preview"), - ]); - - extensions.extend( - TARGETS - .iter() - .filter(|&&target| target != host) - .map(|target| Component::from_str("rust-std", target)), - ); - extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-dev", target))); - extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-docs", target))); - extensions.push(Component::from_str("rust-src", "*")); - // If the components/extensions don't actually exist for this // particular host/target combination then nix it entirely from our // lists. diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index 967433a86ad3..cea34905db6a 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -39,7 +39,6 @@ macro_rules! pkg_type { } } - /// Component name in the manifest. In particular, this includes the `-preview` suffix where appropriate. pub(crate) fn all() -> &'static [PkgType] { &[ $(PkgType::$variant),+ ] } @@ -69,7 +68,7 @@ pkg_type! { } impl PkgType { - // / Component name in the manifest. In particular, this includes the `-preview` suffix where appropriate. + /// Component name in the manifest. In particular, this includes the `-preview` suffix where appropriate. pub(crate) fn manifest_component_name(&self) -> String { if self.is_preview() { format!("{}-preview", self.tarball_component_name()) From 1e9d2187ed0addf59e5e73811454e46246b4fdf0 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 27 Oct 2022 12:07:34 -0500 Subject: [PATCH 011/221] Use PkgType in more places In particular, this avoids serializing and parsing the pkg to a string, which allows getting rid of `PkgType::Other` altogether --- src/tools/build-manifest/README.md | 1 + src/tools/build-manifest/src/main.rs | 57 ++++++++++-------------- src/tools/build-manifest/src/manifest.rs | 5 ++- src/tools/build-manifest/src/versions.rs | 11 ----- 4 files changed, 27 insertions(+), 47 deletions(-) diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md index b5c6371e553a..40dce38742a1 100644 --- a/src/tools/build-manifest/README.md +++ b/src/tools/build-manifest/README.md @@ -2,6 +2,7 @@ This tool generates the manifests uploaded to static.rust-lang.org and used by rustup. You can see a full list of all manifests at . +This listing is updated by every 7 days. This gets called by `promote-release` via `x.py dist hash-and-sign`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index efe4412726a9..ebc220cfce59 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -180,7 +180,7 @@ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin" static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"]; -static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-docs-json-preview"]; +static NIGHTLY_ONLY_COMPONENTS: &[PkgType] = &[PkgType::Miri, PkgType::JsonDocs]; macro_rules! t { ($e:expr) => { @@ -285,12 +285,7 @@ impl Builder { fn add_packages_to(&mut self, manifest: &mut Manifest) { for pkg in PkgType::all() { let fallback = if pkg.use_docs_fallback() { DOCS_FALLBACK } else { &[] }; - self.package( - &pkg.manifest_component_name(), - &mut manifest.pkg, - pkg.targets(), - fallback, - ); + self.package(pkg, &mut manifest.pkg, fallback); } } @@ -401,26 +396,27 @@ impl Builder { let mut components = Vec::new(); let mut extensions = Vec::new(); - let host_component = |pkg: &_| Component::from_str(pkg, host); + let host_component = |pkg: &_| Component::from_pkg(pkg, host); for pkg in PkgType::all() { match pkg { // rustc/rust-std/cargo/docs are all required PkgType::Rustc | PkgType::Cargo | PkgType::HtmlDocs => { - components.push(host_component(&pkg.manifest_component_name())); + components.push(host_component(pkg)); } PkgType::RustStd => { - components.push(host_component(&pkg.manifest_component_name())); + components.push(host_component(pkg)); extensions.extend( - TARGETS.iter().filter(|&&target| target != host).map(|target| { - Component::from_str(&pkg.manifest_component_name(), target) - }), + TARGETS + .iter() + .filter(|&&target| target != host) + .map(|target| Component::from_pkg(pkg, target)), ); } // so is rust-mingw if it's available for the target PkgType::RustMingw => { if host.contains("pc-windows-gnu") { - components.push(host_component("rust-mingw")); + components.push(host_component(pkg)); } } // Tools are always present in the manifest, @@ -433,20 +429,16 @@ impl Builder { | PkgType::LlvmTools | PkgType::RustAnalysis | PkgType::JsonDocs => { - extensions.push(host_component(&pkg.manifest_component_name())); + extensions.push(host_component(pkg)); } PkgType::RustcDev | PkgType::RustcDocs => { - extensions.extend( - HOSTS.iter().map(|target| { - Component::from_str(&pkg.manifest_component_name(), target) - }), - ); + extensions.extend(HOSTS.iter().map(|target| Component::from_pkg(pkg, target))); } PkgType::RustSrc => { - extensions.push(Component::from_str(&pkg.manifest_component_name(), "*")); + extensions.push(Component::from_pkg(pkg, "*")); } - PkgType::Rust | PkgType::Other(_) => {} - // FIXME: is this correct? maybe we should add it so rustup knows about it ... + PkgType::Rust => {} + // NOTE: this is intentional, these artifacts aren't intended to be used with rustup PkgType::ReproducibleArtifacts => {} } } @@ -494,31 +486,27 @@ impl Builder { fn package( &mut self, - pkgname: &str, + pkg: &PkgType, dst: &mut BTreeMap, - targets: &[&str], fallback: &[(&str, &str)], ) { - if pkgname == "rust" { + if *pkg == PkgType::Rust { // This is handled specially by `rust_package` later. // Order is important, so don't call `rust_package` here. return; } - let version_info = self - .versions - .version(&PkgType::from_component(pkgname)) - .expect("failed to load package version"); + let version_info = self.versions.version(&pkg).expect("failed to load package version"); let mut is_present = version_info.present; // Never ship nightly-only components for other trains. - if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkgname) { + if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkg) { is_present = false; // Pretend the component is entirely missing. } macro_rules! tarball_name { ($target_name:expr) => { - self.versions.tarball_name(&PkgType::from_component(pkgname), $target_name).unwrap() + self.versions.tarball_name(pkg, $target_name).unwrap() }; } let mut target_from_compressed_tar = |target_name| { @@ -547,7 +535,8 @@ impl Builder { Target::unavailable() }; - let targets = targets + let targets = pkg + .targets() .iter() .map(|name| { let target = if is_present { @@ -562,7 +551,7 @@ impl Builder { .collect(); dst.insert( - pkgname.to_string(), + pkg.manifest_component_name(), Package { version: version_info.version.unwrap_or_default(), git_commit_hash: version_info.git_commit, diff --git a/src/tools/build-manifest/src/manifest.rs b/src/tools/build-manifest/src/manifest.rs index 547c270d89ab..a9f19d8e5653 100644 --- a/src/tools/build-manifest/src/manifest.rs +++ b/src/tools/build-manifest/src/manifest.rs @@ -1,3 +1,4 @@ +use crate::versions::PkgType; use crate::Builder; use serde::{Serialize, Serializer}; use std::collections::BTreeMap; @@ -116,8 +117,8 @@ pub(crate) struct Component { } impl Component { - pub(crate) fn from_str(pkg: &str, target: &str) -> Self { - Self { pkg: pkg.to_string(), target: target.to_string() } + pub(crate) fn from_pkg(pkg: &PkgType, target: &str) -> Self { + Self { pkg: pkg.manifest_component_name(), target: target.to_string() } } } diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index cea34905db6a..dde9745afb78 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -13,7 +13,6 @@ macro_rules! pkg_type { #[derive(Debug, Hash, Eq, PartialEq, Clone)] pub(crate) enum PkgType { $($variant,)+ - Other(String), } impl PkgType { @@ -24,18 +23,10 @@ macro_rules! pkg_type { } } - pub(crate) fn from_component(component: &str) -> Self { - match component { - $( $component $( | concat!($($is_preview)? $component, "-preview") )? => PkgType::$variant,)+ - _ => PkgType::Other(component.into()), - } - } - /// First part of the tarball name. pub(crate) fn tarball_component_name(&self) -> &str { match self { $( PkgType::$variant => $component,)+ - PkgType::Other(component) => component, } } @@ -100,7 +91,6 @@ impl PkgType { PkgType::ReproducibleArtifacts => true, PkgType::RustMingw => true, PkgType::RustAnalysis => true, - PkgType::Other(_) => true, } } @@ -127,7 +117,6 @@ impl PkgType { Rustfmt => HOSTS, RustAnalysis => TARGETS, LlvmTools => TARGETS, - Other(pkg) => panic!("add {pkg} to the list of known `PkgType`s"), } } From fde05ea0898bf0436f9a85d6f58064cba9c8336c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 27 Oct 2022 12:23:27 -0500 Subject: [PATCH 012/221] Use PkgType for profiles, too This makes it easier to remove `is_preview` from components in the future if we choose to do so. --- src/tools/build-manifest/src/main.rs | 61 +++++++++++----------------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index ebc220cfce59..92be95c9420c 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -311,44 +311,28 @@ impl Builder { } fn add_profiles_to(&mut self, manifest: &mut Manifest) { - let mut profile = |name, pkgs| self.profile(name, &mut manifest.profiles, pkgs); - profile("minimal", &["rustc", "cargo", "rust-std", "rust-mingw"]); - profile( - "default", - &[ - "rustc", - "cargo", - "rust-std", - "rust-mingw", - "rust-docs", - "rustfmt-preview", - "clippy-preview", - ], - ); - profile( - "complete", - &[ - "rustc", - "cargo", - "rust-std", - "rust-mingw", - "rust-docs", - "rustfmt-preview", - "clippy-preview", - "rls-preview", - "rust-analyzer-preview", - "rust-src", - "llvm-tools-preview", - "rust-analysis", - "miri-preview", - ], - ); + use PkgType::*; + + let mut profile = |name, pkgs: &_| self.profile(name, &mut manifest.profiles, pkgs); + + // Use a Vec here to make sure we don't exclude any components in an earlier profile. + let minimal = vec![Rustc, Cargo, RustStd, RustMingw]; + profile("minimal", &minimal); + + let mut default = minimal; + default.extend([HtmlDocs, Rustfmt, Clippy]); + profile("default", &default); + + // NOTE: this profile is effectively deprecated; do not add new components to it. + let mut complete = default; + complete.extend([Rls, RustAnalyzer, RustSrc, LlvmTools, RustAnalysis, Miri]); + profile("complete", &complete); // The compiler libraries are not stable for end users, and they're also huge, so we only // `rustc-dev` for nightly users, and only in the "complete" profile. It's still possible // for users to install the additional component manually, if needed. if self.versions.channel() == "nightly" { - self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]); + self.extend_profile("complete", &mut manifest.profiles, &[RustcDev]); // Do not include the rustc-docs component for now, as it causes // conflicts with the rust-docs component when installed. See // #75833. @@ -468,20 +452,23 @@ impl Builder { &mut self, profile_name: &str, dst: &mut BTreeMap>, - pkgs: &[&str], + pkgs: &[PkgType], ) { - dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect()); + dst.insert( + profile_name.to_owned(), + pkgs.iter().map(|s| s.manifest_component_name()).collect(), + ); } fn extend_profile( &mut self, profile_name: &str, dst: &mut BTreeMap>, - pkgs: &[&str], + pkgs: &[PkgType], ) { dst.get_mut(profile_name) .expect("existing profile") - .extend(pkgs.iter().map(|s| (*s).to_owned())); + .extend(pkgs.iter().map(|s| s.manifest_component_name())); } fn package( From f5e390e8631a759579674b0899087a51bb073dd3 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 27 Oct 2022 18:20:56 +0000 Subject: [PATCH 013/221] Fix rustc_parse_format spans following escaped utf-8 multibyte chars --- compiler/rustc_parse_format/src/lib.rs | 47 +++++++++------ src/test/ui/fmt/unicode-escape-spans.rs | 19 +++++++ src/test/ui/fmt/unicode-escape-spans.stderr | 63 +++++++++++++++++++++ 3 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/fmt/unicode-escape-spans.rs create mode 100644 src/test/ui/fmt/unicode-escape-spans.stderr diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 1394993abade..54bf4d1d6b73 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -819,19 +819,19 @@ fn find_skips_from_snippet( }; fn find_skips(snippet: &str, is_raw: bool) -> Vec { - let mut s = snippet.char_indices().peekable(); + let mut s = snippet.char_indices(); let mut skips = vec![]; while let Some((pos, c)) = s.next() { - match (c, s.peek()) { + match (c, s.clone().next()) { // skip whitespace and empty lines ending in '\\' ('\\', Some((next_pos, '\n'))) if !is_raw => { skips.push(pos); - skips.push(*next_pos); + skips.push(next_pos); let _ = s.next(); - while let Some((pos, c)) = s.peek() { + while let Some((pos, c)) = s.clone().next() { if matches!(c, ' ' | '\n' | '\t') { - skips.push(*pos); + skips.push(pos); let _ = s.next(); } else { break; @@ -839,7 +839,7 @@ fn find_skips_from_snippet( } } ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { - skips.push(*next_pos); + skips.push(next_pos); let _ = s.next(); } ('\\', Some((_, 'x'))) if !is_raw => { @@ -858,19 +858,30 @@ fn find_skips_from_snippet( } if let Some((next_pos, next_c)) = s.next() { if next_c == '{' { - skips.push(next_pos); - let mut i = 0; // consume up to 6 hexanumeric chars + closing `}` - while let (Some((next_pos, c)), true) = (s.next(), i < 7) { - if c.is_digit(16) { - skips.push(next_pos); - } else if c == '}' { - skips.push(next_pos); - break; - } else { - break; - } - i += 1; + // consume up to 6 hexanumeric chars + let digits_len = + s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count(); + + let len_utf8 = s + .as_str() + .get(..digits_len) + .and_then(|digits| u32::from_str_radix(digits, 16).ok()) + .and_then(char::from_u32) + .map_or(1, char::len_utf8); + + // Skip the digits, for chars that encode to more than 1 utf-8 byte + // exclude as many digits as it is greater than 1 byte + // + // So for a 3 byte character, exclude 2 digits + let required_skips = + digits_len.saturating_sub(len_utf8.saturating_sub(1)); + + // skip '{' and '}' also + for pos in (next_pos..).take(required_skips + 2) { + skips.push(pos) } + + s.nth(digits_len); } else if next_c.is_digit(16) { skips.push(next_pos); // We suggest adding `{` and `}` when appropriate, accept it here as if diff --git a/src/test/ui/fmt/unicode-escape-spans.rs b/src/test/ui/fmt/unicode-escape-spans.rs new file mode 100644 index 000000000000..753d91ce58e6 --- /dev/null +++ b/src/test/ui/fmt/unicode-escape-spans.rs @@ -0,0 +1,19 @@ +fn main() { + // 1 byte in UTF-8 + format!("\u{000041}{a}"); //~ ERROR cannot find value + format!("\u{0041}{a}"); //~ ERROR cannot find value + format!("\u{41}{a}"); //~ ERROR cannot find value + format!("\u{0}{a}"); //~ ERROR cannot find value + + // 2 bytes + format!("\u{0df}{a}"); //~ ERROR cannot find value + format!("\u{df}{a}"); //~ ERROR cannot find value + + // 3 bytes + format!("\u{00211d}{a}"); //~ ERROR cannot find value + format!("\u{211d}{a}"); //~ ERROR cannot find value + + // 4 bytes + format!("\u{1f4a3}{a}"); //~ ERROR cannot find value + format!("\u{10ffff}{a}"); //~ ERROR cannot find value +} diff --git a/src/test/ui/fmt/unicode-escape-spans.stderr b/src/test/ui/fmt/unicode-escape-spans.stderr new file mode 100644 index 000000000000..1d8473f01b82 --- /dev/null +++ b/src/test/ui/fmt/unicode-escape-spans.stderr @@ -0,0 +1,63 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:3:25 + | +LL | format!("\u{000041}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:4:23 + | +LL | format!("\u{0041}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:5:21 + | +LL | format!("\u{41}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:6:20 + | +LL | format!("\u{0}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:9:22 + | +LL | format!("\u{0df}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:10:21 + | +LL | format!("\u{df}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:13:25 + | +LL | format!("\u{00211d}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:14:23 + | +LL | format!("\u{211d}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:17:24 + | +LL | format!("\u{1f4a3}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:18:25 + | +LL | format!("\u{10ffff}{a}"); + | ^ not found in this scope + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0425`. From e9502010b470fdd60e90e9a2216c2a568882ae30 Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Fri, 28 Oct 2022 12:20:45 +0200 Subject: [PATCH 014/221] Remove #![allow(rustc::potential_query_instability)] from rustc_infer Change reported_violations to use IndexSet It is being used to iterate and to insert, without a lot of lookups so hopefully it won't be a perf hit Change MiniGraph.nodes to use IndexSet It is being used to iterate and to insert, without performing lookups so hopefully it won't be a perf hit Change RegionConstraintData.givens to a FxIndexSet This might result in a perf hit. Remove was being used in `givens`, and `FxIndexSet` doesn't allow calling remove without losing the fixed iteration order. So it was necessary to change remove to `shift_remove`, but this method is slower. Change OpaqueTypesVisitor to use stable sets and maps This could also be a perf hit. Make TraitObject visitor use a stable set --- .../rustc_borrowck/src/diagnostics/region_errors.rs | 8 ++++---- .../rustc_infer/src/infer/error_reporting/mod.rs | 12 ++++++------ .../nice_region_error/mismatched_static_lifetime.rs | 4 ++-- .../nice_region_error/static_impl_trait.rs | 12 ++++++------ .../infer/error_reporting/nice_region_error/util.rs | 2 ++ .../src/infer/lexical_region_resolve/mod.rs | 3 +++ .../src/infer/region_constraints/leak_check.rs | 7 ++++--- .../rustc_infer/src/infer/region_constraints/mod.rs | 4 ++-- compiler/rustc_infer/src/lib.rs | 1 - .../rustc_infer/src/traits/error_reporting/mod.rs | 4 ++-- 10 files changed, 31 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 15230718dc0d..1db7ef032b1f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -2,7 +2,7 @@ #![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -276,7 +276,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn get_impl_ident_and_self_ty_from_trait( &self, def_id: DefId, - trait_objects: &FxHashSet, + trait_objects: &FxIndexSet, ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { let tcx = self.infcx.tcx; match tcx.hir().get_if_local(def_id) { @@ -830,7 +830,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; debug!(?param); - let mut visitor = TraitObjectVisitor(FxHashSet::default()); + let mut visitor = TraitObjectVisitor(FxIndexSet::default()); visitor.visit_ty(param.param_ty); let Some((ident, self_ty)) = @@ -843,7 +843,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn suggest_constrain_dyn_trait_in_impl( &self, err: &mut Diagnostic, - found_dids: &FxHashSet, + found_dids: &FxIndexSet, ident: Ident, self_ty: &hir::Ty<'_>, ) -> bool { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 9ff703e521ff..e4a76fbd4513 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -58,7 +58,7 @@ use crate::traits::{ StatementAsExpression, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; @@ -1498,9 +1498,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { values = None; } struct OpaqueTypesVisitor<'tcx> { - types: FxHashMap>, - expected: FxHashMap>, - found: FxHashMap>, + types: FxIndexMap>, + expected: FxIndexMap>, + found: FxIndexMap>, ignore_span: Span, tcx: TyCtxt<'tcx>, } @@ -1538,7 +1538,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, err: &mut Diagnostic, target: &str, - types: &FxHashMap>, + types: &FxIndexMap>, ) { for (key, values) in types.iter() { let count = values.len(); @@ -3254,7 +3254,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if blk.expr.is_some() { return false; } - let mut shadowed = FxHashSet::default(); + let mut shadowed = FxIndexSet::default(); let mut candidate_idents = vec![]; let mut find_compatible_candidates = |pat: &hir::Pat<'_>| { if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index c5f2a1a3f7dc..1067ccda20ca 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -9,7 +9,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::ObligationCauseCode; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; @@ -73,7 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Next, let's figure out the set of trait objects with implicit static bounds let ty = self.tcx().type_of(*impl_def_id); - let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default()); + let mut v = super::static_impl_trait::TraitObjectVisitor(FxIndexSet::default()); v.visit_ty(ty); let mut traits = vec![]; for matching_def_id in v.0 { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index a74c172fa0c1..3c50e8bf013b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -4,7 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; @@ -236,7 +236,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` // lifetime as above, but called using a fully-qualified path to the method: // `Foo::qux(bar)`. - let mut v = TraitObjectVisitor(FxHashSet::default()); + let mut v = TraitObjectVisitor(FxIndexSet::default()); v.visit_ty(param.param_ty); if let Some((ident, self_ty)) = self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0) @@ -408,7 +408,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn get_impl_ident_and_self_ty_from_trait( &self, def_id: DefId, - trait_objects: &FxHashSet, + trait_objects: &FxIndexSet, ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { let tcx = self.tcx(); match tcx.hir().get_if_local(def_id) { @@ -490,7 +490,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { return false; }; - let mut v = TraitObjectVisitor(FxHashSet::default()); + let mut v = TraitObjectVisitor(FxIndexSet::default()); v.visit_ty(ty); // Get the `Ident` of the method being called and the corresponding `impl` (to point at @@ -506,7 +506,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn suggest_constrain_dyn_trait_in_impl( &self, err: &mut Diagnostic, - found_dids: &FxHashSet, + found_dids: &FxIndexSet, ident: Ident, self_ty: &hir::Ty<'_>, ) -> bool { @@ -538,7 +538,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime. -pub struct TraitObjectVisitor(pub FxHashSet); +pub struct TraitObjectVisitor(pub FxIndexSet); impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index f1461d7010d5..fd26d7d29c5e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -149,6 +149,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { region: ty::BoundRegionKind, ) -> bool { let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty); + // We are only checking is any region meets the condition so order doesn't matter + #[allow(rustc::potential_query_instability)] late_bound_regions.iter().any(|r| *r == region) } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 5f13b2b3deb1..ba990acfe6fc 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -842,6 +842,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // are placeholders as upper bounds, but the universe of the // variable `'a`, or some variable that `'a` has to outlive, doesn't // permit those placeholders. + // + // We only iterate to find the min, which means it doesn't cause reproducibility issues + #[allow(rustc::potential_query_instability)] let min_universe = lower_vid_bounds .into_iter() .map(|vid| self.var_infos[vid].universe) diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 90858e3072ac..22b4bbb17d47 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -1,6 +1,7 @@ use super::*; use crate::infer::CombinedSnapshot; use rustc_data_structures::{ + fx::FxIndexMap, graph::{scc::Sccs, vec_graph::VecGraph}, undo_log::UndoLogs, }; @@ -371,7 +372,7 @@ rustc_index::newtype_index! { /// an edge `R1 -> R2` in the graph. struct MiniGraph<'tcx> { /// Map from a region to the index of the node in the graph. - nodes: FxHashMap, LeakCheckNode>, + nodes: FxIndexMap, LeakCheckNode>, /// Map from node index to SCC, and stores the successors of each SCC. All /// the regions in the same SCC are equal to one another, and if `S1 -> S2`, @@ -388,7 +389,7 @@ impl<'tcx> MiniGraph<'tcx> { where 'tcx: 'a, { - let mut nodes = FxHashMap::default(); + let mut nodes = FxIndexMap::default(); let mut edges = Vec::new(); // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter. @@ -438,7 +439,7 @@ impl<'tcx> MiniGraph<'tcx> { } fn add_node( - nodes: &mut FxHashMap, LeakCheckNode>, + nodes: &mut FxIndexMap, LeakCheckNode>, r: ty::Region<'tcx>, ) -> LeakCheckNode { let l = nodes.len(); diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 67b3da687200..985c5d360db8 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -7,7 +7,7 @@ use super::{ InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; @@ -125,7 +125,7 @@ pub struct RegionConstraintData<'tcx> { /// we record the fact that `'a <= 'b` is implied by the fn /// signature, and then ignore the constraint when solving /// equations. This is a bit of a hack but seems to work. - pub givens: FxHashSet<(Region<'tcx>, ty::RegionVid)>, + pub givens: FxIndexSet<(Region<'tcx>, ty::RegionVid)>, } /// Represents a constraint that influences the inference process. diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index e040634edb08..4c119a443555 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -12,7 +12,6 @@ //! //! This API is completely unstable and subject to change. -#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index f8b5009a58d4..4d53519581b3 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -1,7 +1,7 @@ use super::ObjectSafetyViolation; use crate::infer::InferCtxt; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -56,7 +56,7 @@ pub fn report_object_safety_error<'tcx>( ); err.span_label(span, format!("`{}` cannot be made into an object", trait_str)); - let mut reported_violations = FxHashSet::default(); + let mut reported_violations = FxIndexSet::default(); let mut multi_span = vec![]; let mut messages = vec![]; for violation in violations { From 8498e3a9bbee8048a9cf81790a627400d3d87569 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 28 Oct 2022 19:48:38 +0400 Subject: [PATCH 015/221] Add examples for `pointer::mask` --- library/core/src/ptr/const_ptr.rs | 25 +++++++++++++++++++++++++ library/core/src/ptr/mut_ptr.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index ed16c5f051f7..298a26ef5880 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -568,6 +568,31 @@ impl *const T { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// ## Examples + /// + /// ``` + /// #![feature(ptr_mask, strict_provenance)] + /// let v = 17_u32; + /// let ptr: *const u32 = &v; + /// + /// // `u32` is 4 bytes aligned, + /// // which means that lower 2 bits are always 0. + /// let tag_mask = 0b11; + /// let ptr_mask = !tag_mask; + /// + /// // We can store something in these lower bits + /// let tagged_ptr = ptr.map_addr(|a| a | 0b10); + /// + /// // Get the "tag" back + /// let tag = tagged_ptr.addr() & tag_mask; + /// assert_eq!(tag, 0b10); + /// + /// // Note that `tagged_ptr` is unaligned, it's UB to read from it. + /// // To get original pointer `mask` can be used: + /// let masked_ptr = tagged_ptr.mask(ptr_mask); + /// assert_eq!(unsafe { *masked_ptr }, 17); + /// ``` #[unstable(feature = "ptr_mask", issue = "98290")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6764002bcd43..f71696e9ca0f 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -588,6 +588,34 @@ impl *mut T { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. + /// + /// ## Examples + /// + /// ``` + /// #![feature(ptr_mask, strict_provenance)] + /// let mut v = 17_u32; + /// let ptr: *mut u32 = &mut v; + /// + /// // `u32` is 4 bytes aligned, + /// // which means that lower 2 bits are always 0. + /// let tag_mask = 0b11; + /// let ptr_mask = !tag_mask; + /// + /// // We can store something in these lower bits + /// let tagged_ptr = ptr.map_addr(|a| a | 0b10); + /// + /// // Get the "tag" back + /// let tag = tagged_ptr.addr() & tag_mask; + /// assert_eq!(tag, 0b10); + /// + /// // Note that `tagged_ptr` is unaligned, it's UB to read from/write to it. + /// // To get original pointer `mask` can be used: + /// let masked_ptr = tagged_ptr.mask(ptr_mask); + /// assert_eq!(unsafe { *masked_ptr }, 17); + /// + /// unsafe { *masked_ptr = 0 }; + /// assert_eq!(v, 0); + /// ``` #[unstable(feature = "ptr_mask", issue = "98290")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] From 3b6b6047b6d60879c589b4ad52badfc5752624ac Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Sat, 29 Oct 2022 18:03:47 +0800 Subject: [PATCH 016/221] Lint against usages of `struct_span_lint_hir`. --- compiler/rustc_middle/src/ty/context.rs | 5 ++++- compiler/rustc_passes/src/lib.rs | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 94e3f3b63c81..e686eeb553a6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2819,7 +2819,9 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into, decorator: impl for<'a> DecorateLint<'a, ()>, ) { - self.struct_span_lint_hir(lint, hir_id, span, decorator.msg(), |diag| { + let msg = decorator.msg(); + let (level, src) = self.lint_level_at_node(lint, hir_id); + struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| { decorator.decorate_lint(diag) }) } @@ -2829,6 +2831,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] pub fn struct_span_lint_hir( self, lint: &'static Lint, diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 15f60f626c89..6e621b7eb5eb 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -5,8 +5,6 @@ //! This API is completely unstable and subject to change. #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(iter_intersperse)] #![feature(let_chains)] From f9e1f6ffdf03ec33cb29e20c88fc7bcc938c7f42 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 24 Oct 2022 01:28:55 -0700 Subject: [PATCH 017/221] rustdoc: add hash to filename of toolchain files All static files used by rustdoc are now stored in static.files/ and include a hash of their contents. They no longer include the contents of the --resource-suffix flag. This clarifies caching semantics. Anything in static.files can use Cache-Control: immutable because any updates will show up as a new URL. Invocation-specific files like crates-NN.js, search-index-NN.js, and sidebar-items-NN.js still get the resource suffix. The --disable-minification flag is removed because it would vary the output of static files based on invocation flags. Instead, for rustdoc development purposes it's preferable to symlink static files to a non-minified copy for quick iteration. --- src/librustdoc/config.rs | 13 +- src/librustdoc/html/layout.rs | 14 +- src/librustdoc/html/render/context.rs | 26 +- src/librustdoc/html/render/print_item.rs | 6 +- src/librustdoc/html/render/write_shared.rs | 288 +++--------------- src/librustdoc/html/static/css/rustdoc.css | 24 +- src/librustdoc/html/static/fonts/README.txt | 12 + src/librustdoc/html/static/js/main.js | 10 +- src/librustdoc/html/static/js/settings.js | 10 +- src/librustdoc/html/static/js/storage.js | 24 +- src/librustdoc/html/static_files.rs | 252 +++++++-------- src/librustdoc/html/templates/page.html | 56 ++-- src/librustdoc/html/templates/print_item.html | 2 +- src/librustdoc/lib.rs | 4 +- src/test/run-make/emit-shared-files/Makefile | 12 +- .../output-default.stdout | 4 +- src/test/rustdoc/static-root-path.rs | 12 +- src/tools/rustdoc-js/tester.js | 7 +- 18 files changed, 267 insertions(+), 509 deletions(-) create mode 100644 src/librustdoc/html/static/fonts/README.txt diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 67ea39fb9657..9c08eac4edcb 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -239,9 +239,6 @@ pub(crate) struct RenderOptions { pub(crate) default_settings: FxHashMap, /// If present, suffix added to CSS/JavaScript files when referencing them in generated pages. pub(crate) resource_suffix: String, - /// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by - /// default. - pub(crate) enable_minification: bool, /// Whether to create an index page in the root of the output directory. If this is true but /// `enable_index_page` is None, generate a static listing of crates instead. pub(crate) enable_index_page: bool, @@ -416,7 +413,9 @@ impl Options { let to_check = matches.opt_strs("check-theme"); if !to_check.is_empty() { - let paths = match theme::load_css_paths(static_files::themes::LIGHT) { + let paths = match theme::load_css_paths( + std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), + ) { Ok(p) => p, Err(e) => { diag.struct_err(&e.to_string()).emit(); @@ -557,7 +556,9 @@ impl Options { let mut themes = Vec::new(); if matches.opt_present("theme") { - let paths = match theme::load_css_paths(static_files::themes::LIGHT) { + let paths = match theme::load_css_paths( + std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), + ) { Ok(p) => p, Err(e) => { diag.struct_err(&e.to_string()).emit(); @@ -675,7 +676,6 @@ impl Options { ModuleSorting::Alphabetical }; let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default(); - let enable_minification = !matches.opt_present("disable-minification"); let markdown_no_toc = matches.opt_present("markdown-no-toc"); let markdown_css = matches.opt_strs("markdown-css"); let markdown_playground_url = matches.opt_str("markdown-playground-url"); @@ -768,7 +768,6 @@ impl Options { extern_html_root_takes_precedence, default_settings, resource_suffix, - enable_minification, enable_index_page, index_page, static_root_path, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 7d6d4b71e2ea..087e9219b67c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -2,13 +2,14 @@ use std::path::PathBuf; use rustc_data_structures::fx::FxHashMap; -use crate::error::Error; use crate::externalfiles::ExternalHtml; use crate::html::format::{Buffer, Print}; use crate::html::render::{ensure_trailing_slash, StylePath}; use askama::Template; +use super::static_files::{StaticFiles, STATIC_FILES}; + #[derive(Clone)] pub(crate) struct Layout { pub(crate) logo: String, @@ -45,6 +46,9 @@ struct PageLayout<'a> { static_root_path: &'a str, page: &'a Page<'a>, layout: &'a Layout, + + files: &'static StaticFiles, + themes: Vec, sidebar: String, content: String, @@ -61,12 +65,9 @@ pub(crate) fn render( ) -> String { let static_root_path = page.get_static_root_path(); let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string(); - let mut themes: Vec = style_files - .iter() - .map(StylePath::basename) - .collect::>() - .unwrap_or_default(); + let mut themes: Vec = style_files.iter().map(|s| s.basename().unwrap()).collect(); themes.sort(); + let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version"); let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar. let sidebar = Buffer::html().to_display(sidebar); @@ -74,6 +75,7 @@ pub(crate) fn render( static_root_path, page, layout, + files: &STATIC_FILES, themes, sidebar, content, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5733d1f9c79d..5263d0d22328 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -32,7 +32,7 @@ use crate::html::escape::Escape; use crate::html::format::{join_with_double_colon, Buffer}; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; use crate::html::url_parts_builder::UrlPartsBuilder; -use crate::html::{layout, sources}; +use crate::html::{layout, sources, static_files}; use crate::scrape_examples::AllCallLocations; use crate::try_err; @@ -498,7 +498,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { ); let (sender, receiver) = channel(); - let mut scx = SharedContext { + let scx = SharedContext { tcx, src_root, local_sources, @@ -521,19 +521,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { call_locations, }; - // Add the default themes to the `Vec` of stylepaths - // - // Note that these must be added before `sources::render` is called - // so that the resulting source pages are styled - // - // `light.css` is not disabled because it is the stylesheet that stays loaded - // by the browser as the theme stylesheet. The theme system (hackily) works by - // changing the href to this stylesheet. All other themes are disabled to - // prevent rule conflicts - scx.style_files.push(StylePath { path: PathBuf::from("light.css") }); - scx.style_files.push(StylePath { path: PathBuf::from("dark.css") }); - scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") }); - let dst = output; scx.ensure_dir(&dst)?; @@ -647,10 +634,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { \ \ \ - ", - root_path = page.static_root_path.unwrap_or(""), - suffix = page.resource_suffix, + href=\"{static_root_path}{settings_css}\">\ + ", + static_root_path = page.static_root_path.unwrap_or(""), + settings_css = static_files::STATIC_FILES.settings_css, + settings_js = static_files::STATIC_FILES.settings_js, ) }, &shared.style_files, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 6327817364a5..713c5d1bcb66 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -30,10 +30,10 @@ use crate::html::format::{ join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause, Buffer, Ending, PrintWithSpace, }; -use crate::html::highlight; use crate::html::layout::Page; use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::url_parts_builder::UrlPartsBuilder; +use crate::html::{highlight, static_files}; use askama::Template; use itertools::Itertools; @@ -52,8 +52,8 @@ struct PathComponent { #[derive(Template)] #[template(path = "print_item.html")] struct ItemVars<'a> { - page: &'a Page<'a>, static_root_path: &'a str, + clipboard_svg: &'static static_files::StaticFile, typ: &'a str, name: &'a str, item_type: &'a str, @@ -147,8 +147,8 @@ pub(super) fn print_item( }; let item_vars = ItemVars { - page, static_root_path: page.get_static_root_path(), + clipboard_svg: &static_files::STATIC_FILES.clipboard_svg, typ, name: item.name.as_ref().unwrap().as_str(), item_type: &item.type_().to_string(), diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 85f63c985b37..723c502c584f 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -1,10 +1,8 @@ -use std::ffi::OsStr; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufReader}; -use std::path::{Component, Path, PathBuf}; +use std::path::{Component, Path}; use std::rc::Rc; -use std::sync::LazyLock as Lazy; use itertools::Itertools; use rustc_data_structures::flock; @@ -20,123 +18,19 @@ use crate::error::Error; use crate::html::{layout, static_files}; use crate::{try_err, try_none}; -static FILES_UNVERSIONED: Lazy> = Lazy::new(|| { - map! { - "FiraSans-Regular.woff2" => static_files::fira_sans::REGULAR, - "FiraSans-Medium.woff2" => static_files::fira_sans::MEDIUM, - "FiraSans-LICENSE.txt" => static_files::fira_sans::LICENSE, - "SourceSerif4-Regular.ttf.woff2" => static_files::source_serif_4::REGULAR, - "SourceSerif4-Bold.ttf.woff2" => static_files::source_serif_4::BOLD, - "SourceSerif4-It.ttf.woff2" => static_files::source_serif_4::ITALIC, - "SourceSerif4-LICENSE.md" => static_files::source_serif_4::LICENSE, - "SourceCodePro-Regular.ttf.woff2" => static_files::source_code_pro::REGULAR, - "SourceCodePro-Semibold.ttf.woff2" => static_files::source_code_pro::SEMIBOLD, - "SourceCodePro-It.ttf.woff2" => static_files::source_code_pro::ITALIC, - "SourceCodePro-LICENSE.txt" => static_files::source_code_pro::LICENSE, - "NanumBarunGothic.ttf.woff2" => static_files::nanum_barun_gothic::REGULAR, - "NanumBarunGothic-LICENSE.txt" => static_files::nanum_barun_gothic::LICENSE, - "LICENSE-MIT.txt" => static_files::LICENSE_MIT, - "LICENSE-APACHE.txt" => static_files::LICENSE_APACHE, - "COPYRIGHT.txt" => static_files::COPYRIGHT, - } -}); - -enum SharedResource<'a> { - /// This file will never change, no matter what toolchain is used to build it. - /// - /// It does not have a resource suffix. - Unversioned { name: &'static str }, - /// This file may change depending on the toolchain. - /// - /// It has a resource suffix. - ToolchainSpecific { basename: &'static str }, - /// This file may change for any crate within a build, or based on the CLI arguments. - /// - /// This differs from normal invocation-specific files because it has a resource suffix. - InvocationSpecific { basename: &'a str }, -} - -impl SharedResource<'_> { - fn extension(&self) -> Option<&OsStr> { - use SharedResource::*; - match self { - Unversioned { name } - | ToolchainSpecific { basename: name } - | InvocationSpecific { basename: name } => Path::new(name).extension(), - } - } - - fn path(&self, cx: &Context<'_>) -> PathBuf { - match self { - SharedResource::Unversioned { name } => cx.dst.join(name), - SharedResource::ToolchainSpecific { basename } => cx.suffix_path(basename), - SharedResource::InvocationSpecific { basename } => cx.suffix_path(basename), - } - } - - fn should_emit(&self, emit: &[EmitType]) -> bool { - if emit.is_empty() { - return true; - } - let kind = match self { - SharedResource::Unversioned { .. } => EmitType::Unversioned, - SharedResource::ToolchainSpecific { .. } => EmitType::Toolchain, - SharedResource::InvocationSpecific { .. } => EmitType::InvocationSpecific, - }; - emit.contains(&kind) - } -} - -impl Context<'_> { - fn suffix_path(&self, filename: &str) -> PathBuf { - // We use splitn vs Path::extension here because we might get a filename - // like `style.min.css` and we want to process that into - // `style-suffix.min.css`. Path::extension would just return `css` - // which would result in `style.min-suffix.css` which isn't what we - // want. - let (base, ext) = filename.split_once('.').unwrap(); - let filename = format!("{}{}.{}", base, self.shared.resource_suffix, ext); - self.dst.join(&filename) - } - - fn write_shared( - &self, - resource: SharedResource<'_>, - contents: impl 'static + Send + AsRef<[u8]>, - emit: &[EmitType], - ) -> Result<(), Error> { - if resource.should_emit(emit) { - self.shared.fs.write(resource.path(self), contents) - } else { - Ok(()) - } - } - - fn write_minify( - &self, - resource: SharedResource<'_>, - contents: impl 'static + Send + AsRef + AsRef<[u8]>, - minify: bool, - emit: &[EmitType], - ) -> Result<(), Error> { - if minify { - let contents = contents.as_ref(); - let contents = if resource.extension() == Some(OsStr::new("css")) { - minifier::css::minify(contents) - .map_err(|e| { - Error::new(format!("failed to minify CSS file: {}", e), resource.path(self)) - })? - .to_string() - } else { - minifier::js::minify(contents).to_string() - }; - self.write_shared(resource, contents, emit) - } else { - self.write_shared(resource, contents, emit) - } - } -} - +/// Rustdoc writes out two kinds of shared files: +/// - Static files, which are embedded in the rustdoc binary and are written with a +/// filename that includes a hash of their contents. These will always have a new +/// URL if the contents change, so they are safe to cache with the +/// `Cache-Control: immutable` directive. They are written under the static.files/ +/// directory and are written when --emit-type is empty (default) or contains +/// "toolchain-specific". +/// - Invocation specific files. These are generated based on the crate(s) being +/// documented. Their filenames need to be predictable without knowing their +/// contents, so they do not include a hash in their filename and are not safe to +/// cache with `Cache-Control: immutable`. They include the contents of the +/// --resource-suffix flag and are emitted when --emit-type is empty (default) +/// or contains "invocation-specific". pub(super) fn write_shared( cx: &mut Context<'_>, krate: &Crate, @@ -149,139 +43,51 @@ pub(super) fn write_shared( let lock_file = cx.dst.join(".lock"); let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); - // Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly. - fn write_minify( - basename: &'static str, - contents: impl 'static + Send + AsRef + AsRef<[u8]>, - cx: &Context<'_>, - options: &RenderOptions, - ) -> Result<(), Error> { - cx.write_minify( - SharedResource::ToolchainSpecific { basename }, - contents, - options.enable_minification, - &options.emit, - ) - } - - // Toolchain resources should never be dynamic. - let write_toolchain = |p: &'static _, c: &'static _| { - cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit) - }; - - // Crate resources should always be dynamic. - let write_crate = |p: &_, make_content: &dyn Fn() -> Result, Error>| { + // InvocationSpecific resources should always be dynamic. + let write_invocation_specific = |p: &str, make_content: &dyn Fn() -> Result, Error>| { let content = make_content()?; - cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit) + if options.emit.is_empty() || options.emit.contains(&EmitType::InvocationSpecific) { + let output_filename = static_files::suffix_path(p, &cx.shared.resource_suffix); + cx.shared.fs.write(cx.dst.join(output_filename), content) + } else { + Ok(()) + } }; - // Given "foo.svg", return e.g. "url(\"foo1.58.0.svg\")" - fn ver_url(cx: &Context<'_>, basename: &'static str) -> String { - format!( - "url(\"{}\")", - SharedResource::ToolchainSpecific { basename } - .path(cx) - .file_name() - .unwrap() - .to_str() - .unwrap() - ) - } - - // We use the AUTOREPLACE mechanism to inject into our static JS and CSS certain - // values that are only known at doc build time. Since this mechanism is somewhat - // surprising when reading the code, please limit it to rustdoc.css. - write_minify( - "rustdoc.css", - static_files::RUSTDOC_CSS - .replace( - "/* AUTOREPLACE: */url(\"toggle-minus.svg\")", - &ver_url(cx, "toggle-minus.svg"), - ) - .replace("/* AUTOREPLACE: */url(\"toggle-plus.svg\")", &ver_url(cx, "toggle-plus.svg")) - .replace("/* AUTOREPLACE: */url(\"down-arrow.svg\")", &ver_url(cx, "down-arrow.svg")), - cx, - options, - )?; - - // Add all the static files. These may already exist, but we just - // overwrite them anyway to make sure that they're fresh and up-to-date. - write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?; - write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?; - - // To avoid "light.css" to be overwritten, we'll first run over the received themes and only - // then we'll run over the "official" styles. - let mut themes: FxHashSet = FxHashSet::default(); + cx.shared + .fs + .create_dir_all(cx.dst.join("static.files")) + .map_err(|e| PathError::new(e, "static.files"))?; + // Handle added third-party themes for entry in &cx.shared.style_files { let theme = entry.basename()?; let extension = try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path); - // Handle the official themes - match theme.as_str() { - "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?, - "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?, - "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?, - _ => { - // Handle added third-party themes - let filename = format!("{}.{}", theme, extension); - write_crate(&filename, &|| Ok(try_err!(fs::read(&entry.path), &entry.path)))?; - } - }; + // Skip the official themes. They are written below as part of STATIC_FILES_LIST. + if matches!(theme.as_str(), "light" | "dark" | "ayu") { + continue; + } - themes.insert(theme.to_owned()); - } - - if (*cx.shared).layout.logo.is_empty() { - write_toolchain("rust-logo.svg", static_files::RUST_LOGO_SVG)?; - } - if (*cx.shared).layout.favicon.is_empty() { - write_toolchain("favicon.svg", static_files::RUST_FAVICON_SVG)?; - write_toolchain("favicon-16x16.png", static_files::RUST_FAVICON_PNG_16)?; - write_toolchain("favicon-32x32.png", static_files::RUST_FAVICON_PNG_32)?; - } - write_toolchain("wheel.svg", static_files::WHEEL_SVG)?; - write_toolchain("clipboard.svg", static_files::CLIPBOARD_SVG)?; - write_toolchain("down-arrow.svg", static_files::DOWN_ARROW_SVG)?; - write_toolchain("toggle-minus.svg", static_files::TOGGLE_MINUS_PNG)?; - write_toolchain("toggle-plus.svg", static_files::TOGGLE_PLUS_PNG)?; - - let mut themes: Vec<&String> = themes.iter().collect(); - themes.sort(); - - write_minify("main.js", static_files::MAIN_JS, cx, options)?; - write_minify("search.js", static_files::SEARCH_JS, cx, options)?; - write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?; - - if cx.include_sources { - write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?; - } - - write_minify("storage.js", static_files::STORAGE_JS, cx, options)?; - - if cx.shared.layout.scrape_examples_extension { - cx.write_minify( - SharedResource::InvocationSpecific { basename: "scrape-examples.js" }, - static_files::SCRAPE_EXAMPLES_JS, - options.enable_minification, - &options.emit, - )?; + let bytes = try_err!(fs::read(&entry.path), &entry.path); + let filename = format!("{}{}.{}", theme, cx.shared.resource_suffix, extension); + cx.shared.fs.write(cx.dst.join(filename), bytes)?; } + // When the user adds their own CSS files with --extend-css, we write that as an + // invocation-specific file (that is, with a resource suffix). if let Some(ref css) = cx.shared.layout.css_file_extension { let buffer = try_err!(fs::read_to_string(css), css); - // This varies based on the invocation, so it can't go through the write_minify wrapper. - cx.write_minify( - SharedResource::InvocationSpecific { basename: "theme.css" }, - buffer, - options.enable_minification, - &options.emit, - )?; + let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix); + cx.shared.fs.write(cx.dst.join(path), buffer)?; } - write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?; - for (name, contents) in &*FILES_UNVERSIONED { - cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?; + + if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) { + for f in static_files::STATIC_FILES_LIST { + let filename = static_files::static_filename(f.filename, f.bytes); + cx.shared.fs.write(cx.dst.join(filename), f.minified())?; + } } /// Read a file and return all lines that match the `"{crate}":{data},` format, @@ -463,7 +269,7 @@ pub(super) fn write_shared( v.push_str("\\\n}');\ncreateSourceSidebar();\n"); Ok(v.into_bytes()) }; - write_crate("source-files.js", &make_sources)?; + write_invocation_specific("source-files.js", &make_sources)?; } // Update the search index and crate list. @@ -477,7 +283,7 @@ pub(super) fn write_shared( // Sort the indexes by crate so the file will be generated identically even // with rustdoc running in parallel. all_indexes.sort(); - write_crate("search-index.js", &|| { + write_invocation_specific("search-index.js", &|| { let mut v = String::from("var searchIndex = JSON.parse('{\\\n"); v.push_str(&all_indexes.join(",\\\n")); v.push_str( @@ -490,7 +296,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; Ok(v.into_bytes()) })?; - write_crate("crates.js", &|| { + write_invocation_specific("crates.js", &|| { let krates = krates.iter().map(|k| format!("\"{}\"", k)).join(","); Ok(format!("window.ALL_CRATES = [{}];", krates).into_bytes()) })?; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 1cc954a98dc3..96c9afd8cb62 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -4,7 +4,7 @@ font-style: normal; font-weight: 400; src: local('Fira Sans'), - url("FiraSans-Regular.woff2") format("woff2"); + url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2"); font-display: swap; } @font-face { @@ -12,7 +12,7 @@ font-style: normal; font-weight: 500; src: local('Fira Sans Medium'), - url("FiraSans-Medium.woff2") format("woff2"); + url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2"); font-display: swap; } @@ -22,7 +22,7 @@ font-style: normal; font-weight: 400; src: local('Source Serif 4'), - url("SourceSerif4-Regular.ttf.woff2") format("woff2"); + url("SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2") format("woff2"); font-display: swap; } @font-face { @@ -30,7 +30,7 @@ font-style: italic; font-weight: 400; src: local('Source Serif 4 Italic'), - url("SourceSerif4-It.ttf.woff2") format("woff2"); + url("SourceSerif4-It-d034fe4ef9d0fa00.ttf.woff2") format("woff2"); font-display: swap; } @font-face { @@ -38,7 +38,7 @@ font-style: normal; font-weight: 700; src: local('Source Serif 4 Bold'), - url("SourceSerif4-Bold.ttf.woff2") format("woff2"); + url("SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2") format("woff2"); font-display: swap; } @@ -49,28 +49,28 @@ font-weight: 400; /* Avoid using locally installed font because bad versions are in circulation: * see https://github.com/rust-lang/rust/issues/24355 */ - src: url("SourceCodePro-Regular.ttf.woff2") format("woff2"); + src: url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: italic; font-weight: 400; - src: url("SourceCodePro-It.ttf.woff2") format("woff2"); + src: url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 600; - src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2"); + src: url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2"); font-display: swap; } /* Avoid using legacy CJK serif fonts in Windows like Batang. */ @font-face { font-family: 'NanumBarunGothic'; - src: url("NanumBarunGothic.ttf.woff2") format("woff2"); + src: url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2"); font-display: swap; unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF; } @@ -848,7 +848,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ background-size: 20px; background-position: calc(100% - 2px) 56%; /* image is black color, themes should apply a "filter" property to change the color */ - background-image: /* AUTOREPLACE: */url("down-arrow.svg"); + background-image: url("down-arrow-2d685a4bae708e15.svg"); } #crate-search > option { font-size: 1rem; @@ -1625,11 +1625,11 @@ details.rustdoc-toggle[open] > summary.hideme > span { details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle[open] > summary.hideme::before { - background-image: /* AUTOREPLACE: */url("toggle-minus.svg"); + background-image: url("toggle-minus-31bbd6e4c77f5c96.svg"); } details.rustdoc-toggle > summary::before { - background-image: /* AUTOREPLACE: */url("toggle-plus.svg"); + background-image: url("toggle-plus-1092eb4930d581b0.svg"); } details.rustdoc-toggle[open] > summary::before, diff --git a/src/librustdoc/html/static/fonts/README.txt b/src/librustdoc/html/static/fonts/README.txt new file mode 100644 index 000000000000..0db15996d2ec --- /dev/null +++ b/src/librustdoc/html/static/fonts/README.txt @@ -0,0 +1,12 @@ +The Nanum Barun Gothic fonts are shipped with rustdoc because the default fonts +on many Windows installs render Korean very badly. See: + - https://github.com/rust-lang/rust/pull/84048, + - https://github.com/rust-lang/rust/issues/84035 + - https://github.com/rust-lang/rust/pull/90232 + +The font files were generated with these commands: + +```sh +pyftsubset NanumBarunGothic.ttf \ +--unicodes=U+AC00-D7AF:U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \ +--output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2 diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 33480fa41cf0..1c84393cb4e6 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -183,9 +183,9 @@ function browserSupportsHistoryApi() { } // eslint-disable-next-line no-unused-vars -function loadCss(cssFileName) { +function loadCss(cssUrl) { const link = document.createElement("link"); - link.href = resourcePath(cssFileName, ".css"); + link.href = cssUrl; link.type = "text/css"; link.rel = "stylesheet"; document.getElementsByTagName("head")[0].appendChild(link); @@ -208,8 +208,8 @@ function loadCss(cssFileName) { event.preventDefault(); // Sending request for the CSS and the JS files at the same time so it will // hopefully be loaded when the JS will generate the settings content. - loadCss("settings"); - loadScript(resourcePath("settings", ".js")); + loadCss(getVar("static-root-path") + getVar("settings-css")); + loadScript(getVar("static-root-path") + getVar("settings-js")); }; window.searchState = { @@ -286,7 +286,7 @@ function loadCss(cssFileName) { function loadSearch() { if (!searchLoaded) { searchLoaded = true; - loadScript(resourcePath("search", ".js")); + loadScript(getVar("static-root-path") + getVar("search-js")); loadScript(resourcePath("search-index", ".js")); } } diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 5e1c7e6f03e7..141563bd46a1 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -154,7 +154,9 @@ * @return {HTMLElement} */ function buildSettingsPage() { - const themes = getVar("themes").split(","); + const theme_names = getVar("themes").split(",").filter(t => t); + theme_names.push("light", "dark", "ayu"); + const settings = [ { "name": "Use system theme", @@ -165,19 +167,19 @@ "name": "Theme", "js_name": "theme", "default": "light", - "options": themes, + "options": theme_names, }, { "name": "Preferred light theme", "js_name": "preferred-light-theme", "default": "light", - "options": themes, + "options": theme_names, }, { "name": "Preferred dark theme", "js_name": "preferred-dark-theme", "default": "dark", - "options": themes, + "options": theme_names, }, { "name": "Auto-hide item contents for large items", diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index b462a2c50f14..db2db83ca631 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -126,33 +126,29 @@ function getCurrentValue(name) { } } -function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { - const newHref = mainStyleElem.href.replace( - /\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css"); - +function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) { // If this new value comes from a system setting or from the previously // saved theme, no need to save it. if (saveTheme) { - updateLocalStorage("theme", newTheme); + updateLocalStorage("theme", newThemeName); } - if (styleElem.href === newHref) { - return; - } - - let found = false; if (savedHref.length === 0) { onEachLazy(document.getElementsByTagName("link"), el => { savedHref.push(el.href); }); } - onEach(savedHref, el => { - if (el === newHref) { - found = true; + const newHref = savedHref.find(url => { + const m = url.match(/static\.files\/(.*)-[a-f0-9]{16}\.css$/); + if (m && m[1] === newThemeName) { + return true; + } + const m2 = url.match(/\/([^/]*)\.css$/); + if (m2 && m2[1].startsWith(newThemeName)) { return true; } }); - if (found) { + if (newHref && newHref !== styleElem.href) { styleElem.href = newHref; } } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 75f2b7e3570d..7b89dc8cd9f7 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -2,167 +2,119 @@ //! //! All the static files are included here for centralized access in case anything other than the //! HTML rendering code (say, the theme checker) needs to access one of these files. -//! -//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the -//! minifier to run on them. All other files are included as `&'static [u8]` so they can be -//! directly written to a `Write` handle. -/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page. -pub(crate) static RUSTDOC_CSS: &str = include_str!("static/css/rustdoc.css"); +use rustc_data_structures::fx::FxHasher; +use std::hash::Hasher; +use std::path::{Path, PathBuf}; +use std::{fmt, str}; -/// The file contents of `settings.css`, responsible for the items on the settings page. -pub(crate) static SETTINGS_CSS: &str = include_str!("static/css/settings.css"); - -/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled. -pub(crate) static NOSCRIPT_CSS: &str = include_str!("static/css/noscript.css"); - -/// The file contents of `normalize.css`, included to even out standard elements between browser -/// implementations. -pub(crate) static NORMALIZE_CSS: &str = include_str!("static/css/normalize.css"); - -/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages, -/// including search behavior and docblock folding, among others. -pub(crate) static MAIN_JS: &str = include_str!("static/js/main.js"); - -/// The file contents of `search.js`, which contains the search behavior. -pub(crate) static SEARCH_JS: &str = include_str!("static/js/search.js"); - -/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings -/// page. -pub(crate) static SETTINGS_JS: &str = include_str!("static/js/settings.js"); - -/// The file contents of `storage.js`, which contains functionality related to browser Local -/// Storage, used to store documentation settings. -pub(crate) static STORAGE_JS: &str = include_str!("static/js/storage.js"); - -/// The file contents of `scraped-examples.js`, which contains functionality related to the -/// --scrape-examples flag that inserts automatically-found examples of usages of items. -pub(crate) static SCRAPE_EXAMPLES_JS: &str = include_str!("static/js/scrape-examples.js"); - -pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md"); - -/// The file contents of `wheel.svg`, the icon used for the settings button. -pub(crate) static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg"); - -/// The file contents of `clipboard.svg`, the icon used for the "copy path" button. -pub(crate) static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg"); - -/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox. -pub(crate) static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg"); - -/// The file contents of `toggle-minus.svg`, the icon used for opened toggles. -pub(crate) static TOGGLE_MINUS_PNG: &[u8] = include_bytes!("static/images/toggle-minus.svg"); - -/// The file contents of `toggle-plus.svg`, the icon used for closed toggles. -pub(crate) static TOGGLE_PLUS_PNG: &[u8] = include_bytes!("static/images/toggle-plus.svg"); - -/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation -/// output. -pub(crate) static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt"); - -/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0. -pub(crate) static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt"); - -/// The contents of `LICENSE-MIT.txt`, the text of the MIT License. -pub(crate) static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt"); - -/// The contents of `rust-logo.svg`, the default icon of the documentation. -pub(crate) static RUST_LOGO_SVG: &[u8] = include_bytes!("static/images/rust-logo.svg"); - -/// The default documentation favicons (SVG and PNG fallbacks) -pub(crate) static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg"); -pub(crate) static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png"); -pub(crate) static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png"); - -/// The built-in themes given to every documentation site. -pub(crate) mod themes { - /// The "light" theme, selected by default when no setting is available. Used as the basis for - /// the `--check-theme` functionality. - pub(crate) static LIGHT: &str = include_str!("static/css/themes/light.css"); - - /// The "dark" theme. - pub(crate) static DARK: &str = include_str!("static/css/themes/dark.css"); - - /// The "ayu" theme. - pub(crate) static AYU: &str = include_str!("static/css/themes/ayu.css"); +pub(crate) struct StaticFile { + pub(crate) filename: &'static str, + pub(crate) bytes: &'static [u8], } -/// Files related to the Fira Sans font. -pub(crate) mod fira_sans { - /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2. - pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff2"); +impl StaticFile { + pub(crate) fn minified(&self) -> Vec { + if self.filename.ends_with(".css") { + minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into() + } else if self.filename.ends_with(".js") { + minifier::js::minify(str::from_utf8(self.bytes).unwrap()).to_string().into() + } else { + self.bytes.to_owned() + } + } - /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2. - pub(crate) static MEDIUM: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff2"); - - /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/FiraSans-LICENSE.txt"); + pub(crate) fn output_filename(&self) -> PathBuf { + static_filename(self.filename, self.bytes) + } } -/// Files related to the Source Serif 4 font. -pub(crate) mod source_serif_4 { - /// The file `SourceSerif4-Regular.ttf.woff2`, the Regular variant of the Source Serif 4 font in - /// woff2. - pub(crate) static REGULAR: &[u8] = - include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff2"); - - /// The file `SourceSerif4-Bold.ttf.woff2`, the Bold variant of the Source Serif 4 font in - /// woff2. - pub(crate) static BOLD: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff2"); - - /// The file `SourceSerif4-It.ttf.woff2`, the Italic variant of the Source Serif 4 font in - /// woff2. - pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff2"); - - /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceSerif4-LICENSE.md"); +/// The Display implementation for a StaticFile outputs its filename. This makes it +/// convenient to interpolate static files into HTML templates. +impl fmt::Display for StaticFile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.output_filename().display()) + } } -/// Files related to the Source Code Pro font. -pub(crate) mod source_code_pro { - /// The file `SourceCodePro-Regular.ttf.woff2`, the Regular variant of the Source Code Pro font - /// in woff2. - pub(crate) static REGULAR: &[u8] = - include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff2"); - - /// The file `SourceCodePro-Semibold.ttf.woff2`, the Semibold variant of the Source Code Pro - /// font in woff2. - pub(crate) static SEMIBOLD: &[u8] = - include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff2"); - - /// The file `SourceCodePro-It.ttf.woff2`, the Italic variant of the Source Code Pro font in - /// woff2. - pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff2"); - - /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt"); +/// Insert the provided suffix into a filename just before the extension. +pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { + // We use splitn vs Path::extension here because we might get a filename + // like `style.min.css` and we want to process that into + // `style-suffix.min.css`. Path::extension would just return `css` + // which would result in `style.min-suffix.css` which isn't what we + // want. + let (base, ext) = filename.split_once('.').unwrap(); + let filename = format!("{}{}.{}", base, suffix, ext); + filename.into() } -/// Files related to the Nanum Barun Gothic font. -/// -/// These files are used to avoid some legacy CJK serif fonts in Windows. -/// -/// Note that the Noto Sans KR font, which was used previously but was not very readable on Windows, -/// has been replaced by the Nanum Barun Gothic font. This is due to Windows' implementation of font -/// rendering that distorts OpenType fonts too much. -/// -/// The font files were generated with these commands: -/// -/// ```sh -/// pyftsubset NanumBarunGothic.ttf \ -/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \ -/// --output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2 -/// ``` -pub(crate) mod nanum_barun_gothic { - /// The file `NanumBarunGothic.ttf.woff2`, the Regular variant of the Nanum Barun Gothic font. - pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff2"); - - /// The file `NanumBarunGothic-LICENSE.txt`, the license text of the Nanum Barun Gothic font. - pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/NanumBarunGothic-LICENSE.txt"); +pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf { + let filename = filename.rsplit("/").next().unwrap(); + Path::new("static.files").join(suffix_path(filename, &static_suffix(contents))) } -/// Files related to the sidebar in rustdoc sources. -pub(crate) mod sidebar { - /// File script to handle sidebar. - pub(crate) static SOURCE_SCRIPT: &str = include_str!("static/js/source-script.js"); +fn static_suffix(bytes: &[u8]) -> String { + let mut hasher = FxHasher::default(); + hasher.write(bytes); + format!("-{:016x}", hasher.finish()) } + +macro_rules! static_files { + ($($field:ident => $file_path:literal,)+) => { + pub(crate) struct StaticFiles { + $(pub $field: StaticFile,)+ + } + + pub(crate) const STATIC_FILES: StaticFiles = StaticFiles { + $($field: StaticFile { filename: $file_path, bytes: include_bytes!($file_path) },)+ + }; + + pub(crate) static STATIC_FILES_LIST: &[&'static StaticFile] = &[ + $(&STATIC_FILES.$field,)+ + ]; + } +} + +static_files! { + rustdoc_css => "static/css/rustdoc.css", + settings_css => "static/css/settings.css", + noscript_css => "static/css/noscript.css", + normalize_css => "static/css/normalize.css", + main_js => "static/js/main.js", + search_js => "static/js/search.js", + settings_js => "static/js/settings.js", + source_script_js => "static/js/source-script.js", + storage_js => "static/js/storage.js", + scrape_examples_js => "static/js/scrape-examples.js", + wheel_svg => "static/images/wheel.svg", + clipboard_svg => "static/images/clipboard.svg", + down_arrow_svg => "static/images/down-arrow.svg", + toggle_minus_png => "static/images/toggle-minus.svg", + toggle_plus_png => "static/images/toggle-plus.svg", + copyright => "static/COPYRIGHT.txt", + license_apache => "static/LICENSE-APACHE.txt", + license_mit => "static/LICENSE-MIT.txt", + rust_logo_svg => "static/images/rust-logo.svg", + rust_favicon_svg => "static/images/favicon.svg", + rust_favicon_png_16 => "static/images/favicon-16x16.png", + rust_favicon_png_32 => "static/images/favicon-32x32.png", + theme_light_css => "static/css/themes/light.css", + theme_dark_css => "static/css/themes/dark.css", + theme_ayu_css => "static/css/themes/ayu.css", + fira_sans_regular => "static/fonts/FiraSans-Regular.woff2", + fira_sans_medium => "static/fonts/FiraSans-Medium.woff2", + fira_sans_license => "static/fonts/FiraSans-LICENSE.txt", + source_serif_4_regular => "static/fonts/SourceSerif4-Regular.ttf.woff2", + source_serif_4_bold => "static/fonts/SourceSerif4-Bold.ttf.woff2", + source_serif_4_italic => "static/fonts/SourceSerif4-It.ttf.woff2", + source_serif_4_license => "static/fonts/SourceSerif4-LICENSE.md", + source_code_pro_regular => "static/fonts/SourceCodePro-Regular.ttf.woff2", + source_code_pro_semibold => "static/fonts/SourceCodePro-Semibold.ttf.woff2", + source_code_pro_italic => "static/fonts/SourceCodePro-It.ttf.woff2", + source_code_pro_license => "static/fonts/SourceCodePro-LICENSE.txt", + nanum_barun_gothic_regular => "static/fonts/NanumBarunGothic.ttf.woff2", + nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt", +} + +pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/js/scrape-examples.js"); diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index c32386916878..4efcfc510a25 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -7,48 +7,44 @@ {#- -#} {#- -#} {{page.title}} {#- -#} - {#- -#} - {#- -#} - {#- -#} - {#- -#} - {#- -#} - {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} {#- -#} + href="{{static_root_path|safe}}{{files.normalize_css}}"> {#- -#} {#- -#} + {#- -#} + {#- -#} + {#- -#} {%- for theme in themes -%} - + {#- -#} {%- endfor -%} {#- -#} - {#- -#} + {#- -#} {%- if page.css_class.contains("crate") -%} {#- -#} {%- else if page.css_class == "source" -%} - {#- -#} + {#- -#} {#- -#} {%- else if !page.css_class.contains("mod") -%} {#- -#} {%- endif -%} - {#- -#} + {#- -#} {%- if layout.scrape_examples_extension -%} - {#- -#} + {#- -#} {%- endif -%} {#- -#} {%- if layout.css_file_extension.is_some() -%} {#- -#} {%- else -%} {#- -#} + href="{{static_root_path|safe}}{{files.rust_favicon_png_16}}"> {#- -#} {#- -#} + href="{{static_root_path|safe}}{{files.rust_favicon_png_32}}"> {#- -#} {#- -#} + href="{{static_root_path|safe}}{{files.rust_favicon_svg}}"> {#- -#} {%- endif -%} {{- layout.external_html.in_header|safe -}} {#- -#} @@ -81,7 +77,7 @@ {%- if !layout.logo.is_empty() -%} logo {#- -#} {%- else -%} - {#- -#} + {#- -#} {%- endif -%} {#- -#} {#- -#} @@ -95,7 +91,7 @@ {%- if !layout.logo.is_empty() %} logo {#- -#} {%- else -%} - {#- -#} + {#- -#} {%- endif -%} {#- -#} {#- -#} @@ -110,7 +106,7 @@ {%- if !layout.logo.is_empty() %} logo {#- -#} {%- else -%} - {#- -#} + {#- -#} {%- endif -%} {#- -#} {%- endif -%} @@ -129,7 +125,7 @@

{#- -#} {#- -#} @@ -140,10 +136,14 @@ {{- layout.external_html.after_content|safe -}}
{#- -#}
{#- -#} {#- -#} diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index b6ce3ea3dee9..4c8c27095751 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -7,7 +7,7 @@ {%- endfor -%} {{name}} {#- -#} {#- -#} diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4cf9435d9c8e..1982c066b6ff 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -469,9 +469,6 @@ fn opts() -> Vec { stable("json", |o| { o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") }), - unstable("disable-minification", |o| { - o.optflagmulti("", "disable-minification", "Disable minification applied on JS files") - }), stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")), stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")), stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")), @@ -610,6 +607,7 @@ fn opts() -> Vec { ) }), // deprecated / removed options + unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")), stable("plugin-path", |o| { o.optmulti( "", diff --git a/src/test/run-make/emit-shared-files/Makefile b/src/test/run-make/emit-shared-files/Makefile index 09b4c29c1dd3..cad0c9e5b815 100644 --- a/src/test/run-make/emit-shared-files/Makefile +++ b/src/test/run-make/emit-shared-files/Makefile @@ -23,24 +23,24 @@ invocation-only: toolchain-only: $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs - [ -e $(TOOLCHAIN_ONLY)/storage-xxx.js ] - ! [ -e $(TOOLCHAIN_ONLY)/SourceSerif4-It.ttf.woff2 ] + [ -e $(TOOLCHAIN_ONLY)/static.files/storage-*.js ] + [ -e $(TOOLCHAIN_ONLY)/static.files/SourceSerif4-It-*.ttf.woff2 ] ! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ] ! [ -e $(TOOLCHAIN_ONLY)/x/index.html ] ! [ -e $(TOOLCHAIN_ONLY)/theme.css ] - [ -e $(TOOLCHAIN_ONLY)/main-xxx.js ] + [ -e $(TOOLCHAIN_ONLY)/static.files/main-*.js ] ! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ] all-shared: $(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs - [ -e $(ALL_SHARED)/storage-xxx.js ] - [ -e $(ALL_SHARED)/SourceSerif4-It.ttf.woff2 ] + [ -e $(ALL_SHARED)/static.files/storage-*.js ] + [ -e $(ALL_SHARED)/static.files/SourceSerif4-It-*.ttf.woff2 ] ! [ -e $(ALL_SHARED)/search-index-xxx.js ] ! [ -e $(ALL_SHARED)/settings.html ] ! [ -e $(ALL_SHARED)/x ] ! [ -e $(ALL_SHARED)/src ] ! [ -e $(ALL_SHARED)/theme.css ] - [ -e $(ALL_SHARED)/main-xxx.js ] + [ -e $(ALL_SHARED)/static.files/main-*.js ] ! [ -e $(ALL_SHARED)/y-xxx.css ] diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout index 80cd08ee1673..b280698230dd 100644 --- a/src/test/run-make/issue-88756-default-output/output-default.stdout +++ b/src/test/run-make/issue-88756-default-output/output-default.stdout @@ -115,8 +115,6 @@ Options: Provide width of the output for truncated error messages --json CONFIG Configure the structure of JSON diagnostics - --disable-minification - Disable minification applied on JS files -A, --allow LINT Set lint allowed -W, --warn LINT Set lint warnings --force-warn LINT @@ -173,6 +171,8 @@ Options: --scrape-tests Include test code when scraping examples --with-examples path to function call information (for displaying examples in the documentation) + --disable-minification + removed --plugin-path DIR removed, see issue #44136 for diff --git a/src/test/rustdoc/static-root-path.rs b/src/test/rustdoc/static-root-path.rs index 08c055c5b8db..04de52c0df0f 100644 --- a/src/test/rustdoc/static-root-path.rs +++ b/src/test/rustdoc/static-root-path.rs @@ -1,18 +1,18 @@ // compile-flags:-Z unstable-options --static-root-path /cache/ // @has static_root_path/struct.SomeStruct.html -// @matchesraw - '"/cache/main\.js"' -// @!matchesraw - '"\.\./main\.js"' +// @matchesraw - '"/cache/static.files/main-' +// @!matchesraw - '"\.\./main' // @matchesraw - 'data-root-path="\.\./"' // @!matchesraw - '"/cache/search-index\.js"' pub struct SomeStruct; // @has src/static_root_path/static-root-path.rs.html -// @matchesraw - '"/cache/source-script\.js"' -// @!matchesraw - '"\.\./\.\./source-script\.js"' +// @matchesraw - '"/cache/static.files/source-script-' +// @!matchesraw - '"\.\./\.\./source-script' // @matchesraw - '"\.\./\.\./source-files.js"' // @!matchesraw - '"/cache/source-files\.js"' // @has settings.html -// @matchesraw - '/cache/settings\.js' -// @!matchesraw - '\./settings\.js' +// @matchesraw - '/cache/static.files/settings-' +// @!matchesraw - '\../settings' diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index df3185758bfc..3da4fed33e11 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -307,10 +307,13 @@ function runChecks(testFile, doSearch, parseQuery) { * `parseQuery` function exported from the search module. */ function loadSearchJS(doc_folder, resource_suffix) { - const searchJs = path.join(doc_folder, "search" + resource_suffix + ".js"); const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js"); const searchIndex = require(searchIndexJs); - const searchModule = require(searchJs); + + const staticFiles = path.join(doc_folder, "static.files"); + const searchJs = fs.readdirSync(staticFiles).find( + f => f.match(/search.*\.js$/)); + const searchModule = require(path.join(staticFiles, searchJs)); const searchWords = searchModule.initSearch(searchIndex.searchIndex); return { From bf2533406670078a9110122f8c90e53285f994b6 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Wed, 28 Sep 2022 23:52:00 -0700 Subject: [PATCH 018/221] Make --static-root-path point to static.files --- src/librustdoc/html/layout.rs | 9 ++++++--- src/librustdoc/html/render/context.rs | 2 +- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/render/write_shared.rs | 9 ++++++--- src/librustdoc/html/static_files.rs | 4 ++-- src/test/rustdoc/static-root-path.rs | 6 +++--- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 087e9219b67c..c1b3526eb454 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -35,15 +35,18 @@ pub(crate) struct Page<'a> { } impl<'a> Page<'a> { - pub(crate) fn get_static_root_path(&self) -> &str { - self.static_root_path.unwrap_or(self.root_path) + pub(crate) fn get_static_root_path(&self) -> String { + match self.static_root_path { + Some(s) => s.to_string(), + None => format!("{}{}", self.root_path, "static.files/"), + } } } #[derive(Template)] #[template(path = "page.html")] struct PageLayout<'a> { - static_root_path: &'a str, + static_root_path: String, page: &'a Page<'a>, layout: &'a Layout, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5263d0d22328..51843a505f70 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -636,7 +636,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { \ ", - static_root_path = page.static_root_path.unwrap_or(""), + static_root_path = page.get_static_root_path(), settings_css = static_files::STATIC_FILES.settings_css, settings_js = static_files::STATIC_FILES.settings_js, ) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 713c5d1bcb66..2920a81e5b22 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -147,7 +147,7 @@ pub(super) fn print_item( }; let item_vars = ItemVars { - static_root_path: page.get_static_root_path(), + static_root_path: &page.get_static_root_path(), clipboard_svg: &static_files::STATIC_FILES.clipboard_svg, typ, name: item.name.as_ref().unwrap().as_str(), diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 723c502c584f..07d139e9e121 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -24,7 +24,8 @@ use crate::{try_err, try_none}; /// URL if the contents change, so they are safe to cache with the /// `Cache-Control: immutable` directive. They are written under the static.files/ /// directory and are written when --emit-type is empty (default) or contains -/// "toolchain-specific". +/// "toolchain-specific". If using the --static-root-path flag, it should point +/// to a URL path prefix where each of these filenames can be fetched. /// - Invocation specific files. These are generated based on the crate(s) being /// documented. Their filenames need to be predictable without knowing their /// contents, so they do not include a hash in their filename and are not safe to @@ -85,8 +86,10 @@ pub(super) fn write_shared( if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) { for f in static_files::STATIC_FILES_LIST { - let filename = static_files::static_filename(f.filename, f.bytes); - cx.shared.fs.write(cx.dst.join(filename), f.minified())?; + let filename = cx.dst.join( + Path::new("static.files/").join(static_files::static_filename(f.filename, f.bytes)), + ); + cx.shared.fs.write(filename, f.minified())?; } } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 7b89dc8cd9f7..c922890bc0ba 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHasher; use std::hash::Hasher; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::{fmt, str}; pub(crate) struct StaticFile { @@ -51,7 +51,7 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf { let filename = filename.rsplit("/").next().unwrap(); - Path::new("static.files").join(suffix_path(filename, &static_suffix(contents))) + suffix_path(filename, &static_suffix(contents)) } fn static_suffix(bytes: &[u8]) -> String { diff --git a/src/test/rustdoc/static-root-path.rs b/src/test/rustdoc/static-root-path.rs index 04de52c0df0f..86928b0fb0a8 100644 --- a/src/test/rustdoc/static-root-path.rs +++ b/src/test/rustdoc/static-root-path.rs @@ -1,18 +1,18 @@ // compile-flags:-Z unstable-options --static-root-path /cache/ // @has static_root_path/struct.SomeStruct.html -// @matchesraw - '"/cache/static.files/main-' +// @matchesraw - '"/cache/main-' // @!matchesraw - '"\.\./main' // @matchesraw - 'data-root-path="\.\./"' // @!matchesraw - '"/cache/search-index\.js"' pub struct SomeStruct; // @has src/static_root_path/static-root-path.rs.html -// @matchesraw - '"/cache/static.files/source-script-' +// @matchesraw - '"/cache/source-script-' // @!matchesraw - '"\.\./\.\./source-script' // @matchesraw - '"\.\./\.\./source-files.js"' // @!matchesraw - '"/cache/source-files\.js"' // @has settings.html -// @matchesraw - '/cache/static.files/settings-' +// @matchesraw - '/cache/settings-' // @!matchesraw - '\../settings' From 0b0bf10533ce955e6bcc44c2392674f53c2f3952 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Sat, 29 Oct 2022 01:57:39 -0700 Subject: [PATCH 019/221] Generate static file hashes once --- src/librustdoc/html/render/write_shared.rs | 11 ++++----- src/librustdoc/html/static_files.rs | 27 ++++++++++++++-------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 07d139e9e121..94d8a9feca69 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -85,12 +85,11 @@ pub(super) fn write_shared( } if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) { - for f in static_files::STATIC_FILES_LIST { - let filename = cx.dst.join( - Path::new("static.files/").join(static_files::static_filename(f.filename, f.bytes)), - ); - cx.shared.fs.write(filename, f.minified())?; - } + let static_dir = cx.dst.join(Path::new("static.files")); + static_files::for_each(|f: &static_files::StaticFile| { + let filename = static_dir.join(f.output_filename()); + cx.shared.fs.write(filename, f.minified()) + })?; } /// Read a file and return all lines that match the `"{crate}":{data},` format, diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index c922890bc0ba..afe920b7fa1e 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -5,15 +5,19 @@ use rustc_data_structures::fx::FxHasher; use std::hash::Hasher; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::{fmt, str}; pub(crate) struct StaticFile { - pub(crate) filename: &'static str, + pub(crate) filename: PathBuf, pub(crate) bytes: &'static [u8], } impl StaticFile { + fn new(filename: &str, bytes: &'static [u8]) -> StaticFile { + Self { filename: static_filename(filename, bytes), bytes } + } + pub(crate) fn minified(&self) -> Vec { if self.filename.ends_with(".css") { minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into() @@ -24,8 +28,8 @@ impl StaticFile { } } - pub(crate) fn output_filename(&self) -> PathBuf { - static_filename(self.filename, self.bytes) + pub(crate) fn output_filename(&self) -> &Path { + &self.filename } } @@ -66,13 +70,18 @@ macro_rules! static_files { $(pub $field: StaticFile,)+ } - pub(crate) const STATIC_FILES: StaticFiles = StaticFiles { - $($field: StaticFile { filename: $file_path, bytes: include_bytes!($file_path) },)+ - }; + pub(crate) static STATIC_FILES: std::sync::LazyLock = std::sync::LazyLock::new(|| StaticFiles { + $($field: StaticFile::new($file_path, include_bytes!($file_path)),)+ + }); - pub(crate) static STATIC_FILES_LIST: &[&'static StaticFile] = &[ + pub(crate) fn for_each(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> { + for sf in [ $(&STATIC_FILES.$field,)+ - ]; + ] { + f(sf)? + } + Ok(()) + } } } From c9dbfe31e2e7001571e4d21e46f93d96489df791 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Sat, 29 Oct 2022 14:49:00 -0700 Subject: [PATCH 020/221] Move string literal into format string Co-authored-by: Michael Howell --- src/librustdoc/html/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index c1b3526eb454..48c6abfca90c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -38,7 +38,7 @@ impl<'a> Page<'a> { pub(crate) fn get_static_root_path(&self) -> String { match self.static_root_path { Some(s) => s.to_string(), - None => format!("{}{}", self.root_path, "static.files/"), + None => format!("{}static.files/", self.root_path), } } } From c905fd285a4bbec0c1fdbb823c1825ca0493ab66 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 30 Oct 2022 10:28:46 +0100 Subject: [PATCH 021/221] skip bootstrap target sanity checks when testing Miri --- src/bootstrap/sanity.rs | 10 ++++++++++ .../docker/host-x86_64/x86_64-gnu-tools/checktools.sh | 11 ++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index e905517253c0..9890480709bd 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -155,6 +155,11 @@ than building it. continue; } + // Some environments don't want or need these tools, such as when testing Miri. + if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { + continue; + } + if !build.config.dry_run { cmd_finder.must_have(build.cc(*target)); if let Some(ar) = build.ar(*target) { @@ -212,6 +217,11 @@ than building it. } } + // Some environments don't want or need these tools, such as when testing Miri. + if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { + continue; + } + if need_cmake && target.contains("msvc") { // There are three builds of cmake on windows: MSVC, MinGW, and // Cygwin. The Cygwin build does not have generators for Visual diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index d87384556106..7dde6370904b 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -27,10 +27,7 @@ python3 "$X_PY" test --stage 2 src/tools/rustfmt python3 "$X_PY" test --stage 2 src/tools/miri # We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc. # Also cover some other targets (on both of these hosts) via cross-testing. -# -# Currently disabled -- we end up pulling in a cross-compile of LLVM (maybe -# just overly eager sanity checks), but in any case this won't work when -# building LLVM as of this comment. -#python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc -#FIXME(https://github.com/rust-lang/rust/issues/103519): macOS testing is currently disabled -# python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin +export BOOTSTRAP_SKIP_TARGET_SANITY=1 # we don't need `cc` for these targets +python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc +python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin +unset BOOTSTRAP_SKIP_TARGET_SANITY From 2159df22a287a024e194d83763c67fbcfd001150 Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Sun, 30 Oct 2022 11:50:00 +0100 Subject: [PATCH 022/221] Mention const and lifetime parameters in error E0207 Error Index for E0207 must mention const and lifetime parameters. In addition, add code examples for these situations. Fixes #80862 --- .../src/error_codes/E0207.md | 75 ++++++++++++++++++- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0207.md b/compiler/rustc_error_codes/src/error_codes/E0207.md index 8a7923ac93f9..95e7c9fc76ce 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0207.md +++ b/compiler/rustc_error_codes/src/error_codes/E0207.md @@ -1,4 +1,5 @@ -A type parameter that is specified for `impl` is not constrained. +A type, const or lifetime parameter that is specified for `impl` is not +constrained. Erroneous code example: @@ -14,8 +15,8 @@ impl Foo { } ``` -Any type parameter of an `impl` must meet at least one of -the following criteria: +Any type or const parameter of an `impl` must meet at least one of the +following criteria: - it appears in the _implementing type_ of the impl, e.g. `impl Foo` - for a trait impl, it appears in the _implemented trait_, e.g. @@ -23,6 +24,9 @@ the following criteria: - it is bound as an associated type, e.g. `impl SomeTrait for T where T: AnotherTrait` +Any unconstrained lifetime parameter of an `impl` is not supported if the +lifetime parameter is used by an associated type. + ### Error example 1 Suppose we have a struct `Foo` and we would like to define some methods for it. @@ -32,7 +36,6 @@ The problem is that the parameter `T` does not appear in the implementing type (`Foo`) of the impl. In this case, we can fix the error by moving the type parameter from the `impl` to the method `get`: - ``` struct Foo; @@ -128,6 +131,70 @@ impl Maker> for FooMaker { } ``` +### Error example 3 + +Suppose we have a struct `Foo` and we would like to define some methods for it. +The following code example has a definition which leads to a compiler error: + +```compile_fail,E0207 +struct Foo; + +impl Foo { + // error: the const parameter `T` is not constrained by the impl trait, self + // type, or predicates [E0207] + fn get(&self) -> i32 { + i32::default() + } +} +``` + +The problem is that the const parameter `T` does not appear in the implementing +type (`Foo`) of the impl. In this case, we can fix the error by moving the type +parameter from the `impl` to the method `get`: + + +``` +struct Foo; + +// Move the const parameter from the impl to the method +impl Foo { + fn get(&self) -> i32 { + i32::default() + } +} +``` + +### Error example 4 + +Suppose we have a struct `Foo` and a struct `Bar` that uses lifetime `'a`. We +would like to implement trait `Contains` for `Foo`. The trait `Contains` have +the associated type `B`. The following code example has a definition which +leads to a compiler error: + +```compile_fail,E0207 +struct Foo; +struct Bar<'a>; + +trait Contains { + type B; + + fn get(&self) -> i32; +} + +impl<'a> Contains for Foo { + type B = Bar<'a>; + + // error: the lifetime parameter `'a` is not constrained by the impl trait, + // self type, or predicates [E0207] + fn get(&self) -> i32 { + i32::default() + } +} +``` + +Please note that unconstrained lifetime parameters are not supported if they are +being used by an associated type. + ### Additional information For more information, please see [RFC 447]. From 1aab5d570baca5d776b9e6c670791391fe39bd6d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 1 Oct 2022 23:05:32 -0500 Subject: [PATCH 023/221] More build-manifest docs --- src/tools/build-manifest/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md index 40dce38742a1..9d30c554186b 100644 --- a/src/tools/build-manifest/README.md +++ b/src/tools/build-manifest/README.md @@ -8,10 +8,9 @@ This gets called by `promote-release` Date: Sun, 30 Oct 2022 16:38:40 -0500 Subject: [PATCH 024/221] Remove unnecessary argument to `package` --- src/tools/build-manifest/src/main.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 92be95c9420c..371e60f969e5 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -284,8 +284,7 @@ impl Builder { fn add_packages_to(&mut self, manifest: &mut Manifest) { for pkg in PkgType::all() { - let fallback = if pkg.use_docs_fallback() { DOCS_FALLBACK } else { &[] }; - self.package(pkg, &mut manifest.pkg, fallback); + self.package(pkg, &mut manifest.pkg); } } @@ -471,18 +470,14 @@ impl Builder { .extend(pkgs.iter().map(|s| s.manifest_component_name())); } - fn package( - &mut self, - pkg: &PkgType, - dst: &mut BTreeMap, - fallback: &[(&str, &str)], - ) { + fn package(&mut self, pkg: &PkgType, dst: &mut BTreeMap) { if *pkg == PkgType::Rust { // This is handled specially by `rust_package` later. // Order is important, so don't call `rust_package` here. return; } + let fallback = if pkg.use_docs_fallback() { DOCS_FALLBACK } else { &[] }; let version_info = self.versions.version(&pkg).expect("failed to load package version"); let mut is_present = version_info.present; From 0cd2dd7263a20ba62591039cd3591c8eaef13878 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 25 Oct 2022 12:28:03 +0200 Subject: [PATCH 025/221] [debuginfo] Make debuginfo type names for slices and str consistent. Before this PR, the compiler would emit the debuginfo name `slice$` for all kinds of slices, regardless of whether they are behind a reference or not and regardless of the kind of reference. As a consequence, the types `Foo<&[T]>`, `Foo<[T]>`, and `Foo<&mut [T]>` would end up with the same type name `Foo >` in debuginfo, making it impossible to disambiguate between them by name. Similarly, `&str` would get the name `str` in debuginfo, so the debuginfo name for `Foo` and `Foo<&str>` would be the same. In contrast, `*const [bool]` and `*mut [bool]` would be `ptr_const$ >` and `ptr_mut$ >`, i.e. the encoding does not lose information about the type. This PR removes all special handling for slices and `str`. The types `&[bool]`, `&mut [bool]`, and `&str` thus get the names `ref$ >`, `ref_mut$ >`, and `ref$` respectively -- as one would expect. --- .../src/debuginfo/type_names.rs | 26 +++++++++---------- src/etc/natvis/intrinsic.natvis | 12 +++++++-- src/etc/natvis/liballoc.natvis | 8 +++--- src/test/debuginfo/basic-types.rs | 8 +++--- src/test/debuginfo/msvc-pretty-enums.rs | 6 ++--- src/test/debuginfo/msvc-scalarpair-params.rs | 4 +-- src/test/debuginfo/pretty-std.rs | 4 +-- src/test/debuginfo/rc_arc.rs | 8 +++--- src/test/debuginfo/result-types.rs | 6 ++--- src/test/debuginfo/type-names.rs | 10 +++---- src/test/debuginfo/unsized.rs | 12 ++++----- 11 files changed, 56 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index e05646e1e86a..8647fbace2a7 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -59,7 +59,13 @@ fn push_debuginfo_type_name<'tcx>( match *t.kind() { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), - ty::Str => output.push_str("str"), + ty::Str => { + if cpp_like_debuginfo { + output.push_str("str$") + } else { + output.push_str("str") + } + } ty::Never => { if cpp_like_debuginfo { output.push_str("never$"); @@ -152,25 +158,19 @@ fn push_debuginfo_type_name<'tcx>( } } ty::Ref(_, inner_type, mutbl) => { - // Slices and `&str` are treated like C++ pointers when computing debug - // info for MSVC debugger. However, wrapping these types' names in a synthetic type - // causes the .natvis engine for WinDbg to fail to display their data, so we opt these - // types out to aid debugging in MSVC. - let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str); - - if !cpp_like_debuginfo { - output.push('&'); - output.push_str(mutbl.prefix_str()); - } else if !is_slice_or_str { + if cpp_like_debuginfo { match mutbl { Mutability::Not => output.push_str("ref$<"), Mutability::Mut => output.push_str("ref_mut$<"), } + } else { + output.push('&'); + output.push_str(mutbl.prefix_str()); } push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_debuginfo && !is_slice_or_str { + if cpp_like_debuginfo { push_close_angle_bracket(cpp_like_debuginfo, output); } } @@ -195,7 +195,7 @@ fn push_debuginfo_type_name<'tcx>( } ty::Slice(inner_type) => { if cpp_like_debuginfo { - output.push_str("slice$<"); + output.push_str("slice2$<"); } else { output.push('['); } diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 277e57aaf6fc..8c16a562e349 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -1,6 +1,10 @@  - + + + + + {(char*)data_ptr,[length]s8} (char*)data_ptr,[length]s8 @@ -15,7 +19,11 @@ - + + + + + {{ len={length} }} length diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index bf6c02b91461..41f4a3767f59 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -85,7 +85,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -115,7 +115,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -144,7 +144,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -173,7 +173,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 07d33be2a071..9e82f0714690 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -47,7 +47,6 @@ // gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13} // gdbr-check:$15 = "Hello, World!" - // === LLDB TESTS ================================================================================== // lldb-command:run @@ -96,7 +95,6 @@ // lldbg-check:[...]$12 = 3.5 // lldbr-check:(f64) f64 = 3.5 - // === CDB TESTS =================================================================================== // cdb-command:g @@ -131,7 +129,7 @@ // cdb-command:.enable_unicode 1 // FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str. // cdb-command:dx s -// cdb-check:s : [...] [Type: str] +// cdb-check:s : [...] [Type: ref$] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] @@ -156,4 +154,6 @@ fn main() { _zzz(); // #break } -fn _zzz() {()} +fn _zzz() { + () +} diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 7f1be6f27847..d66e4c660f7b 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -116,13 +116,13 @@ // cdb-check: niche_w_fields_3_niche5,d : F [Type: enum2$] // cdb-command: dx -r3 niche_w_fields_std_result_ok,d -// cdb-check: niche_w_fields_std_result_ok,d : Ok [Type: enum2$,alloc::alloc::Global>,u64> >] -// cdb-check: [+0x[...]] __0 [Type: alloc::boxed::Box,alloc::alloc::Global>] +// cdb-check: niche_w_fields_std_result_ok,d : Ok [Type: enum2$,alloc::alloc::Global>,u64> >] +// cdb-check: [+0x[...]] __0 [Type: alloc::boxed::Box,alloc::alloc::Global>] // cdb-check: [+0x[...]] data_ptr : [...] // cdb-check: [+0x[...]] length : 3 [...] // cdb-command: dx -r3 niche_w_fields_std_result_err,d -// cdb-check: niche_w_fields_std_result_err,d : Err [Type: enum2$,alloc::alloc::Global>,u64> >] +// cdb-check: niche_w_fields_std_result_err,d : Err [Type: enum2$,alloc::alloc::Global>,u64> >] // cdb-check: [+0x[...]] __0 : 789 [Type: unsigned __int64] // cdb-command: dx -r2 arbitrary_discr1,d diff --git a/src/test/debuginfo/msvc-scalarpair-params.rs b/src/test/debuginfo/msvc-scalarpair-params.rs index 9630952cbaae..ae67f6981519 100644 --- a/src/test/debuginfo/msvc-scalarpair-params.rs +++ b/src/test/debuginfo/msvc-scalarpair-params.rs @@ -38,14 +38,14 @@ // cdb-command: g // cdb-command: dx s -// cdb-check:s : "this is a static str" [Type: str] +// cdb-check:s : "this is a static str" [Type: ref$] // cdb-check: [len] : 0x14 [Type: unsigned [...]] // cdb-check: [chars] // cdb-command: g // cdb-command: dx s -// cdb-check:s : { len=0x5 } [Type: slice$] +// cdb-check:s : { len=0x5 } [Type: ref$ >] // cdb-check: [len] : 0x5 [Type: unsigned [...]] // cdb-check: [0] : 0x1 [Type: unsigned char] // cdb-check: [1] : 0x2 [Type: unsigned char] diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index a51b37205e8a..d8c6344e0b6a 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -69,7 +69,7 @@ // cdb-command: g // cdb-command: dx slice,d -// cdb-check:slice,d : { len=4 } [Type: slice$] +// cdb-check:slice,d : { len=4 } [Type: ref$ >] // cdb-check: [len] : 4 [Type: [...]] // cdb-check: [0] : 0 [Type: int] // cdb-check: [1] : 1 [Type: int] @@ -86,7 +86,7 @@ // cdb-check: [3] : 7 [Type: unsigned __int64] // cdb-command: dx str_slice -// cdb-check:str_slice : "IAMA string slice!" [Type: str] +// cdb-check:str_slice : "IAMA string slice!" [Type: ref$] // cdb-command: dx string // cdb-check:string : "IAMA string!" [Type: [...]::String] diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs index c05c565d9563..5d5492d72177 100644 --- a/src/test/debuginfo/rc_arc.rs +++ b/src/test/debuginfo/rc_arc.rs @@ -57,7 +57,7 @@ // cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] // cdb-command:dx slice_rc,d -// cdb-check:slice_rc,d : { len=3 } [Type: alloc::rc::Rc >] +// cdb-check:slice_rc,d : { len=3 } [Type: alloc::rc::Rc >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 41 [Type: core::cell::Cell] // cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] @@ -66,7 +66,7 @@ // cdb-check: [2] : 3 [Type: u32] // cdb-command:dx slice_rc_weak,d -// cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rc::Weak >] +// cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rc::Weak >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 41 [Type: core::cell::Cell] // cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] @@ -85,7 +85,7 @@ // cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] // cdb-command:dx slice_arc,d -// cdb-check:slice_arc,d : { len=3 } [Type: alloc::sync::Arc >] +// cdb-check:slice_arc,d : { len=3 } [Type: alloc::sync::Arc >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize] // cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] @@ -94,7 +94,7 @@ // cdb-check: [2] : 6 [Type: u32] // cdb-command:dx slice_arc_weak,d -// cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak >] +// cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak >] // cdb-check: [Length] : 3 [Type: [...]] // cdb-check: [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize] // cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs index cdac47a784d9..f1944fa38d27 100644 --- a/src/test/debuginfo/result-types.rs +++ b/src/test/debuginfo/result-types.rs @@ -7,12 +7,12 @@ // cdb-command: g // cdb-command: dx x,d -// cdb-check:x,d : Ok [Type: enum2$ >] +// cdb-check:x,d : Ok [Type: enum2$ > >] // cdb-check: [...] __0 : -3 [Type: int] // cdb-command: dx y -// cdb-check:y : Err [Type: enum2$ >] -// cdb-check: [...] __0 : "Some error message" [Type: str] +// cdb-check:y : Err [Type: enum2$ > >] +// cdb-check: [...] __0 : "Some error message" [Type: ref$] fn main() { let x: Result = Ok(-3); diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 9cc99d7767c1..d7b79a845d25 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -95,7 +95,7 @@ // gdb-check:type = &[usize] // gdb-command:whatis slice2 -// gdb-check:type = &[type_names::mod1::Enum2] +// gdb-check:type = &mut [type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait @@ -218,8 +218,8 @@ // cdb-check:struct alloc::vec::Vec vec1 = [...] // cdb-check:struct alloc::vec::Vec,alloc::alloc::Global> vec2 = [...] // cdb-command:dv /t slice* -// cdb-check:struct slice$ slice1 = [...] -// cdb-check:struct slice$ > slice2 = [...] +// cdb-check:struct ref$ > slice1 = [...] +// cdb-check:struct ref_mut$ > > slice2 = [...] // TRAITS // cdb-command:dv /t *_trait @@ -417,8 +417,8 @@ fn main() { let vec1 = vec![0_usize, 2, 3]; let slice1 = &*vec1; - let vec2 = vec![mod1::Enum2::Variant2(Struct1)]; - let slice2 = &*vec2; + let mut vec2 = vec![mod1::Enum2::Variant2(Struct1)]; + let slice2 = &mut *vec2; // Trait Objects let box_trait = Box::new(0_isize) as Box; diff --git a/src/test/debuginfo/unsized.rs b/src/test/debuginfo/unsized.rs index 7cb0002ca512..b1ec9b068305 100644 --- a/src/test/debuginfo/unsized.rs +++ b/src/test/debuginfo/unsized.rs @@ -32,13 +32,13 @@ // cdb-command: g // cdb-command:dx a -// cdb-check:a [Type: ref$ > >] -// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo > *] +// cdb-check:a [Type: ref$ > >] +// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo > *] // cdb-check: [...] length : 0x4 [Type: unsigned [...]int[...] // cdb-command:dx b -// cdb-check:b [Type: ref$ > > >] -// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo > > *] +// cdb-check:b [Type: ref$ > > >] +// cdb-check: [+0x000] data_ptr : 0x[...] [Type: unsized::Foo > > *] // cdb-check: [...] length : 0x4 [Type: unsigned [...]int[...] // cdb-command:dx c @@ -53,8 +53,8 @@ // cdb-check:[...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]] // cdb-command:dx tuple_slice -// cdb-check:tuple_slice [Type: ref$ > >] -// cdb-check: [+0x000] data_ptr : 0x[...] [Type: tuple$ > *] +// cdb-check:tuple_slice [Type: ref$ > >] +// cdb-check: [+0x000] data_ptr : 0x[...] [Type: tuple$ > *] // cdb-check: [...] length : 0x2 [Type: unsigned [...]int[...] // cdb-command:dx tuple_dyn From a2037e3012ed6c59e91fadb693b35fd503cba117 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Nov 2022 01:34:59 +0000 Subject: [PATCH 026/221] Check for substs compatibility for RPITITs --- .../src/traits/project.rs | 18 +++++++++++++++--- .../impl-trait/in-trait/generics-mismatch.rs | 17 +++++++++++++++++ .../in-trait/generics-mismatch.stderr | 12 ++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/generics-mismatch.rs create mode 100644 src/test/ui/impl-trait/in-trait/generics-mismatch.stderr diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c8276854016f..ad216e5502d8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2192,7 +2192,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( // Verify that the trait item and its implementation have compatible substs lists fn check_substs_compatible<'tcx>( tcx: TyCtxt<'tcx>, - assoc_ty: &ty::AssocItem, + assoc_item: &ty::AssocItem, substs: ty::SubstsRef<'tcx>, ) -> bool { fn check_substs_compatible_inner<'tcx>( @@ -2224,7 +2224,10 @@ fn check_substs_compatible<'tcx>( true } - check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice()) + let generics = tcx.generics_of(assoc_item.def_id); + // Chop off any additional substs (RPITIT) substs + let substs = &substs[0..generics.count().min(substs.len())]; + check_substs_compatible_inner(tcx, generics, substs) } fn confirm_impl_trait_in_trait_candidate<'tcx>( @@ -2253,12 +2256,21 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( }; } - let impl_fn_def_id = leaf_def.item.def_id; // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque}, // since `data.substs` are the impl substs. let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); + if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) { + let err = tcx.ty_error_with_message( + obligation.cause.span, + "impl method and trait method have different parameters", + ); + return Progress { term: err.into(), obligations }; + } + + let impl_fn_def_id = leaf_def.item.def_id; + let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.rs b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs new file mode 100644 index 000000000000..cc0fc720ebbf --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs @@ -0,0 +1,17 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct U; + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl Foo for U { + fn bar(&self) {} + //~^ ERROR method `bar` has 1 type parameter but its trait declaration has 0 type parameters +} + +fn main() { + U.bar(); +} diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr new file mode 100644 index 000000000000..cd42683e0224 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/generics-mismatch.rs:11:12 + | +LL | fn bar(&self) -> impl Sized; + | - expected 0 type parameters +... +LL | fn bar(&self) {} + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. From 32dae918a181e01b8ee01d256c1e54ddd6d0ea76 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Nov 2022 01:36:50 +0000 Subject: [PATCH 027/221] Remap RPITIT substs properly --- .../src/traits/project.rs | 7 ++++++ .../in-trait/specialization-substs-remap.rs | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ad216e5502d8..474ae22e3d58 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2260,6 +2260,13 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( // since `data.substs` are the impl substs. let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); + let impl_fn_substs = translate_substs( + selcx.infcx(), + obligation.param_env, + data.impl_def_id, + impl_fn_substs, + leaf_def.defining_node, + ); if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) { let err = tcx.ty_error_with_message( diff --git a/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs new file mode 100644 index 000000000000..c9ee877db8ec --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + *self + } +} + +impl Foo for i32 {} + +fn main() { + let _: i32 = 1i32.bar(); +} From 0f632c8f7882a4470bf1c7b6a4d6b14379b8e163 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 1 Nov 2022 01:42:47 +0000 Subject: [PATCH 028/221] Fix ICE in default impl error reporting --- compiler/rustc_middle/src/ty/error.rs | 4 ++- .../in-trait/specialization-broken.rs | 26 +++++++++++++++++++ .../in-trait/specialization-broken.stderr | 23 ++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/impl-trait/in-trait/specialization-broken.rs create mode 100644 src/test/ui/impl-trait/in-trait/specialization-broken.stderr diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 4e6cdb786025..dc13374f992e 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -430,7 +430,9 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Projection(_), ty::Projection(_)) => { diag.note("an associated type was expected, but a different one was found"); } - (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => { + (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) + if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder => + { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); if !sp.contains(p_span) { diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.rs b/src/test/ui/impl-trait/in-trait/specialization-broken.rs new file mode 100644 index 000000000000..9d27d3710a60 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-broken.rs @@ -0,0 +1,26 @@ +// FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not. +// But we fixed an ICE anyways. + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +default impl Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + //~^ ERROR method `bar` has an incompatible type for trait + *self + } +} + +impl Foo for i32 {} + +fn main() { + 1i32.bar(); +} diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr new file mode 100644 index 000000000000..a30e6346b292 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr @@ -0,0 +1,23 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/specialization-broken.rs:16:22 + | +LL | default impl Foo for U + | - this type parameter +... +LL | fn bar(&self) -> U { + | ^ + | | + | expected associated type, found type parameter `U` + | help: change the output type to match the trait: `impl Sized` + | +note: type in trait + --> $DIR/specialization-broken.rs:9:22 + | +LL | fn bar(&self) -> impl Sized; + | ^^^^^^^^^^ + = note: expected fn pointer `fn(&U) -> impl Sized` + found fn pointer `fn(&U) -> U` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. From 749afe57c3e16667128c3e983166d7a69d03a3dd Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 1 Nov 2022 15:46:58 +0800 Subject: [PATCH 029/221] fix #103751: Fix capacity overflow issue during transmutability check --- compiler/rustc_transmute/src/layout/tree.rs | 4 +-- .../ui/transmute/transmute-padding-ice.rs | 29 +++++++++++++++++++ .../ui/transmute/transmute-padding-ice.stderr | 24 +++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/transmute/transmute-padding-ice.rs create mode 100644 src/test/ui/transmute/transmute-padding-ice.stderr diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index acd4fa63d782..621e2b0d2ec2 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -435,8 +435,8 @@ pub(crate) mod rustc { // finally: padding let padding_span = trace_span!("adding trailing padding").entered(); - let padding_needed = layout_summary.total_size - variant_layout.size(); - if padding_needed > 0 { + if layout_summary.total_size > variant_layout.size() { + let padding_needed = layout_summary.total_size - variant_layout.size(); tree = tree.then(Self::padding(padding_needed)); }; drop(padding_span); diff --git a/src/test/ui/transmute/transmute-padding-ice.rs b/src/test/ui/transmute/transmute-padding-ice.rs new file mode 100644 index 000000000000..a1be7075a8a0 --- /dev/null +++ b/src/test/ui/transmute/transmute-padding-ice.rs @@ -0,0 +1,29 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, + >, + { + } +} + +fn test() { + #[repr(C, align(2))] + struct A(u8, u8); + + #[repr(C)] + struct B(u8, u8); + + assert::is_maybe_transmutable::(); + //~^ ERROR cannot be safely transmuted +} diff --git a/src/test/ui/transmute/transmute-padding-ice.stderr b/src/test/ui/transmute/transmute-padding-ice.stderr new file mode 100644 index 000000000000..c9233890f7aa --- /dev/null +++ b/src/test/ui/transmute/transmute-padding-ice.stderr @@ -0,0 +1,24 @@ +error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + --> $DIR/transmute-padding-ice.rs:27:40 + | +LL | assert::is_maybe_transmutable::(); + | ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `A` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/transmute-padding-ice.rs:11:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom< + | ______________^ +LL | | Src, +LL | | Context, +LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, +LL | | >, + | |_________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 66847ff56b933609618b0899cb3bfdd74f9817d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Mon, 21 Feb 2022 01:45:03 +0100 Subject: [PATCH 030/221] Test that target feature mix up with homogeneous floats is sound This is basically is ripoff of src/test/ui/simd/target-feature-mixup.rs but for floats and without #[repr(simd)] --- .../homogenous-floats-target-feature-mixup.rs | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 src/test/ui/abi/homogenous-floats-target-feature-mixup.rs diff --git a/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs new file mode 100644 index 000000000000..d7f5e19219ed --- /dev/null +++ b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs @@ -0,0 +1,192 @@ +// This test check that even if we mixup target feature of function with homogenous floats, +// the abi is sound and still produce the right answer. +// +// This is basically the same test as src/test/ui/simd/target-feature-mixup.rs but for floats and +// without #[repr(simd)] + +// run-pass +// ignore-emscripten +// ignore-sgx no processes + +#![feature(avx512_target_feature)] + +#![allow(overflowing_literals)] +#![allow(unused_variables)] + +use std::process::{Command, ExitStatus}; +use std::env; + +fn main() { + if let Some(level) = env::args().nth(1) { + return test::main(&level) + } + + match std::env::var("TARGET") { + Ok(s) => { + // Skip this tests on i586-unknown-linux-gnu where sse2 is disabled + if s.contains("i586") { + return + } + } + Err(_) => return, + } + + let me = env::current_exe().unwrap(); + for level in ["sse", "avx", "avx512"].iter() { + let status = Command::new(&me).arg(level).status().unwrap(); + if status.success() { + println!("success with {}", level); + continue + } + + // We don't actually know if our computer has the requisite target features + // for the test below. Testing for that will get added to libstd later so + // for now just assume sigill means this is a machine that can't run this test. + if is_sigill(status) { + println!("sigill with {}, assuming spurious", level); + continue + } + panic!("invalid status at {}: {}", level, status); + } +} + +#[cfg(unix)] +fn is_sigill(status: ExitStatus) -> bool { + use std::os::unix::prelude::*; + status.signal() == Some(4) +} + +#[cfg(windows)] +fn is_sigill(status: ExitStatus) -> bool { + status.code() == Some(0xc000001d) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[allow(nonstandard_style)] +mod test { + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x2(f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x4(f32, f32, f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); + + pub fn main(level: &str) { + unsafe { + main_normal(level); + main_sse(level); + if level == "sse" { + return + } + main_avx(level); + if level == "avx" { + return + } + main_avx512(level); + } + } + + macro_rules! mains { + ($( + $(#[$attr:meta])* + unsafe fn $main:ident(level: &str) { + ... + } + )*) => ($( + $(#[$attr])* + unsafe fn $main(level: &str) { + let m128 = f32x2(1., 2.); + let m256 = f32x4(3., 4., 5., 6.); + let m512 = f32x8(7., 8., 9., 10., 11., 12., 13., 14.); + assert_eq!(id_sse_128(m128), m128); + assert_eq!(id_sse_256(m256), m256); + assert_eq!(id_sse_512(m512), m512); + + if level == "sse" { + return + } + assert_eq!(id_avx_128(m128), m128); + assert_eq!(id_avx_256(m256), m256); + assert_eq!(id_avx_512(m512), m512); + + if level == "avx" { + return + } + assert_eq!(id_avx512_128(m128), m128); + assert_eq!(id_avx512_256(m256), m256); + assert_eq!(id_avx512_512(m512), m512); + } + )*) + } + + mains! { + unsafe fn main_normal(level: &str) { ... } + #[target_feature(enable = "sse2")] + unsafe fn main_sse(level: &str) { ... } + #[target_feature(enable = "avx")] + unsafe fn main_avx(level: &str) { ... } + #[target_feature(enable = "avx512bw")] + unsafe fn main_avx512(level: &str) { ... } + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } +} + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +mod test { + pub fn main(level: &str) {} +} From 6e1361f358849b55f9112dd374282161dfb67e2e Mon Sep 17 00:00:00 2001 From: viandoxdev Date: Tue, 1 Nov 2022 21:50:28 +0100 Subject: [PATCH 031/221] Fixes #103816 make --json work --- src/bootstrap/builder.rs | 1 + src/bootstrap/doc.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index c8285c85d035..e2d76a0c57e8 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -689,6 +689,7 @@ impl<'a> Builder<'a> { doc::UnstableBookGen, doc::TheBook, doc::Standalone, + doc::JsonStd, doc::Std, doc::Rustc, doc::Rustdoc, diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5d265b9ad0c1..649c11be8e05 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -529,7 +529,7 @@ impl Step for JsonStd { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target }); + run.builder.ensure(JsonStd { stage: run.builder.top_stage, target: run.target }); } /// Build JSON documentation for the standard library crates. From ffd4078264c4892b5098d6191e0adfe3564d62ca Mon Sep 17 00:00:00 2001 From: viandoxdev Date: Tue, 1 Nov 2022 22:18:19 +0100 Subject: [PATCH 032/221] fix json running all the time --- src/bootstrap/doc.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 649c11be8e05..827a5346491d 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -524,8 +524,13 @@ impl Step for JsonStd { const DEFAULT: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - let default = run.builder.config.docs && run.builder.config.cmd.json(); - run.all_krates("test").path("library").default_condition(default) + if run.builder.config.cmd.json() { + let default = run.builder.config.docs && run.builder.config.cmd.json(); + run.all_krates("test").path("library").default_condition(default) + } else { + // Without this JsonStd would take priority on Std and prevent it from running. + run.never() + } } fn make_run(run: RunConfig<'_>) { From 20bb56ebfd4a9d8b21de8f8e75e062ae48d04810 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Nov 2022 00:38:43 +0000 Subject: [PATCH 033/221] Use codegen_select in vtable_trait_upcasting_coercion_new_vptr_slot --- .../rustc_trait_selection/src/traits/mod.rs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 0bf54c096cd4..4e764d70ba9d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -933,25 +933,13 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( def_id: unsize_trait_did, substs: tcx.mk_substs_trait(source, &[target.into()]), }; - let obligation = Obligation::new( - ObligationCause::dummy(), - ty::ParamEnv::reveal_all(), - ty::Binder::dummy(ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }), - ); - let infcx = tcx.infer_ctxt().build(); - let mut selcx = SelectionContext::new(&infcx); - let implsrc = selcx.select(&obligation).unwrap(); - - let Some(ImplSource::TraitUpcasting(implsrc_traitcasting)) = implsrc else { - bug!(); - }; - - implsrc_traitcasting.vtable_vptr_slot + match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) { + Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => { + implsrc_traitcasting.vtable_vptr_slot + } + otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"), + } } pub fn provide(providers: &mut ty::query::Providers) { From 972d075aa62c87bc9fb660335e7dc1f75fa853c1 Mon Sep 17 00:00:00 2001 From: viandoxdev Date: Wed, 2 Nov 2022 11:23:42 +0100 Subject: [PATCH 034/221] merge JsonStd and Std steps --- src/bootstrap/builder.rs | 1 - src/bootstrap/dist.rs | 7 +++- src/bootstrap/doc.rs | 77 ++++++++++++---------------------------- src/bootstrap/test.rs | 7 +++- 4 files changed, 34 insertions(+), 58 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e2d76a0c57e8..c8285c85d035 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -689,7 +689,6 @@ impl<'a> Builder<'a> { doc::UnstableBookGen, doc::TheBook, doc::Standalone, - doc::JsonStd, doc::Std, doc::Rustc, doc::Rustdoc, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 805633c926c3..110a3ee4918d 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -19,6 +19,7 @@ use crate::cache::{Interned, INTERNER}; use crate::channel; use crate::compile; use crate::config::TargetSelection; +use crate::doc::DocumentationFormat; use crate::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::tool::{self, Tool}; use crate::util::{exe, is_dylib, output, t, timeit}; @@ -97,7 +98,11 @@ impl Step for JsonDocs { /// Builds the `rust-docs-json` installer component. fn run(self, builder: &Builder<'_>) -> Option { let host = self.host; - builder.ensure(crate::doc::JsonStd { stage: builder.top_stage, target: host }); + builder.ensure(crate::doc::Std { + stage: builder.top_stage, + target: host, + format: DocumentationFormat::JSON, + }); let dest = "share/doc/rust/json"; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 827a5346491d..bbd8830a01c9 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -434,6 +434,7 @@ impl Step for SharedAssets { pub struct Std { pub stage: u32, pub target: TargetSelection, + pub format: DocumentationFormat, } impl Step for Std { @@ -446,7 +447,15 @@ impl Step for Std { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target }); + run.builder.ensure(Std { + stage: run.builder.top_stage, + target: run.target, + format: if run.builder.config.cmd.json() { + DocumentationFormat::JSON + } else { + DocumentationFormat::HTML + }, + }); } /// Compile all standard library documentation. @@ -462,13 +471,16 @@ impl Step for Std { builder.ensure(SharedAssets { target: self.target }); let index_page = builder.src.join("src/doc/index.md").into_os_string(); - let mut extra_args = vec![ - OsStr::new("--markdown-css"), - OsStr::new("rust.css"), - OsStr::new("--markdown-no-toc"), - OsStr::new("--index-page"), - &index_page, - ]; + let mut extra_args = match self.format { + DocumentationFormat::HTML => vec![ + OsStr::new("--markdown-css"), + OsStr::new("rust.css"), + OsStr::new("--markdown-no-toc"), + OsStr::new("--index-page"), + &index_page, + ], + DocumentationFormat::JSON => vec![OsStr::new("--output-format"), OsStr::new("json")], + }; if !builder.config.docs_minification { extra_args.push(OsStr::new("--disable-minification")); @@ -492,15 +504,7 @@ impl Step for Std { }) .collect::>(); - doc_std( - builder, - DocumentationFormat::HTML, - stage, - target, - &out, - &extra_args, - &requested_crates, - ); + doc_std(builder, self.format, stage, target, &out, &extra_args, &requested_crates); // Look for library/std, library/core etc in the `x.py doc` arguments and // open the corresponding rendered docs. @@ -513,43 +517,6 @@ impl Step for Std { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct JsonStd { - pub stage: u32, - pub target: TargetSelection, -} - -impl Step for JsonStd { - type Output = (); - const DEFAULT: bool = false; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - if run.builder.config.cmd.json() { - let default = run.builder.config.docs && run.builder.config.cmd.json(); - run.all_krates("test").path("library").default_condition(default) - } else { - // Without this JsonStd would take priority on Std and prevent it from running. - run.never() - } - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(JsonStd { stage: run.builder.top_stage, target: run.target }); - } - - /// Build JSON documentation for the standard library crates. - /// - /// This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - let out = builder.json_doc_out(target); - t!(fs::create_dir_all(&out)); - let extra_args = [OsStr::new("--output-format"), OsStr::new("json")]; - doc_std(builder, DocumentationFormat::JSON, stage, target, &out, &extra_args, &[]) - } -} - /// Name of the crates that are visible to consumers of the standard library. /// Documentation for internal crates is handled by the rustc step, so internal crates will show /// up there. @@ -562,7 +529,7 @@ impl Step for JsonStd { const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"]; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -enum DocumentationFormat { +pub enum DocumentationFormat { HTML, JSON, } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e168dd571f6d..a73e0bb7b8c2 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -16,6 +16,7 @@ use crate::cache::Interned; use crate::compile; use crate::config::TargetSelection; use crate::dist; +use crate::doc::DocumentationFormat; use crate::flags::Subcommand; use crate::native; use crate::tool::{self, SourceType, Tool}; @@ -822,7 +823,11 @@ impl Step for RustdocJSStd { command.arg("--test-file").arg(path); } } - builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage }); + builder.ensure(crate::doc::Std { + target: self.target, + stage: builder.top_stage, + format: DocumentationFormat::HTML, + }); builder.run(&mut command); } else { builder.info("No nodejs found, skipping \"src/test/rustdoc-js-std\" tests"); From 1bc2bfa44cb70bb744bfd469f05d2d92e040e247 Mon Sep 17 00:00:00 2001 From: viandoxdev Date: Wed, 2 Nov 2022 11:28:31 +0100 Subject: [PATCH 035/221] prevent open with json --- src/bootstrap/doc.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index bbd8830a01c9..f3883e5e6bfd 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -506,6 +506,11 @@ impl Step for Std { doc_std(builder, self.format, stage, target, &out, &extra_args, &requested_crates); + // Don't open if the format is json + if let DocumentationFormat::JSON = self.format { + return; + } + // Look for library/std, library/core etc in the `x.py doc` arguments and // open the corresponding rendered docs. for requested_crate in requested_crates { From f32e6781b2932aed55342ad8a4a7f1023acb30b4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2022 11:31:07 +1100 Subject: [PATCH 036/221] Rename some variables. These have been bugging me for a while. - `literal_text`: `src` is also used and is shorter and better. - `first_char`: used even when "first" doesn't make sense; `c` is shorter and better. - `curr`: `c` is shorter and better. - `unescaped_char`: `result` is also used and is shorter and better. - `second_char`: these have a single use and can be elided. --- compiler/rustc_lexer/src/unescape.rs | 70 +++++++++++++--------------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 8f64b5f5158e..a6752c82bd3c 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -78,54 +78,52 @@ impl EscapeError { /// Takes a contents of a literal (without quotes) and produces a /// sequence of escaped characters or errors. /// Values are returned through invoking of the provided callback. -pub fn unescape_literal(literal_text: &str, mode: Mode, callback: &mut F) +pub fn unescape_literal(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { match mode { Mode::Char | Mode::Byte => { - let mut chars = literal_text.chars(); + let mut chars = src.chars(); let result = unescape_char_or_byte(&mut chars, mode); // The Chars iterator moved forward. - callback(0..(literal_text.len() - chars.as_str().len()), result); + callback(0..(src.len() - chars.as_str().len()), result); } - Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(literal_text, mode, callback), + Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode, callback), // NOTE: Raw strings do not perform any explicit character escaping, here we // only translate CRLF to LF and produce errors on bare CR. - Mode::RawStr | Mode::RawByteStr => { - unescape_raw_str_or_raw_byte_str(literal_text, mode, callback) - } + Mode::RawStr | Mode::RawByteStr => unescape_raw_str_or_raw_byte_str(src, mode, callback), } } /// Takes a contents of a byte, byte string or raw byte string (without quotes) /// and produces a sequence of bytes or errors. /// Values are returned through invoking of the provided callback. -pub fn unescape_byte_literal(literal_text: &str, mode: Mode, callback: &mut F) +pub fn unescape_byte_literal(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { debug_assert!(mode.is_bytes()); - unescape_literal(literal_text, mode, &mut |range, result| { + unescape_literal(src, mode, &mut |range, result| { callback(range, result.map(byte_from_char)); }) } /// Takes a contents of a char literal (without quotes), and returns an /// unescaped char or an error -pub fn unescape_char(literal_text: &str) -> Result { - let mut chars = literal_text.chars(); +pub fn unescape_char(src: &str) -> Result { + let mut chars = src.chars(); unescape_char_or_byte(&mut chars, Mode::Char) - .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) + .map_err(|err| (src.len() - chars.as_str().len(), err)) } /// Takes a contents of a byte literal (without quotes), and returns an /// unescaped byte or an error. -pub fn unescape_byte(literal_text: &str) -> Result { - let mut chars = literal_text.chars(); +pub fn unescape_byte(src: &str) -> Result { + let mut chars = src.chars(); unescape_char_or_byte(&mut chars, Mode::Byte) .map(byte_from_char) - .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) + .map_err(|err| (src.len() - chars.as_str().len(), err)) } /// What kind of literal do we parse. @@ -157,10 +155,7 @@ impl Mode { fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result { // Previous character was '\\', unescape what follows. - - let second_char = chars.next().ok_or(EscapeError::LoneSlash)?; - - let res = match second_char { + let res = match chars.next().ok_or(EscapeError::LoneSlash)? { '"' => '"', 'n' => '\n', 'r' => '\r', @@ -249,23 +244,23 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result { } #[inline] -fn ascii_check(first_char: char, mode: Mode) -> Result { - if mode.is_bytes() && !first_char.is_ascii() { +fn ascii_check(c: char, mode: Mode) -> Result { + if mode.is_bytes() && !c.is_ascii() { // Byte literal can't be a non-ascii character. Err(EscapeError::NonAsciiCharInByte) } else { - Ok(first_char) + Ok(c) } } fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result { debug_assert!(mode == Mode::Char || mode == Mode::Byte); - let first_char = chars.next().ok_or(EscapeError::ZeroChars)?; - let res = match first_char { + let c = chars.next().ok_or(EscapeError::ZeroChars)?; + let res = match c { '\\' => scan_escape(chars, mode), '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(first_char, mode), + _ => ascii_check(c, mode), }?; if chars.next().is_some() { return Err(EscapeError::MoreThanOneChar); @@ -282,13 +277,12 @@ where debug_assert!(mode == Mode::Str || mode == Mode::ByteStr); let initial_len = src.len(); let mut chars = src.chars(); - while let Some(first_char) = chars.next() { - let start = initial_len - chars.as_str().len() - first_char.len_utf8(); + while let Some(c) = chars.next() { + let start = initial_len - chars.as_str().len() - c.len_utf8(); - let unescaped_char = match first_char { + let result = match c { '\\' => { - let second_char = chars.clone().next(); - match second_char { + match chars.clone().next() { Some('\n') => { // Rust language specification requires us to skip whitespaces // if unescaped '\' character is followed by '\n'. @@ -304,10 +298,10 @@ where '\t' => Ok('\t'), '"' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(first_char, mode), + _ => ascii_check(c, mode), }; let end = initial_len - chars.as_str().len(); - callback(start..end, unescaped_char); + callback(start..end, result); } fn skip_ascii_whitespace(chars: &mut Chars<'_>, start: usize, callback: &mut F) @@ -341,18 +335,18 @@ where /// sequence of characters or errors. /// NOTE: Raw strings do not perform any explicit character escaping, here we /// only translate CRLF to LF and produce errors on bare CR. -fn unescape_raw_str_or_raw_byte_str(literal_text: &str, mode: Mode, callback: &mut F) +fn unescape_raw_str_or_raw_byte_str(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr); - let initial_len = literal_text.len(); + let initial_len = src.len(); - let mut chars = literal_text.chars(); - while let Some(curr) = chars.next() { - let start = initial_len - chars.as_str().len() - curr.len_utf8(); + let mut chars = src.chars(); + while let Some(c) = chars.next() { + let start = initial_len - chars.as_str().len() - c.len_utf8(); - let result = match curr { + let result = match c { '\r' => Err(EscapeError::BareCarriageReturnInRawString), c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString), c => Ok(c), From 84ca2c3bab370ee58ebd23050e9286e1d9e664b9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2022 12:15:55 +1100 Subject: [PATCH 037/221] Clarify range calculations. There is some subtlety here. --- compiler/rustc_lexer/src/unescape.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index a6752c82bd3c..dc2fd359e278 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -275,11 +275,13 @@ where F: FnMut(Range, Result), { debug_assert!(mode == Mode::Str || mode == Mode::ByteStr); - let initial_len = src.len(); let mut chars = src.chars(); - while let Some(c) = chars.next() { - let start = initial_len - chars.as_str().len() - c.len_utf8(); + // The `start` and `end` computation here is complicated because + // `skip_ascii_whitespace` makes us to skip over chars without counting + // them in the range computation. + while let Some(c) = chars.next() { + let start = src.len() - chars.as_str().len() - c.len_utf8(); let result = match c { '\\' => { match chars.clone().next() { @@ -300,7 +302,7 @@ where '\r' => Err(EscapeError::BareCarriageReturn), _ => ascii_check(c, mode), }; - let end = initial_len - chars.as_str().len(); + let end = src.len() - chars.as_str().len(); callback(start..end, result); } @@ -340,19 +342,19 @@ where F: FnMut(Range, Result), { debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr); - let initial_len = src.len(); - let mut chars = src.chars(); - while let Some(c) = chars.next() { - let start = initial_len - chars.as_str().len() - c.len_utf8(); + // The `start` and `end` computation here matches the one in + // `unescape_str_or_byte_str` for consistency, even though this function + // doesn't have to worry about skipping any chars. + while let Some(c) = chars.next() { + let start = src.len() - chars.as_str().len() - c.len_utf8(); let result = match c { '\r' => Err(EscapeError::BareCarriageReturnInRawString), c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString), c => Ok(c), }; - let end = initial_len - chars.as_str().len(); - + let end = src.len() - chars.as_str().len(); callback(start..end, result); } } From 34b32b0dac9da3fad7861bdc2bad89d771172bb3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2022 13:35:49 +1100 Subject: [PATCH 038/221] Use `Mode` less. It's passed to numerous places where we just need an `is_byte` bool. Passing the bool avoids the need for some assertions. Also rename `is_bytes()` as `is_byte()`, to better match `Mode::Byte`, `Mode::ByteStr`, and `Mode::RawByteStr`. --- compiler/rustc_lexer/src/unescape.rs | 46 +++++++++---------- .../src/lexer/unescape_error_reporting.rs | 14 +++--- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index dc2fd359e278..f0042a397c2c 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -85,14 +85,16 @@ where match mode { Mode::Char | Mode::Byte => { let mut chars = src.chars(); - let result = unescape_char_or_byte(&mut chars, mode); + let result = unescape_char_or_byte(&mut chars, mode == Mode::Byte); // The Chars iterator moved forward. callback(0..(src.len() - chars.as_str().len()), result); } - Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode, callback), + Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode == Mode::ByteStr, callback), // NOTE: Raw strings do not perform any explicit character escaping, here we // only translate CRLF to LF and produce errors on bare CR. - Mode::RawStr | Mode::RawByteStr => unescape_raw_str_or_raw_byte_str(src, mode, callback), + Mode::RawStr | Mode::RawByteStr => { + unescape_raw_str_or_raw_byte_str(src, mode == Mode::RawByteStr, callback) + } } } @@ -103,7 +105,7 @@ pub fn unescape_byte_literal(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { - debug_assert!(mode.is_bytes()); + debug_assert!(mode.is_byte()); unescape_literal(src, mode, &mut |range, result| { callback(range, result.map(byte_from_char)); }) @@ -113,15 +115,14 @@ where /// unescaped char or an error pub fn unescape_char(src: &str) -> Result { let mut chars = src.chars(); - unescape_char_or_byte(&mut chars, Mode::Char) - .map_err(|err| (src.len() - chars.as_str().len(), err)) + unescape_char_or_byte(&mut chars, false).map_err(|err| (src.len() - chars.as_str().len(), err)) } /// Takes a contents of a byte literal (without quotes), and returns an /// unescaped byte or an error. pub fn unescape_byte(src: &str) -> Result { let mut chars = src.chars(); - unescape_char_or_byte(&mut chars, Mode::Byte) + unescape_char_or_byte(&mut chars, true) .map(byte_from_char) .map_err(|err| (src.len() - chars.as_str().len(), err)) } @@ -145,7 +146,7 @@ impl Mode { } } - pub fn is_bytes(self) -> bool { + pub fn is_byte(self) -> bool { match self { Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true, Mode::Char | Mode::Str | Mode::RawStr => false, @@ -153,7 +154,7 @@ impl Mode { } } -fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result { +fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result { // Previous character was '\\', unescape what follows. let res = match chars.next().ok_or(EscapeError::LoneSlash)? { '"' => '"', @@ -176,7 +177,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result { let value = hi * 16 + lo; // For a non-byte literal verify that it is within ASCII range. - if !mode.is_bytes() && !is_ascii(value) { + if !is_byte && !is_ascii(value) { return Err(EscapeError::OutOfRangeHexEscape); } let value = value as u8; @@ -212,7 +213,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result { // Incorrect syntax has higher priority for error reporting // than unallowed value for a literal. - if mode.is_bytes() { + if is_byte { return Err(EscapeError::UnicodeEscapeInByte); } @@ -244,8 +245,8 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result { } #[inline] -fn ascii_check(c: char, mode: Mode) -> Result { - if mode.is_bytes() && !c.is_ascii() { +fn ascii_check(c: char, is_byte: bool) -> Result { + if is_byte && !c.is_ascii() { // Byte literal can't be a non-ascii character. Err(EscapeError::NonAsciiCharInByte) } else { @@ -253,14 +254,13 @@ fn ascii_check(c: char, mode: Mode) -> Result { } } -fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result { - debug_assert!(mode == Mode::Char || mode == Mode::Byte); +fn unescape_char_or_byte(chars: &mut Chars<'_>, is_byte: bool) -> Result { let c = chars.next().ok_or(EscapeError::ZeroChars)?; let res = match c { - '\\' => scan_escape(chars, mode), + '\\' => scan_escape(chars, is_byte), '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(c, mode), + _ => ascii_check(c, is_byte), }?; if chars.next().is_some() { return Err(EscapeError::MoreThanOneChar); @@ -270,11 +270,10 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result(src: &str, mode: Mode, callback: &mut F) +fn unescape_str_or_byte_str(src: &str, is_byte: bool, callback: &mut F) where F: FnMut(Range, Result), { - debug_assert!(mode == Mode::Str || mode == Mode::ByteStr); let mut chars = src.chars(); // The `start` and `end` computation here is complicated because @@ -293,14 +292,14 @@ where skip_ascii_whitespace(&mut chars, start, callback); continue; } - _ => scan_escape(&mut chars, mode), + _ => scan_escape(&mut chars, is_byte), } } '\n' => Ok('\n'), '\t' => Ok('\t'), '"' => Err(EscapeError::EscapeOnlyChar), '\r' => Err(EscapeError::BareCarriageReturn), - _ => ascii_check(c, mode), + _ => ascii_check(c, is_byte), }; let end = src.len() - chars.as_str().len(); callback(start..end, result); @@ -337,11 +336,10 @@ where /// sequence of characters or errors. /// NOTE: Raw strings do not perform any explicit character escaping, here we /// only translate CRLF to LF and produce errors on bare CR. -fn unescape_raw_str_or_raw_byte_str(src: &str, mode: Mode, callback: &mut F) +fn unescape_raw_str_or_raw_byte_str(src: &str, is_byte: bool, callback: &mut F) where F: FnMut(Range, Result), { - debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr); let mut chars = src.chars(); // The `start` and `end` computation here matches the one in @@ -351,7 +349,7 @@ where let start = src.len() - chars.as_str().len() - c.len_utf8(); let result = match c { '\r' => Err(EscapeError::BareCarriageReturnInRawString), - c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString), + c if is_byte && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString), c => Ok(c), }; let end = src.len() - chars.as_str().len(); diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index f075de714267..055ee98a00aa 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -108,7 +108,7 @@ pub(crate) fn emit_unescape_error( } if !has_help { - let (prefix, msg) = if mode.is_bytes() { + let (prefix, msg) = if mode.is_byte() { ("b", "if you meant to write a byte string literal, use double quotes") } else { ("", "if you meant to write a `str` literal, use double quotes") @@ -142,7 +142,7 @@ pub(crate) fn emit_unescape_error( EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); - let msg = if mode.is_bytes() { + let msg = if mode.is_byte() { "byte constant must be escaped" } else { "character constant must be escaped" @@ -182,11 +182,11 @@ pub(crate) fn emit_unescape_error( let (c, span) = last_char(); let label = - if mode.is_bytes() { "unknown byte escape" } else { "unknown character escape" }; + if mode.is_byte() { "unknown byte escape" } else { "unknown character escape" }; let ec = escaped_char(c); let mut diag = handler.struct_span_err(span, &format!("{}: `{}`", label, ec)); diag.span_label(span, label); - if c == '{' || c == '}' && !mode.is_bytes() { + if c == '{' || c == '}' && !mode.is_byte() { diag.help( "if used in a formatting string, curly braces are escaped with `{{` and `}}`", ); @@ -196,7 +196,7 @@ pub(crate) fn emit_unescape_error( version control settings", ); } else { - if !mode.is_bytes() { + if !mode.is_byte() { diag.span_suggestion( span_with_quotes, "if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal", @@ -231,7 +231,7 @@ pub(crate) fn emit_unescape_error( .emit(); } EscapeError::NonAsciiCharInByte => { - assert!(mode.is_bytes()); + assert!(mode.is_byte()); let (c, span) = last_char(); let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant"); let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { @@ -271,7 +271,7 @@ pub(crate) fn emit_unescape_error( err.emit(); } EscapeError::NonAsciiCharInByteString => { - assert!(mode.is_bytes()); + assert!(mode.is_byte()); let (c, span) = last_char(); let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { format!(" but is {:?}", c) From 6bc36d18ce5bcbf542718a177f179f169bfd756b Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 3 Nov 2022 11:42:51 +0100 Subject: [PATCH 039/221] move browser opening logic in Builder This allows open() to be called from other places in bootstrap (I need this for Ferrocene), and it simplifies the callers by moving the "was_invoked_explicitly" check into the function. --- src/bootstrap/builder.rs | 18 ++++++++++++++++++ src/bootstrap/doc.rs | 40 +++++++++++----------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6de374636333..406bae02d84d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -2207,6 +2207,24 @@ impl<'a> Builder<'a> { false } + + pub(crate) fn maybe_open_in_browser(&self, path: impl AsRef) { + if self.was_invoked_explicitly::(Kind::Doc) { + self.open_in_browser(path); + } + } + + pub(crate) fn open_in_browser(&self, path: impl AsRef) { + if self.config.dry_run || !self.config.cmd.open() { + return; + } + + let path = path.as_ref(); + self.info(&format!("Opening doc {}", path.display())); + if let Err(err) = opener::open(path) { + self.info(&format!("{}\n", err)); + } + } } #[cfg(test)] diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5d265b9ad0c1..0045856e2c95 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -12,7 +12,7 @@ use std::fs; use std::io; use std::path::{Path, PathBuf}; -use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; +use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::{Config, TargetSelection}; @@ -85,18 +85,6 @@ book!( StyleGuide, "src/doc/style-guide", "style-guide"; ); -fn open(builder: &Builder<'_>, path: impl AsRef) { - if builder.config.dry_run || !builder.config.cmd.open() { - return; - } - - let path = path.as_ref(); - builder.info(&format!("Opening doc {}", path.display())); - if let Err(err) = opener::open(path) { - builder.info(&format!("{}\n", err)); - } -} - // "library/std" -> ["library", "std"] // // Used for deciding whether a particular step is one requested by the user on @@ -240,11 +228,9 @@ impl Step for TheBook { invoke_rustdoc(builder, compiler, &shared_assets, target, path); } - if builder.was_invoked_explicitly::(Kind::Doc) { - let out = builder.doc_out(target); - let index = out.join("book").join("index.html"); - open(builder, &index); - } + let out = builder.doc_out(target); + let index = out.join("book").join("index.html"); + builder.maybe_open_in_browser::(index); } } @@ -384,10 +370,7 @@ impl Step for Standalone { // We open doc/index.html as the default if invoked as `x.py doc --open` // with no particular explicit doc requested (e.g. library/core). - if builder.paths.is_empty() || builder.was_invoked_explicitly::(Kind::Doc) { - let index = out.join("index.html"); - open(builder, &index); - } + builder.maybe_open_in_browser::(out.join("index.html")); } } @@ -507,7 +490,7 @@ impl Step for Std { for requested_crate in requested_crates { if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) { let index = out.join(requested_crate).join("index.html"); - open(builder, &index); + builder.open_in_browser(index); } } } @@ -759,7 +742,7 @@ impl Step for Rustc { // Let's open the first crate documentation page: if let Some(krate) = to_open { let index = out.join(krate).join("index.html"); - open(builder, &index); + builder.open_in_browser(index); } } } @@ -1019,10 +1002,9 @@ impl Step for RustcBook { name: INTERNER.intern_str("rustc"), src: INTERNER.intern_path(out_base), }); - if builder.was_invoked_explicitly::(Kind::Doc) { - let out = builder.doc_out(self.target); - let index = out.join("rustc").join("index.html"); - open(builder, &index); - } + + let out = builder.doc_out(self.target); + let index = out.join("rustc").join("index.html"); + builder.maybe_open_in_browser::(index); } } From cf6efe8137d88237b7e280a22eaea2f2193da47d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 25 Oct 2022 16:57:21 -0400 Subject: [PATCH 040/221] Add test case --- .../codegen/auxiliary/static_dllimport_aux.rs | 13 +++++++++++++ .../issue-81408-dllimport-thinlto-windows.rs | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/codegen/auxiliary/static_dllimport_aux.rs create mode 100644 src/test/codegen/issue-81408-dllimport-thinlto-windows.rs diff --git a/src/test/codegen/auxiliary/static_dllimport_aux.rs b/src/test/codegen/auxiliary/static_dllimport_aux.rs new file mode 100644 index 000000000000..afb0dc42f443 --- /dev/null +++ b/src/test/codegen/auxiliary/static_dllimport_aux.rs @@ -0,0 +1,13 @@ +use std::sync::atomic::{AtomicPtr, Ordering}; + +#[inline(always)] +pub fn memrchr() { + fn detect() {} + + static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ()); + + unsafe { + let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst); + std::mem::transmute::<*mut (), fn()>(fun)() + } +} diff --git a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs new file mode 100644 index 000000000000..e674c0561d3b --- /dev/null +++ b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs @@ -0,0 +1,15 @@ +// compile-flags: -O -C lto=thin -C prefer-dynamic=no +// only-windows +// aux-build:static_dllimport_aux.rs + +// Test that on Windows, when performing ThinLTO, we do not mark cross-crate static items with +// dllimport because lld does not fix the symbol names for us. + +extern crate static_dllimport_aux; + +// CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} = +// CHECK-SAME: external dllimport local_unnamed_addr global %"{{.+}}::AtomicPtr + +pub fn main() { + static_dllimport_aux::memrchr(); +} From 296489c89268e56abb8f6050842d006b16ed4f09 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 20 Oct 2022 17:45:09 -0400 Subject: [PATCH 041/221] Fix Access Violation when using lld & ThinLTO on windows-msvc Users report an AV at runtime of the compiled binary when using lld and ThinLTO on windows-msvc. The AV occurs when accessing a static value which is defined in one crate but used in another. Based on the disassembly of the cross-crate use, it appears that the use is not correctly linked with the definition and is instead assigned a garbage pointer value. If we look at the symbol tables for each crates' obj file, we can see what is happening: *lib.obj*: ``` COFF SYMBOL TABLE ... 00E 00000000 SECT2 notype External | _ZN10reproducer7memrchr2FN17h612b61ca0e168901E ... ``` *bin.obj*: ``` COFF SYMBOL TABLE ... 010 00000000 UNDEF notype External | __imp__ZN10reproducer7memrchr2FN17h612b61ca0e168901E ... ``` The use of the symbol has the "import" style symbol name but the declaration doesn't generate any symbol with the same name. As a result, linking the files generates a warning from lld: > rust-lld: warning: bin.obj: locally defined symbol imported: reproducer::memrchr::FN::h612b61ca0e168901 (defined in lib.obj) [LNK4217] and the symbol reference remains undefined at runtime leading to the AV. To fix this, we just need to detect that we are performing ThinLTO (and thus, static linking) and omit the `dllimport` attribute on the extern item in LLVM IR. --- compiler/rustc_codegen_llvm/src/consts.rs | 4 +++- src/test/codegen/issue-81408-dllimport-thinlto-windows.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index dd3c43ba5ca7..bf5ac4e503e3 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -19,6 +19,7 @@ use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; +use rustc_session::config::Lto; use rustc_target::abi::{ AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange, }; @@ -303,7 +304,8 @@ impl<'ll> CodegenCx<'ll, '_> { // ThinLTO can't handle this workaround in all cases, so we don't // emit the attrs. Instead we make them unnecessary by disallowing // dynamic linking when linker plugin based LTO is enabled. - !self.tcx.sess.opts.cg.linker_plugin_lto.enabled(); + !self.tcx.sess.opts.cg.linker_plugin_lto.enabled() && + self.tcx.sess.lto() != Lto::Thin; // If this assertion triggers, there's something wrong with commandline // argument validation. diff --git a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs index e674c0561d3b..0b6ab4f7ecb3 100644 --- a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs +++ b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs @@ -8,7 +8,7 @@ extern crate static_dllimport_aux; // CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} = -// CHECK-SAME: external dllimport local_unnamed_addr global %"{{.+}}::AtomicPtr +// CHECK-SAME: external local_unnamed_addr global %"{{.+}}AtomicPtr pub fn main() { static_dllimport_aux::memrchr(); From 5e4618ff1433e92009c7478933874f5f23b34e29 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 3 Nov 2022 16:42:28 +0100 Subject: [PATCH 042/221] address review comment --- src/bootstrap/doc.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 0045856e2c95..1357718b84e3 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -12,7 +12,7 @@ use std::fs; use std::io; use std::path::{Path, PathBuf}; -use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; +use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::{Config, TargetSelection}; @@ -370,7 +370,10 @@ impl Step for Standalone { // We open doc/index.html as the default if invoked as `x.py doc --open` // with no particular explicit doc requested (e.g. library/core). - builder.maybe_open_in_browser::(out.join("index.html")); + if builder.paths.is_empty() || builder.was_invoked_explicitly::(Kind::Doc) { + let index = out.join("index.html"); + builder.open_in_browser(&index); + } } } From cf83a1d81b203714251a3c4b9c5aab6bd097c7ba Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 3 Nov 2022 10:10:15 -0700 Subject: [PATCH 043/221] std: sync "Dependencies of the `backtrace` crate" with `backtrace` Compare: https://github.com/rust-lang/backtrace-rs/blob/07872f28cd8a65c3c7428811548dc85f1f2fb05b/Cargo.toml#L43 https://github.com/rust-lang/rust/blob/160b19429523ea44c4c3b7cad4233b2a35f58b8f/library/std/Cargo.toml#L26 --- Cargo.lock | 78 ++++++++++++++---------------------------- library/std/Cargo.toml | 6 ++-- 2 files changed, 29 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c2b460d9a857..b032ee3649ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,25 +2,16 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" -dependencies = [ - "compiler_builtins", - "gimli 0.25.0", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "addr2line" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ - "gimli 0.26.1", + "compiler_builtins", + "gimli", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", ] [[package]] @@ -28,16 +19,16 @@ name = "adler" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] [[package]] name = "ahash" @@ -185,12 +176,12 @@ version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ - "addr2line 0.17.0", + "addr2line", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide 0.5.3", - "object 0.29.0", + "object", "rustc-demangle", ] @@ -1546,25 +1537,17 @@ dependencies = [ "wasi 0.9.0+wasi-snapshot-preview1", ] -[[package]] -name = "gimli" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "gimli" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" dependencies = [ + "compiler_builtins", "fallible-iterator", "indexmap", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", "stable_deref_trait", ] @@ -2234,9 +2217,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f" dependencies = [ "adler 0.2.3", - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", ] [[package]] @@ -2246,6 +2226,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler 1.0.2", + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", ] [[package]] @@ -2338,29 +2321,20 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" -dependencies = [ - "compiler_builtins", - "memchr", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "object" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ + "compiler_builtins", "crc32fast", "flate2", "hashbrown", "indexmap", "memchr", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", ] [[package]] @@ -3297,7 +3271,7 @@ dependencies = [ "cstr", "libc", "measureme", - "object 0.29.0", + "object", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3331,7 +3305,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object 0.29.0", + "object", "pathdiff", "regex", "rustc_arena", @@ -4689,7 +4663,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" name = "std" version = "0.0.0" dependencies = [ - "addr2line 0.16.0", + "addr2line", "alloc", "cfg-if 1.0.0", "compiler_builtins", @@ -4699,8 +4673,8 @@ dependencies = [ "hashbrown", "hermit-abi 0.2.6", "libc", - "miniz_oxide 0.4.0", - "object 0.26.2", + "miniz_oxide 0.5.3", + "object", "panic_abort", "panic_unwind", "profiler_builtins", @@ -4917,9 +4891,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6cb0c7868d7f90407531108ab03263d9452a8811b7cdd87675343a40d4aa254" dependencies = [ - "gimli 0.26.1", + "gimli", "hashbrown", - "object 0.29.0", + "object", "tracing", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index bc10b12ec2af..daa6976c3014 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -23,11 +23,11 @@ hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] } # Dependencies of the `backtrace` crate -addr2line = { version = "0.16.0", optional = true, default-features = false } +addr2line = { version = "0.17.0", optional = true, default-features = false } rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] } -miniz_oxide = { version = "0.4.0", optional = true, default-features = false } +miniz_oxide = { version = "0.5.0", optional = true, default-features = false } [dependencies.object] -version = "0.26.1" +version = "0.29.0" optional = true default-features = false features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] From 1e25882944aabcf0c871182b887cd4ffe9c7b330 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 13 Oct 2022 23:27:17 +0800 Subject: [PATCH 044/221] fix #102806, suggest use .. to fill in the rest of the fields of Struct --- .../locales/en-US/parser.ftl | 3 ++ compiler/rustc_parse/src/errors.rs | 9 ++++ compiler/rustc_parse/src/parser/expr.rs | 21 ++++++-- src/test/ui/parser/issue-102806.rs | 22 ++++++++ src/test/ui/parser/issue-102806.stderr | 51 +++++++++++++++++++ 5 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/parser/issue-102806.rs create mode 100644 src/test/ui/parser/issue-102806.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 13c368d1c585..455ff34f7247 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -112,6 +112,9 @@ parser_missing_semicolon_before_array = expected `;`, found `[` parser_invalid_block_macro_segment = cannot use a `block` macro fragment here .label = the `block` fragment is within this context +parser_expect_dotdot_not_dotdotdot = expected `..`, found `...` + .suggestion = use `..` to fill in the rest of the fields + parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition .add_then_block = add a block here .condition_possibly_unfinished = this binary operation is possibly unfinished diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dc2049028429..b02bd6645337 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -368,6 +368,15 @@ pub(crate) struct MissingSemicolonBeforeArray { pub semicolon: Span, } +#[derive(Diagnostic)] +#[diag(parser_expect_dotdot_not_dotdotdot)] +pub(crate) struct MissingDotDot { + #[primary_span] + pub token_span: Span, + #[suggestion_verbose(applicability = "maybe-incorrect", code = "..")] + pub sugg_span: Span, +} + #[derive(Diagnostic)] #[diag(parser_invalid_block_macro_segment)] pub(crate) struct InvalidBlockMacroSegment { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0eb633f64168..7de025e7860d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -20,9 +20,9 @@ use crate::errors::{ InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, - MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, - NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported, - OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, + MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, + NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, + OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, @@ -2897,6 +2897,21 @@ impl<'a> Parser<'a> { } self.recover_struct_comma_after_dotdot(exp_span); break; + } else if self.token == token::DotDotDot { + // suggest `..v` instead of `...v` + let snapshot = self.create_snapshot_for_diagnostic(); + let span = self.token.span; + self.bump(); + match self.parse_expr() { + Ok(_p) => { + self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span }); + break; + } + Err(inner_err) => { + inner_err.cancel(); + self.restore_snapshot(snapshot); + } + } } let recovery_field = self.find_struct_error_after_field_looking_code(); diff --git a/src/test/ui/parser/issue-102806.rs b/src/test/ui/parser/issue-102806.rs new file mode 100644 index 000000000000..f5513c87a92e --- /dev/null +++ b/src/test/ui/parser/issue-102806.rs @@ -0,0 +1,22 @@ +#![allow(dead_code)] + +struct V3 { + x: f32, + y: f32, + z: f32, +} + +fn pz(v: V3) { + let _ = V3 { z: 0.0, ...v}; + //~^ ERROR expected `..` + //~| ERROR missing fields `x` and `y` in initializer of `V3` + let _ = V3 { z: 0.0, ... }; + //~^ expected identifier + //~| ERROR missing fields `x` and `y` in initializer of `V3` + + let _ = V3 { z: 0.0, ...Default::default() }; + //~^ ERROR expected `..` + //~| ERROR missing fields `x` and `y` in initializer of `V3` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-102806.stderr b/src/test/ui/parser/issue-102806.stderr new file mode 100644 index 000000000000..53a43b539614 --- /dev/null +++ b/src/test/ui/parser/issue-102806.stderr @@ -0,0 +1,51 @@ +error: expected `..`, found `...` + --> $DIR/issue-102806.rs:10:26 + | +LL | let _ = V3 { z: 0.0, ...v}; + | ^^^ + | +help: use `..` to fill in the rest of the fields + | +LL | let _ = V3 { z: 0.0, ..v}; + | ~~ + +error: expected identifier, found `...` + --> $DIR/issue-102806.rs:13:26 + | +LL | let _ = V3 { z: 0.0, ... }; + | -- ^^^ expected identifier + | | + | while parsing this struct + +error: expected `..`, found `...` + --> $DIR/issue-102806.rs:17:26 + | +LL | let _ = V3 { z: 0.0, ...Default::default() }; + | ^^^ + | +help: use `..` to fill in the rest of the fields + | +LL | let _ = V3 { z: 0.0, ..Default::default() }; + | ~~ + +error[E0063]: missing fields `x` and `y` in initializer of `V3` + --> $DIR/issue-102806.rs:10:13 + | +LL | let _ = V3 { z: 0.0, ...v}; + | ^^ missing `x` and `y` + +error[E0063]: missing fields `x` and `y` in initializer of `V3` + --> $DIR/issue-102806.rs:13:13 + | +LL | let _ = V3 { z: 0.0, ... }; + | ^^ missing `x` and `y` + +error[E0063]: missing fields `x` and `y` in initializer of `V3` + --> $DIR/issue-102806.rs:17:13 + | +LL | let _ = V3 { z: 0.0, ...Default::default() }; + | ^^ missing `x` and `y` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0063`. From 7dbf2c0ed86a6fc97aa0b93bc2ac865d6f2cc438 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2022 15:17:37 +1100 Subject: [PATCH 045/221] Make non-ASCII errors more consistent. There are three kinds of "byte" literals: byte literals, byte string literals, and raw byte string literals. None are allowed to have non-ASCII chars in them. Two `EscapeError` variants exist for when that constraint is violated. - `NonAsciiCharInByte`: used for byte literals and byte string literals. - `NonAsciiCharInByteString`: used for raw byte string literals. As a result, the messages for raw byte string literals use different wording, without good reason. Also, byte string literals are incorrectly described as "byte constants" in some error messages. This commit eliminates `NonAsciiCharInByteString` so the three cases are handled similarly, and described correctly. The `mode` is enough to distinguish them. Note: Some existing error messages mention "byte constants" and some mention "byte literals". I went with the latter here, because it's a more correct name, as used by the Reference. --- compiler/rustc_lexer/src/unescape.rs | 7 ++-- compiler/rustc_lexer/src/unescape/tests.rs | 7 ++-- .../src/lexer/unescape_error_reporting.rs | 32 ++++++++----------- src/test/ui/attributes/key-value-non-ascii.rs | 2 +- .../ui/attributes/key-value-non-ascii.stderr | 4 +-- src/test/ui/parser/byte-literals.rs | 2 +- src/test/ui/parser/byte-literals.stderr | 4 +-- src/test/ui/parser/byte-string-literals.rs | 4 +-- .../ui/parser/byte-string-literals.stderr | 6 ++-- .../ui/parser/raw/raw-byte-string-literals.rs | 2 +- .../raw/raw-byte-string-literals.stderr | 2 +- .../ui/parser/unicode-control-codepoints.rs | 16 +++++----- .../parser/unicode-control-codepoints.stderr | 24 +++++++------- src/test/ui/suggestions/multibyte-escapes.rs | 12 +++---- .../ui/suggestions/multibyte-escapes.stderr | 12 +++---- 15 files changed, 62 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index f0042a397c2c..9c9cce7cbd48 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -52,10 +52,8 @@ pub enum EscapeError { /// Unicode escape code in byte literal. UnicodeEscapeInByte, - /// Non-ascii character in byte literal. + /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. NonAsciiCharInByte, - /// Non-ascii character in byte string literal. - NonAsciiCharInByteString, /// After a line ending with '\', the next line contains whitespace /// characters that are not skipped. @@ -349,8 +347,7 @@ where let start = src.len() - chars.as_str().len() - c.len_utf8(); let result = match c { '\r' => Err(EscapeError::BareCarriageReturnInRawString), - c if is_byte && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString), - c => Ok(c), + _ => ascii_check(c, is_byte), }; let end = src.len() - chars.as_str().len(); callback(start..end, result); diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs index fa61554afde6..008edef5a638 100644 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ b/compiler/rustc_lexer/src/unescape/tests.rs @@ -289,9 +289,6 @@ fn test_unescape_raw_byte_str() { } check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); - check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]); - check( - "🦀a", - &[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))], - ); + check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByte))]); + check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok(byte_from_char('a')))]); } diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 055ee98a00aa..6373f5b4fd6f 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -231,16 +231,23 @@ pub(crate) fn emit_unescape_error( .emit(); } EscapeError::NonAsciiCharInByte => { - assert!(mode.is_byte()); let (c, span) = last_char(); - let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant"); + let desc = match mode { + Mode::Byte => "byte literal", + Mode::ByteStr => "byte string literal", + Mode::RawByteStr => "raw byte string literal", + _ => panic!("non-is_byte literal paired with NonAsciiCharInByte"), + }; + let mut err = handler.struct_span_err(span, format!("non-ASCII character in {}", desc)); let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { format!(" but is {:?}", c) } else { String::new() }; - err.span_label(span, &format!("byte constant must be ASCII{}", postfix)); - if (c as u32) <= 0xFF { + err.span_label(span, &format!("must be ASCII{}", postfix)); + // Note: the \\xHH suggestions are not given for raw byte string + // literals, because they are araw and so cannot use any escapes. + if (c as u32) <= 0xFF && mode != Mode::RawByteStr { err.span_suggestion( span, &format!( @@ -250,9 +257,9 @@ pub(crate) fn emit_unescape_error( format!("\\x{:X}", c as u32), Applicability::MaybeIncorrect, ); - } else if matches!(mode, Mode::Byte) { + } else if mode == Mode::Byte { err.span_label(span, "this multibyte character does not fit into a single byte"); - } else if matches!(mode, Mode::ByteStr) { + } else if mode != Mode::RawByteStr { let mut utf8 = String::new(); utf8.push(c); err.span_suggestion( @@ -270,19 +277,6 @@ pub(crate) fn emit_unescape_error( } err.emit(); } - EscapeError::NonAsciiCharInByteString => { - assert!(mode.is_byte()); - let (c, span) = last_char(); - let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { - format!(" but is {:?}", c) - } else { - String::new() - }; - handler - .struct_span_err(span, "raw byte string must be ASCII") - .span_label(span, &format!("must be ASCII{}", postfix)) - .emit(); - } EscapeError::OutOfRangeHexEscape => { handler .struct_span_err(span, "out of range hex escape") diff --git a/src/test/ui/attributes/key-value-non-ascii.rs b/src/test/ui/attributes/key-value-non-ascii.rs index 12942eabdf7b..e14e2fc05ad3 100644 --- a/src/test/ui/attributes/key-value-non-ascii.rs +++ b/src/test/ui/attributes/key-value-non-ascii.rs @@ -1,4 +1,4 @@ #![feature(rustc_attrs)] -#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte constant +#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte string literal fn main() {} diff --git a/src/test/ui/attributes/key-value-non-ascii.stderr b/src/test/ui/attributes/key-value-non-ascii.stderr index 422107867f7f..23d482de6a86 100644 --- a/src/test/ui/attributes/key-value-non-ascii.stderr +++ b/src/test/ui/attributes/key-value-non-ascii.stderr @@ -1,8 +1,8 @@ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/key-value-non-ascii.rs:3:19 | LL | #[rustc_dummy = b"ffi.rs"] - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes | diff --git a/src/test/ui/parser/byte-literals.rs b/src/test/ui/parser/byte-literals.rs index 05a510b24a7a..896dc1a1a5fb 100644 --- a/src/test/ui/parser/byte-literals.rs +++ b/src/test/ui/parser/byte-literals.rs @@ -7,6 +7,6 @@ pub fn main() { b'\x0Z'; //~ ERROR invalid character in numeric character escape: `Z` b' '; //~ ERROR byte constant must be escaped b'''; //~ ERROR byte constant must be escaped - b'é'; //~ ERROR non-ASCII character in byte constant + b'é'; //~ ERROR non-ASCII character in byte literal b'a //~ ERROR unterminated byte constant [E0763] } diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr index c3d000616300..efa55ae05bd3 100644 --- a/src/test/ui/parser/byte-literals.stderr +++ b/src/test/ui/parser/byte-literals.stderr @@ -32,11 +32,11 @@ error: byte constant must be escaped: `'` LL | b'''; | ^ help: escape the character: `\'` -error: non-ASCII character in byte constant +error: non-ASCII character in byte literal --> $DIR/byte-literals.rs:10:7 | LL | b'é'; - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the unicode code point for 'é', use a \xHH escape | diff --git a/src/test/ui/parser/byte-string-literals.rs b/src/test/ui/parser/byte-string-literals.rs index b1f11024a7bb..30a4f50c4e40 100644 --- a/src/test/ui/parser/byte-string-literals.rs +++ b/src/test/ui/parser/byte-string-literals.rs @@ -3,7 +3,7 @@ static FOO: &'static [u8] = b"\f"; //~ ERROR unknown byte escape pub fn main() { b"\f"; //~ ERROR unknown byte escape b"\x0Z"; //~ ERROR invalid character in numeric character escape: `Z` - b"é"; //~ ERROR non-ASCII character in byte constant - br##"é"##; //~ ERROR raw byte string must be ASCII + b"é"; //~ ERROR non-ASCII character in byte string literal + br##"é"##; //~ ERROR non-ASCII character in raw byte string literal b"a //~ ERROR unterminated double quote byte string } diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr index 3b8b3692e053..5b96cc3d18ab 100644 --- a/src/test/ui/parser/byte-string-literals.stderr +++ b/src/test/ui/parser/byte-string-literals.stderr @@ -20,18 +20,18 @@ error: invalid character in numeric character escape: `Z` LL | b"\x0Z"; | ^ invalid character in numeric character escape -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/byte-string-literals.rs:6:7 | LL | b"é"; - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the unicode code point for 'é', use a \xHH escape | LL | b"\xE9"; | ~~~~ -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/byte-string-literals.rs:7:10 | LL | br##"é"##; diff --git a/src/test/ui/parser/raw/raw-byte-string-literals.rs b/src/test/ui/parser/raw/raw-byte-string-literals.rs index 163c8ac66b02..1b859fee596a 100644 --- a/src/test/ui/parser/raw/raw-byte-string-literals.rs +++ b/src/test/ui/parser/raw/raw-byte-string-literals.rs @@ -2,6 +2,6 @@ pub fn main() { br"a "; //~ ERROR bare CR not allowed in raw string - br"é"; //~ ERROR raw byte string must be ASCII + br"é"; //~ ERROR non-ASCII character in raw byte string literal br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation } diff --git a/src/test/ui/parser/raw/raw-byte-string-literals.stderr b/src/test/ui/parser/raw/raw-byte-string-literals.stderr index cfc877104bd9..a2f27d1ed70a 100644 --- a/src/test/ui/parser/raw/raw-byte-string-literals.stderr +++ b/src/test/ui/parser/raw/raw-byte-string-literals.stderr @@ -4,7 +4,7 @@ error: bare CR not allowed in raw string LL | br"a "; | ^ -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/raw-byte-string-literals.rs:5:8 | LL | br"é"; diff --git a/src/test/ui/parser/unicode-control-codepoints.rs b/src/test/ui/parser/unicode-control-codepoints.rs index 5af0b585a127..df099bb62ad1 100644 --- a/src/test/ui/parser/unicode-control-codepoints.rs +++ b/src/test/ui/parser/unicode-control-codepoints.rs @@ -14,15 +14,15 @@ fn main() { println!("{:?}", r##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##); //~^ ERROR unicode codepoint changing visible direction of text present in literal println!("{:?}", b"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "); - //~^ ERROR non-ASCII character in byte constant - //~| ERROR non-ASCII character in byte constant - //~| ERROR non-ASCII character in byte constant - //~| ERROR non-ASCII character in byte constant + //~^ ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal println!("{:?}", br##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##); - //~^ ERROR raw byte string must be ASCII - //~| ERROR raw byte string must be ASCII - //~| ERROR raw byte string must be ASCII - //~| ERROR raw byte string must be ASCII + //~^ ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal println!("{:?}", '‮'); //~^ ERROR unicode codepoint changing visible direction of text present in literal } diff --git a/src/test/ui/parser/unicode-control-codepoints.stderr b/src/test/ui/parser/unicode-control-codepoints.stderr index 44548c72ff5d..fc071a941914 100644 --- a/src/test/ui/parser/unicode-control-codepoints.stderr +++ b/src/test/ui/parser/unicode-control-codepoints.stderr @@ -14,69 +14,69 @@ LL | println!("{:?}", b"us\u{202B}e\u{202A}r"); | = help: unicode escape sequences cannot be used as a byte or in a byte string -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:26 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{202e}' + | ^ must be ASCII but is '\u{202e}' | help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes | LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only "); | ~~~~~~~~~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:30 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{2066}' + | ^ must be ASCII but is '\u{2066}' | help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes | LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only "); | ~~~~~~~~~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:41 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{2069}' + | ^ must be ASCII but is '\u{2069}' | help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes | LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only "); | ~~~~~~~~~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:43 | LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ byte constant must be ASCII but is '\u{2066}' + | ^ must be ASCII but is '\u{2066}' | help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes | LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only "); | ~~~~~~~~~~~~ -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:29 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); | ^ must be ASCII but is '\u{202e}' -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:33 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); | ^ must be ASCII but is '\u{2066}' -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:44 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); | ^ must be ASCII but is '\u{2069}' -error: raw byte string must be ASCII +error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:46 | LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); diff --git a/src/test/ui/suggestions/multibyte-escapes.rs b/src/test/ui/suggestions/multibyte-escapes.rs index fd5d46a4e923..c4105186244d 100644 --- a/src/test/ui/suggestions/multibyte-escapes.rs +++ b/src/test/ui/suggestions/multibyte-escapes.rs @@ -2,17 +2,17 @@ fn main() { b'µ'; - //~^ ERROR: non-ASCII character in byte constant + //~^ ERROR: non-ASCII character in byte literal //~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape - //~| NOTE: byte constant must be ASCII + //~| NOTE: must be ASCII b'字'; - //~^ ERROR: non-ASCII character in byte constant + //~^ ERROR: non-ASCII character in byte literal //~| NOTE: this multibyte character does not fit into a single byte - //~| NOTE: byte constant must be ASCII + //~| NOTE: must be ASCII b"字"; - //~^ ERROR: non-ASCII character in byte constant + //~^ ERROR: non-ASCII character in byte string literal //~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes - //~| NOTE: byte constant must be ASCII + //~| NOTE: must be ASCII } diff --git a/src/test/ui/suggestions/multibyte-escapes.stderr b/src/test/ui/suggestions/multibyte-escapes.stderr index 6e26bc1f01ce..1e7c43e6538f 100644 --- a/src/test/ui/suggestions/multibyte-escapes.stderr +++ b/src/test/ui/suggestions/multibyte-escapes.stderr @@ -1,28 +1,28 @@ -error: non-ASCII character in byte constant +error: non-ASCII character in byte literal --> $DIR/multibyte-escapes.rs:4:7 | LL | b'µ'; - | ^ byte constant must be ASCII + | ^ must be ASCII | help: if you meant to use the unicode code point for 'µ', use a \xHH escape | LL | b'\xB5'; | ~~~~ -error: non-ASCII character in byte constant +error: non-ASCII character in byte literal --> $DIR/multibyte-escapes.rs:9:7 | LL | b'字'; | ^^ | | - | byte constant must be ASCII + | must be ASCII | this multibyte character does not fit into a single byte -error: non-ASCII character in byte constant +error: non-ASCII character in byte string literal --> $DIR/multibyte-escapes.rs:14:7 | LL | b"字"; - | ^^ byte constant must be ASCII + | ^^ must be ASCII | help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes | From a21c0458979d786d821c2d75a1b109fe38914da0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2022 16:26:27 +1100 Subject: [PATCH 046/221] Improve comments. Remove a low-value comment, remove a duplicate comment, and correct a third comment. --- compiler/rustc_lexer/src/unescape.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 9c9cce7cbd48..db7bf02e71ad 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -84,12 +84,9 @@ where Mode::Char | Mode::Byte => { let mut chars = src.chars(); let result = unescape_char_or_byte(&mut chars, mode == Mode::Byte); - // The Chars iterator moved forward. callback(0..(src.len() - chars.as_str().len()), result); } Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode == Mode::ByteStr, callback), - // NOTE: Raw strings do not perform any explicit character escaping, here we - // only translate CRLF to LF and produce errors on bare CR. Mode::RawStr | Mode::RawByteStr => { unescape_raw_str_or_raw_byte_str(src, mode == Mode::RawByteStr, callback) } @@ -333,7 +330,7 @@ where /// Takes a contents of a string literal (without quotes) and produces a /// sequence of characters or errors. /// NOTE: Raw strings do not perform any explicit character escaping, here we -/// only translate CRLF to LF and produce errors on bare CR. +/// only produce errors on bare CR. fn unescape_raw_str_or_raw_byte_str(src: &str, is_byte: bool, callback: &mut F) where F: FnMut(Range, Result), From d963686f5a87b9eaa2ac2bdc29ddb796e0e83f1f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Nov 2022 09:19:34 +1100 Subject: [PATCH 047/221] Refactor `cook_lexer_literal`. It deals with eight cases: ints, floats, and the six quoted types (char/byte/strings). For ints and floats we have an early return, and the other six types fall through to the code at the end, which makes the function hard to read. This commit rearranges things to avoid the early returns. --- compiler/rustc_parse/src/lexer/mod.rs | 78 +++++++++++++-------------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 462bce16ad71..61b5be424041 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -363,55 +363,55 @@ impl<'a> StringReader<'a> { fn cook_lexer_literal( &self, start: BytePos, - suffix_start: BytePos, + end: BytePos, kind: rustc_lexer::LiteralKind, ) -> (token::LitKind, Symbol) { - // prefix means `"` or `br"` or `r###"`, ... - let (lit_kind, mode, prefix_len, postfix_len) = match kind { + match kind { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start, suffix_start), + self.mk_sp(start, end), "unterminated character literal", error_code!(E0762), ) } - (token::Char, Mode::Char, 1, 1) // ' ' + self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' ' } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start + BytePos(1), suffix_start), + self.mk_sp(start + BytePos(1), end), "unterminated byte constant", error_code!(E0763), ) } - (token::Byte, Mode::Byte, 2, 1) // b' ' + self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' ' } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start, suffix_start), + self.mk_sp(start, end), "unterminated double quote string", error_code!(E0765), ) } - (token::Str, Mode::Str, 1, 1) // " " + self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " " } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { self.sess.span_diagnostic.span_fatal_with_code( - self.mk_sp(start + BytePos(1), suffix_start), + self.mk_sp(start + BytePos(1), end), "unterminated double quote byte string", error_code!(E0766), ) } - (token::ByteStr, Mode::ByteStr, 2, 1) // b" " + self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" " } rustc_lexer::LiteralKind::RawStr { n_hashes } => { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); - (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "## + let kind = token::StrRaw(n_hashes); + self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "## } else { self.report_raw_str_error(start, 1); } @@ -419,56 +419,47 @@ impl<'a> StringReader<'a> { rustc_lexer::LiteralKind::RawByteStr { n_hashes } => { if let Some(n_hashes) = n_hashes { let n = u32::from(n_hashes); - (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "## + let kind = token::ByteStrRaw(n_hashes); + self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "## } else { self.report_raw_str_error(start, 2); } } rustc_lexer::LiteralKind::Int { base, empty_int } => { - return if empty_int { + if empty_int { self.sess .span_diagnostic .struct_span_err_with_code( - self.mk_sp(start, suffix_start), + self.mk_sp(start, end), "no valid digits found for number", error_code!(E0768), ) .emit(); (token::Integer, sym::integer(0)) } else { - self.validate_int_literal(base, start, suffix_start); - (token::Integer, self.symbol_from_to(start, suffix_start)) - }; + self.validate_int_literal(base, start, end); + (token::Integer, self.symbol_from_to(start, end)) + } } rustc_lexer::LiteralKind::Float { base, empty_exponent } => { if empty_exponent { self.err_span_(start, self.pos, "expected at least one digit in exponent"); } - match base { - Base::Hexadecimal => self.err_span_( - start, - suffix_start, - "hexadecimal float literal is not supported", - ), + Base::Hexadecimal => { + self.err_span_(start, end, "hexadecimal float literal is not supported") + } Base::Octal => { - self.err_span_(start, suffix_start, "octal float literal is not supported") + self.err_span_(start, end, "octal float literal is not supported") } Base::Binary => { - self.err_span_(start, suffix_start, "binary float literal is not supported") + self.err_span_(start, end, "binary float literal is not supported") } - _ => (), + _ => {} } - - let id = self.symbol_from_to(start, suffix_start); - return (token::Float, id); + (token::Float, self.symbol_from_to(start, end)) } - }; - let content_start = start + BytePos(prefix_len); - let content_end = suffix_start - BytePos(postfix_len); - let id = self.symbol_from_to(content_start, content_end); - self.validate_literal_escape(mode, content_start, content_end, prefix_len, postfix_len); - (lit_kind, id) + } } #[inline] @@ -659,20 +650,22 @@ impl<'a> StringReader<'a> { ) } - fn validate_literal_escape( + fn cook_quoted( &self, + kind: token::LitKind, mode: Mode, - content_start: BytePos, - content_end: BytePos, + start: BytePos, + end: BytePos, prefix_len: u32, postfix_len: u32, - ) { + ) -> (token::LitKind, Symbol) { + let content_start = start + BytePos(prefix_len); + let content_end = end - BytePos(postfix_len); let lit_content = self.str_from_to(content_start, content_end); unescape::unescape_literal(lit_content, mode, &mut |range, result| { // Here we only check for errors. The actual unescaping is done later. if let Err(err) = result { - let span_with_quotes = self - .mk_sp(content_start - BytePos(prefix_len), content_end + BytePos(postfix_len)); + let span_with_quotes = self.mk_sp(start, end); let (start, end) = (range.start as u32, range.end as u32); let lo = content_start + BytePos(start); let hi = lo + BytePos(end - start); @@ -688,6 +681,7 @@ impl<'a> StringReader<'a> { ); } }); + (kind, Symbol::intern(lit_content)) } fn validate_int_literal(&self, base: Base, content_start: BytePos, content_end: BytePos) { From a203482d2a20cba0c86298334ebd74438bd477ba Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Nov 2022 10:02:29 +1100 Subject: [PATCH 048/221] Inline and remove `validate_int_literal`. It has a single callsite, and is fairly small. The `Float` match arm already has base-specific checking inline, so this makes things more consistent. --- compiler/rustc_lexer/src/lib.rs | 10 ++++----- compiler/rustc_parse/src/lexer/mod.rs | 31 +++++++++++---------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 51515976e4ee..0d29d7b1e3d9 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -203,13 +203,13 @@ pub enum RawStrError { #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum Base { /// Literal starts with "0b". - Binary, + Binary = 2, /// Literal starts with "0o". - Octal, - /// Literal starts with "0x". - Hexadecimal, + Octal = 8, /// Literal doesn't contain a prefix. - Decimal, + Decimal = 10, + /// Literal starts with "0x". + Hexadecimal = 16, } /// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun", diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 61b5be424041..9de0c74f4b1d 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -437,7 +437,19 @@ impl<'a> StringReader<'a> { .emit(); (token::Integer, sym::integer(0)) } else { - self.validate_int_literal(base, start, end); + if matches!(base, Base::Binary | Base::Octal) { + let base = base as u32; + let s = self.str_from_to(start + BytePos(2), end); + for (idx, c) in s.char_indices() { + if c != '_' && c.to_digit(base).is_none() { + self.err_span_( + start + BytePos::from_usize(2 + idx), + start + BytePos::from_usize(2 + idx + c.len_utf8()), + &format!("invalid digit for a base {} literal", base), + ); + } + } + } (token::Integer, self.symbol_from_to(start, end)) } } @@ -683,23 +695,6 @@ impl<'a> StringReader<'a> { }); (kind, Symbol::intern(lit_content)) } - - fn validate_int_literal(&self, base: Base, content_start: BytePos, content_end: BytePos) { - let base = match base { - Base::Binary => 2, - Base::Octal => 8, - _ => return, - }; - let s = self.str_from_to(content_start + BytePos(2), content_end); - for (idx, c) in s.char_indices() { - let idx = idx as u32; - if c != '_' && c.to_digit(base).is_none() { - let lo = content_start + BytePos(2 + idx); - let hi = content_start + BytePos(2 + idx + c.len_utf8() as u32); - self.err_span_(lo, hi, &format!("invalid digit for a base {} literal", base)); - } - } - } } pub fn nfc_normalize(string: &str) -> Symbol { From f8e2cef5faa7ff77e91ea2d0416006f0b7aa52bf Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 3 Nov 2022 22:01:58 -0700 Subject: [PATCH 049/221] Move intra-doc link checks to a separate function. --- src/tools/linkchecker/main.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 7842611bd4ff..4092722501d0 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -365,6 +365,23 @@ impl Checker { } }); + self.check_intra_doc_links(file, &pretty_path, &source, report); + + // we don't need the source anymore, + // so drop to reduce memory-usage + match self.cache.get_mut(&pretty_path).unwrap() { + FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()), + _ => unreachable!("must be html file"), + } + } + + fn check_intra_doc_links( + &mut self, + file: &Path, + pretty_path: &str, + source: &str, + report: &mut Report, + ) { // Search for intra-doc links that rustdoc didn't warn about // FIXME(#77199, 77200) Rustdoc should just warn about these directly. // NOTE: only looks at one line at a time; in practice this should find most links @@ -379,12 +396,6 @@ impl Checker { } } } - // we don't need the source anymore, - // so drop to reduce memory-usage - match self.cache.get_mut(&pretty_path).unwrap() { - FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()), - _ => unreachable!("must be html file"), - } } /// Load a file from disk, or from the cache if available. From 57b229086e274c21e5544e6719271ae79a952194 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 3 Nov 2022 22:02:39 -0700 Subject: [PATCH 050/221] Remove reference from the intra-doc link checker. --- src/tools/linkchecker/main.rs | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 4092722501d0..4170c32f1fe2 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -55,30 +55,6 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[ #[rustfmt::skip] const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[ - // This will never have links that are not in other pages. - // To avoid repeating the exceptions twice, an empty list means all broken links are allowed. - ("reference/print.html", &[]), - // All the reference 'links' are actually ENBF highlighted as code - ("reference/comments.html", &[ - "/ !", - "* !", - ]), - ("reference/identifiers.html", &[ - "a-z A-Z", - "a-z A-Z 0-9 _", - "a-z A-Z] [a-z A-Z 0-9 _", - ]), - ("reference/tokens.html", &[ - "0-1", - "0-7", - "0-9", - "0-9", - "0-9 a-f A-F", - ]), - ("reference/notation.html", &[ - "b B", - "a-z", - ]), // This is being used in the sense of 'inclusive range', not a markdown link ("core/ops/struct.RangeInclusive.html", &["begin, end"]), ("std/ops/struct.RangeInclusive.html", &["begin, end"]), @@ -382,6 +358,16 @@ impl Checker { source: &str, report: &mut Report, ) { + let relative = file.strip_prefix(&self.root).expect("should always be relative to root"); + // Don't check the reference. It has several legitimate things that + // look like []. The reference has its own broken link + // checker in its CI which handles this using pulldown_cmark. + // + // This checks both the end of the root (when checking just the + // reference directory) or the beginning (when checking all docs). + if self.root.ends_with("reference") || relative.starts_with("reference") { + return; + } // Search for intra-doc links that rustdoc didn't warn about // FIXME(#77199, 77200) Rustdoc should just warn about these directly. // NOTE: only looks at one line at a time; in practice this should find most links From ee7c58bc1615963079edfed0e43d8d3578a55bf3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 4 Nov 2022 06:09:35 +0000 Subject: [PATCH 051/221] Update linker-plugin-lto.md to contain up to Rust 1.65 The table rows were obtained via the script embedded in the page. --- src/doc/rustc/src/linker-plugin-lto.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index b1854b22a7cd..5730f95ad2b9 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -136,7 +136,7 @@ able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS ```sh rustup toolchain install --profile minimal nightly MINOR_VERSION=$(rustc +nightly --version | cut -d . -f 2) -LOWER_BOUND=61 +LOWER_BOUND=66 llvm_version() { toolchain="$1" @@ -193,5 +193,10 @@ The following table shows known good combinations of toolchain versions. | Rust 1.58 | Clang 13 | | Rust 1.59 | Clang 13 | | Rust 1.60 | Clang 14 | +| Rust 1.61 | Clang 14 | +| Rust 1.62 | Clang 14 | +| Rust 1.63 | Clang 14 | +| Rust 1.64 | Clang 14 | +| Rust 1.65 | Clang 15 | Note that the compatibility policy for this feature might change in the future. From 4b77e730b5c9e5126abf12ccca5e36f2a2c66868 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 14 Oct 2022 06:52:23 +0800 Subject: [PATCH 052/221] fake a base to suppress later extra error message --- compiler/rustc_parse/src/errors.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 29 +++++++++----------- src/test/ui/parser/issue-102806.rs | 11 +++++--- src/test/ui/parser/issue-102806.stderr | 36 +++++++++++-------------- 4 files changed, 36 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index b02bd6645337..0924c8537159 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -373,7 +373,7 @@ pub(crate) struct MissingSemicolonBeforeArray { pub(crate) struct MissingDotDot { #[primary_span] pub token_span: Span, - #[suggestion_verbose(applicability = "maybe-incorrect", code = "..")] + #[suggestion(applicability = "maybe-incorrect", code = "..", style = "verbose")] pub sugg_span: Span, } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7de025e7860d..338e6a8e2895 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2880,7 +2880,7 @@ impl<'a> Parser<'a> { }; while self.token != token::CloseDelim(close_delim) { - if self.eat(&token::DotDot) { + if self.eat(&token::DotDot) || self.recover_struct_fileds_dots(close_delim) { let exp_span = self.prev_token.span; // We permit `.. }` on the left-hand side of a destructuring assignment. if self.check(&token::CloseDelim(close_delim)) { @@ -2897,21 +2897,6 @@ impl<'a> Parser<'a> { } self.recover_struct_comma_after_dotdot(exp_span); break; - } else if self.token == token::DotDotDot { - // suggest `..v` instead of `...v` - let snapshot = self.create_snapshot_for_diagnostic(); - let span = self.token.span; - self.bump(); - match self.parse_expr() { - Ok(_p) => { - self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span }); - break; - } - Err(inner_err) => { - inner_err.cancel(); - self.restore_snapshot(snapshot); - } - } } let recovery_field = self.find_struct_error_after_field_looking_code(); @@ -3042,6 +3027,18 @@ impl<'a> Parser<'a> { self.recover_stmt(); } + fn recover_struct_fileds_dots(&mut self, close_delim: Delimiter) -> bool { + if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim)) + && self.eat(&token::DotDotDot) + { + // recover from typo of `...`, suggest `..` + let span = self.prev_token.span; + self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span }); + return true; + } + false + } + /// Parses `ident (COLON expr)?`. fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { let attrs = self.parse_outer_attributes()?; diff --git a/src/test/ui/parser/issue-102806.rs b/src/test/ui/parser/issue-102806.rs index f5513c87a92e..ba297bdc9677 100644 --- a/src/test/ui/parser/issue-102806.rs +++ b/src/test/ui/parser/issue-102806.rs @@ -1,5 +1,6 @@ #![allow(dead_code)] +#[derive(Default)] struct V3 { x: f32, y: f32, @@ -9,14 +10,16 @@ struct V3 { fn pz(v: V3) { let _ = V3 { z: 0.0, ...v}; //~^ ERROR expected `..` - //~| ERROR missing fields `x` and `y` in initializer of `V3` + + let _ = V3 { z: 0.0, ...Default::default() }; + //~^ ERROR expected `..` + let _ = V3 { z: 0.0, ... }; //~^ expected identifier //~| ERROR missing fields `x` and `y` in initializer of `V3` - let _ = V3 { z: 0.0, ...Default::default() }; - //~^ ERROR expected `..` - //~| ERROR missing fields `x` and `y` in initializer of `V3` + let V3 { z: val, ... } = v; + //~^ ERROR expected field pattern } fn main() {} diff --git a/src/test/ui/parser/issue-102806.stderr b/src/test/ui/parser/issue-102806.stderr index 53a43b539614..6872b8bc0afe 100644 --- a/src/test/ui/parser/issue-102806.stderr +++ b/src/test/ui/parser/issue-102806.stderr @@ -1,5 +1,5 @@ error: expected `..`, found `...` - --> $DIR/issue-102806.rs:10:26 + --> $DIR/issue-102806.rs:11:26 | LL | let _ = V3 { z: 0.0, ...v}; | ^^^ @@ -9,16 +9,8 @@ help: use `..` to fill in the rest of the fields LL | let _ = V3 { z: 0.0, ..v}; | ~~ -error: expected identifier, found `...` - --> $DIR/issue-102806.rs:13:26 - | -LL | let _ = V3 { z: 0.0, ... }; - | -- ^^^ expected identifier - | | - | while parsing this struct - error: expected `..`, found `...` - --> $DIR/issue-102806.rs:17:26 + --> $DIR/issue-102806.rs:14:26 | LL | let _ = V3 { z: 0.0, ...Default::default() }; | ^^^ @@ -28,24 +20,26 @@ help: use `..` to fill in the rest of the fields LL | let _ = V3 { z: 0.0, ..Default::default() }; | ~~ -error[E0063]: missing fields `x` and `y` in initializer of `V3` - --> $DIR/issue-102806.rs:10:13 - | -LL | let _ = V3 { z: 0.0, ...v}; - | ^^ missing `x` and `y` - -error[E0063]: missing fields `x` and `y` in initializer of `V3` - --> $DIR/issue-102806.rs:13:13 +error: expected identifier, found `...` + --> $DIR/issue-102806.rs:17:26 | LL | let _ = V3 { z: 0.0, ... }; - | ^^ missing `x` and `y` + | -- ^^^ expected identifier + | | + | while parsing this struct + +error: expected field pattern, found `...` + --> $DIR/issue-102806.rs:21:22 + | +LL | let V3 { z: val, ... } = v; + | ^^^ help: to omit remaining fields, use one fewer `.`: `..` error[E0063]: missing fields `x` and `y` in initializer of `V3` --> $DIR/issue-102806.rs:17:13 | -LL | let _ = V3 { z: 0.0, ...Default::default() }; +LL | let _ = V3 { z: 0.0, ... }; | ^^ missing `x` and `y` -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0063`. From 971a146e5547b0b4963480a880e22d138f1240de Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 3 Nov 2022 12:49:49 -0400 Subject: [PATCH 053/221] Promote {aarch64,i686,x86_64}-unknown-uefi to Tier 2 MCP: https://github.com/rust-lang/compiler-team/issues/555 --- .../host-x86_64/dist-various-2/Dockerfile | 3 ++ src/doc/rustc/src/platform-support.md | 6 +-- .../src/platform-support/unknown-uefi.md | 38 ++++--------------- src/tools/build-manifest/src/main.rs | 3 ++ 4 files changed, 17 insertions(+), 33 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 126c292b38ea..e1adabaac9b5 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -118,6 +118,9 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi ENV TARGETS=$TARGETS,i686-unknown-freebsd ENV TARGETS=$TARGETS,x86_64-unknown-none +ENV TARGETS=$TARGETS,aarch64-unknown-uefi +ENV TARGETS=$TARGETS,i686-unknown-uefi +ENV TARGETS=$TARGETS,x86_64-unknown-uefi # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 3ae9872cf62d..5b4e436da7d5 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -128,6 +128,7 @@ target | std | notes [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat +[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | ARM64 UEFI [`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android `arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL `arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat @@ -149,6 +150,7 @@ target | std | notes [`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL +[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL @@ -181,6 +183,7 @@ target | std | notes `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat `x86_64-unknown-redox` | ✓ | Redox OS +[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI [Fortanix ABI]: https://edp.fortanix.com/ @@ -213,7 +216,6 @@ target | std | host | notes [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore -[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | ARM64 UEFI `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) `aarch64-unknown-netbsd` | ✓ | ✓ | [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD @@ -252,7 +254,6 @@ target | std | host | notes `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD -[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 32-bit UEFI `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | `i686-wrs-vxworks` | ? | | @@ -311,7 +312,6 @@ target | std | host | notes `x86_64-unknown-l4re-uclibc` | ? | | `x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD -[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 64-bit UEFI `x86_64-uwp-windows-gnu` | ✓ | | `x86_64-uwp-windows-msvc` | ✓ | | `x86_64-wrs-vxworks` | ? | | diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 295dec0f0e48..e2bdf73a9299 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -1,6 +1,6 @@ # `*-unknown-uefi` -**Tier: 3** +**Tier: 2** Unified Extensible Firmware Interface (UEFI) targets for application, driver, and core UEFI binaries. @@ -72,28 +72,14 @@ target = ["x86_64-unknown-uefi"] ## Building Rust programs -Rust does not yet ship pre-compiled artifacts for this target. To compile for -this target, you will either need to build Rust with the target enabled (see -"Building rust for UEFI targets" above), or build your own copy of `core` by -using `build-std`, `cargo-buildx`, or similar. - -A native build with the unstable `build-std`-feature can be achieved via: +Starting with Rust 1.67, precompiled artifacts are provided via +`rustup`. For example, to use `x86_64-unknown-uefi`: ```sh -cargo +nightly build \ - -Zbuild-std=core,compiler_builtins \ - -Zbuild-std-features=compiler-builtins-mem \ - --target x86_64-unknown-uefi -``` - -Alternatively, you can install `cargo-xbuild` via -`cargo install --force cargo-xbuild` and build for the UEFI targets via: - -```sh -cargo \ - +nightly \ - xbuild \ - --target x86_64-unknown-uefi +# install cross-compile toolchain +rustup target add x86_64-unknown-uefi +# target flag may be used with any cargo or rustc command +cargo build --target x86_64-unknown-uefi ``` ## Testing @@ -167,18 +153,10 @@ The following code is a valid UEFI application returning immediately upon execution with an exit code of 0. A panic handler is provided. This is executed by rust on panic. For simplicity, we simply end up in an infinite loop. -Note that as of rust-1.31.0, all features used here are stabilized. No unstable -features are required, nor do we rely on nightly compilers. However, if you do -not compile rustc for the UEFI targets, you need a nightly compiler to support -the `-Z build-std` flag. - This example can be compiled as binary crate via `cargo`: ```sh -cargo +nightly build \ - -Zbuild-std=core,compiler_builtins \ - -Zbuild-std-features=compiler-builtins-mem \ - --target x86_64-unknown-uefi +cargo build --target x86_64-unknown-uefi ``` ```rust,ignore (platform-specific,eh-personality-is-unstable) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index b0006cb90bdd..8d081c998653 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -64,6 +64,7 @@ static TARGETS: &[&str] = &[ "aarch64-unknown-none", "aarch64-unknown-none-softfloat", "aarch64-unknown-redox", + "aarch64-unknown-uefi", "arm-linux-androideabi", "arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabihf", @@ -99,6 +100,7 @@ static TARGETS: &[&str] = &[ "i686-unknown-freebsd", "i686-unknown-linux-gnu", "i686-unknown-linux-musl", + "i686-unknown-uefi", "m68k-unknown-linux-gnu", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", @@ -155,6 +157,7 @@ static TARGETS: &[&str] = &[ "x86_64-unknown-none", "x86_64-unknown-redox", "x86_64-unknown-hermit", + "x86_64-unknown-uefi", ]; /// This allows the manifest to contain rust-docs for hosts that don't build From a2325fe3a97f1820a4bd18d180e24c1ac07b9368 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 4 Nov 2022 16:28:01 +0000 Subject: [PATCH 054/221] Remove an option and choose a behaviour-preserving default instead. --- .../rustc_hir_analysis/src/astconv/mod.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 7747ae14a24b..2a61a3ec3306 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -274,7 +274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, - None, + ty::BoundConstness::NotConst, ); if let Some(b) = item_segment.args().bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -324,7 +324,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, - constness: Option, + constness: ty::BoundConstness, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, @@ -538,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut substs_ctx, ); - if let Some(ty::BoundConstness::ConstIfConst) = constness + if let ty::BoundConstness::ConstIfConst = constness && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) { tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } ); @@ -611,7 +611,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, - None, + ty::BoundConstness::NotConst, ); if let Some(b) = item_segment.args().bindings.first() { @@ -641,7 +641,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_ref.path.segments.last().unwrap(), true, - Some(constness), + constness, ) } @@ -668,7 +668,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, Some(self_ty), - Some(constness), + constness, ); let tcx = self.tcx(); @@ -798,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, is_impl: bool, - constness: Option, + constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { let (substs, _) = self.create_substs_for_ast_trait_ref( span, @@ -822,7 +822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, is_impl: bool, - constness: Option, + constness: ty::BoundConstness, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); @@ -2115,7 +2115,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_segment, false, - Some(constness), + constness, ); let item_substs = self.create_substs_for_associated_item( @@ -2686,7 +2686,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &GenericArgs::none(), true, None, - None, + ty::BoundConstness::NotConst, ); EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) .subst(tcx, substs) From 44d1936d003cf393fb69c47d5c316f94850eb403 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 20 Oct 2022 09:39:09 +0000 Subject: [PATCH 055/221] Some tracing and comment cleanups --- .../src/transform/check_consts/qualifs.rs | 3 ++ compiler/rustc_hir/src/hir.rs | 2 ++ compiler/rustc_hir_typeck/src/callee.rs | 5 +-- .../src/infer/canonical/canonicalizer.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 4 +-- .../rustc_mir_dataflow/src/elaborate_drops.rs | 5 ++- compiler/rustc_mir_transform/src/shim.rs | 8 ++--- compiler/rustc_trait_selection/src/infer.rs | 12 ++----- .../rustc_trait_selection/src/traits/mod.rs | 34 +++---------------- .../src/traits/select/mod.rs | 4 ++- 10 files changed, 23 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 335992342a64..d995d533ca3e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -146,6 +146,7 @@ impl Qualif for NeedsNonConstDrop { qualifs.needs_non_const_drop } + #[instrument(level = "trace", skip(cx), ret)] fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { // Avoid selecting for simple cases, such as builtin types. if ty::util::is_trivially_const_drop(ty) { @@ -174,6 +175,8 @@ impl Qualif for NeedsNonConstDrop { return true; }; + trace!(?impl_src); + if !matches!( impl_src, ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ef00c1ffc302..82e260d158bc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -388,6 +388,8 @@ impl<'hir> GenericArgs<'hir> { } #[inline] + /// This function returns the number of type and const generic params. + /// It should only be used for diagnostics. pub fn num_generic_params(&self) -> usize { self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count() } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1b33f2f02b8a..000f4c9b6842 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -129,6 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { output } + #[instrument(level = "debug", skip(self, call_expr, callee_expr, arg_exprs, autoderef), ret)] fn try_overloaded_call_step( &self, call_expr: &'tcx hir::Expr<'tcx>, @@ -138,10 +139,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option> { let adjusted_ty = self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); - debug!( - "try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", - call_expr, adjusted_ty - ); // If the callee is a bare function or a closure, then we're all set. match *adjusted_ty.kind() { diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index a3ff70363403..cb3193e04742 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -495,7 +495,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { } ty::ConstKind::Bound(debruijn, _) => { if debruijn >= self.binder_index { - bug!("escaping bound type during canonicalization") + bug!("escaping bound const during canonicalization") } else { return ct; } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 6c1414f7b8ac..ae0f158ede99 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -511,12 +511,12 @@ impl<'tcx> Instance<'tcx> { Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap() } + #[instrument(level = "debug", skip(tcx), ret)] pub fn fn_once_adapter_instance( tcx: TyCtxt<'tcx>, closure_did: DefId, substs: ty::SubstsRef<'tcx>, ) -> Option> { - debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); let fn_once = tcx.require_lang_item(LangItem::FnOnce, None); let call_once = tcx .associated_items(fn_once) @@ -536,7 +536,7 @@ impl<'tcx> Instance<'tcx> { assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); - debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig); + debug!(?self_ty, ?sig); Some(Instance { def, substs }) } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 23403628c53f..14d265a402ef 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -407,9 +407,8 @@ where self.drop_ladder(fields, succ, unwind).0 } + #[instrument(level = "debug", ret)] fn open_drop_for_box(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock { - debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs); - // drop glue is sent straight to codegen // box cannot be directly dereferenced let unique_ty = adt.non_enum_variant().fields[0].ty(self.tcx(), substs); @@ -431,8 +430,8 @@ where self.drop_subpath(interior, interior_path, succ, unwind_succ) } + #[instrument(level = "debug", ret)] fn open_drop_for_adt(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock { - debug!("open_drop_for_adt({:?}, {:?}, {:?})", self, adt, substs); if adt.variants().is_empty() { return self.elaborator.patch().new_block(BasicBlockData { statements: vec![], diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index bf5906741441..a0ff7550faeb 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -569,17 +569,13 @@ impl<'tcx> CloneShimBuilder<'tcx> { /// Builds a "call" shim for `instance`. The shim calls the function specified by `call_kind`, /// first adjusting its first argument according to `rcvr_adjustment`. +#[instrument(level = "debug", skip(tcx), ret)] fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, rcvr_adjustment: Option, call_kind: CallKind<'tcx>, ) -> Body<'tcx> { - debug!( - "build_call_shim(instance={:?}, rcvr_adjustment={:?}, call_kind={:?})", - instance, rcvr_adjustment, call_kind - ); - // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used // to substitute into the signature of the shim. It is not necessary for users of this // MIR body to perform further substitutions (see `InstanceDef::has_polymorphic_mir_body`). @@ -641,7 +637,7 @@ fn build_call_shim<'tcx>( let span = tcx.def_span(def_id); - debug!("build_call_shim: sig={:?}", sig); + debug!(?sig); let mut local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo::outermost(span); diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 96ac4e9c1292..0f2e22604dc7 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -93,6 +93,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// Normalizes associated types in `value`, potentially returning /// new obligations that must further be processed. + #[instrument(level = "debug", skip(self, cause, param_env), ret)] fn partially_normalize_associated_types_in( &self, cause: ObligationCause<'tcx>, @@ -102,17 +103,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { where T: TypeFoldable<'tcx>, { - debug!("partially_normalize_associated_types_in(value={:?})", value); let mut selcx = traits::SelectionContext::new(self); let traits::Normalized { value, obligations } = traits::normalize(&mut selcx, param_env, cause, value); - debug!( - "partially_normalize_associated_types_in: result={:?} predicates={:?}", - value, obligations - ); InferOk { value, obligations } } + #[instrument(level = "debug", skip(self), ret)] fn type_implements_trait( &self, trait_def_id: DefId, @@ -120,11 +117,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { params: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> traits::EvaluationResult { - debug!( - "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}", - trait_def_id, ty, params, param_env - ); - let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) }; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 9ee6e0a2bf3a..3417bb87c204 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -117,14 +117,12 @@ pub enum TraitQueryMode { } /// Creates predicate obligations from the generic bounds. +#[instrument(level = "debug", skip(cause, param_env))] pub fn predicates_for_generics<'tcx>( cause: impl Fn(usize, Span) -> ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, generic_bounds: ty::InstantiatedPredicates<'tcx>, ) -> impl Iterator> { - let generic_bounds = generic_bounds; - debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); - std::iter::zip(generic_bounds.predicates, generic_bounds.spans).enumerate().map( move |(idx, (predicate, span))| Obligation { cause: cause(idx, span), @@ -140,6 +138,7 @@ pub fn predicates_for_generics<'tcx>( /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). +#[instrument(level = "debug", skip(infcx, param_env, span), ret)] pub fn type_known_to_meet_bound_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -147,12 +146,6 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( def_id: DefId, span: Span, ) -> bool { - debug!( - "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})", - ty, - infcx.tcx.def_path_str(def_id) - ); - let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }); let obligation = Obligation { @@ -163,12 +156,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( }; let result = infcx.predicate_must_hold_modulo_regions(&obligation); - debug!( - "type_known_to_meet_ty={:?} bound={} => {:?}", - ty, - infcx.tcx.def_path_str(def_id), - result - ); + debug!(?result); if result && ty.has_non_region_infer() { // Because of inference "guessing", selection can sometimes claim @@ -190,21 +178,9 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( // *definitively* show that it implements `Copy`. Otherwise, // assume it is move; linear is always ok. match &errors[..] { - [] => { - debug!( - "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", - ty, - infcx.tcx.def_path_str(def_id) - ); - true - } + [] => true, errors => { - debug!( - ?ty, - bound = %infcx.tcx.def_path_str(def_id), - ?errors, - "type_known_to_meet_bound_modulo_regions" - ); + debug!(?errors); false } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9ebff4892016..84be1ced520f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1132,12 +1132,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// filter_impls filters constant trait obligations and candidates that have a positive impl /// for a negative goal and a negative impl for a positive goal - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, candidates))] fn filter_impls( &mut self, candidates: Vec>, obligation: &TraitObligation<'tcx>, ) -> Vec> { + trace!("{candidates:#?}"); let tcx = self.tcx(); let mut result = Vec::with_capacity(candidates.len()); @@ -1177,6 +1178,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + trace!("{result:#?}"); result } From 5965af701090591edad308e9877d72bbe2221b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 2 Nov 2022 15:10:36 +0100 Subject: [PATCH 056/221] rustdoc: render late-bound lifetimes in generic parameter list of cross-crate functions and methods --- src/librustdoc/clean/inline.rs | 16 ++++++++++++++-- src/librustdoc/clean/mod.rs | 20 ++++++++++++++++++-- src/librustdoc/clean/simplify.rs | 5 ++--- src/test/rustdoc/issue-20727.rs | 2 +- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 841c4f9d5300..bfbe143c202a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -243,10 +243,22 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box { let sig = cx.tcx.fn_sig(did); - let predicates = cx.tcx.predicates_of(did); + let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => { + Some(clean::GenericParamDef { + name, + kind: clean::GenericParamDefKind::Lifetime { outlives: Vec::new() }, + }) + } + _ => None, + }); + + let predicates = cx.tcx.explicit_predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, |cx| { // NOTE: generics need to be cleaned before the decl! - let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); + let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); + // FIXME: This does not place parameters in source order (late-bound ones come last) + generics.params.extend(late_bound_regions); let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig); (generics, decl) }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8d38f2df0d85..a179bd3c39f9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1144,12 +1144,28 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } } ty::AssocKind::Fn => { - let generics = clean_ty_generics( + let sig = tcx.fn_sig(assoc_item.def_id); + + let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) + if name != kw::UnderscoreLifetime => + { + Some(GenericParamDef { + name, + kind: GenericParamDefKind::Lifetime { outlives: Vec::new() }, + }) + } + _ => None, + }); + + let mut generics = clean_ty_generics( cx, tcx.generics_of(assoc_item.def_id), tcx.explicit_predicates_of(assoc_item.def_id), ); - let sig = tcx.fn_sig(assoc_item.def_id); + // FIXME: This does not place parameters in source order (late-bound ones come last) + generics.params.extend(late_bound_regions); + let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig); if assoc_item.fn_has_self_parameter { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 1c184f9b2695..cd9dab1b1d57 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -99,9 +99,8 @@ pub(crate) fn merge_bounds( let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); trait_ref.generic_params.append(&mut bound_params); - // Since the parameters (probably) originate from `tcx.collect_*_late_bound_regions` which - // returns a hash set, sort them alphabetically to guarantee a stable and deterministic - // output (and to fully deduplicate them). + // Sort parameters (likely) originating from a hashset alphabetically to + // produce predictable output (and to allow for full deduplication). trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str())); trait_ref.generic_params.dedup_by_key(|p| p.name); diff --git a/src/test/rustdoc/issue-20727.rs b/src/test/rustdoc/issue-20727.rs index f7acffcb4e56..c1a98cd57daf 100644 --- a/src/test/rustdoc/issue-20727.rs +++ b/src/test/rustdoc/issue-20727.rs @@ -19,6 +19,6 @@ pub mod reexport { // @has - '//*[@class="rust trait"]' 'trait Deref {' // @has - '//*[@class="rust trait"]' 'type Target: ?Sized;' // @has - '//*[@class="rust trait"]' \ - // "fn deref(&'a self) -> &'a Self::Target;" + // "fn deref<'a>(&'a self) -> &'a Self::Target;" pub use issue_20727::Deref; } From 9cdab67f6e3f249e677abf3580637fe42324a961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 2 Nov 2022 15:13:54 +0100 Subject: [PATCH 057/221] rustdoc: render unnamed arguments as underscores in cross-crate functions & function pointers for consistency with the way we display local definitions (cleaned from HIR, not from rustc_middle). --- src/librustdoc/clean/mod.rs | 20 ++++++++++++------- src/librustdoc/html/format.rs | 11 ++++------ .../inline_cross/assoc_item_trait_bounds.rs | 2 +- src/test/rustdoc/inline_cross/impl_trait.rs | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a179bd3c39f9..4a3337ffa1f1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -957,12 +957,14 @@ fn clean_args_from_types_and_names<'tcx>( values: types .iter() .enumerate() - .map(|(i, ty)| { - let mut name = names.get(i).map_or(kw::Empty, |ident| ident.name); - if name.is_empty() { - name = kw::Underscore; - } - Argument { name, type_: clean_ty(ty, cx), is_const: false } + .map(|(i, ty)| Argument { + type_: clean_ty(ty, cx), + name: names + .get(i) + .map(|ident| ident.name) + .filter(|ident| !ident.is_empty()) + .unwrap_or(kw::Underscore), + is_const: false, }) .collect(), } @@ -1024,7 +1026,11 @@ fn clean_fn_decl_from_did_and_sig<'tcx>( .iter() .map(|t| Argument { type_: clean_middle_ty(*t, cx, None), - name: names.next().map_or(kw::Empty, |i| i.name), + name: names + .next() + .map(|i| i.name) + .filter(|i| !i.is_empty()) + .unwrap_or(kw::Underscore), is_const: false, }) .collect(), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 06db3fb0ec40..a5c3d35b1b59 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1232,9 +1232,8 @@ impl clean::Arguments { ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { for (i, input) in self.values.iter().enumerate() { - if !input.name.is_empty() { - write!(f, "{}: ", input.name)?; - } + write!(f, "{}: ", input.name)?; + if f.alternate() { write!(f, "{:#}", input.type_.print(cx))?; } else { @@ -1367,10 +1366,8 @@ impl clean::FnDecl { args.push_str("const "); args_plain.push_str("const "); } - if !input.name.is_empty() { - write!(args, "{}: ", input.name); - write!(args_plain, "{}: ", input.name); - } + write!(args, "{}: ", input.name); + write!(args_plain, "{}: ", input.name); if f.alternate() { write!(args, "{:#}", input.type_.print(cx)); diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs index 5f4712aab5b1..b58605b9f1cb 100644 --- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs @@ -33,7 +33,7 @@ extern crate assoc_item_trait_bounds as aux; // @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]' // // @has - '//*[@id="tymethod.make"]' \ -// "fn make(F, impl FnMut(&str) -> bool)\ +// "fn make(_: F, _: impl FnMut(&str) -> bool)\ // where \ // F: FnOnce(u32) -> String, \ // Self::Out2<()>: Protocol" diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index 6c1cf8252a9d..9c4f64659203 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -29,7 +29,7 @@ pub use impl_trait_aux::func4; // @has impl_trait/fn.func5.html // @has - '//pre[@class="rust fn"]' "func5(" // @has - '//pre[@class="rust fn"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>," -// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>" +// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>" // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func5; From 2d9755fa21bb2184e522a48fa6f3d18f0e1bf62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 2 Nov 2022 15:17:34 +0100 Subject: [PATCH 058/221] rustdoc: move cross-crate lifetime/outlives bounds on GAT params from where-clause to param declaration site I've overlooked this in #103190. --- src/librustdoc/clean/mod.rs | 11 ++++++++++- .../rustdoc/inline_cross/assoc_item_trait_bounds.rs | 4 ++++ .../inline_cross/auxiliary/assoc_item_trait_bounds.rs | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4a3337ffa1f1..eba2d23bdaa7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1303,7 +1303,16 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( .. }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { - param_bounds.extend(mem::take(bounds)); + param_bounds.append(bounds); + } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { + param_bounds.extend(bounds.drain(..).map(|bound| match bound { + GenericBound::Outlives(lifetime) => lifetime, + _ => unreachable!(), + })); } else { where_predicates.push(pred); } diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs index b58605b9f1cb..db2491b87b4d 100644 --- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs @@ -38,3 +38,7 @@ extern crate assoc_item_trait_bounds as aux; // F: FnOnce(u32) -> String, \ // Self::Out2<()>: Protocol" pub use aux::Main; + +// @has main/trait.Aid.html +// @has - '//*[@id="associatedtype.Result"]' "type Result<'inter: 'src>" +pub use aux::Aid; diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs index d326e61daea2..6644c8e41478 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs @@ -42,5 +42,5 @@ pub trait Helper { } pub trait Aid<'src> { - type Result<'inter>; + type Result<'inter: 'src>; } From 1ac703448186773dbaa30382ed2423473a2f6bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 2 Nov 2022 15:20:44 +0100 Subject: [PATCH 059/221] rustdoc: render `for<>` param lists of cross-crate trait-object types --- src/librustdoc/clean/mod.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index eba2d23bdaa7..8508d08628a6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -12,7 +12,7 @@ pub(crate) mod utils; use rustc_ast as ast; use rustc_attr as attr; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -1710,8 +1710,25 @@ pub(crate) fn clean_middle_ty<'tcx>( }) .collect(); + let late_bound_regions: FxIndexSet<_> = obj + .iter() + .flat_map(|pb| pb.bound_vars()) + .filter_map(|br| match br { + ty::BoundVariableKind::Region(ty::BrNamed(_, name)) + if name != kw::UnderscoreLifetime => + { + Some(GenericParamDef { + name, + kind: GenericParamDefKind::Lifetime { outlives: vec![] }, + }) + } + _ => None, + }) + .collect(); + let late_bound_regions = late_bound_regions.into_iter().collect(); + let path = external_path(cx, did, false, bindings, substs); - bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() }); + bounds.insert(0, PolyTrait { trait_: path, generic_params: late_bound_regions }); DynTrait(bounds, lifetime) } From 71561f82c3e40a86bce330c8fa32aede3958e53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 2 Nov 2022 15:23:25 +0100 Subject: [PATCH 060/221] rustdoc: render the return type of cross-crate `Fn`-family trait bounds in trait-object types --- src/librustdoc/clean/utils.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index df20dc3fc3f7..824d98113c8f 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -4,7 +4,7 @@ use crate::clean::render_macro_matchers::render_macro_matcher; use crate::clean::{ clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, - PathSegment, Primitive, PrimitiveType, Type, TypeBinding, + PathSegment, Primitive, PrimitiveType, Term, Type, TypeBinding, TypeBindingKind, }; use crate::core::DocContext; use crate::html::format::visibility_to_src_with_space; @@ -113,12 +113,12 @@ fn external_generic_args<'tcx>( ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::>().into(), _ => return GenericArgs::AngleBracketed { args: args.into(), bindings }, }; - let output = None; - // FIXME(#20299) return type comes from a projection now - // match types[1].kind { - // ty::Tuple(ref v) if v.is_empty() => None, // -> () - // _ => Some(types[1].clean(cx)) - // }; + let output = bindings.into_iter().next().and_then(|binding| match binding.kind { + TypeBindingKind::Equality { term: Term::Type(ty) } if ty != Type::Tuple(Vec::new()) => { + Some(Box::new(ty)) + } + _ => None, + }); GenericArgs::Parenthesized { inputs, output } } else { GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() } From 7ec50b629c6ef418a819b39fc332f209e8fa4908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 2 Nov 2022 15:25:04 +0100 Subject: [PATCH 061/221] rustdoc: add test for cross-crate trait-object types as well as some FIXMEs --- src/librustdoc/clean/mod.rs | 3 ++ src/test/rustdoc/assoc-consts.rs | 1 + .../inline_cross/auxiliary/dyn_trait.rs | 17 ++++++++++ src/test/rustdoc/inline_cross/dyn_trait.rs | 31 +++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs create mode 100644 src/test/rustdoc/inline_cross/dyn_trait.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8508d08628a6..d9947e59bf82 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1683,6 +1683,9 @@ pub(crate) fn clean_middle_ty<'tcx>( inline::record_extern_fqn(cx, did, ItemType::Trait); + // FIXME(fmease): Hide the trait-object lifetime bound if it coincides with its default + // to partially address #44306. Follow the rules outlined at + // https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes let lifetime = clean_middle_region(*reg); let mut bounds = dids .map(|did| { diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index a3e10ee5555a..3da19a13e533 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -46,6 +46,7 @@ pub fn f(_: &(ToString + 'static)) {} impl Bar { // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \ // "const F: fn(_: &(dyn ToString + 'static))" + // FIXME(fmease): Hide default lifetime, render "const F: fn(_: &dyn ToString)" pub const F: fn(_: &(ToString + 'static)) = f; } diff --git a/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs b/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs new file mode 100644 index 000000000000..9ac2e3d96deb --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs @@ -0,0 +1,17 @@ +pub type Ty0 = dyn for<'any> FnOnce(&'any str) -> bool; + +pub type Ty1<'obj> = dyn std::fmt::Display + 'obj; + +pub type Ty2 = dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>; + +pub type Ty3<'s> = &'s dyn ToString; + +pub fn func0(_: &(dyn Fn() + '_)) {} + +pub fn func1<'func>(_: &(dyn Fn() + 'func)) {} + +pub trait Container<'r> { + type Item<'a, 'ctx>; +} + +pub trait Shape<'a> {} diff --git a/src/test/rustdoc/inline_cross/dyn_trait.rs b/src/test/rustdoc/inline_cross/dyn_trait.rs new file mode 100644 index 000000000000..fa760540e436 --- /dev/null +++ b/src/test/rustdoc/inline_cross/dyn_trait.rs @@ -0,0 +1,31 @@ +#![crate_name = "user"] + +// aux-crate:dyn_trait=dyn_trait.rs +// edition:2021 + +// @has user/type.Ty0.html +// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static" +// FIXME(fmease): Hide default lifetime bound `'static` +pub use dyn_trait::Ty0; + +// @has user/type.Ty1.html +// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj" +pub use dyn_trait::Ty1; + +// @has user/type.Ty2.html +// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>" +pub use dyn_trait::Ty2; + +// @has user/type.Ty3.html +// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)" +// FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString" +pub use dyn_trait::Ty3; + +// @has user/fn.func0.html +// @has - '//pre[@class="rust fn"]' "func0(_: &dyn Fn())" +// FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))" +pub use dyn_trait::func0; + +// @has user/fn.func1.html +// @has - '//pre[@class="rust fn"]' "func1<'func>(_: &(dyn Fn() + 'func))" +pub use dyn_trait::func1; From 5ccaed212e111e0850a764c1c090261c0c431413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 2 Nov 2022 15:56:28 +0100 Subject: [PATCH 062/221] rustdoc: create helper `GenericParamDef::lifetime` --- src/librustdoc/clean/auto_trait.rs | 5 +---- src/librustdoc/clean/inline.rs | 5 +---- src/librustdoc/clean/mod.rs | 22 ++++++---------------- src/librustdoc/clean/simplify.rs | 5 +---- src/librustdoc/clean/types.rs | 4 ++++ 5 files changed, 13 insertions(+), 28 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 84e77e69ecff..85bd8446640d 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -336,10 +336,7 @@ where match br { // We only care about named late bound regions, as we need to add them // to the 'for<>' section - ty::BrNamed(_, name) => Some(GenericParamDef { - name, - kind: GenericParamDefKind::Lifetime { outlives: vec![] }, - }), + ty::BrNamed(_, name) => Some(GenericParamDef::lifetime(name)), _ => None, } }) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index bfbe143c202a..8a5463c10f21 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -245,10 +245,7 @@ fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box { - Some(clean::GenericParamDef { - name, - kind: clean::GenericParamDefKind::Lifetime { outlives: Vec::new() }, - }) + Some(clean::GenericParamDef::lifetime(name)) } _ => None, }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d9947e59bf82..a83a57bfec3a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -182,10 +182,9 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( .collect_referenced_late_bound_regions(&poly_trait_ref) .into_iter() .filter_map(|br| match br { - ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(GenericParamDef { - name, - kind: GenericParamDefKind::Lifetime { outlives: vec![] }, - }), + ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => { + Some(GenericParamDef::lifetime(name)) + } _ => None, }) .collect(); @@ -741,10 +740,7 @@ fn clean_ty_generics<'tcx>( p.get_bound_params() .into_iter() .flatten() - .map(|param| GenericParamDef { - name: param.0, - kind: GenericParamDefKind::Lifetime { outlives: Vec::new() }, - }) + .map(|param| GenericParamDef::lifetime(param.0)) .collect(), )); } @@ -1156,10 +1152,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => { - Some(GenericParamDef { - name, - kind: GenericParamDefKind::Lifetime { outlives: Vec::new() }, - }) + Some(GenericParamDef::lifetime(name)) } _ => None, }); @@ -1720,10 +1713,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => { - Some(GenericParamDef { - name, - kind: GenericParamDefKind::Lifetime { outlives: vec![] }, - }) + Some(GenericParamDef::lifetime(name)) } _ => None, }) diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index cd9dab1b1d57..7d97d2994e46 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -51,10 +51,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> ThinVec Self { + Self { name, kind: GenericParamDefKind::Lifetime { outlives: Vec::new() } } + } + pub(crate) fn is_synthetic_type_param(&self) -> bool { match self.kind { GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false, From a0cdc85b32765b6f227f6c7d9ae6e8cc661ab5d0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Nov 2022 21:17:39 +0000 Subject: [PATCH 063/221] Remove in_tail_expr from FnCtxt --- compiler/rustc_hir_typeck/src/_match.rs | 123 +++++++++++-------- compiler/rustc_hir_typeck/src/check.rs | 2 - compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 5 - 3 files changed, 73 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 2b15d4dcd084..2290ac948f00 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,6 +1,6 @@ use crate::coercion::{AsCoercionSite, CoerceMany}; use crate::{Diverges, Expectation, FnCtxt, Needs}; -use rustc_errors::{Applicability, MultiSpan}; +use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; @@ -137,55 +137,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(&arm.body), arm_ty, Some(&mut |err| { - let Some(ret) = self - .tcx - .hir() - .find_by_def_id(self.body_id.owner.def_id) - .and_then(|owner| owner.fn_decl()) - .map(|decl| decl.output.span()) - else { return; }; - let Expectation::IsLast(stmt) = orig_expected else { - return - }; - let can_coerce_to_return_ty = match self.ret_coercion.as_ref() { - Some(ret_coercion) if self.in_tail_expr => { - let ret_ty = ret_coercion.borrow().expected_ty(); - let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); - self.can_coerce(arm_ty, ret_ty) - && prior_arm.map_or(true, |(_, t, _)| self.can_coerce(t, ret_ty)) - // The match arms need to unify for the case of `impl Trait`. - && !matches!(ret_ty.kind(), ty::Opaque(..)) - } - _ => false, - }; - if !can_coerce_to_return_ty { - return; - } - - let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi()); - let mut ret_span: MultiSpan = semi_span.into(); - ret_span.push_span_label( - expr.span, - "this could be implicitly returned but it is a statement, not a \ - tail expression", - ); - ret_span - .push_span_label(ret, "the `match` arms can conform to this return type"); - ret_span.push_span_label( - semi_span, - "the `match` is a statement because of this semicolon, consider \ - removing it", - ); - err.span_note( - ret_span, - "you might have meant to return the `match` expression", - ); - err.tool_only_span_suggestion( - semi_span, - "remove this semicolon", - "", - Applicability::MaybeIncorrect, - ); + self.suggest_removing_semicolon_for_coerce( + err, + expr, + orig_expected, + arm_ty, + prior_arm, + ) }), false, ); @@ -219,6 +177,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coercion.complete(self) } + fn suggest_removing_semicolon_for_coerce( + &self, + diag: &mut Diagnostic, + expr: &hir::Expr<'tcx>, + expectation: Expectation<'tcx>, + arm_ty: Ty<'tcx>, + prior_arm: Option<(Option, Ty<'tcx>, Span)>, + ) { + let hir = self.tcx.hir(); + + // First, check that we're actually in the tail of a function. + let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, _), .. }) = + hir.get(self.body_id) else { return; }; + let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. }) + = block.innermost_block().stmts.last() else { return; }; + if last_expr.hir_id != expr.hir_id { + return; + } + + // Next, make sure that we have no type expectation. + let Some(ret) = hir + .find_by_def_id(self.body_id.owner.def_id) + .and_then(|owner| owner.fn_decl()) + .map(|decl| decl.output.span()) else { return; }; + let Expectation::IsLast(stmt) = expectation else { + return; + }; + + let can_coerce_to_return_ty = match self.ret_coercion.as_ref() { + Some(ret_coercion) => { + let ret_ty = ret_coercion.borrow().expected_ty(); + let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); + self.can_coerce(arm_ty, ret_ty) + && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty)) + // The match arms need to unify for the case of `impl Trait`. + && !matches!(ret_ty.kind(), ty::Opaque(..)) + } + _ => false, + }; + if !can_coerce_to_return_ty { + return; + } + + let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi()); + let mut ret_span: MultiSpan = semi_span.into(); + ret_span.push_span_label( + expr.span, + "this could be implicitly returned but it is a statement, not a \ + tail expression", + ); + ret_span.push_span_label(ret, "the `match` arms can conform to this return type"); + ret_span.push_span_label( + semi_span, + "the `match` is a statement because of this semicolon, consider \ + removing it", + ); + diag.span_note(ret_span, "you might have meant to return the `match` expression"); + diag.tool_only_span_suggestion( + semi_span, + "remove this semicolon", + "", + Applicability::MaybeIncorrect, + ); + } + /// When the previously checked expression (the scrutinee) diverges, /// warn the user about the match arms being unreachable. fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm<'tcx>]) { diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index b706d786b525..3b0b00f2aba5 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -142,7 +142,6 @@ pub(super) fn check_fn<'a, 'tcx>( inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); - fcx.in_tail_expr = true; if let ty::Dynamic(..) = declared_ret_ty.kind() { // FIXME: We need to verify that the return type is `Sized` after the return expression has // been evaluated so that we have types available for all the nodes being returned, but that @@ -161,7 +160,6 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); fcx.check_return_expr(&body.value, false); } - fcx.in_tail_expr = false; // We insert the deferred_generator_interiors entry after visiting the body. // This ensures that all nested generators appear before the entry of this generator. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index c36c01e1b46d..02b3e06d9024 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -68,10 +68,6 @@ pub struct FnCtxt<'a, 'tcx> { /// any). pub(super) ret_coercion: Option>>, - /// Used exclusively to reduce cost of advanced evaluation used for - /// more helpful diagnostics. - pub(super) in_tail_expr: bool, - /// First span of a return site that we find. Used in error messages. pub(super) ret_coercion_span: Cell>, @@ -140,7 +136,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_env, err_count_on_creation: inh.tcx.sess.err_count(), ret_coercion: None, - in_tail_expr: false, ret_coercion_span: Cell::new(None), resume_yield_tys: None, ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)), From 4e7fc663cc674a33cc7078096ad1b0269618c456 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Nov 2022 21:16:20 +0000 Subject: [PATCH 064/221] Don't silently eat label before block in block-like expr --- .../rustc_parse/src/parser/diagnostics.rs | 12 +- src/test/ui/parser/label-after-block-like.rs | 43 +++++ .../ui/parser/label-after-block-like.stderr | 176 ++++++++++++++++++ 3 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/parser/label-after-block-like.rs create mode 100644 src/test/ui/parser/label-after-block-like.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7dc4fd0044f1..c609aa93da3a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2468,11 +2468,15 @@ impl<'a> Parser<'a> { } pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool { - let Some(label) = self.eat_label().filter(|_| { - self.eat(&token::Colon) && self.token.kind == token::OpenDelim(Delimiter::Brace) - }) else { + // Check for `'a : {` + if !(self.check_lifetime() + && self.look_ahead(1, |tok| tok.kind == token::Colon) + && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Brace))) + { return false; - }; + } + let label = self.eat_label().expect("just checked if a label exists"); + self.bump(); // eat `:` let span = label.ident.span.to(self.prev_token.span); let mut err = self.struct_span_err(span, "block label not supported here"); err.span_label(span, "not supported here"); diff --git a/src/test/ui/parser/label-after-block-like.rs b/src/test/ui/parser/label-after-block-like.rs new file mode 100644 index 000000000000..55f3f8f9f5f0 --- /dev/null +++ b/src/test/ui/parser/label-after-block-like.rs @@ -0,0 +1,43 @@ +fn a() { + if let () = () 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn b() { + if true 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn c() { + loop 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn d() { + while true 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn e() { + while let () = () 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn f() { + for _ in 0..0 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn g() { + unsafe 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn main() {} diff --git a/src/test/ui/parser/label-after-block-like.stderr b/src/test/ui/parser/label-after-block-like.stderr new file mode 100644 index 000000000000..8ff50b124b32 --- /dev/null +++ b/src/test/ui/parser/label-after-block-like.stderr @@ -0,0 +1,176 @@ +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:2:20 + | +LL | if let () = () 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:2:20 + | +LL | if let () = () 'a {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/label-after-block-like.rs:2:8 + | +LL | if let () = () 'a {} + | ^^^^^^^^^^^ +help: try placing this code inside a block + | +LL | if let () = () { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:8:13 + | +LL | if true 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:8:13 + | +LL | if true 'a {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/label-after-block-like.rs:8:8 + | +LL | if true 'a {} + | ^^^^ +help: try placing this code inside a block + | +LL | if true { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:14:10 + | +LL | loop 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:14:10 + | +LL | loop 'a {} + | ---- ^^ expected `{` + | | + | while parsing this `loop` expression + | +help: try placing this code inside a block + | +LL | loop { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:20:16 + | +LL | while true 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:20:16 + | +LL | while true 'a {} + | ----- ---- ^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + | +help: try placing this code inside a block + | +LL | while true { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:26:23 + | +LL | while let () = () 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:26:23 + | +LL | while let () = () 'a {} + | ----- ----------- ^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + | +help: try placing this code inside a block + | +LL | while let () = () { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:32:19 + | +LL | for _ in 0..0 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:32:19 + | +LL | for _ in 0..0 'a {} + | ^^ expected `{` + | +help: try placing this code inside a block + | +LL | for _ in 0..0 { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:38:12 + | +LL | unsafe 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:38:12 + | +LL | unsafe 'a {} + | ------ ^^ expected `{` + | | + | while parsing this `unsafe` expression + | +help: try placing this code inside a block + | +LL | unsafe { 'a {} } + | + + + +error: aborting due to 14 previous errors + From cb184bb0233b32371be8b3c0681c7a41fa036c10 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 4 Nov 2022 15:13:13 -0700 Subject: [PATCH 065/221] rustdoc: clean up `.logo-container` layout CSS This commit should result in no appearance changes. To make the logo container exactly the desired height, you want to get rid of the part of the box used for typographic descenders (you know, the part of g, y, and j that descends below the baseline). After all, it contains no text, but the space is still left open in the layout by default, because `` is `display:inline`. The CSS used to employ three different tricks to accomplish this: * By making `.sidebar .logo-container` a flex container, the image becomes a flex item and is [blockified], without synthesizing any inline boxes. No inline boxes means no descenders. * By giving `.mobile-topbar .logo-container` a max-height exactly the same as the height of the image plus the padding, the descender area gets cut off. * By setting `.sub-logo-container { line-height: 0 }`, we ensure that the only box that contributes to the height of the line box is the image itself, and not any zero-content text boxes that neighbor it. See the [logical height algorithm]. This commit gets rid of the first two hacks, leaving only the third, since it requires only one line of code to accomplish and doesn't require setting the value based on math. [blockified]: https://drafts.csswg.org/css-flexbox-1/#flex-items [logical height algorithm]: https://www.w3.org/TR/css-inline-3/#inline-height --- src/librustdoc/html/static/css/rustdoc.css | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 54f6e1ed4d51..41341e9c3c56 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -367,7 +367,8 @@ img { overflow: visible; } -.sub-logo-container { +.sub-logo-container, .logo-container { + /* zero text boxes so that computed line height = image height exactly */ line-height: 0; } @@ -465,10 +466,9 @@ img { } .sidebar .logo-container { - display: flex; margin-top: 10px; margin-bottom: 10px; - justify-content: center; + text-align: center; } .version { @@ -1762,10 +1762,6 @@ in storage.js white-space: nowrap; } - .mobile-topbar .logo-container { - max-height: 45px; - } - .mobile-topbar .logo-container > img { max-width: 35px; max-height: 35px; From a838952239493d9dafe2d5f2ca1204f326841ae9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Nov 2022 11:09:23 +1100 Subject: [PATCH 066/221] Remove `unescape_byte_literal`. It's easy to just use `unescape_literal` + `byte_from_char`. --- compiler/rustc_ast/src/util/literal.rs | 29 +++++++------------ compiler/rustc_lexer/src/unescape.rs | 16 ++-------- compiler/rustc_lexer/src/unescape/tests.rs | 12 ++++---- .../crates/syntax/src/validation.rs | 6 ++-- 4 files changed, 20 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 536b385606c6..8f342175f7d3 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -2,12 +2,9 @@ use crate::ast::{self, Lit, LitKind}; use crate::token::{self, Token}; - -use rustc_lexer::unescape::{unescape_byte, unescape_char}; -use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode}; +use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; - use std::ascii; pub enum LitError { @@ -109,13 +106,11 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Err(LitError::LexerError); } } }); @@ -127,13 +122,11 @@ impl LitKind { let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Err(LitError::LexerError); } } }); diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index db7bf02e71ad..8d5eac29452e 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -93,19 +93,6 @@ where } } -/// Takes a contents of a byte, byte string or raw byte string (without quotes) -/// and produces a sequence of bytes or errors. -/// Values are returned through invoking of the provided callback. -pub fn unescape_byte_literal(src: &str, mode: Mode, callback: &mut F) -where - F: FnMut(Range, Result), -{ - debug_assert!(mode.is_byte()); - unescape_literal(src, mode, &mut |range, result| { - callback(range, result.map(byte_from_char)); - }) -} - /// Takes a contents of a char literal (without quotes), and returns an /// unescaped char or an error pub fn unescape_char(src: &str) -> Result { @@ -351,7 +338,8 @@ where } } -fn byte_from_char(c: char) -> u8 { +#[inline] +pub fn byte_from_char(c: char) -> u8 { let res = c as u32; debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr"); res as u8 diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs index 008edef5a638..00c8401efdfe 100644 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ b/compiler/rustc_lexer/src/unescape/tests.rs @@ -246,10 +246,10 @@ fn test_unescape_byte_good() { fn test_unescape_byte_str_good() { fn check(literal_text: &str, expected: &[u8]) { let mut buf = Ok(Vec::with_capacity(literal_text.len())); - unescape_byte_literal(literal_text, Mode::ByteStr, &mut |range, c| { + unescape_literal(literal_text, Mode::ByteStr, &mut |range, c| { if let Ok(b) = &mut buf { match c { - Ok(c) => b.push(c), + Ok(c) => b.push(byte_from_char(c)), Err(e) => buf = Err((range, e)), } } @@ -280,15 +280,13 @@ fn test_unescape_raw_str() { #[test] fn test_unescape_raw_byte_str() { - fn check(literal: &str, expected: &[(Range, Result)]) { + fn check(literal: &str, expected: &[(Range, Result)]) { let mut unescaped = Vec::with_capacity(literal.len()); - unescape_byte_literal(literal, Mode::RawByteStr, &mut |range, res| { - unescaped.push((range, res)) - }); + unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res))); assert_eq!(unescaped, expected); } check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByte))]); - check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok(byte_from_char('a')))]); + check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok('a'))]); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index b9f2b5132353..1eea2346451d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -5,9 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{ - self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode, -}; +use rustc_lexer::unescape::{self, unescape_byte, unescape_char, unescape_literal, Mode}; use crate::{ algo, @@ -143,7 +141,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { ast::LiteralKind::ByteString(s) => { if !s.is_raw() { if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { if let Err(err) = char { push_err(2, (range.start, err)); } From 43d21b535f003c81a55331c31e16313a90050b18 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Nov 2022 13:52:44 +1100 Subject: [PATCH 067/221] Rename some `result` variables as `res`, for consistency. --- compiler/rustc_lexer/src/unescape.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 8d5eac29452e..674bbff0878c 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -83,8 +83,8 @@ where match mode { Mode::Char | Mode::Byte => { let mut chars = src.chars(); - let result = unescape_char_or_byte(&mut chars, mode == Mode::Byte); - callback(0..(src.len() - chars.as_str().len()), result); + let res = unescape_char_or_byte(&mut chars, mode == Mode::Byte); + callback(0..(src.len() - chars.as_str().len()), res); } Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode == Mode::ByteStr, callback), Mode::RawStr | Mode::RawByteStr => { @@ -263,7 +263,7 @@ where // them in the range computation. while let Some(c) = chars.next() { let start = src.len() - chars.as_str().len() - c.len_utf8(); - let result = match c { + let res = match c { '\\' => { match chars.clone().next() { Some('\n') => { @@ -284,7 +284,7 @@ where _ => ascii_check(c, is_byte), }; let end = src.len() - chars.as_str().len(); - callback(start..end, result); + callback(start..end, res); } fn skip_ascii_whitespace(chars: &mut Chars<'_>, start: usize, callback: &mut F) @@ -329,12 +329,12 @@ where // doesn't have to worry about skipping any chars. while let Some(c) = chars.next() { let start = src.len() - chars.as_str().len() - c.len_utf8(); - let result = match c { + let res = match c { '\r' => Err(EscapeError::BareCarriageReturnInRawString), _ => ascii_check(c, is_byte), }; let end = src.len() - chars.as_str().len(); - callback(start..end, result); + callback(start..end, res); } } From df668b9fb960855ca1483ea520862c1eb8184d25 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 3 Oct 2022 12:14:48 +0300 Subject: [PATCH 068/221] simplify applying closure requirements Don't use `ConstraintCategory::ClosureBounds`! Set the category and the span for the promoted constraints to that of the original constraint earlier than before. This eliminates the need for `closure_bounds_mapping`. --- .../rustc_borrowck/src/constraints/graph.rs | 1 + .../rustc_borrowck/src/constraints/mod.rs | 3 + compiler/rustc_borrowck/src/nll.rs | 2 - .../src/region_infer/dump_mir.rs | 3 +- .../rustc_borrowck/src/region_infer/mod.rs | 146 ++---------------- .../src/type_check/constraint_conversion.rs | 75 +++++++-- compiler/rustc_borrowck/src/type_check/mod.rs | 96 +++--------- .../src/type_check/relate_tys.rs | 1 + ...tion-two-region-trait-bound-closure.stderr | 7 +- 9 files changed, 97 insertions(+), 237 deletions(-) diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs index 609fbc2bc151..385f153174c3 100644 --- a/compiler/rustc_borrowck/src/constraints/graph.rs +++ b/compiler/rustc_borrowck/src/constraints/graph.rs @@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> { span: DUMMY_SP, category: ConstraintCategory::Internal, variance_info: VarianceDiagInfo::default(), + from_closure: false, }) } else { None diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index df04128135b8..9d9c4abb0aa5 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> { /// Variance diagnostic information pub variance_info: VarianceDiagInfo<'tcx>, + + /// If this constraint is promoted from closure requirements. + pub from_closure: bool, } impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> { diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 08fdd28eb01b..4e0205f8d43a 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( mut liveness_constraints, outlives_constraints, member_constraints, - closure_bounds_mapping, universe_causes, type_tests, } = constraints; @@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( universal_region_relations, outlives_constraints, member_constraints, - closure_bounds_mapping, universe_causes, type_tests, liveness_constraints, diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index fe5193102f95..cc9450999525 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); constraints.sort_by_key(|c| (c.sup, c.sub)); for constraint in &constraints { - let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } = - constraint; + let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint; let (name, arg) = match locations { Locations::All(span) => { ("All", tcx.sess.source_map().span_to_embeddable_string(*span)) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 0e7f243bcf36..6782fc0665f0 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; use rustc_errors::Diagnostic; -use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; +use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::CRATE_HIR_ID; use rustc_index::vec::IndexVec; -use rustc_infer::infer::canonical::QueryOutlivesConstraint; use rustc_infer::infer::outlives::test_type_match; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; @@ -19,9 +18,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::{ - self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable, -}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_span::Span; use crate::{ @@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> { /// `member_region_scc`. member_constraints_applied: Vec, - /// Map closure bounds to a `Span` that should be used for error reporting. - closure_bounds_mapping: - FxHashMap, Span)>>, - /// Map universe indexes to information on why we created it. universe_causes: FxHashMap>, @@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { universal_region_relations: Frozen>, outlives_constraints: OutlivesConstraintSet<'tcx>, member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, - closure_bounds_mapping: FxHashMap< - Location, - FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>, - >, universe_causes: FxHashMap>, type_tests: Vec>, liveness_constraints: LivenessValues, @@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { rev_scc_graph: None, member_constraints, member_constraints_applied: Vec::new(), - closure_bounds_mapping, universe_causes, scc_universes, scc_representatives, @@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - pub(crate) fn retrieve_closure_constraint_info( - &self, - constraint: OutlivesConstraint<'tcx>, - ) -> Option<(ConstraintCategory<'tcx>, Span)> { - match constraint.locations { - Locations::All(_) => None, - Locations::Single(loc) => { - self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied() - } - } - } - /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`. pub(crate) fn find_outlives_blame_span( &self, @@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { span: p_c.definition_span, category: ConstraintCategory::OpaqueType, variance_info: ty::VarianceDiagInfo::default(), + from_closure: false, }; handle_constraint(constraint); } @@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Classify each of the constraints along the path. let mut categorized_path: Vec> = path .iter() - .map(|constraint| { - let (category, span, from_closure, cause_code) = - if constraint.category == ConstraintCategory::ClosureBounds { - if let Some((category, span)) = - self.retrieve_closure_constraint_info(*constraint) - { - (category, span, true, ObligationCauseCode::MiscObligation) - } else { - ( - constraint.category, - constraint.span, - false, - ObligationCauseCode::MiscObligation, - ) - } - } else { - (constraint.category, constraint.span, false, cause_code.clone()) - }; - BlameConstraint { - category, - from_closure, - cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code), - variance_info: constraint.variance_info, - outlives_constraint: *constraint, - } + .map(|constraint| BlameConstraint { + category: constraint.category, + from_closure: constraint.from_closure, + cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()), + variance_info: constraint.variance_info, + outlives_constraint: *constraint, }) .collect(); debug!("categorized_path={:#?}", categorized_path); @@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> { } } -pub trait ClosureRegionRequirementsExt<'tcx> { - fn apply_requirements( - &self, - tcx: TyCtxt<'tcx>, - closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, - ) -> Vec>; -} - -impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> { - /// Given an instance T of the closure type, this method - /// instantiates the "extra" requirements that we computed for the - /// closure into the inference context. This has the effect of - /// adding new outlives obligations to existing variables. - /// - /// As described on `ClosureRegionRequirements`, the extra - /// requirements are expressed in terms of regionvids that index - /// into the free regions that appear on the closure type. So, to - /// do this, we first copy those regions out from the type T into - /// a vector. Then we can just index into that vector to extract - /// out the corresponding region from T and apply the - /// requirements. - fn apply_requirements( - &self, - tcx: TyCtxt<'tcx>, - closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, - ) -> Vec> { - debug!( - "apply_requirements(closure_def_id={:?}, closure_substs={:?})", - closure_def_id, closure_substs - ); - - // Extract the values of the free regions in `closure_substs` - // into a vector. These are the regions that we will be - // relating to one another. - let closure_mapping = &UniversalRegions::closure_mapping( - tcx, - closure_substs, - self.num_external_vids, - closure_def_id.expect_local(), - ); - debug!("apply_requirements: closure_mapping={:?}", closure_mapping); - - // Create the predicates. - self.outlives_requirements - .iter() - .map(|outlives_requirement| { - let outlived_region = closure_mapping[outlives_requirement.outlived_free_region]; - - match outlives_requirement.subject { - ClosureOutlivesSubject::Region(region) => { - let region = closure_mapping[region]; - debug!( - "apply_requirements: region={:?} \ - outlived_region={:?} \ - outlives_requirement={:?}", - region, outlived_region, outlives_requirement, - ); - ( - ty::Binder::dummy(ty::OutlivesPredicate( - region.into(), - outlived_region, - )), - ConstraintCategory::BoringNoLocation, - ) - } - - ClosureOutlivesSubject::Ty(ty) => { - debug!( - "apply_requirements: ty={:?} \ - outlived_region={:?} \ - outlives_requirement={:?}", - ty, outlived_region, outlives_requirement, - ); - ( - ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)), - ConstraintCategory::BoringNoLocation, - ) - } - } - }) - .collect() - } -} - #[derive(Clone, Debug)] pub struct BlameConstraint<'tcx> { pub category: ConstraintCategory<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index d5bfc2f52082..88be80c0b558 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -1,10 +1,10 @@ -use rustc_infer::infer::canonical::QueryOutlivesConstraint; +use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; -use rustc_middle::mir::ConstraintCategory; +use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, TyCtxt}; @@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { locations: Locations, span: Span, category: ConstraintCategory<'tcx>, + from_closure: bool, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } @@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { span, category, constraints, + from_closure: false, } } @@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } self.constraints.member_constraints = tmp; - for query_constraint in outlives { - self.convert(query_constraint); + for (predicate, constraint_category) in outlives { + // At the moment, we never generate any "higher-ranked" + // region constraints like `for<'a> 'a: 'b`. At some point + // when we move to universes, we will, and this assertion + // will start to fail. + let predicate = predicate.no_bound_vars().unwrap_or_else(|| { + bug!("query_constraint {:?} contained bound vars", predicate,); + }); + + self.convert(predicate, *constraint_category); } } - fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) { + /// Given an instance of the closure type, this method instantiates the "extra" requirements + /// that we computed for the closure. This has the effect of adding new outlives obligations + /// to existing region variables in `closure_substs`. + #[instrument(skip(self), level = "debug")] + pub fn apply_closure_requirements( + &mut self, + closure_requirements: &ClosureRegionRequirements<'tcx>, + closure_def_id: DefId, + closure_substs: ty::SubstsRef<'tcx>, + ) { + // Extract the values of the free regions in `closure_substs` + // into a vector. These are the regions that we will be + // relating to one another. + let closure_mapping = &UniversalRegions::closure_mapping( + self.tcx, + closure_substs, + closure_requirements.num_external_vids, + closure_def_id.expect_local(), + ); + debug!(?closure_mapping); + + // Create the predicates. + let backup = (self.category, self.span, self.from_closure); + self.from_closure = true; + for outlives_requirement in &closure_requirements.outlives_requirements { + let outlived_region = closure_mapping[outlives_requirement.outlived_free_region]; + let subject = match outlives_requirement.subject { + ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(), + ClosureOutlivesSubject::Ty(ty) => ty.into(), + }; + + self.category = outlives_requirement.category; + self.span = outlives_requirement.blame_span; + self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category); + } + (self.category, self.span, self.from_closure) = backup; + } + + fn convert( + &mut self, + predicate: ty::OutlivesPredicate, ty::Region<'tcx>>, + constraint_category: ConstraintCategory<'tcx>, + ) { debug!("generate: constraints at: {:#?}", self.locations); // Extract out various useful fields we'll need below. @@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { tcx, region_bound_pairs, implicit_region_bound, param_env, .. } = *self; - // At the moment, we never generate any "higher-ranked" - // region constraints like `for<'a> 'a: 'b`. At some point - // when we move to universes, we will, and this assertion - // will start to fail. - let ty::OutlivesPredicate(k1, r2) = - query_constraint.0.no_bound_vars().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound vars", query_constraint,); - }); - - let constraint_category = query_constraint.1; - + let ty::OutlivesPredicate(k1, r2) = predicate; match k1.unpack() { GenericArgKind::Lifetime(r1) => { let r1_vid = self.to_region_vid(r1); @@ -188,6 +230,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { sub, sup, variance_info: ty::VarianceDiagInfo::default(), + from_closure: self.from_closure, }); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3c1c3ab45ce7..3d9e08b4ca7b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::AssertKind; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::cast::CastTy; -use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; +use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic, @@ -61,7 +61,7 @@ use crate::{ region_infer::values::{ LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, }, - region_infer::{ClosureRegionRequirementsExt, TypeTest}, + region_infer::TypeTest, type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, universal_regions::{DefiningTy, UniversalRegions}, Upvar, @@ -144,7 +144,6 @@ pub(crate) fn type_check<'mir, 'tcx>( liveness_constraints: LivenessValues::new(elements.clone()), outlives_constraints: OutlivesConstraintSet::default(), member_constraints: MemberConstraintSet::default(), - closure_bounds_mapping: Default::default(), type_tests: Vec::default(), universe_causes: FxHashMap::default(), }; @@ -585,7 +584,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let all_facts = &mut None; let mut constraints = Default::default(); let mut type_tests = Default::default(); - let mut closure_bounds = Default::default(); let mut liveness_constraints = LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body))); // Don't try to add borrow_region facts for the promoted MIR @@ -597,10 +595,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { &mut constraints, ); mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests); - mem::swap( - &mut this.cx.borrowck_context.constraints.closure_bounds_mapping, - &mut closure_bounds, - ); mem::swap( &mut this.cx.borrowck_context.constraints.liveness_constraints, &mut liveness_constraints, @@ -653,18 +647,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { .add_element(region, location); } } - - if !closure_bounds.is_empty() { - let combined_bounds_mapping = - closure_bounds.into_iter().flat_map(|(_, value)| value).collect(); - let existing = self - .cx - .borrowck_context - .constraints - .closure_bounds_mapping - .insert(location, combined_bounds_mapping); - assert!(existing.is_none(), "Multiple promoteds/closures at the same location."); - } } fn sanitize_projection( @@ -941,9 +923,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>, - pub(crate) closure_bounds_mapping: - FxHashMap, Span)>>, - pub(crate) universe_causes: FxHashMap>, pub(crate) type_tests: Vec>, @@ -2562,6 +2541,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span: location.to_locations().span(body), category, variance_info: ty::VarianceDiagInfo::default(), + from_closure: false, }); match mutbl { @@ -2679,62 +2659,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { substs: SubstsRef<'tcx>, location: Location, ) -> ty::InstantiatedPredicates<'tcx> { - if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements - { - let closure_constraints = QueryRegionConstraints { - outlives: closure_region_requirements.apply_requirements( - tcx, - def_id.to_def_id(), - substs, - ), - - // Presently, closures never propagate member - // constraints to their parents -- they are enforced - // locally. This is largely a non-issue as member - // constraints only come from `-> impl Trait` and - // friends which don't appear (thus far...) in - // closures. - member_constraints: vec![], - }; - - let bounds_mapping = closure_constraints - .outlives - .iter() - .enumerate() - .filter_map(|(idx, constraint)| { - let ty::OutlivesPredicate(k1, r2) = - constraint.0.no_bound_vars().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound vars", constraint,); - }); - - match k1.unpack() { - GenericArgKind::Lifetime(r1) => { - // constraint is r1: r2 - let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1); - let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2); - let outlives_requirements = - &closure_region_requirements.outlives_requirements[idx]; - Some(( - (r1_vid, r2_vid), - (outlives_requirements.category, outlives_requirements.blame_span), - )) - } - GenericArgKind::Type(_) | GenericArgKind::Const(_) => None, - } - }) - .collect(); - - let existing = self - .borrowck_context - .constraints - .closure_bounds_mapping - .insert(location, bounds_mapping); - assert!(existing.is_none(), "Multiple closures at the same location."); - - self.push_region_constraints( + if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements { + constraint_conversion::ConstraintConversion::new( + self.infcx, + self.borrowck_context.universal_regions, + self.region_bound_pairs, + self.implicit_region_bound, + self.param_env, location.to_locations(), - ConstraintCategory::ClosureBounds, - &closure_constraints, + DUMMY_SP, // irrelevant; will be overrided. + ConstraintCategory::Boring, // same as above. + &mut self.borrowck_context.constraints, + ) + .apply_closure_requirements( + &closure_requirements, + def_id.to_def_id(), + substs, ); } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 4f2dc263bf57..94d510328660 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -136,6 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> span: self.locations.span(self.type_checker.body), category: self.category, variance_info: info, + from_closure: false, }, ); } diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 0195a693e5ff..1260a656c98f 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -167,7 +167,7 @@ LL | | T: Anything<'b, 'b>, = note: defining type: two_regions::<'_#1r, T> error: lifetime may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:87:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:87:5 | LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -175,9 +175,12 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:97:29 From 02f78fdb940b913228953b7530c9e429ce35bb8a Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 3 Oct 2022 13:45:02 +0300 Subject: [PATCH 069/221] use spans in TypeTest rather than mir::Location Spans are independent of the body being borrow-checked, so they don't need remapping when promoting type-tests and they yield more specific error spans inside bodies of closures/inline consts. --- .../src/diagnostics/region_errors.rs | 2 +- .../rustc_borrowck/src/region_infer/mod.rs | 16 ++++----- .../src/type_check/constraint_conversion.rs | 7 ++-- compiler/rustc_borrowck/src/type_check/mod.rs | 9 ----- src/test/ui/consts/issue-102117.rs | 4 +-- src/test/ui/consts/issue-102117.stderr | 24 ++++--------- .../generic-associated-types/issue-91139.rs | 1 + .../issue-91139.stderr | 13 ++++++- .../propagate-from-trait-match.rs | 3 +- .../propagate-from-trait-match.stderr | 13 ++----- ...98589-closures-relate-named-regions.stderr | 8 ++--- src/test/ui/nll/issue-98693.rs | 2 +- src/test/ui/nll/issue-98693.stderr | 9 ++--- .../projection-implied-bounds.stderr | 4 +-- .../projection-no-regions-closure.stderr | 8 ++--- .../projection-one-region-closure.stderr | 8 ++--- ...tion-two-region-trait-bound-closure.stderr | 8 ++--- ...ram-closure-approximate-lower-bound.stderr | 4 +-- ...m-closure-outlives-from-return-type.stderr | 4 +-- ...aram-closure-outlives-from-where-clause.rs | 5 ++- ...-closure-outlives-from-where-clause.stderr | 36 +++++++------------ 21 files changed, 76 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 15230718dc0d..196ddbe8d504 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Try to convert the lower-bound region into something named we can print for the user. let lower_bound_region = self.to_error_region(type_test.lower_bound); - let type_test_span = type_test.locations.span(&self.body); + let type_test_span = type_test.span; if let Some(lower_bound_region) = lower_bound_region { let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx); diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 6782fc0665f0..94e9e05e5d64 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -214,8 +214,8 @@ pub struct TypeTest<'tcx> { /// The region `'x` that the type must outlive. pub lower_bound: RegionVid, - /// Where did this constraint arise and why? - pub locations: Locations, + /// The span to blame. + pub span: Span, /// A test which, if met by the region `'x`, proves that this type /// constraint is satisfied. @@ -870,13 +870,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { if deduplicate_errors.insert(( erased_generic_kind, type_test.lower_bound, - type_test.locations, + type_test.span, )) { debug!( "check_type_test: reporting error for erased_generic_kind={:?}, \ lower_bound_region={:?}, \ - type_test.locations={:?}", - erased_generic_kind, type_test.lower_bound, type_test.locations, + type_test.span={:?}", + erased_generic_kind, type_test.lower_bound, type_test.span, ); errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); @@ -919,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> bool { let tcx = infcx.tcx; - let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test; + let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test; let generic_ty = generic_kind.to_ty(tcx); let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { @@ -947,7 +947,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { propagated_outlives_requirements.push(ClosureOutlivesRequirement { subject, outlived_free_region: static_r, - blame_span: locations.span(body), + blame_span: type_test.span, category: ConstraintCategory::Boring, }); @@ -999,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let requirement = ClosureOutlivesRequirement { subject, outlived_free_region: upper_bound, - blame_span: locations.span(body), + blame_span: type_test.span, category: ConstraintCategory::Boring, }; debug!("try_promote_type_test: pushing {:#?}", requirement); diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 88be80c0b558..ce7f857e2731 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -169,10 +169,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { .type_must_outlive(origin, t1, r2, constraint_category); } - GenericArgKind::Const(_) => { - // Consts cannot outlive one another, so we - // don't need to handle any relations here. - } + GenericArgKind::Const(_) => unreachable!(), } } @@ -202,7 +199,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { verify_bound: VerifyBound<'tcx>, ) -> TypeTest<'tcx> { let lower_bound = self.to_region_vid(region); - TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound } + TypeTest { generic_kind, lower_bound, span: self.span, verify_bound } } fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3d9e08b4ca7b..50af229baaae 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -583,7 +583,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // modify their locations. let all_facts = &mut None; let mut constraints = Default::default(); - let mut type_tests = Default::default(); let mut liveness_constraints = LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body))); // Don't try to add borrow_region facts for the promoted MIR @@ -594,7 +593,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { &mut this.cx.borrowck_context.constraints.outlives_constraints, &mut constraints, ); - mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests); mem::swap( &mut this.cx.borrowck_context.constraints.liveness_constraints, &mut liveness_constraints, @@ -615,13 +613,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { swap_constraints(self); let locations = location.to_locations(); - - // Use location of promoted const in collected constraints - for type_test in type_tests.iter() { - let mut type_test = type_test.clone(); - type_test.locations = locations; - self.cx.borrowck_context.constraints.type_tests.push(type_test) - } for constraint in constraints.outlives().iter() { let mut constraint = constraint.clone(); constraint.locations = locations; diff --git a/src/test/ui/consts/issue-102117.rs b/src/test/ui/consts/issue-102117.rs index b77342c4135e..3ed90aed2350 100644 --- a/src/test/ui/consts/issue-102117.rs +++ b/src/test/ui/consts/issue-102117.rs @@ -14,11 +14,11 @@ pub struct VTable { impl VTable { pub fn new() -> &'static Self { const { - //~^ ERROR the parameter type `T` may not live long enough - //~| ERROR the parameter type `T` may not live long enough &VTable { layout: Layout::new::(), type_id: TypeId::of::(), + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough drop_in_place: unsafe { transmute::(drop_in_place::) }, diff --git a/src/test/ui/consts/issue-102117.stderr b/src/test/ui/consts/issue-102117.stderr index eb4b329bd813..f42bcf90fb75 100644 --- a/src/test/ui/consts/issue-102117.stderr +++ b/src/test/ui/consts/issue-102117.stderr @@ -1,14 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-102117.rs:16:9 + --> $DIR/issue-102117.rs:19:26 | -LL | / const { -LL | | -LL | | -LL | | &VTable { -... | -LL | | } -LL | | } - | |_________^ ...so that the type `T` will meet its required lifetime bounds +LL | type_id: TypeId::of::(), + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -16,16 +10,10 @@ LL | pub fn new() -> &'static Self { | +++++++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-102117.rs:16:9 + --> $DIR/issue-102117.rs:19:26 | -LL | / const { -LL | | -LL | | -LL | | &VTable { -... | -LL | | } -LL | | } - | |_________^ ...so that the type `T` will meet its required lifetime bounds +LL | type_id: TypeId::of::(), + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs index 5fc6071c9396..e321da53d566 100644 --- a/src/test/ui/generic-associated-types/issue-91139.rs +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -21,6 +21,7 @@ fn foo() { //~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough //~| ERROR `T` may not live long enough + //~| ERROR `T` may not live long enough // // FIXME: This error is bogus, but it arises because we try to validate // that `<() as Foo>::Type<'a>` is valid, which requires proving diff --git a/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr index 8bbe98fa1e50..5485570cecd7 100644 --- a/src/test/ui/generic-associated-types/issue-91139.stderr +++ b/src/test/ui/generic-associated-types/issue-91139.stderr @@ -22,6 +22,17 @@ error: `T` does not live long enough LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-91139.rs:14:58 + | +LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo() { + | +++++++++ + error: `T` does not live long enough --> $DIR/issue-91139.rs:14:58 | @@ -57,6 +68,6 @@ error: `T` does not live long enough LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs index 3bdb54339485..cda781d8e263 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs @@ -30,8 +30,6 @@ where T: Trait<'a>, { establish_relationships(value, |value| { - //~^ ERROR the parameter type `T` may not live long enough - // This function call requires that // // (a) T: Trait<'a> @@ -43,6 +41,7 @@ where // The latter does not hold. require(value); + //~^ ERROR the parameter type `T` may not live long enough }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 750b08bbe855..038a5e11f88c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -23,17 +23,10 @@ LL | | T: Trait<'a>, = note: defining type: supply::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/propagate-from-trait-match.rs:32:36 + --> $DIR/propagate-from-trait-match.rs:43:9 | -LL | establish_relationships(value, |value| { - | ____________________________________^ -LL | | -LL | | -LL | | // This function call requires that -... | -LL | | require(value); -LL | | }); - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | require(value); + | ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr index 6def5602e70b..d8b26f0b0171 100644 --- a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr +++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr @@ -35,10 +35,10 @@ LL | || { None::<&'a &'b ()>; }; = help: consider adding the following bound: `'b: 'a` error[E0309]: the parameter type `T` may not live long enough - --> $DIR/issue-98589-closures-relate-named-regions.rs:26:5 + --> $DIR/issue-98589-closures-relate-named-regions.rs:26:10 | LL | || { None::<&'a T>; }; - | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -46,10 +46,10 @@ LL | fn test_early_type<'a: 'a, T: 'a>() { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/issue-98589-closures-relate-named-regions.rs:32:5 + --> $DIR/issue-98589-closures-relate-named-regions.rs:32:10 | LL | || { None::<&'a T>; }; - | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/issue-98693.rs b/src/test/ui/nll/issue-98693.rs index 18e6ec630464..7a325e2e998f 100644 --- a/src/test/ui/nll/issue-98693.rs +++ b/src/test/ui/nll/issue-98693.rs @@ -13,8 +13,8 @@ where fn test() { || { - //~^ ERROR the parameter type `T` may not live long enough assert_static::(); + //~^ ERROR the parameter type `T` may not live long enough }; } diff --git a/src/test/ui/nll/issue-98693.stderr b/src/test/ui/nll/issue-98693.stderr index 31689620c641..15ca38aa25dc 100644 --- a/src/test/ui/nll/issue-98693.stderr +++ b/src/test/ui/nll/issue-98693.stderr @@ -1,11 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/issue-98693.rs:15:5 + --> $DIR/issue-98693.rs:16:9 | -LL | / || { -LL | | -LL | | assert_static::(); -LL | | }; - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | assert_static::(); + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr index 3b9b2956c518..d949e29b2b81 100644 --- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -1,8 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/projection-implied-bounds.rs:30:18 + --> $DIR/projection-implied-bounds.rs:30:36 | LL | twice(value, |value_ref, item| invoke2(value_ref, item)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index ee1f7b64bb23..4933b9348683 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -23,10 +23,10 @@ LL | | T: Iterator, = note: defining type: no_region::<'_#1r, T> error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:25:23 + --> $DIR/projection-no-regions-closure.rs:25:31 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'a`... = note: ...so that the type `::Item` will meet its required lifetime bounds @@ -80,10 +80,10 @@ LL | | T: 'b + Iterator, = note: defining type: wrong_region::<'_#1r, '_#2r, T> error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:42:23 + --> $DIR/projection-no-regions-closure.rs:42:31 | LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'a`... = note: ...so that the type `::Item` will meet its required lifetime bounds diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 4e57dfad794e..dbda04c42c5c 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -25,10 +25,10 @@ LL | | T: Anything<'b>, = note: defining type: no_relationships_late::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:45:29 + --> $DIR/projection-one-region-closure.rs:45:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -75,10 +75,10 @@ LL | | 'a: 'a, = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:56:29 + --> $DIR/projection-one-region-closure.rs:56:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 1260a656c98f..90f04914286c 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -24,10 +24,10 @@ LL | | T: Anything<'b, 'c>, = note: defining type: no_relationships_late::<'_#1r, '_#2r, T> error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:38:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... = note: ...so that the type `>::AssocType` will meet its required lifetime bounds @@ -58,10 +58,10 @@ LL | | 'a: 'a, = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:48:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... = note: ...so that the type `>::AssocType` will meet its required lifetime bounds diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 61c7d2550caa..f316a551cffa 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -44,10 +44,10 @@ LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { = note: defining type: generic_fail:: error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:31 | LL | twice(cell, value, |a, b| invoke(a, b)); - | ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 50d9e3aabe2d..35979c8bf517 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -23,10 +23,10 @@ LL | | T: Debug, = note: defining type: no_region::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27 | LL | with_signature(x, |y| y) - | ^^^^^ ...so that the type `T` will meet its required lifetime bounds + | ^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs index d7702def32c5..b80287610504 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs @@ -25,13 +25,12 @@ where #[rustc_regions] fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { with_signature(a, b, |x, y| { - //~^ ERROR the parameter type `T` may not live long enough - // // See `correct_region`, which explains the point of this // test. The only difference is that, in the case of this // function, there is no where clause *anywhere*, and hence we // get an error (but reported by the closure creator). require(&x, &y) + //~^ ERROR the parameter type `T` may not live long enough }) } @@ -62,9 +61,9 @@ where T: 'b, { with_signature(a, b, |x, y| { - //~^ ERROR the parameter type `T` may not live long enough // See `correct_region` require(&x, &y) + //~^ ERROR the parameter type `T` may not live long enough }) } diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 14c55e32a3eb..4c97db58c6c3 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -22,17 +22,10 @@ LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { = note: defining type: no_region:: error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:32:9 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | -LL | | // -LL | | // See `correct_region`, which explains the point of this -... | -LL | | require(&x, &y) -LL | | }) - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | require(&x, &y) + | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -40,7 +33,7 @@ LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) { | ++++ note: external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:42:26 | LL | with_signature(a, b, |x, y| { | ^^^^^^ @@ -54,7 +47,7 @@ LL | with_signature(a, b, |x, y| { = note: where T: '_#2r note: no external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:1 | LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) LL | | where @@ -64,7 +57,7 @@ LL | | T: 'a, = note: defining type: correct_region::<'_#1r, T> note: external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:63:26 | LL | with_signature(a, b, |x, y| { | ^^^^^^ @@ -79,7 +72,7 @@ LL | with_signature(a, b, |x, y| { = note: where T: '_#2r note: no external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:59:1 | LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | | where @@ -89,15 +82,10 @@ LL | | T: 'b, = note: defining type: wrong_region::<'_#1r, T> error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9 | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | -LL | | // See `correct_region` -LL | | require(&x, &y) -LL | | }) - | |_____^ ...so that the type `T` will meet its required lifetime bounds +LL | require(&x, &y) + | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | @@ -105,7 +93,7 @@ LL | T: 'b + 'a, | ++++ note: external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26 | LL | with_signature(a, b, |x, y| { | ^^^^^^ @@ -119,7 +107,7 @@ LL | with_signature(a, b, |x, y| { = note: where T: '_#3r note: no external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1 | LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | | where From d5899efbdab28d6f5ecd95c68d03dfd1bdbfba1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Sat, 5 Nov 2022 12:19:55 +0100 Subject: [PATCH 070/221] Update several crates for improved support of the new targets This helps with `*-windows-gnullvm` targets --- Cargo.lock | 64 +++++++++++-------- compiler/rustc_data_structures/Cargo.toml | 2 +- src/bootstrap/Cargo.lock | 75 ++++++++++++++++++++--- src/bootstrap/Cargo.toml | 2 +- 4 files changed, 107 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f230f50212a3..9b452e051f99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2522,7 +2522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.3", + "parking_lot_core 0.9.4", ] [[package]] @@ -2541,15 +2541,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -2774,9 +2774,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.16" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" dependencies = [ "cc", ] @@ -4677,9 +4677,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90939d5171a4420b3ff5fbc8954d641e7377335454c259dcb80786f3f21dc9b4" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" dependencies = [ "cc", "cfg-if 1.0.0", @@ -5499,17 +5499,25 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.28.0" @@ -5518,9 +5526,9 @@ checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" @@ -5530,9 +5538,9 @@ checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" @@ -5542,9 +5550,9 @@ checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" @@ -5554,9 +5562,15 @@ checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" @@ -5566,9 +5580,9 @@ checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "xattr" diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 5152d5ab0465..5afce15e26bf 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -23,7 +23,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } stable_deref_trait = "1.0.0" -stacker = "0.1.14" +stacker = "0.1.15" tempfile = "3.2" thin-vec = "0.2.9" tracing = "0.1" diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index baecca44cd98..e1a108cea957 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -224,13 +224,13 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517" +checksum = "0c93a581058d957dc4176875aad04f82f81613e6611d64aa1a9c755bdfb16711" dependencies = [ "cfg-if", "rustix", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -528,7 +528,7 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -721,43 +721,100 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "xattr" version = "0.2.3" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 95e711737738..f74738437ea3 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,7 +36,7 @@ test = false [dependencies] cmake = "0.1.38" -fd-lock = "3.0.6" +fd-lock = "3.0.7" filetime = "0.2" getopts = "0.2.19" cc = "1.0.69" From dad327090af66f0519f5beaf471ae293834dae7f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Nov 2022 12:25:58 +0100 Subject: [PATCH 071/221] fix a comment in UnsafeCell::new --- library/core/src/cell.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 7bf32cb0d98f..bb924fb9e8e2 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1936,7 +1936,7 @@ impl UnsafeCell { /// Constructs a new instance of `UnsafeCell` which will wrap the specified /// value. /// - /// All access to the inner value through methods is `unsafe`. + /// All access to the inner value through `&UnsafeCell` requires `unsafe` code. /// /// # Examples /// From e49d10db14c618e2635d0e21b6e32cb2e1df78cf Mon Sep 17 00:00:00 2001 From: AndyJado <101876416+AndyJado@users.noreply.github.com> Date: Wed, 26 Oct 2022 10:42:05 +0800 Subject: [PATCH 072/221] first move on a nested span_label Apply suggestions from code review Co-authored-by: David Wood --- .../src/diagnostics/conflict_errors.rs | 14 ++++++--- .../rustc_borrowck/src/diagnostics/mod.rs | 20 +++++++++++++ .../rustc_borrowck/src/session_diagnostics.rs | 30 +++++++++++++++++++ .../locales/en-US/borrowck.ftl | 12 ++++++++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8987a51757cd..7f26e970e309 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -724,13 +724,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - - borrow_spans.var_span_label( + borrow_spans.var_subdiag( &mut err, - { + |var_span| { + use crate::session_diagnostics::CaptureVarCause::*; let place = &borrow.borrowed_place; let desc_place = self.describe_any_place(place.as_ref()); - format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) + match borrow_spans { + UseSpans::ClosureUse { generator_kind, .. } => match generator_kind { + Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span }, + None => BorrowUsePlaceClosure { place: desc_place, var_span }, + }, + _ => BorrowUsePlace { place: desc_place, var_span }, + } }, "mutable", ); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 534d9ecae6e6..61518378e3d0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -623,6 +623,26 @@ impl UseSpans<'_> { } } + /// Add a subdiagnostic to the use of the captured variable, if it exists. + pub(super) fn var_subdiag( + self, + err: &mut Diagnostic, + f: impl Fn(Span) -> crate::session_diagnostics::CaptureVarCause, + kind_desc: impl Into, + ) { + if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self { + if capture_kind_span == path_span { + err.subdiagnostic(f(capture_kind_span)); + } else { + err.subdiagnostic(crate::session_diagnostics::CaptureVarKind { + kind_desc: kind_desc.into(), + kind_span: capture_kind_span, + }); + err.subdiagnostic(f(path_span)); + } + } + } + /// Returns `false` if this place is not used in a closure. pub(super) fn for_closure(&self) -> bool { match *self { diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index fe24f85fae10..824f20a31bb0 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -148,3 +148,33 @@ pub(crate) enum RequireStaticErr { multi_span: MultiSpan, }, } + +#[derive(Subdiagnostic)] +#[label(borrowck_capture_kind_label)] +pub(crate) struct CaptureVarKind { + pub kind_desc: String, + #[primary_span] + pub kind_span: Span, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureVarCause { + #[label(borrowck_var_borrow_by_use_place)] + BorrowUsePlace { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_place_in_generator)] + BorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_place_in_closure)] + BorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, +} diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 67f2156f32e5..80fc4c6e4f5d 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -58,3 +58,15 @@ borrowck_returned_lifetime_short = borrowck_used_impl_require_static = the used `impl` has a `'static` requirement + +borrowck_capture_kind_label = + capture is {$kind_desc} because of use here + +borrowck_var_borrow_by_use_place_in_generator = + borrow occurs due to use of {$place} in closure in generator + +borrowck_var_borrow_by_use_place_in_closure = + borrow occurs due to use of {$place} in closure + +borrowck_var_borrow_by_use_place = + borrow occurs due to use of {$place} From 24093fc6bd442be45a3ddb935b7056ab77cf96f5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 28 Oct 2022 14:58:21 +0400 Subject: [PATCH 073/221] resolve: More detailed effective visibility tracking for imports Also drop `extern` blocks from the effective visibility table, they are nominally private and it doesn't make sense to keep them there. --- compiler/rustc_middle/src/middle/privacy.rs | 43 ++-- .../src/effective_visibilities.rs | 203 +++++++++++------- compiler/rustc_resolve/src/lib.rs | 23 +- src/test/ui/privacy/effective_visibilities.rs | 2 +- .../ui/privacy/effective_visibilities.stderr | 2 +- .../ui/privacy/effective_visibilities_glob.rs | 21 ++ .../effective_visibilities_glob.stderr | 26 +++ 7 files changed, 213 insertions(+), 107 deletions(-) create mode 100644 src/test/ui/privacy/effective_visibilities_glob.rs create mode 100644 src/test/ui/privacy/effective_visibilities_glob.stderr diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index ffbd6d10da6b..3d7a379c56cd 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -7,6 +7,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::LocalDefId; +use std::hash::Hash; /// Represents the levels of effective visibility an item can have. /// @@ -74,9 +75,9 @@ impl EffectiveVisibility { } /// Holds a map of effective visibilities for reachable HIR nodes. -#[derive(Default, Clone, Debug)] -pub struct EffectiveVisibilities { - map: FxHashMap, +#[derive(Clone, Debug)] +pub struct EffectiveVisibilities { + map: FxHashMap, } impl EffectiveVisibilities { @@ -111,10 +112,6 @@ impl EffectiveVisibilities { }) } - pub fn effective_vis(&self, id: LocalDefId) -> Option<&EffectiveVisibility> { - self.map.get(&id) - } - pub fn iter(&self) -> impl Iterator { self.map.iter() } @@ -136,27 +133,31 @@ impl EffectiveVisibilities { } self.map.insert(id, effective_vis); } +} + +impl EffectiveVisibilities { + pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { + self.map.get(&id) + } // `parent_id` is not necessarily a parent in source code tree, // it is the node from which the maximum effective visibility is inherited. pub fn update( &mut self, - id: LocalDefId, + id: Id, nominal_vis: Visibility, - default_vis: impl FnOnce() -> Visibility, - parent_id: LocalDefId, + default_vis: Visibility, + inherited_eff_vis: Option, level: Level, tree: impl DefIdTree, ) -> bool { let mut changed = false; - let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| { - if id.is_top_level_module() { - EffectiveVisibility::from_vis(Visibility::Public) - } else { - EffectiveVisibility::from_vis(default_vis()) - } - }); - if let Some(inherited_effective_vis) = self.effective_vis(parent_id) { + let mut current_effective_vis = self + .map + .get(&id) + .copied() + .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis)); + if let Some(inherited_effective_vis) = inherited_eff_vis { let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level); let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; @@ -194,6 +195,12 @@ impl EffectiveVisibilities { } } +impl Default for EffectiveVisibilities { + fn default() -> Self { + EffectiveVisibilities { map: Default::default() } + } +} + impl<'a> HashStable> for EffectiveVisibilities { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let EffectiveVisibilities { ref map } = *self; diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 17ce854cb438..56dde6f8ca74 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -1,16 +1,38 @@ -use crate::{ImportKind, NameBindingKind, Resolver}; +use crate::{ImportKind, NameBinding, NameBindingKind, Resolver, ResolverTree}; use rustc_ast::ast; use rustc_ast::visit; use rustc_ast::visit::Visitor; use rustc_ast::Crate; use rustc_ast::EnumDef; +use rustc_data_structures::intern::Interned; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::middle::privacy::Level; -use rustc_middle::ty::{DefIdTree, Visibility}; +use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; +use rustc_middle::ty::Visibility; + +type ImportId<'a> = Interned<'a, NameBinding<'a>>; + +#[derive(Clone, Copy)] +enum ParentId<'a> { + Def(LocalDefId), + Import(ImportId<'a>), +} + +impl ParentId<'_> { + fn level(self) -> Level { + match self { + ParentId::Def(_) => Level::Direct, + ParentId::Import(_) => Level::Reexported, + } + } +} pub struct EffectiveVisibilitiesVisitor<'r, 'a> { r: &'r mut Resolver<'a>, + /// While walking import chains we need to track effective visibilities per-binding, and def id + /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple + /// bindings can correspond to a single def id in imports. So we keep a separate table. + import_effective_visibilities: EffectiveVisibilities>, changed: bool, } @@ -19,21 +41,25 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we /// need access to a TyCtxt for that. pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { - let mut visitor = EffectiveVisibilitiesVisitor { r, changed: false }; + let mut visitor = EffectiveVisibilitiesVisitor { + r, + import_effective_visibilities: Default::default(), + changed: false, + }; - visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, Level::Direct); + visitor.update(CRATE_DEF_ID, CRATE_DEF_ID); visitor.set_bindings_effective_visibilities(CRATE_DEF_ID); while visitor.changed { - visitor.reset(); + visitor.changed = false; visit::walk_crate(&mut visitor, krate); } info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities); } - fn reset(&mut self) { - self.changed = false; + fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId { + self.r.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local() } /// Update effective visibilities of bindings in the given module, @@ -48,92 +74,114 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { // Set the given effective visibility level to `Level::Direct` and // sets the rest of the `use` chain to `Level::Reexported` until // we hit the actual exported item. + let mut parent_id = ParentId::Def(module_id); + while let NameBindingKind::Import { binding: nested_binding, import, .. } = + binding.kind + { + let binding_id = ImportId::new_unchecked(binding); + self.update_import(binding_id, parent_id); - // FIXME: tag and is_public() condition should be removed, but assertions occur. - let tag = if binding.is_import() { Level::Reexported } else { Level::Direct }; - if binding.vis.is_public() { - let mut prev_parent_id = module_id; - let mut level = Level::Direct; - while let NameBindingKind::Import { binding: nested_binding, import, .. } = - binding.kind - { + // Update visibilities for import ids. These are not used during this pass, + // because we have more detailed binding-based information, but are used by + // later passes. Effective visibility of an import def id is the maximum value + // among visibilities of bindings corresponding to that def id. + if let Some(node_id) = import.id() { let mut update = |node_id| { - self.update( + self.update_def( self.r.local_def_id(node_id), binding.vis.expect_local(), - prev_parent_id, - level, + parent_id, ) }; - match import.kind { - ImportKind::Single { id, additional_ids, .. } => { - // In theory all the import IDs have individual visibilities and - // effective visibilities, but in practice these IDs go straigth to - // HIR where all their few uses assume that their (effective) - // visibility applies to the whole syntactic `use` item. So we - // update them all to the maximum value among the potential - // individual effective visibilities. Maybe HIR for imports - // shouldn't use three IDs at all. - update(id); - update(additional_ids.0); - update(additional_ids.1); - prev_parent_id = self.r.local_def_id(id); + update(node_id); + if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { + // In theory all the single import IDs have individual visibilities and + // effective visibilities, but in practice these IDs go straigth to HIR + // where all their few uses assume that their (effective) visibility + // applies to the whole syntactic `use` item. So they all get the same + // value which is the maximum of all bindings. Maybe HIR for imports + // shouldn't use three IDs at all. + if id1 != ast::DUMMY_NODE_ID { + update(id1); } - ImportKind::Glob { id, .. } | ImportKind::ExternCrate { id, .. } => { - update(id); - prev_parent_id = self.r.local_def_id(id); - } - ImportKind::MacroUse => { - // In theory we should reset the parent id to something private - // here, but `macro_use` imports always refer to external items, - // so it doesn't matter and we can just do nothing. - } - ImportKind::MacroExport => { - // In theory we should reset the parent id to something public - // here, but it has the same effect as leaving the previous parent, - // so we can just do nothing. + if id2 != ast::DUMMY_NODE_ID { + update(id2); } } - - level = Level::Reexported; - binding = nested_binding; } + + parent_id = ParentId::Import(binding_id); + binding = nested_binding; } if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) { - self.update(def_id, binding.vis.expect_local(), module_id, tag); + self.update_def(def_id, binding.vis.expect_local(), parent_id); } } } } - fn update( - &mut self, - def_id: LocalDefId, + fn effective_vis(&self, parent_id: ParentId<'a>) -> Option { + match parent_id { + ParentId::Def(def_id) => self.r.effective_visibilities.effective_vis(def_id), + ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding), + } + .copied() + } + + /// The update is guaranteed to not change the table and we can skip it. + fn is_noop_update( + &self, + parent_id: ParentId<'a>, nominal_vis: Visibility, - parent_id: LocalDefId, - tag: Level, - ) { - let module_id = self - .r - .get_nearest_non_block_module(def_id.to_def_id()) - .nearest_parent_mod() - .expect_local(); - if nominal_vis == Visibility::Restricted(module_id) - || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id) - { + default_vis: Visibility, + ) -> bool { + nominal_vis == default_vis + || match parent_id { + ParentId::Def(def_id) => self.r.visibilities[&def_id], + ParentId::Import(binding) => binding.vis.expect_local(), + } == default_vis + } + + fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) { + let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; + let nominal_vis = binding.vis.expect_local(); + let default_vis = Visibility::Restricted( + import + .id() + .map(|id| self.nearest_normal_mod(self.r.local_def_id(id))) + .unwrap_or(CRATE_DEF_ID), + ); + if self.is_noop_update(parent_id, nominal_vis, default_vis) { return; } - let mut effective_visibilities = std::mem::take(&mut self.r.effective_visibilities); - self.changed |= effective_visibilities.update( + self.changed |= self.import_effective_visibilities.update( + binding, + nominal_vis, + default_vis, + self.effective_vis(parent_id), + parent_id.level(), + ResolverTree(&self.r.definitions, &self.r.crate_loader), + ); + } + + fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) { + let default_vis = Visibility::Restricted(self.nearest_normal_mod(def_id)); + if self.is_noop_update(parent_id, nominal_vis, default_vis) { + return; + } + self.changed |= self.r.effective_visibilities.update( def_id, nominal_vis, - || Visibility::Restricted(module_id), - parent_id, - tag, - &*self.r, + if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis }, + self.effective_vis(parent_id), + parent_id.level(), + ResolverTree(&self.r.definitions, &self.r.crate_loader), ); - self.r.effective_visibilities = effective_visibilities; + } + + fn update(&mut self, def_id: LocalDefId, parent_id: LocalDefId) { + self.update_def(def_id, self.r.visibilities[&def_id], ParentId::Def(parent_id)); } } @@ -151,12 +199,6 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage" ), - // Foreign modules inherit level from parents. - ast::ItemKind::ForeignMod(..) => { - let parent_id = self.r.local_parent(def_id); - self.update(def_id, Visibility::Public, parent_id, Level::Direct); - } - ast::ItemKind::Mod(..) => { self.set_bindings_effective_visibilities(def_id); visit::walk_item(self, item); @@ -167,18 +209,14 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); for field in variant.data.fields() { - let field_def_id = self.r.local_def_id(field.id); - let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, variant_def_id, Level::Direct); + self.update(self.r.local_def_id(field.id), variant_def_id); } } } ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { for field in def.fields() { - let field_def_id = self.r.local_def_id(field.id); - let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, def_id, Level::Direct); + self.update(self.r.local_def_id(field.id), def_id); } } @@ -194,6 +232,7 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { | ast::ItemKind::TyAlias(..) | ast::ItemKind::TraitAlias(..) | ast::ItemKind::MacroDef(..) + | ast::ItemKind::ForeignMod(..) | ast::ItemKind::Fn(..) => return, } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ee1c97d5ad2b..a1ff477c6fef 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1106,14 +1106,27 @@ impl<'a> AsMut> for Resolver<'a> { } } +/// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes +/// required to satisfy borrow checker by avoiding borrowing the whole resolver. +#[derive(Clone, Copy)] +struct ResolverTree<'a, 'b>(&'a Definitions, &'a CrateLoader<'b>); + +impl DefIdTree for ResolverTree<'_, '_> { + #[inline] + fn opt_parent(self, id: DefId) -> Option { + let ResolverTree(definitions, crate_loader) = self; + match id.as_local() { + Some(id) => definitions.def_key(id).parent, + None => crate_loader.cstore().def_key(id).parent, + } + .map(|index| DefId { index, ..id }) + } +} + impl<'a, 'b> DefIdTree for &'a Resolver<'b> { #[inline] fn opt_parent(self, id: DefId) -> Option { - match id.as_local() { - Some(id) => self.definitions.def_key(id).parent, - None => self.cstore().def_key(id).parent, - } - .map(|index| DefId { index, ..id }) + ResolverTree(&self.definitions, &self.crate_loader).opt_parent(id) } } diff --git a/src/test/ui/privacy/effective_visibilities.rs b/src/test/ui/privacy/effective_visibilities.rs index c1f9ee8dfdf7..187bd7593304 100644 --- a/src/test/ui/privacy/effective_visibilities.rs +++ b/src/test/ui/privacy/effective_visibilities.rs @@ -6,7 +6,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub pub mod inner1 { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub #[rustc_effective_visibility] - extern "C" {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + extern "C" {} //~ ERROR not in the table #[rustc_effective_visibility] pub trait PubTrait { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub diff --git a/src/test/ui/privacy/effective_visibilities.stderr b/src/test/ui/privacy/effective_visibilities.stderr index 5a8f7db38fc8..10ed14aa1503 100644 --- a/src/test/ui/privacy/effective_visibilities.stderr +++ b/src/test/ui/privacy/effective_visibilities.stderr @@ -10,7 +10,7 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl LL | pub mod inner1 { | ^^^^^^^^^^^^^^ -error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub +error: not in the table --> $DIR/effective_visibilities.rs:9:9 | LL | extern "C" {} diff --git a/src/test/ui/privacy/effective_visibilities_glob.rs b/src/test/ui/privacy/effective_visibilities_glob.rs new file mode 100644 index 000000000000..eb9dcd6cd1fa --- /dev/null +++ b/src/test/ui/privacy/effective_visibilities_glob.rs @@ -0,0 +1,21 @@ +// Effective visibility tracking for imports is fine-grained, so `S2` is not fully exported +// even if its parent import (`m::*`) is fully exported as a `use` item. + +#![feature(rustc_attrs)] + +mod m { + #[rustc_effective_visibility] + pub struct S1 {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + pub struct S2 {} //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) +} + +mod glob { + #[rustc_effective_visibility] + pub use crate::m::*; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub +} + +#[rustc_effective_visibility] +pub use glob::S1; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + +fn main() {} diff --git a/src/test/ui/privacy/effective_visibilities_glob.stderr b/src/test/ui/privacy/effective_visibilities_glob.stderr new file mode 100644 index 000000000000..0496cd5df8db --- /dev/null +++ b/src/test/ui/privacy/effective_visibilities_glob.stderr @@ -0,0 +1,26 @@ +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:8:5 + | +LL | pub struct S1 {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities_glob.rs:10:5 + | +LL | pub struct S2 {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:15:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:19:9 + | +LL | pub use glob::S1; + | ^^^^^^^^ + +error: aborting due to 4 previous errors + From bb401bd04d6239932c37a8f741fefb278f009a1b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 4 Nov 2022 16:28:03 +0400 Subject: [PATCH 074/221] privacy: Print effective visibilities of constructors --- compiler/rustc_privacy/src/lib.rs | 8 ++++ src/test/ui/privacy/effective_visibilities.rs | 2 + .../ui/privacy/effective_visibilities.stderr | 44 ++++++++++++------- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 865d6306bd34..bda3b55cfc33 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -959,6 +959,10 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { for variant in def.variants.iter() { let variant_id = self.tcx.hir().local_def_id(variant.id); self.effective_visibility_diagnostic(variant_id); + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { + let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); + self.effective_visibility_diagnostic(ctor_def_id); + } for field in variant.data.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); self.effective_visibility_diagnostic(def_id); @@ -966,6 +970,10 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { + if let Some(ctor_hir_id) = def.ctor_hir_id() { + let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); + self.effective_visibility_diagnostic(ctor_def_id); + } for field in def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); self.effective_visibility_diagnostic(def_id); diff --git a/src/test/ui/privacy/effective_visibilities.rs b/src/test/ui/privacy/effective_visibilities.rs index 187bd7593304..4479b0d8f61b 100644 --- a/src/test/ui/privacy/effective_visibilities.rs +++ b/src/test/ui/privacy/effective_visibilities.rs @@ -18,6 +18,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub #[rustc_effective_visibility] struct PrivStruct; //~ ERROR not in the table + //~| ERROR not in the table #[rustc_effective_visibility] pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub @@ -31,6 +32,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub pub enum Enum { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub #[rustc_effective_visibility] A( //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + //~| ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub #[rustc_effective_visibility] PubUnion, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub ), diff --git a/src/test/ui/privacy/effective_visibilities.stderr b/src/test/ui/privacy/effective_visibilities.stderr index 10ed14aa1503..019aaf8086a6 100644 --- a/src/test/ui/privacy/effective_visibilities.stderr +++ b/src/test/ui/privacy/effective_visibilities.stderr @@ -28,92 +28,104 @@ error: not in the table LL | struct PrivStruct; | ^^^^^^^^^^^^^^^^^ +error: not in the table + --> $DIR/effective_visibilities.rs:20:9 + | +LL | struct PrivStruct; + | ^^^^^^^^^^^^^^^^^ + error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:23:9 + --> $DIR/effective_visibilities.rs:24:9 | LL | pub union PubUnion { | ^^^^^^^^^^^^^^^^^^ error: not in the table - --> $DIR/effective_visibilities.rs:25:13 + --> $DIR/effective_visibilities.rs:26:13 | LL | a: u8, | ^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:27:13 + --> $DIR/effective_visibilities.rs:28:13 | LL | pub b: u8, | ^^^^^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:31:9 + --> $DIR/effective_visibilities.rs:32:9 | LL | pub enum Enum { | ^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:33:13 + --> $DIR/effective_visibilities.rs:34:13 | LL | A( | ^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:35:17 + --> $DIR/effective_visibilities.rs:34:13 + | +LL | A( + | ^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:37:17 | LL | PubUnion, | ^^^^^^^^ error: not in the table - --> $DIR/effective_visibilities.rs:41:5 + --> $DIR/effective_visibilities.rs:43:5 | LL | macro_rules! none_macro { | ^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(self), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:47:5 + --> $DIR/effective_visibilities.rs:49:5 | LL | macro_rules! public_macro { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:52:5 + --> $DIR/effective_visibilities.rs:54:5 | LL | pub struct ReachableStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:54:9 + --> $DIR/effective_visibilities.rs:56:9 | LL | pub a: u8, | ^^^^^^^^^ error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:59:9 + --> $DIR/effective_visibilities.rs:61:9 | LL | pub use outer::inner1; | ^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:65:5 + --> $DIR/effective_visibilities.rs:67:5 | LL | pub type HalfPublicImport = u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) - --> $DIR/effective_visibilities.rs:68:5 + --> $DIR/effective_visibilities.rs:70:5 | LL | pub(crate) const HalfPublicImport: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:72:9 + --> $DIR/effective_visibilities.rs:74:9 | LL | pub use half_public_import::HalfPublicImport; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub - --> $DIR/effective_visibilities.rs:72:9 + --> $DIR/effective_visibilities.rs:74:9 | LL | pub use half_public_import::HalfPublicImport; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,5 +142,5 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl LL | type B; | ^^^^^^ -error: aborting due to 22 previous errors +error: aborting due to 24 previous errors From 448261a78a35026b3f5e855b705f35c916ecb19b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 4 Nov 2022 17:44:40 +0400 Subject: [PATCH 075/221] privacy: Check effective visibility invariants --- compiler/rustc_middle/src/middle/privacy.rs | 51 ++++++++++++++++++++- compiler/rustc_privacy/src/lib.rs | 2 + 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 3d7a379c56cd..11fbefefcc9e 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -1,9 +1,10 @@ //! A pass that checks to make sure private fields and methods aren't used //! outside their scopes. This pass will also generate a set of exported items //! which are available for use externally when compiled as a library. -use crate::ty::{DefIdTree, Visibility}; +use crate::ty::{DefIdTree, TyCtxt, Visibility}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir::def::DefKind; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::LocalDefId; @@ -133,6 +134,54 @@ impl EffectiveVisibilities { } self.map.insert(id, effective_vis); } + + pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) { + if !cfg!(debug_assertions) { + return; + } + for (&def_id, ev) in &self.map { + // More direct visibility levels can never go farther than less direct ones, + // neither of effective visibilities can go farther than nominal visibility, + // and all effective visibilities are larger or equal than private visibility. + let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id)); + let span = tcx.def_span(def_id.to_def_id()); + if !ev.direct.is_at_least(private_vis, tcx) { + span_bug!(span, "private {:?} > direct {:?}", private_vis, ev.direct); + } + if !ev.reexported.is_at_least(ev.direct, tcx) { + span_bug!(span, "direct {:?} > reexported {:?}", ev.direct, ev.reexported); + } + if !ev.reachable.is_at_least(ev.reexported, tcx) { + span_bug!(span, "reexported {:?} > reachable {:?}", ev.reexported, ev.reachable); + } + if !ev.reachable_through_impl_trait.is_at_least(ev.reachable, tcx) { + span_bug!( + span, + "reachable {:?} > reachable_through_impl_trait {:?}", + ev.reachable, + ev.reachable_through_impl_trait + ); + } + let nominal_vis = tcx.visibility(def_id); + let def_kind = tcx.opt_def_kind(def_id); + // FIXME: `rustc_privacy` is not yet updated for the new logic and can set + // effective visibilities that are larger than the nominal one. + if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early { + span_bug!( + span, + "{:?}: reachable_through_impl_trait {:?} > nominal {:?}", + def_id, + ev.reachable_through_impl_trait, + nominal_vis + ); + } + // Fully private items are never put into the table, this is important for performance. + // FIXME: Fully private `mod` items are currently put into the table. + if ev.reachable_through_impl_trait == private_vis && def_kind != Some(DefKind::Mod) { + span_bug!(span, "fully private item in the table {:?}: {:?}", def_id, ev.direct); + } + } + } } impl EffectiveVisibilities { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index bda3b55cfc33..e17f85c1aae0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -2139,6 +2139,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { changed: false, }; + visitor.effective_visibilities.check_invariants(tcx, true); loop { tcx.hir().walk_toplevel_module(&mut visitor); if visitor.changed { @@ -2147,6 +2148,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { break; } } + visitor.effective_visibilities.check_invariants(tcx, false); let mut check_visitor = TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities }; From c72c646625504fa1e772b1265d88e70cc5ba340b Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 5 Nov 2022 09:58:13 -0300 Subject: [PATCH 076/221] Move some tests to more reasonable directories --- src/test/ui/{issues => consts}/issue-54954.rs | 0 src/test/ui/{issues => consts}/issue-54954.stderr | 0 src/test/ui/{issues => dropck}/issue-54943-1.rs | 0 src/test/ui/{issues => dropck}/issue-54943-2.rs | 0 src/test/ui/{issues => match}/issue-12552.rs | 0 src/test/ui/{issues => match}/issue-12552.stderr | 0 src/test/ui/{issues => nll}/issue-54943.rs | 0 src/test/ui/{issues => nll}/issue-54943.stderr | 0 src/test/ui/{issues => typeck}/issue-10969.rs | 0 src/test/ui/{issues => typeck}/issue-10969.stderr | 0 src/test/ui/{issues => typeck}/issue-50687-ice-on-borrow.rs | 0 src/test/ui/{issues => typeck}/issue-50687-ice-on-borrow.stderr | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{issues => consts}/issue-54954.rs (100%) rename src/test/ui/{issues => consts}/issue-54954.stderr (100%) rename src/test/ui/{issues => dropck}/issue-54943-1.rs (100%) rename src/test/ui/{issues => dropck}/issue-54943-2.rs (100%) rename src/test/ui/{issues => match}/issue-12552.rs (100%) rename src/test/ui/{issues => match}/issue-12552.stderr (100%) rename src/test/ui/{issues => nll}/issue-54943.rs (100%) rename src/test/ui/{issues => nll}/issue-54943.stderr (100%) rename src/test/ui/{issues => typeck}/issue-10969.rs (100%) rename src/test/ui/{issues => typeck}/issue-10969.stderr (100%) rename src/test/ui/{issues => typeck}/issue-50687-ice-on-borrow.rs (100%) rename src/test/ui/{issues => typeck}/issue-50687-ice-on-borrow.stderr (100%) diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/consts/issue-54954.rs similarity index 100% rename from src/test/ui/issues/issue-54954.rs rename to src/test/ui/consts/issue-54954.rs diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/consts/issue-54954.stderr similarity index 100% rename from src/test/ui/issues/issue-54954.stderr rename to src/test/ui/consts/issue-54954.stderr diff --git a/src/test/ui/issues/issue-54943-1.rs b/src/test/ui/dropck/issue-54943-1.rs similarity index 100% rename from src/test/ui/issues/issue-54943-1.rs rename to src/test/ui/dropck/issue-54943-1.rs diff --git a/src/test/ui/issues/issue-54943-2.rs b/src/test/ui/dropck/issue-54943-2.rs similarity index 100% rename from src/test/ui/issues/issue-54943-2.rs rename to src/test/ui/dropck/issue-54943-2.rs diff --git a/src/test/ui/issues/issue-12552.rs b/src/test/ui/match/issue-12552.rs similarity index 100% rename from src/test/ui/issues/issue-12552.rs rename to src/test/ui/match/issue-12552.rs diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/match/issue-12552.stderr similarity index 100% rename from src/test/ui/issues/issue-12552.stderr rename to src/test/ui/match/issue-12552.stderr diff --git a/src/test/ui/issues/issue-54943.rs b/src/test/ui/nll/issue-54943.rs similarity index 100% rename from src/test/ui/issues/issue-54943.rs rename to src/test/ui/nll/issue-54943.rs diff --git a/src/test/ui/issues/issue-54943.stderr b/src/test/ui/nll/issue-54943.stderr similarity index 100% rename from src/test/ui/issues/issue-54943.stderr rename to src/test/ui/nll/issue-54943.stderr diff --git a/src/test/ui/issues/issue-10969.rs b/src/test/ui/typeck/issue-10969.rs similarity index 100% rename from src/test/ui/issues/issue-10969.rs rename to src/test/ui/typeck/issue-10969.rs diff --git a/src/test/ui/issues/issue-10969.stderr b/src/test/ui/typeck/issue-10969.stderr similarity index 100% rename from src/test/ui/issues/issue-10969.stderr rename to src/test/ui/typeck/issue-10969.stderr diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.rs b/src/test/ui/typeck/issue-50687-ice-on-borrow.rs similarity index 100% rename from src/test/ui/issues/issue-50687-ice-on-borrow.rs rename to src/test/ui/typeck/issue-50687-ice-on-borrow.rs diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.stderr b/src/test/ui/typeck/issue-50687-ice-on-borrow.stderr similarity index 100% rename from src/test/ui/issues/issue-50687-ice-on-borrow.stderr rename to src/test/ui/typeck/issue-50687-ice-on-borrow.stderr From f63ac6a13fc0afddfa808fe791f56564b41eb150 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 5 Nov 2022 09:59:27 -0300 Subject: [PATCH 077/221] Tidy --- src/tools/tidy/src/ui_tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index aee36f061c5d..2b82e9b3f998 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -9,8 +9,8 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. -const ROOT_ENTRY_LIMIT: usize = 941; -const ISSUES_ENTRY_LIMIT: usize = 2117; +const ROOT_ENTRY_LIMIT: usize = 939; +const ISSUES_ENTRY_LIMIT: usize = 2105; fn check_entries(path: &Path, bad: &mut bool) { for dir in Walk::new(&path.join("test/ui")) { From 43bea6cf69501dee3d71e4440d947182a67137a0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 5 Nov 2022 16:54:45 +0400 Subject: [PATCH 078/221] resolve: Fill effective visibilities for import def ids in a separate pass This should result in less update calls than doing it repeatedly during the fix point iteration. --- compiler/rustc_middle/src/middle/privacy.rs | 30 ++++++++- .../src/effective_visibilities.rs | 65 ++++++++++--------- 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 11fbefefcc9e..3a91522d3622 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -113,8 +113,30 @@ impl EffectiveVisibilities { }) } - pub fn iter(&self) -> impl Iterator { - self.map.iter() + // FIXME: Share code with `fn update`. + pub fn update_eff_vis( + &mut self, + def_id: LocalDefId, + eff_vis: &EffectiveVisibility, + tree: impl DefIdTree, + ) { + use std::collections::hash_map::Entry; + match self.map.entry(def_id) { + Entry::Occupied(mut occupied) => { + let old_eff_vis = occupied.get_mut(); + for l in Level::all_levels() { + let vis_at_level = eff_vis.at_level(l); + let old_vis_at_level = old_eff_vis.at_level_mut(l); + if vis_at_level != old_vis_at_level + && vis_at_level.is_at_least(*old_vis_at_level, tree) + { + *old_vis_at_level = *vis_at_level + } + } + old_eff_vis + } + Entry::Vacant(vacant) => vacant.insert(*eff_vis), + }; } pub fn set_public_at_level( @@ -185,6 +207,10 @@ impl EffectiveVisibilities { } impl EffectiveVisibilities { + pub fn iter(&self) -> impl Iterator { + self.map.iter() + } + pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { self.map.get(&id) } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 56dde6f8ca74..fa6d34be0cc3 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -55,6 +55,38 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { visit::walk_crate(&mut visitor, krate); } + // Update visibilities for import def ids. These are not used during the + // `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based + // information, but are used by later passes. Effective visibility of an import def id + // is the maximum value among visibilities of bindings corresponding to that def id. + for (binding, eff_vis) in visitor.import_effective_visibilities.iter() { + let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; + if let Some(node_id) = import.id() { + let mut update = |node_id| { + r.effective_visibilities.update_eff_vis( + r.local_def_id(node_id), + eff_vis, + ResolverTree(&r.definitions, &r.crate_loader), + ) + }; + update(node_id); + if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { + // In theory all the single import IDs have individual visibilities and + // effective visibilities, but in practice these IDs go straigth to HIR + // where all their few uses assume that their (effective) visibility + // applies to the whole syntactic `use` item. So they all get the same + // value which is the maximum of all bindings. Maybe HIR for imports + // shouldn't use three IDs at all. + if id1 != ast::DUMMY_NODE_ID { + update(id1); + } + if id2 != ast::DUMMY_NODE_ID { + update(id2); + } + } + } + } + info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities); } @@ -75,41 +107,10 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { // sets the rest of the `use` chain to `Level::Reexported` until // we hit the actual exported item. let mut parent_id = ParentId::Def(module_id); - while let NameBindingKind::Import { binding: nested_binding, import, .. } = - binding.kind - { + while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { let binding_id = ImportId::new_unchecked(binding); self.update_import(binding_id, parent_id); - // Update visibilities for import ids. These are not used during this pass, - // because we have more detailed binding-based information, but are used by - // later passes. Effective visibility of an import def id is the maximum value - // among visibilities of bindings corresponding to that def id. - if let Some(node_id) = import.id() { - let mut update = |node_id| { - self.update_def( - self.r.local_def_id(node_id), - binding.vis.expect_local(), - parent_id, - ) - }; - update(node_id); - if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { - // In theory all the single import IDs have individual visibilities and - // effective visibilities, but in practice these IDs go straigth to HIR - // where all their few uses assume that their (effective) visibility - // applies to the whole syntactic `use` item. So they all get the same - // value which is the maximum of all bindings. Maybe HIR for imports - // shouldn't use three IDs at all. - if id1 != ast::DUMMY_NODE_ID { - update(id1); - } - if id2 != ast::DUMMY_NODE_ID { - update(id2); - } - } - } - parent_id = ParentId::Import(binding_id); binding = nested_binding; } From 36be251a35512d98cc50afc4b73b3ea7ec1271ff Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 16:04:43 +0100 Subject: [PATCH 079/221] Merge `QueryDescription` into `QueryConfig` `QueryDescription` has gone through a lot of refactoring and doesn't make sense anymore. --- compiler/rustc_query_impl/src/lib.rs | 2 +- .../rustc_query_impl/src/on_disk_cache.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 29 ++++++------ .../rustc_query_system/src/query/config.rs | 44 +++++++++---------- compiler/rustc_query_system/src/query/mod.rs | 2 +- .../rustc_query_system/src/query/plumbing.rs | 8 ++-- 6 files changed, 42 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 11d4c97e71ca..18cb0e0ca0b1 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -36,7 +36,7 @@ mod keys; use keys::Key; pub use rustc_query_system::query::QueryConfig; -pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable}; +pub(crate) use rustc_query_system::query::QueryVTable; mod on_disk_cache; pub use on_disk_cache::OnDiskCache; diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 8b14ce210a20..a6cb8f7bd553 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -1063,7 +1063,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>( query_result_index: &mut EncodedDepNodeIndex, ) where CTX: QueryContext + 'tcx, - Q: super::QueryDescription, + Q: super::QueryConfig, Q::Value: Encodable>, { let _timer = tcx diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 1d17f4221969..992e777904e6 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -17,8 +17,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ - force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap, - QuerySideEffects, QueryStackFrame, + force_query, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame, }; use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value}; use rustc_serialize::Decodable; @@ -340,7 +339,7 @@ pub(crate) fn create_query_frame< fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) where - Q: QueryDescription>, + Q: QueryConfig>, Q::Key: DepNodeParams>, { debug_assert!(tcx.dep_graph.is_green(&dep_node)); @@ -365,7 +364,7 @@ where fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where - Q: QueryDescription>, + Q: QueryConfig>, Q::Key: DepNodeParams>, Q::Value: Value>, { @@ -398,12 +397,9 @@ where } } -pub(crate) fn query_callback<'tcx, Q: QueryConfig>( - is_anon: bool, - is_eval_always: bool, -) -> DepKindStruct<'tcx> +pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx> where - Q: QueryDescription>, + Q: QueryConfig>, Q::Key: DepNodeParams>, { let fingerprint_style = Q::Key::fingerprint_style(); @@ -458,14 +454,12 @@ macro_rules! define_queries { })* } - $(impl<'tcx> QueryConfig for queries::$name<'tcx> { + $(impl<'tcx> QueryConfig> for queries::$name<'tcx> { type Key = query_keys::$name<'tcx>; type Value = query_values::$name<'tcx>; type Stored = query_stored::$name<'tcx>; const NAME: &'static str = stringify!($name); - } - impl<'tcx> QueryDescription> for queries::$name<'tcx> { #[inline] fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { ::rustc_middle::query::cached::$name(tcx, key) @@ -662,12 +656,15 @@ macro_rules! define_queries_struct { local_providers: Box, extern_providers: Box, query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>, - pub on_disk_cache: Option>, - jobs: AtomicU64, - $($(#[$attr])* $name: QueryState< as QueryConfig>::Key>,)* + $( + $(#[$attr])* + $name: QueryState< + as QueryConfig>>::Key + >, + )* } impl<'tcx> Queries<'tcx> { @@ -704,7 +701,7 @@ macro_rules! define_queries_struct { &'tcx self, tcx: TyCtxt<'tcx>, span: Span, - key: as QueryConfig>::Key, + key: as QueryConfig>>::Key, mode: QueryMode, ) -> Option> { let qcx = QueryCtxt { tcx, queries: self }; diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 0a1cffa3b333..db3ae559ad15 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -11,12 +11,32 @@ use rustc_data_structures::fingerprint::Fingerprint; use std::fmt::Debug; use std::hash::Hash; -pub trait QueryConfig { +pub trait QueryConfig { const NAME: &'static str; type Key: Eq + Hash + Clone + Debug; type Value; type Stored: Clone; + + type Cache: QueryCache; + + // Don't use this method to access query results, instead use the methods on TyCtxt + fn query_state<'a>(tcx: CTX) -> &'a QueryState + where + CTX: 'a; + + // Don't use this method to access query results, instead use the methods on TyCtxt + fn query_cache<'a>(tcx: CTX) -> &'a Self::Cache + where + CTX: 'a; + + // Don't use this method to compute query results, instead use the methods on TyCtxt + fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVTable; + + fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool; + + // Don't use this method to compute query results, instead use the methods on TyCtxt + fn execute_query(tcx: CTX::DepContext, k: Self::Key) -> Self::Stored; } #[derive(Copy, Clone)] @@ -45,25 +65,3 @@ impl QueryVTable { (self.compute)(tcx, key) } } - -pub trait QueryDescription: QueryConfig { - type Cache: QueryCache; - - // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(tcx: CTX) -> &'a QueryState - where - CTX: 'a; - - // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(tcx: CTX) -> &'a Self::Cache - where - CTX: 'a; - - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVTable; - - fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool; - - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(tcx: CTX::DepContext, k: Self::Key) -> Self::Stored; -} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 118703fc0d48..94adef41e68f 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -12,7 +12,7 @@ pub use self::caches::{ }; mod config; -pub use self::config::{QueryConfig, QueryDescription, QueryVTable}; +pub use self::config::{QueryConfig, QueryVTable}; use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; use rustc_data_structures::sync::Lock; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 15b89daa6db1..0f7abe84231b 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -4,7 +4,7 @@ use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams}; use crate::query::caches::QueryCache; -use crate::query::config::{QueryDescription, QueryVTable}; +use crate::query::config::QueryVTable; use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo}; use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame}; use crate::values::Value; @@ -27,6 +27,8 @@ use std::mem; use std::ptr; use thin_vec::ThinVec; +use super::QueryConfig; + pub struct QueryState { #[cfg(parallel_compiler)] active: Sharded>, @@ -715,7 +717,7 @@ pub enum QueryMode { pub fn get_query(tcx: CTX, span: Span, key: Q::Key, mode: QueryMode) -> Option where - Q: QueryDescription, + Q: QueryConfig, Q::Key: DepNodeParams, Q::Value: Value, CTX: QueryContext, @@ -748,7 +750,7 @@ where pub fn force_query(tcx: CTX, key: Q::Key, dep_node: DepNode) where - Q: QueryDescription, + Q: QueryConfig, Q::Key: DepNodeParams, Q::Value: Value, CTX: QueryContext, From b1994ce80662c6cdebdf42cb64e87572f0ab8839 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 3 Nov 2022 14:35:15 +0000 Subject: [PATCH 080/221] Do not make typo suggestions when suggesting pattern matching Fixes #103909. --- .../rustc_resolve/src/late/diagnostics.rs | 15 +++++++++++-- src/test/ui/did_you_mean/issue-103909.rs | 9 ++++++++ src/test/ui/did_you_mean/issue-103909.stderr | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/did_you_mean/issue-103909.rs create mode 100644 src/test/ui/did_you_mean/issue-103909.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 103187b00d1b..a1338dcd4771 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -322,7 +322,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } self.suggest_bare_struct_literal(&mut err); - self.suggest_pattern_match_with_let(&mut err, source, span); + + if self.suggest_pattern_match_with_let(&mut err, source, span) { + // Fallback label. + err.span_label(base_error.span, &base_error.fallback_label); + return (err, Vec::new()); + } self.suggest_self_or_self_ref(&mut err, path, span); self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error); @@ -341,7 +346,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if !self.type_ascription_suggestion(&mut err, base_error.span) { let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); + + // if we have suggested using pattern matching, then don't add needless suggestions + // for typos. fallback |= self.suggest_typo(&mut err, source, path, span, &base_error); + if fallback { // Fallback label. err.span_label(base_error.span, &base_error.fallback_label); @@ -937,7 +946,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err: &mut Diagnostic, source: PathSource<'_>, span: Span, - ) { + ) -> bool { if let PathSource::Expr(_) = source && let Some(Expr { span: expr_span, @@ -954,8 +963,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { "let ", Applicability::MaybeIncorrect, ); + return true; } } + false } fn get_single_associated_item( diff --git a/src/test/ui/did_you_mean/issue-103909.rs b/src/test/ui/did_you_mean/issue-103909.rs new file mode 100644 index 000000000000..20b67cd102d7 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-103909.rs @@ -0,0 +1,9 @@ +#![allow(unused_variables)] +use std::fs::File; + +fn main() { + if Err(err) = File::open("hello.txt") { + //~^ ERROR: cannot find value `err` in this scope + //~| ERROR: mismatched types + } +} diff --git a/src/test/ui/did_you_mean/issue-103909.stderr b/src/test/ui/did_you_mean/issue-103909.stderr new file mode 100644 index 000000000000..a28914051b98 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-103909.stderr @@ -0,0 +1,21 @@ +error[E0425]: cannot find value `err` in this scope + --> $DIR/issue-103909.rs:5:12 + | +LL | if Err(err) = File::open("hello.txt") { + | ^^^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | if let Err(err) = File::open("hello.txt") { + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-103909.rs:5:8 + | +LL | if Err(err) = File::open("hello.txt") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. From 94ba7f09df5931f431473f5af4c731caa39d44bd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Nov 2022 22:36:04 +0100 Subject: [PATCH 081/221] Fix search result bottom border color --- src/librustdoc/html/static/css/rustdoc.css | 2 +- src/librustdoc/html/static/css/themes/ayu.css | 1 + src/librustdoc/html/static/css/themes/dark.css | 1 + src/librustdoc/html/static/css/themes/light.css | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 7c0dab1c527d..b5d79030909f 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -886,7 +886,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ /* A little margin ensures the browser's outlining of focused links has room to display. */ margin-left: 2px; margin-right: 2px; - border-bottom: 1px solid var(--border-color); + border-bottom: 1px solid var(--search-result-border-color); gap: 1em; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index fdfdb3e19667..762384481e69 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -38,6 +38,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --sidebar-link-color: #53b1db; --sidebar-current-link-background-color: transparent; --search-result-link-focus-background-color: #3c3c3c; + --search-result-border-color: #aaa3; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --search-color: #fff; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 361d3d4a2259..1424de5137cc 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -33,6 +33,7 @@ --sidebar-link-color: #fdbf35; --sidebar-current-link-background-color: #444; --search-result-link-focus-background-color: #616161; + --search-result-border-color: #aaa3; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --search-color: #111; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 5eb4bbcf834b..a7ce56c95c7e 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -33,6 +33,7 @@ --sidebar-link-color: #356da4; --sidebar-current-link-background-color: #fff; --search-result-link-focus-background-color: #ccc; + --search-result-border-color: #aaa3; --stab-background-color: #fff5d6; --stab-code-color: #000; --search-color: #000; From 666873b1bb0b7c6663e9be7fc012c5467d873ae3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Nov 2022 22:36:14 +0100 Subject: [PATCH 082/221] Update GUI test for bottom border color --- src/test/rustdoc-gui/search-result-color.goml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml index 0c3b11190742..d437ad75970b 100644 --- a/src/test/rustdoc-gui/search-result-color.goml +++ b/src/test/rustdoc-gui/search-result-color.goml @@ -78,7 +78,7 @@ assert-css: ( // Checking the color of the bottom border. assert-css: ( ".search-results > a", - {"border-bottom-color": "rgb(92, 103, 115)"} + {"border-bottom-color": "rgba(170, 170, 170, 0.2)"} ) // Checking the color of "keyword" text. @@ -190,7 +190,7 @@ assert-css: ( // Checking the color of the bottom border. assert-css: ( ".search-results > a", - {"border-bottom-color": "rgb(224, 224, 224)"} + {"border-bottom-color": "rgba(170, 170, 170, 0.2)"} ) // Checking the color for "keyword" text. @@ -287,7 +287,7 @@ assert-css: ( // Checking the color of the bottom border. assert-css: ( ".search-results > a", - {"border-bottom-color": "rgb(224, 224, 224)"} + {"border-bottom-color": "rgba(170, 170, 170, 0.2)"} ) // Checking the color for "keyword" text. From a69d43493a91b11eb5b840253825330e9320a56f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 5 Nov 2022 09:02:10 -0700 Subject: [PATCH 083/221] rustdoc: use `ThinVec` and `Box` to shrink `clean::ItemKind` --- src/librustdoc/clean/inline.rs | 4 ++-- src/librustdoc/clean/mod.rs | 8 ++++---- src/librustdoc/clean/types.rs | 14 +++++++------- src/librustdoc/clean/utils.rs | 4 ++-- src/librustdoc/json/conversions.rs | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 841c4f9d5300..cd40413c2648 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::sync::Arc; -use thin_vec::ThinVec; +use thin_vec::{thin_vec, ThinVec}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; @@ -596,7 +596,7 @@ fn build_module_items( clean::ImportSource { path: clean::Path { res, - segments: vec![clean::PathSegment { + segments: thin_vec![clean::PathSegment { name: prim_ty.as_sym(), args: clean::GenericArgs::AngleBracketed { args: Default::default(), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8d38f2df0d85..ad02bc592866 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -227,7 +227,7 @@ pub(crate) fn clean_middle_const<'tcx>( // FIXME: instead of storing the stringified expression, store `self` directly instead. Constant { type_: clean_middle_ty(constant.ty(), cx, None), - kind: ConstantKind::TyConst { expr: constant.to_string() }, + kind: ConstantKind::TyConst { expr: constant.to_string().into() }, } } @@ -1200,7 +1200,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( true } (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind { - ConstantKind::TyConst { expr } => expr == param.name.as_str(), + ConstantKind::TyConst { expr } => **expr == *param.name.as_str(), _ => false, }, _ => false, @@ -1529,7 +1529,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } }; - Array(Box::new(clean_ty(ty, cx)), length) + Array(Box::new(clean_ty(ty, cx)), length.into()) } TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), TyKind::OpaqueDef(item_id, _, _) => { @@ -1601,7 +1601,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Array(ty, mut n) => { n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); - Array(Box::new(clean_middle_ty(ty, cx, None)), n) + Array(Box::new(clean_middle_ty(ty, cx, None)), n.into()) } ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))), ty::Ref(r, ty, mutbl) => BorrowedRef { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fea3690e50a2..7ffb38091379 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1621,7 +1621,7 @@ pub(crate) enum Type { /// An array type. /// /// The `String` field is a stringified version of the array's length parameter. - Array(Box, String), + Array(Box, Box), /// A raw pointer type: `*const i32`, `*mut i32` RawPointer(Mutability, Box), /// A reference type: `&i32`, `&'a mut Foo` @@ -2206,7 +2206,7 @@ impl Span { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct Path { pub(crate) res: Res, - pub(crate) segments: Vec, + pub(crate) segments: ThinVec, } impl Path { @@ -2356,7 +2356,7 @@ pub(crate) enum ConstantKind { /// /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified /// by a DefId. So this field must be different from `Extern`. - TyConst { expr: String }, + TyConst { expr: Box }, /// A constant (expression) that's not an item or associated item. These are usually found /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also /// used to define explicit discriminant values for enum variants. @@ -2384,7 +2384,7 @@ impl Constant { impl ConstantKind { pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String { match *self { - ConstantKind::TyConst { ref expr } => expr.clone(), + ConstantKind::TyConst { ref expr } => expr.to_string(), ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { print_const_expr(tcx, body) @@ -2570,13 +2570,13 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Crate, 72); // frequently moved by-value static_assert_size!(DocFragment, 32); - static_assert_size!(GenericArg, 48); + static_assert_size!(GenericArg, 32); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); static_assert_size!(Generics, 16); static_assert_size!(Item, 56); - static_assert_size!(ItemKind, 88); + static_assert_size!(ItemKind, 64); static_assert_size!(PathSegment, 40); - static_assert_size!(Type, 48); + static_assert_size!(Type, 32); // tidy-alphabetical-end } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index df20dc3fc3f7..4e1f39cf87b9 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use std::fmt::Write as _; use std::mem; -use thin_vec::ThinVec; +use thin_vec::{thin_vec, ThinVec}; #[cfg(test)] mod tests; @@ -136,7 +136,7 @@ pub(super) fn external_path<'tcx>( let name = cx.tcx.item_name(did); Path { res: Res::Def(def_kind, did), - segments: vec![PathSegment { + segments: thin_vec![PathSegment { name, args: external_generic_args(cx, did, has_self, bindings, substs), }], diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index cb8b7c18029f..091a1ba70cab 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -485,7 +485,7 @@ impl FromWithTcx for Type { BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), Tuple(t) => Type::Tuple(t.into_tcx(tcx)), Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), - Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s }, + Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() }, ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { From ffb28690aaaa2e5197e6bb342ba83f21ebbe6992 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 5 Nov 2022 17:22:25 +0100 Subject: [PATCH 084/221] Migrate test-arrow to CSS variables --- src/librustdoc/html/static/css/rustdoc.css | 6 ++++++ src/librustdoc/html/static/css/themes/ayu.css | 16 ++++------------ src/librustdoc/html/static/css/themes/dark.css | 13 ++++--------- src/librustdoc/html/static/css/themes/light.css | 13 ++++--------- 4 files changed, 18 insertions(+), 30 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 7c0dab1c527d..e5bfdbd63490 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1204,6 +1204,12 @@ a.test-arrow { top: 5px; right: 5px; z-index: 1; + color: var(--test-arrow-color); + background-color: var(--test-arrow-background-color); +} +a.test-arrow:hover { + color: var(--test-arrow-hover-color); + background-color: var(--test-arrow-hover-background-color); } .example-wrap:hover .test-arrow { visibility: visible; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index fdfdb3e19667..369f11e58f0d 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -58,6 +58,10 @@ Original by Dempfi (https://github.com/dempfi/ayu) --example-line-numbers-border-color: none; --src-line-numbers-span-color: #5c6773; --src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06); + --test-arrow-color: #788797; + --test-arrow-background-color: rgba(57, 175, 215, 0.09); + --test-arrow-hover-color: #c5c5c5; + --test-arrow-hover-background-color: rgba(57, 175, 215, 0.368); } .slider { @@ -171,18 +175,6 @@ details.rustdoc-toggle > summary::before { color: #788797; } -a.test-arrow { - font-size: 100%; - color: #788797; - border-radius: 4px; - background-color: rgba(57, 175, 215, 0.09); -} - -a.test-arrow:hover { - background-color: rgba(57, 175, 215, 0.368); - color: #c5c5c5; -} - :target { background: rgba(255, 236, 164, 0.06); border-right: 3px solid rgba(255, 180, 76, 0.85); diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 361d3d4a2259..08c318b946ad 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -53,6 +53,10 @@ --example-line-numbers-border-color: #4a4949; --src-line-numbers-span-color: #3b91e2; --src-line-number-highlighted-background-color: #0a042f; + --test-arrow-color: #dedede; + --test-arrow-background-color: rgba(78, 139, 202, 0.2); + --test-arrow-hover-color: #dedede; + --test-arrow-hover-background-color: #4e8bca; } .slider { @@ -93,15 +97,6 @@ details.rustdoc-toggle > summary::before { filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%); } -a.test-arrow { - color: #dedede; - background-color: rgba(78, 139, 202, 0.2); -} - -a.test-arrow:hover{ - background-color: #4e8bca; -} - :target { background-color: #494a3d; border-right: 3px solid #bb7410; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 5eb4bbcf834b..637bf45b71c1 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -53,6 +53,10 @@ --example-line-numbers-border-color: #c7c7c7; --src-line-numbers-span-color: #c67e2d; --src-line-number-highlighted-background-color: #fdffd3; + --test-arrow-color: #f5f5f5; + --test-arrow-background-color: rgba(78, 139, 202, 0.2); + --test-arrow-hover-color: #f5f5f5; + --test-arrow-hover-background-color: #4e8bca; } .slider { @@ -88,15 +92,6 @@ body.source .example-wrap pre.rust a { filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%); } -a.test-arrow { - color: #f5f5f5; - background-color: rgba(78, 139, 202, 0.2); -} - -a.test-arrow:hover{ - background-color: #4e8bca; -} - :target { background: #FDFFD3; border-right: 3px solid #AD7C37; From 8e2956d4a9787100ede2410f1d8d6b26d80ec961 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 5 Nov 2022 17:22:38 +0100 Subject: [PATCH 085/221] Extend GUI test for run button --- src/test/rustdoc-gui/run-on-hover.goml | 55 ++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml index 6c785e1c4bba..57d63049f28c 100644 --- a/src/test/rustdoc-gui/run-on-hover.goml +++ b/src/test/rustdoc-gui/run-on-hover.goml @@ -1,7 +1,54 @@ // Example code blocks sometimes have a "Run" button to run them on the // Playground. That button is hidden until the user hovers over the code block. -// This test checks that it is hidden, and that it shows on hover. +// This test checks that it is hidden, and that it shows on hover. It also +// checks for its color. goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html" -assert-css: (".test-arrow", {"visibility": "hidden"}) -move-cursor-to: ".example-wrap" -assert-css: (".test-arrow", {"visibility": "visible"}) +show-text: true + +define-function: ( + "check-run-button", + (theme, color, background, hover_color, hover_background), + [ + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + ("assert-css", (".test-arrow", {"visibility": "hidden"})), + ("move-cursor-to", ".example-wrap"), + ("assert-css", (".test-arrow", { + "visibility": "visible", + "color": |color|, + "background-color": |background|, + "font-size": "22px", + "border-radius": "5px", + })), + ("move-cursor-to", ".test-arrow"), + ("assert-css", (".test-arrow:hover", { + "visibility": "visible", + "color": |hover_color|, + "background-color": |hover_background|, + "font-size": "22px", + "border-radius": "5px", + })), + ], +) + +call-function: ("check-run-button", { + "theme": "ayu", + "color": "rgb(120, 135, 151)", + "background": "rgba(57, 175, 215, 0.09)", + "hover_color": "rgb(197, 197, 197)", + "hover_background": "rgba(57, 175, 215, 0.37)", +}) +call-function: ("check-run-button", { + "theme": "dark", + "color": "rgb(222, 222, 222)", + "background": "rgba(78, 139, 202, 0.2)", + "hover_color": "rgb(222, 222, 222)", + "hover_background": "rgb(78, 139, 202)", +}) +call-function: ("check-run-button", { + "theme": "light", + "color": "rgb(245, 245, 245)", + "background": "rgba(78, 139, 202, 0.2)", + "hover_color": "rgb(245, 245, 245)", + "hover_background": "rgb(78, 139, 202)", +}) From c33ee13391e71d037499f584520aba58289d5791 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 5 Nov 2022 12:30:28 -0400 Subject: [PATCH 086/221] Remove linuxkernel targets These are not used by the actual Rust-for-Linux project, so they're mostly just confusing. --- .../src/spec/linux_kernel_base.rs | 18 ------------ compiler/rustc_target/src/spec/mod.rs | 5 +--- .../rustc_target/src/spec/tests/tests_impl.rs | 9 +++--- .../spec/x86_64_unknown_none_linuxkernel.rs | 28 ------------------- library/unwind/src/lib.rs | 1 - src/doc/rustc/src/platform-support.md | 1 - 6 files changed, 5 insertions(+), 57 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/linux_kernel_base.rs delete mode 100644 compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs deleted file mode 100644 index f41533a9548f..000000000000 --- a/compiler/rustc_target/src/spec/linux_kernel_base.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::spec::TargetOptions; -use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType}; - -pub fn opts() -> TargetOptions { - TargetOptions { - env: "gnu".into(), - disable_redzone: true, - panic_strategy: PanicStrategy::Abort, - stack_probes: StackProbeType::X86, - frame_pointer: FramePointer::Always, - position_independent_executables: true, - needs_plt: true, - relro_level: RelroLevel::Full, - relocation_model: RelocModel::Static, - - ..Default::default() - } -} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 72b088d663b1..61de5d624cc9 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -71,7 +71,6 @@ mod illumos_base; mod l4re_base; mod linux_base; mod linux_gnu_base; -mod linux_kernel_base; mod linux_musl_base; mod linux_uclibc_base; mod msvc_base; @@ -1003,7 +1002,7 @@ macro_rules! supported_targets { $( #[test] // `#[test]` fn $module() { - tests_impl::test_target(super::$module::target(), $triple); + tests_impl::test_target(super::$module::target()); } )+ } @@ -1071,8 +1070,6 @@ supported_targets! { ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi), ("aarch64-linux-android", aarch64_linux_android), - ("x86_64-unknown-none-linuxkernel", x86_64_unknown_none_linuxkernel), - ("aarch64-unknown-freebsd", aarch64_unknown_freebsd), ("armv6-unknown-freebsd", armv6_unknown_freebsd), ("armv7-unknown-freebsd", armv7_unknown_freebsd), diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index 172da0ed5df8..e0ecf8037c3e 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -2,15 +2,15 @@ use super::super::*; use std::assert_matches::assert_matches; // Test target self-consistency and JSON encoding/decoding roundtrip. -pub(super) fn test_target(mut target: Target, triple: &str) { +pub(super) fn test_target(mut target: Target) { let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j); target.update_to_cli(); - target.check_consistency(triple); + target.check_consistency(); assert_eq!(recycled_target, Ok(target)); } impl Target { - fn check_consistency(&self, triple: &str) { + fn check_consistency(&self) { assert_eq!(self.is_like_osx, self.vendor == "apple"); assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos"); assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi"); @@ -129,8 +129,7 @@ impl Target { if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") { assert_eq!(self.relocation_model, RelocModel::Pic); } - // PIEs are supported but not enabled by default with linuxkernel target. - if self.position_independent_executables && !triple.ends_with("-linuxkernel") { + if self.position_independent_executables { assert_eq!(self.relocation_model, RelocModel::Pic); } // The UEFI targets do not support dynamic linking but still require PIC (#101377). diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs deleted file mode 100644 index ebd9636ff510..000000000000 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs +++ /dev/null @@ -1,28 +0,0 @@ -// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for -// generic Linux kernel options. - -use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, Target}; - -pub fn target() -> Target { - let mut base = super::linux_kernel_base::opts(); - base.cpu = "x86-64".into(); - base.max_atomic_width = Some(64); - base.features = - "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into(); - base.code_model = Some(CodeModel::Kernel); - base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); - - Target { - // FIXME: Some dispute, the linux-on-clang folks think this should use - // "Linux". We disagree because running *on* Linux is nothing like - // running *as" linux, and historically the "os" component as has always - // been used to mean the "on" part. - llvm_target: "x86_64-unknown-none-elf".into(), - pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), - arch: "x86_64".into(), - - options: base, - } -} diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 46fe50cb9453..32c0ef3e1168 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -15,7 +15,6 @@ cfg_if::cfg_if! { target_os = "espidf", ))] { // These "unix" family members do not have unwinder. - // Note this also matches x86_64-unknown-none-linuxkernel. } else if #[cfg(any( unix, windows, diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 3ae9872cf62d..46fee8abb232 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -309,7 +309,6 @@ target | std | host | notes `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku `x86_64-unknown-hermit` | ✓ | | HermitCore `x86_64-unknown-l4re-uclibc` | ? | | -`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD [`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 64-bit UEFI `x86_64-uwp-windows-gnu` | ✓ | | From 04583f29c8eb33bf2c444c549d8fc0c7a4f0735d Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 17:54:06 +0100 Subject: [PATCH 087/221] Simplify code --- compiler/rustc_interface/src/proc_macro_decls.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 4c236c693d0f..9bf7778bfb29 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -4,21 +4,16 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option { - let mut finder = Finder { tcx, decls: None }; + let mut decls = None; for id in tcx.hir().items() { - let attrs = finder.tcx.hir().attrs(id.hir_id()); - if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { - finder.decls = Some(id.owner_id.def_id); + let attrs = tcx.hir().attrs(id.hir_id()); + if tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { + decls = Some(id.owner_id.def_id); } } - finder.decls -} - -struct Finder<'tcx> { - tcx: TyCtxt<'tcx>, - decls: Option, + decls } pub(crate) fn provide(providers: &mut Providers) { From 27e0f03d411b867ea0605c43aea1eccdd4b9c71c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 17:54:15 +0100 Subject: [PATCH 088/221] Add internal descriptions to a few queries --- compiler/rustc_middle/src/query/mod.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 33acaed435b8..00242e7eed77 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -271,6 +271,10 @@ rustc_queries! { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } + /// Look up all native libraries this crate depends on. + /// These are assembled from the following places: + /// - `extern` blocks (depending on their `link` attributes) + /// - the `libs` (`-l`) option query native_libraries(_: CrateNum) -> Vec { arena_cache desc { "looking up the native libraries of a linked crate" } @@ -1539,6 +1543,7 @@ rustc_queries! { desc { "available upstream drop-glue for `{:?}`", substs } } + /// Returns a list of all `extern` blocks of a crate. query foreign_modules(_: CrateNum) -> FxHashMap { arena_cache desc { "looking up the foreign modules of a linked crate" } @@ -1550,9 +1555,12 @@ rustc_queries! { query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { desc { "looking up the entry function of a crate" } } + + /// Finds the `rustc_proc_macro_decls` item of a crate. query proc_macro_decls_static(_: ()) -> Option { - desc { "looking up the derive registrar for a crate" } + desc { "looking up the proc macro declarations for a crate" } } + // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. // Changing the name should cause a compiler error, but in case that changes, be aware. query crate_hash(_: CrateNum) -> Svh { @@ -1560,17 +1568,24 @@ rustc_queries! { desc { "looking up the hash a crate" } separate_provide_extern } + + /// Gets the hash for the host proc macro. Used to support -Z dual-proc-macro. query crate_host_hash(_: CrateNum) -> Option { eval_always desc { "looking up the hash of a host version of a crate" } separate_provide_extern } + + /// Gets the extra data to put in each output filename for a crate. + /// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file. query extra_filename(_: CrateNum) -> String { arena_cache eval_always desc { "looking up the extra filename for a crate" } separate_provide_extern } + + /// Gets the paths where the crate came from in the file system. query crate_extern_paths(_: CrateNum) -> Vec { arena_cache eval_always @@ -1594,6 +1609,7 @@ rustc_queries! { separate_provide_extern } + /// Get the corresponding native library from the `native_libraries` query query native_library(def_id: DefId) -> Option<&'tcx NativeLib> { desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } } From 900af414a3dfabab74357f5038371a08b1cb0db1 Mon Sep 17 00:00:00 2001 From: viandoxdev Date: Sat, 5 Nov 2022 18:30:01 +0100 Subject: [PATCH 089/221] fix out dir being wrong in json --- src/bootstrap/doc.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index f3883e5e6bfd..218c71997317 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -465,7 +465,11 @@ impl Step for Std { fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; - let out = builder.doc_out(target); + let out = match self.format { + DocumentationFormat::HTML => builder.doc_out(target), + DocumentationFormat::JSON => builder.json_doc_out(target), + }; + t!(fs::create_dir_all(&out)); builder.ensure(SharedAssets { target: self.target }); From 2786acce98a87a22a01fdc0ab82ca6f90d62d44e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Jul 2022 01:53:53 +0000 Subject: [PATCH 090/221] Enforce Tuple trait on Fn traits --- library/alloc/src/boxed.rs | 31 +++ library/alloc/src/lib.rs | 1 + library/core/src/intrinsics.rs | 66 +++++++ library/core/src/ops/function.rs | 321 +++++++++++++++++++++++++++++++ 4 files changed, 419 insertions(+) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b7e7d5a38a5b..66f4c19e0f91 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -158,6 +158,8 @@ use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] use core::iter::FromIterator; use core::iter::{FusedIterator, Iterator}; +#[cfg(not(bootstrap))] +use core::marker::Tuple; use core::marker::{Destruct, Unpin, Unsize}; use core::mem; use core::ops::{ @@ -1979,6 +1981,7 @@ impl ExactSizeIterator for Box FusedIterator for Box {} +#[cfg(bootstrap)] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl + ?Sized, A: Allocator> FnOnce for Box { type Output = >::Output; @@ -1988,6 +1991,17 @@ impl + ?Sized, A: Allocator> FnOnce for Box { } } +#[cfg(not(bootstrap))] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + >::call_once(*self, args) + } +} + +#[cfg(bootstrap)] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl + ?Sized, A: Allocator> FnMut for Box { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { @@ -1995,6 +2009,15 @@ impl + ?Sized, A: Allocator> FnMut for Box { } } +#[cfg(not(bootstrap))] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnMut for Box { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + >::call_mut(self, args) + } +} + +#[cfg(bootstrap)] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl + ?Sized, A: Allocator> Fn for Box { extern "rust-call" fn call(&self, args: Args) -> Self::Output { @@ -2002,6 +2025,14 @@ impl + ?Sized, A: Allocator> Fn for Box { } } +#[cfg(not(bootstrap))] +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> Fn for Box { + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + >::call(self, args) + } +} + #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index ce36b116f139..008926666c13 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -150,6 +150,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] +#![cfg_attr(not(bootstrap), feature(tuple_trait))] #![feature(unchecked_math)] #![feature(unicode_internals)] #![feature(unsize)] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 1dc79afe83fd..bfbd4301230a 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -55,6 +55,8 @@ #![allow(missing_docs)] use crate::marker::DiscriminantKind; +#[cfg(not(bootstrap))] +use crate::marker::Tuple; use crate::mem; // These imports are used for simplifying intra-doc links @@ -2169,11 +2171,75 @@ extern "rust-intrinsic" { /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, /// which violates the principle that a `const fn` must behave the same at /// compile-time and at run-time. The unsafe code in crate B is fine. + #[cfg(bootstrap)] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] pub fn const_eval_select(arg: ARG, called_in_const: F, called_at_rt: G) -> RET where G: FnOnce, F: FnOnce; + + /// Selects which function to call depending on the context. + /// + /// If this function is evaluated at compile-time, then a call to this + /// intrinsic will be replaced with a call to `called_in_const`. It gets + /// replaced with a call to `called_at_rt` otherwise. + /// + /// # Type Requirements + /// + /// The two functions must be both function items. They cannot be function + /// pointers or closures. The first function must be a `const fn`. + /// + /// `arg` will be the tupled arguments that will be passed to either one of + /// the two functions, therefore, both functions must accept the same type of + /// arguments. Both functions must return RET. + /// + /// # Safety + /// + /// The two functions must behave observably equivalent. Safe code in other + /// crates may assume that calling a `const fn` at compile-time and at run-time + /// produces the same result. A function that produces a different result when + /// evaluated at run-time, or has any other observable side-effects, is + /// *unsound*. + /// + /// Here is an example of how this could cause a problem: + /// ```no_run + /// #![feature(const_eval_select)] + /// #![feature(core_intrinsics)] + /// use std::hint::unreachable_unchecked; + /// use std::intrinsics::const_eval_select; + /// + /// // Crate A + /// pub const fn inconsistent() -> i32 { + /// fn runtime() -> i32 { 1 } + /// const fn compiletime() -> i32 { 2 } + /// + /// unsafe { + // // ⚠ This code violates the required equivalence of `compiletime` + /// // and `runtime`. + /// const_eval_select((), compiletime, runtime) + /// } + /// } + /// + /// // Crate B + /// const X: i32 = inconsistent(); + /// let x = inconsistent(); + /// if x != X { unsafe { unreachable_unchecked(); }} + /// ``` + /// + /// This code causes Undefined Behavior when being run, since the + /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, + /// which violates the principle that a `const fn` must behave the same at + /// compile-time and at run-time. The unsafe code in crate B is fine. + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] + pub fn const_eval_select( + arg: ARG, + called_in_const: F, + called_at_rt: G, + ) -> RET + where + G: FnOnce, + F: FnOnce; } // Some functions are defined here because they accidentally got made diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 2e0a752c815d..7c93fd30d4ec 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -1,3 +1,6 @@ +#[cfg(not(bootstrap))] +use crate::marker::Tuple; + /// The version of the call operator that takes an immutable receiver. /// /// Instances of `Fn` can be called repeatedly without mutating state. @@ -51,6 +54,7 @@ /// let double = |x| x * 2; /// assert_eq!(call_with_one(double), 2); /// ``` +#[cfg(bootstrap)] #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Fn"] @@ -78,6 +82,87 @@ pub trait Fn: FnMut { extern "rust-call" fn call(&self, args: Args) -> Self::Output; } +/// The version of the call operator that takes an immutable receiver. +/// +/// Instances of `Fn` can be called repeatedly without mutating state. +/// +/// *This trait (`Fn`) is not to be confused with [function pointers] +/// (`fn`).* +/// +/// `Fn` is implemented automatically by closures which only take immutable +/// references to captured variables or don't capture anything at all, as well +/// as (safe) [function pointers] (with some caveats, see their documentation +/// for more details). Additionally, for any type `F` that implements `Fn`, `&F` +/// implements `Fn`, too. +/// +/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any +/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`] +/// is expected. +/// +/// Use `Fn` as a bound when you want to accept a parameter of function-like +/// type and need to call it repeatedly and without mutating state (e.g., when +/// calling it concurrently). If you do not need such strict requirements, use +/// [`FnMut`] or [`FnOnce`] as bounds. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a closure +/// +/// ``` +/// let square = |x| x * x; +/// assert_eq!(square(5), 25); +/// ``` +/// +/// ## Using a `Fn` parameter +/// +/// ``` +/// fn call_with_one(func: F) -> usize +/// where F: Fn(usize) -> usize { +/// func(1) +/// } +/// +/// let double = |x| x * 2; +/// assert_eq!(call_with_one(double), 2); +/// ``` +#[cfg(not(bootstrap))] +#[lang = "fn"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Fn"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{Fn}<{Args}>` closure, found `{Self}`", + label = "expected an `Fn<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +#[const_trait] +pub trait Fn: FnMut { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + /// The version of the call operator that takes a mutable receiver. /// /// Instances of `FnMut` can be called repeatedly and may mutate state. @@ -139,6 +224,7 @@ pub trait Fn: FnMut { /// /// assert_eq!(x, 5); /// ``` +#[cfg(bootstrap)] #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "FnMut"] @@ -166,6 +252,95 @@ pub trait FnMut: FnOnce { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } +/// The version of the call operator that takes a mutable receiver. +/// +/// Instances of `FnMut` can be called repeatedly and may mutate state. +/// +/// `FnMut` is implemented automatically by closures which take mutable +/// references to captured variables, as well as all types that implement +/// [`Fn`], e.g., (safe) [function pointers] (since `FnMut` is a supertrait of +/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F` +/// implements `FnMut`, too. +/// +/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be +/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of +/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected. +/// +/// Use `FnMut` as a bound when you want to accept a parameter of function-like +/// type and need to call it repeatedly, while allowing it to mutate state. +/// If you don't want the parameter to mutate state, use [`Fn`] as a +/// bound; if you don't need to call it repeatedly, use [`FnOnce`]. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a mutably capturing closure +/// +/// ``` +/// let mut x = 5; +/// { +/// let mut square_x = || x *= x; +/// square_x(); +/// } +/// assert_eq!(x, 25); +/// ``` +/// +/// ## Using a `FnMut` parameter +/// +/// ``` +/// fn do_twice(mut func: F) +/// where F: FnMut() +/// { +/// func(); +/// func(); +/// } +/// +/// let mut x: usize = 1; +/// { +/// let add_two_to_x = || x += 2; +/// do_twice(add_two_to_x); +/// } +/// +/// assert_eq!(x, 5); +/// ``` +#[cfg(not(bootstrap))] +#[lang = "fn_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnMut"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`", + label = "expected an `FnMut<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +#[const_trait] +pub trait FnMut: FnOnce { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + /// The version of the call operator that takes a by-value receiver. /// /// Instances of `FnOnce` can be called, but might not be callable multiple @@ -219,6 +394,7 @@ pub trait FnMut: FnOnce { /// /// // `consume_and_return_x` can no longer be invoked at this point /// ``` +#[cfg(bootstrap)] #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "FnOnce"] @@ -251,6 +427,93 @@ pub trait FnOnce { extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } +/// The version of the call operator that takes a by-value receiver. +/// +/// Instances of `FnOnce` can be called, but might not be callable multiple +/// times. Because of this, if the only thing known about a type is that it +/// implements `FnOnce`, it can only be called once. +/// +/// `FnOnce` is implemented automatically by closures that might consume captured +/// variables, as well as all types that implement [`FnMut`], e.g., (safe) +/// [function pointers] (since `FnOnce` is a supertrait of [`FnMut`]). +/// +/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of +/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected. +/// +/// Use `FnOnce` as a bound when you want to accept a parameter of function-like +/// type and only need to call it once. If you need to call the parameter +/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate +/// state, use [`Fn`]. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// some more information on this topic. +/// +/// Also of note is the special syntax for `Fn` traits (e.g. +/// `Fn(usize, bool) -> usize`). Those interested in the technical details of +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. +/// +/// [book]: ../../book/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Using a `FnOnce` parameter +/// +/// ``` +/// fn consume_with_relish(func: F) +/// where F: FnOnce() -> String +/// { +/// // `func` consumes its captured variables, so it cannot be run more +/// // than once. +/// println!("Consumed: {}", func()); +/// +/// println!("Delicious!"); +/// +/// // Attempting to invoke `func()` again will throw a `use of moved +/// // value` error for `func`. +/// } +/// +/// let x = String::from("x"); +/// let consume_and_return_x = move || x; +/// consume_with_relish(consume_and_return_x); +/// +/// // `consume_and_return_x` can no longer be invoked at this point +/// ``` +#[cfg(not(bootstrap))] +#[lang = "fn_once"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnOnce"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`", + label = "expected an `FnOnce<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +#[const_trait] +pub trait FnOnce { + /// The returned type after the call operator is used. + #[lang = "fn_once_output"] + #[stable(feature = "fn_once_output", since = "1.12.0")] + type Output; + + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +#[cfg(bootstrap)] mod impls { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] @@ -310,3 +573,61 @@ mod impls { } } } + +#[cfg(not(bootstrap))] +mod impls { + use crate::marker::Tuple; + + #[stable(feature = "rust1", since = "1.0.0")] + impl Fn for &F + where + F: Fn, + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnMut for &F + where + F: Fn, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnOnce for &F + where + F: Fn, + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnMut for &mut F + where + F: FnMut, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnOnce for &mut F + where + F: FnMut, + { + type Output = F::Output; + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call_mut(args) + } + } +} From 99b3454d374235f83f8706ddf11caf5a9a837817 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Jul 2022 03:41:53 +0000 Subject: [PATCH 091/221] Enforce rust-check ABI in signatures, calls --- .../rustc_hir_analysis/src/check/wfcheck.rs | 22 +++++++++++ compiler/rustc_hir_typeck/src/callee.rs | 16 ++++++++ compiler/rustc_hir_typeck/src/check.rs | 37 ------------------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 1 + compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 2 + .../src/traits/error_reporting/suggestions.rs | 3 +- 7 files changed, 44 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0117bdd0ba81..3ec8f9f5d14e 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::{GenericArgKind, InternalSubsts}; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use rustc_target::spec::abi::Abi; use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; @@ -1542,6 +1543,27 @@ fn check_fn_or_method<'tcx>( sig.output(), hir_decl.output.span(), ); + + if sig.abi == Abi::RustCall { + let span = tcx.def_span(def_id); + let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None; + let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 }); + // Check that the argument is a tuple + if let Some(ty) = inputs.next() { + wfcx.register_bound( + ObligationCause::new(span, wfcx.body_id, ObligationCauseCode::RustCall), + wfcx.param_env, + *ty, + tcx.require_lang_item(hir::LangItem::Tuple, Some(span)), + ); + } else { + tcx.sess.span_err(span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); + } + // No more inputs other than the `self` type and the tuple type + if inputs.next().is_some() { + tcx.sess.span_err(span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); + } + } } /// Basically `check_associated_type_bounds`, but separated for now and should be diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1b33f2f02b8a..eff65980f643 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -471,6 +471,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id, ); + if fn_sig.abi == abi::Abi::RustCall { + let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span); + if let Some(ty) = fn_sig.inputs().last().copied() { + self.register_bound( + ty, + self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)), + traits::ObligationCause::new(sp, self.body_id, traits::RustCall), + ); + } else { + self.tcx.sess.span_err( + sp, + "functions with the \"rust-call\" ABI must take a single non-self tuple argument", + ); + } + } + fn_sig.output() } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 80147d900911..37af6e79c3ef 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -6,13 +6,11 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ImplicitSelfKind, ItemKind, Node}; use rustc_hir_analysis::check::fn_maybe_err; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use std::cell::RefCell; @@ -56,41 +54,6 @@ pub(super) fn check_fn<'a, 'tcx>( fn_maybe_err(tcx, span, fn_sig.abi); - if fn_sig.abi == Abi::RustCall { - let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 }; - - let err = || { - let item = match tcx.hir().get(fn_id) { - Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header), - Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(header, ..), .. - }) => Some(header), - Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(header, ..), - .. - }) => Some(header), - // Closures are RustCall, but they tuple their arguments, so shouldn't be checked - Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None, - node => bug!("Item being checked wasn't a function/closure: {:?}", node), - }; - - if let Some(header) = item { - tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); - } - }; - - if fn_sig.inputs().len() != expected_args { - err() - } else { - // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on - // This will probably require wide-scale changes to support a TupleKind obligation - // We can't resolve this without knowing the type of the param - if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) { - err() - } - } - } - if body.generator_kind.is_some() && can_be_generator.is_some() { let yield_ty = fcx .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e1955d838f25..2239a33a8e9f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -136,6 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tuple_arguments, Some(method.def_id), ); + method.sig.output() } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index d1762598a520..624443d9594c 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -458,7 +458,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<' /// # fn f(x: (isize, isize)) {} /// f((1, 2)); /// ``` -#[derive(Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq)] enum TupleArgumentsFlag { DontTupleArguments, TupleArguments, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 07ee758b32c1..a29f0722ff70 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -438,6 +438,8 @@ pub enum ObligationCauseCode<'tcx> { }, AscribeUserTypeProvePredicate(Span), + + RustCall, } /// The 'location' at which we try to perform HIR-based wf checking. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d7606d88803d..0f4aa87b43f5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2407,7 +2407,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::CheckAssociatedTypeBounds { .. } | ObligationCauseCode::LetElse | ObligationCauseCode::BinOp { .. } - | ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {} + | ObligationCauseCode::AscribeUserTypeProvePredicate(..) + | ObligationCauseCode::RustCall => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } From 2257ba92db333277c957b3934cdebc2a0a2c2604 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Jul 2022 05:37:48 +0000 Subject: [PATCH 092/221] Adjust diagnostics, bless tests --- .../rustc_hir_analysis/src/check/wfcheck.rs | 10 ++- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/traits/error_reporting/mod.rs | 26 ++++-- .../ui/abi/issues/issue-22565-rust-call.rs | 13 ++- .../abi/issues/issue-22565-rust-call.stderr | 33 ++++--- src/test/ui/abi/rustcall-generic.rs | 4 +- .../borrow-immutable-upvar-mutation.rs | 6 +- .../borrow-immutable-upvar-mutation.stderr | 24 ++--- .../ui/borrowck/borrowck-move-by-capture.rs | 6 +- src/test/ui/c-variadic/issue-86053-1.stderr | 4 +- .../ui/cannot-mutate-captured-non-mut-var.rs | 4 +- src/test/ui/chalkify/closure.stderr | 88 +++++++++++++++---- src/test/ui/closures/issue-78720.stderr | 4 +- src/test/ui/error-codes/E0059.stderr | 12 ++- src/test/ui/feature-gates/feature-gate-abi.rs | 3 + .../ui/feature-gates/feature-gate-abi.stderr | 68 +++++++------- src/test/ui/issues/issue-12127.rs | 4 +- src/test/ui/issues/issue-23024.stderr | 2 +- src/test/ui/issues/issue-7607-1.stderr | 4 +- .../lang-items/lang-item-missing-generator.rs | 6 +- .../lang-item-missing-generator.stderr | 11 ++- .../unboxed-closures-vtable-mismatch.rs | 4 +- ...type-move-out-of-closure-env-issue-1965.rs | 4 +- .../overloaded/overloaded-calls-nontuple.rs | 17 ++-- .../overloaded-calls-nontuple.stderr | 49 +++++++---- src/test/ui/span/issue-11925.rs | 4 +- src/test/ui/typeck/issue-83693.stderr | 4 +- .../unboxed-closure-illegal-move.rs | 8 +- .../unboxed-closures-mutate-upvar.rs | 6 +- .../unboxed-closures-mutate-upvar.stderr | 4 +- ...nboxed-closures-static-call-wrong-trait.rs | 4 +- 31 files changed, 280 insertions(+), 158 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3ec8f9f5d14e..416b555db5c5 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1557,11 +1557,17 @@ fn check_fn_or_method<'tcx>( tcx.require_lang_item(hir::LangItem::Tuple, Some(span)), ); } else { - tcx.sess.span_err(span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); + tcx.sess.span_err( + hir_decl.inputs.last().map_or(span, |input| input.span), + "functions with the \"rust-call\" ABI must take a single non-self tuple argument", + ); } // No more inputs other than the `self` type and the tuple type if inputs.next().is_some() { - tcx.sess.span_err(span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple"); + tcx.sess.span_err( + hir_decl.inputs.last().map_or(span, |input| input.span), + "functions with the \"rust-call\" ABI must take a single non-self tuple argument", + ); } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 2239a33a8e9f..4066cca8a4bd 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -215,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit" ) - .emit(); + .delay_as_bug(); (self.err_args(provided_args.len()), None) } } 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 dacce5cd2f60..46c03757e600 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -700,6 +700,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { + match obligation.cause.code().peel_derives() { + ObligationCauseCode::RustCall => { + err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); + } + ObligationCauseCode::BindingObligation(def_id, _) + | ObligationCauseCode::ItemObligation(def_id) + if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() => + { + err.code(rustc_errors::error_code!(E0059)); + err.set_primary_message(format!( + "type parameter to bare `{}` trait must be a tuple", + tcx.def_path_str(*def_id) + )); + } + _ => {} + } + } + if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait() && predicate_is_const { @@ -848,12 +867,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } - let is_fn_trait = [ - self.tcx.lang_items().fn_trait(), - self.tcx.lang_items().fn_mut_trait(), - self.tcx.lang_items().fn_once_trait(), - ] - .contains(&Some(trait_ref.def_id())); + let is_fn_trait = ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some(); let is_target_feature_fn = if let ty::FnDef(def_id, _) = *trait_ref.skip_binder().self_ty().kind() { diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.rs b/src/test/ui/abi/issues/issue-22565-rust-call.rs index a08e0bfb5e5d..a572666c8887 100644 --- a/src/test/ui/abi/issues/issue-22565-rust-call.rs +++ b/src/test/ui/abi/issues/issue-22565-rust-call.rs @@ -1,32 +1,31 @@ #![feature(unboxed_closures)] extern "rust-call" fn b(_i: i32) {} -//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument that is a tuple +//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument trait Tr { extern "rust-call" fn a(); + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument extern "rust-call" fn b() {} - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument } struct Foo; impl Foo { extern "rust-call" fn bar() {} - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument } impl Tr for Foo { extern "rust-call" fn a() {} - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument } -fn main () { +fn main() { b(10); - Foo::bar(); - ::a(); ::b(); } diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.stderr b/src/test/ui/abi/issues/issue-22565-rust-call.stderr index 3eee10bc5e95..9d205b444fad 100644 --- a/src/test/ui/abi/issues/issue-22565-rust-call.stderr +++ b/src/test/ui/abi/issues/issue-22565-rust-call.stderr @@ -1,26 +1,33 @@ -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument --> $DIR/issue-22565-rust-call.rs:3:1 | LL | extern "rust-call" fn b(_i: i32) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `i32` -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/issue-22565-rust-call.rs:9:5 - | -LL | extern "rust-call" fn b() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/issue-22565-rust-call.rs:16:5 +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:17:5 | LL | extern "rust-call" fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/issue-22565-rust-call.rs:21:5 +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:22:5 | LL | extern "rust-call" fn a() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:7:5 + | +LL | extern "rust-call" fn a(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:10:5 + | +LL | extern "rust-call" fn b() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/abi/rustcall-generic.rs b/src/test/ui/abi/rustcall-generic.rs index 411c98e10313..6eaccc436b69 100644 --- a/src/test/ui/abi/rustcall-generic.rs +++ b/src/test/ui/abi/rustcall-generic.rs @@ -2,9 +2,9 @@ // check-pass //[opt] compile-flags: -Zmir-opt-level=3 -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -extern "rust-call" fn foo(_: T) {} +extern "rust-call" fn foo(_: T) {} fn main() { foo(()); diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs index e2f016614bf8..a3350024e756 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs @@ -1,4 +1,4 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] // Tests that we can't assign to or mutably borrow upvars from `Fn` // closures (issue #17780) @@ -7,10 +7,10 @@ fn set(x: &mut usize) { *x = 5; } -fn to_fn>(f: F) -> F { +fn to_fn>(f: F) -> F { f } -fn to_fn_mut>(f: F) -> F { +fn to_fn_mut>(f: F) -> F { f } diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr index 093589ed0921..a0eaf1f163b0 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -1,8 +1,8 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:21:27 | -LL | fn to_fn>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(|| x = 42); | ----- -- ^^^^^^ cannot assign @@ -13,8 +13,8 @@ LL | let _f = to_fn(|| x = 42); error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:24:31 | -LL | fn to_fn>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(|| set(&mut y)); | ----- -- ^^^^^^ cannot borrow as mutable @@ -25,8 +25,8 @@ LL | let _g = to_fn(|| set(&mut y)); error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:29:22 | -LL | fn to_fn>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | to_fn(|| z = 42); | ----- -- ^^^^^^ cannot assign @@ -37,8 +37,8 @@ LL | to_fn(|| z = 42); error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:36:32 | -LL | fn to_fn>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(move || x = 42); | ----- ------- ^^^^^^ cannot assign @@ -49,8 +49,8 @@ LL | let _f = to_fn(move || x = 42); error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:39:36 | -LL | fn to_fn>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(move || set(&mut y)); | ----- ------- ^^^^^^ cannot borrow as mutable @@ -61,8 +61,8 @@ LL | let _g = to_fn(move || set(&mut y)); error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:44:27 | -LL | fn to_fn>(f: F) -> F { - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | to_fn(move || z = 42); | ----- ------- ^^^^^^ cannot assign diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.rs b/src/test/ui/borrowck/borrowck-move-by-capture.rs index f26edef17f34..6f0eb1870f32 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture.rs +++ b/src/test/ui/borrowck/borrowck-move-by-capture.rs @@ -1,7 +1,7 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_mut>(f: F) -> F { f } -fn to_fn_once>(f: F) -> F { f } +fn to_fn_mut>(f: F) -> F { f } +fn to_fn_once>(f: F) -> F { f } pub fn main() { let bar: Box<_> = Box::new(3); diff --git a/src/test/ui/c-variadic/issue-86053-1.stderr b/src/test/ui/c-variadic/issue-86053-1.stderr index 60b379faf4e0..075bd1fc488e 100644 --- a/src/test/ui/c-variadic/issue-86053-1.stderr +++ b/src/test/ui/c-variadic/issue-86053-1.stderr @@ -66,8 +66,8 @@ LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here | help: a trait with a similar name exists | diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.rs b/src/test/ui/cannot-mutate-captured-non-mut-var.rs index a83884acb1d2..952dab25bf9d 100644 --- a/src/test/ui/cannot-mutate-captured-non-mut-var.rs +++ b/src/test/ui/cannot-mutate-captured-non-mut-var.rs @@ -1,8 +1,8 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] use std::io::Read; -fn to_fn_once>(f: F) -> F { f } +fn to_fn_once>(f: F) -> F { f } fn main() { let x = 1; diff --git a/src/test/ui/chalkify/closure.stderr b/src/test/ui/chalkify/closure.stderr index 515e0cf01429..ca62ad834bc7 100644 --- a/src/test/ui/chalkify/closure.stderr +++ b/src/test/ui/chalkify/closure.stderr @@ -1,22 +1,80 @@ -error[E0382]: borrow of moved value: `b` +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:6:5 + | +LL | t(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:12:5 + | +LL | b(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:16:5 + | +LL | c(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:17:5 + | +LL | b(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:23:5 + | +LL | b(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:27:5 + | +LL | c(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple --> $DIR/closure.rs:28:5 | -LL | let mut c = b; - | - value moved here -... LL | b(); - | ^ value borrowed here after move + | ^^^ `()` is not a tuple | -note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment - --> $DIR/closure.rs:21:9 +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -LL | a = 1; - | ^ -help: consider mutably borrowing `b` - | -LL | let mut c = &mut b; - | ++++ +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0382`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/closures/issue-78720.stderr b/src/test/ui/closures/issue-78720.stderr index 3dd138772983..da3f539a0071 100644 --- a/src/test/ui/closures/issue-78720.stderr +++ b/src/test/ui/closures/issue-78720.stderr @@ -12,8 +12,8 @@ LL | _func: F, | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here | help: a trait with a similar name exists | diff --git a/src/test/ui/error-codes/E0059.stderr b/src/test/ui/error-codes/E0059.stderr index a1b8aeaedbb8..f331d0142260 100644 --- a/src/test/ui/error-codes/E0059.stderr +++ b/src/test/ui/error-codes/E0059.stderr @@ -1,8 +1,14 @@ -error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit - --> $DIR/E0059.rs:3:41 +error[E0059]: type parameter to bare `Fn` trait must be a tuple + --> $DIR/E0059.rs:3:11 | LL | fn foo>(f: F) -> F::Output { f(3) } - | ^^^^ + | ^^^^^^^ the trait `Tuple` is not implemented for `i32` + | +note: required by a bound in `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn: FnMut { + | ^^^^^ required by this bound in `Fn` error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs index 855263595d0b..15b674c62e44 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.rs +++ b/src/test/ui/feature-gates/feature-gate-abi.rs @@ -9,6 +9,9 @@ #[lang="sized"] trait Sized { } +#[lang="tuple_trait"] +trait Tuple { } + // Functions extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change //~^ ERROR intrinsic must be in diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index bcca39c8fb80..33ec250f0906 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -1,5 +1,5 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:13:8 + --> $DIR/feature-gate-abi.rs:16:8 | LL | extern "rust-intrinsic" fn f1() {} | ^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:15:8 + --> $DIR/feature-gate-abi.rs:18:8 | LL | extern "platform-intrinsic" fn f2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | extern "platform-intrinsic" fn f2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:17:8 + --> $DIR/feature-gate-abi.rs:20:8 | LL | extern "rust-call" fn f4(_: ()) {} | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | extern "rust-call" fn f4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:18:8 + --> $DIR/feature-gate-abi.rs:21:8 | LL | extern "efiapi" fn f10() {} | ^^^^^^^^ @@ -34,7 +34,7 @@ LL | extern "efiapi" fn f10() {} = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:22:12 + --> $DIR/feature-gate-abi.rs:25:12 | LL | extern "rust-intrinsic" fn m1(); | ^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | extern "rust-intrinsic" fn m1(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:24:12 + --> $DIR/feature-gate-abi.rs:27:12 | LL | extern "platform-intrinsic" fn m2(); | ^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | extern "platform-intrinsic" fn m2(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:26:12 + --> $DIR/feature-gate-abi.rs:29:12 | LL | extern "rust-call" fn m4(_: ()); | ^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | extern "rust-call" fn m4(_: ()); = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:27:12 + --> $DIR/feature-gate-abi.rs:30:12 | LL | extern "efiapi" fn m10(); | ^^^^^^^^ @@ -69,7 +69,7 @@ LL | extern "efiapi" fn m10(); = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:29:12 + --> $DIR/feature-gate-abi.rs:32:12 | LL | extern "rust-call" fn dm4(_: ()) {} | ^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | extern "rust-call" fn dm4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:30:12 + --> $DIR/feature-gate-abi.rs:33:12 | LL | extern "efiapi" fn dm10() {} | ^^^^^^^^ @@ -87,7 +87,7 @@ LL | extern "efiapi" fn dm10() {} = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:37:12 + --> $DIR/feature-gate-abi.rs:40:12 | LL | extern "rust-intrinsic" fn m1() {} | ^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | extern "rust-intrinsic" fn m1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:39:12 + --> $DIR/feature-gate-abi.rs:42:12 | LL | extern "platform-intrinsic" fn m2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | extern "platform-intrinsic" fn m2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:41:12 + --> $DIR/feature-gate-abi.rs:44:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | extern "rust-call" fn m4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:42:12 + --> $DIR/feature-gate-abi.rs:45:12 | LL | extern "efiapi" fn m10() {} | ^^^^^^^^ @@ -122,7 +122,7 @@ LL | extern "efiapi" fn m10() {} = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:47:12 + --> $DIR/feature-gate-abi.rs:50:12 | LL | extern "rust-intrinsic" fn im1() {} | ^^^^^^^^^^^^^^^^ @@ -130,7 +130,7 @@ LL | extern "rust-intrinsic" fn im1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:49:12 + --> $DIR/feature-gate-abi.rs:52:12 | LL | extern "platform-intrinsic" fn im2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +139,7 @@ LL | extern "platform-intrinsic" fn im2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:51:12 + --> $DIR/feature-gate-abi.rs:54:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | extern "rust-call" fn im4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:52:12 + --> $DIR/feature-gate-abi.rs:55:12 | LL | extern "efiapi" fn im10() {} | ^^^^^^^^ @@ -157,7 +157,7 @@ LL | extern "efiapi" fn im10() {} = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:56:18 + --> $DIR/feature-gate-abi.rs:59:18 | LL | type A1 = extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | type A1 = extern "rust-intrinsic" fn(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:57:18 + --> $DIR/feature-gate-abi.rs:60:18 | LL | type A2 = extern "platform-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +174,7 @@ LL | type A2 = extern "platform-intrinsic" fn(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:58:18 + --> $DIR/feature-gate-abi.rs:61:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -183,7 +183,7 @@ LL | type A4 = extern "rust-call" fn(_: ()); = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:59:19 + --> $DIR/feature-gate-abi.rs:62:19 | LL | type A10 = extern "efiapi" fn(); | ^^^^^^^^ @@ -192,7 +192,7 @@ LL | type A10 = extern "efiapi" fn(); = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:62:8 + --> $DIR/feature-gate-abi.rs:65:8 | LL | extern "rust-intrinsic" {} | ^^^^^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | extern "rust-intrinsic" {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:63:8 + --> $DIR/feature-gate-abi.rs:66:8 | LL | extern "platform-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | extern "platform-intrinsic" {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:64:8 + --> $DIR/feature-gate-abi.rs:67:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | extern "rust-call" {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:65:8 + --> $DIR/feature-gate-abi.rs:68:8 | LL | extern "efiapi" {} | ^^^^^^^^ @@ -227,49 +227,49 @@ LL | extern "efiapi" {} = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:22:32 + --> $DIR/feature-gate-abi.rs:25:32 | LL | extern "rust-intrinsic" fn m1(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:24:36 + --> $DIR/feature-gate-abi.rs:27:36 | LL | extern "platform-intrinsic" fn m2(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:13:33 + --> $DIR/feature-gate-abi.rs:16:33 | LL | extern "rust-intrinsic" fn f1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:15:37 + --> $DIR/feature-gate-abi.rs:18:37 | LL | extern "platform-intrinsic" fn f2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:37:37 + --> $DIR/feature-gate-abi.rs:40:37 | LL | extern "rust-intrinsic" fn m1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:39:41 + --> $DIR/feature-gate-abi.rs:42:41 | LL | extern "platform-intrinsic" fn m2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:47:38 + --> $DIR/feature-gate-abi.rs:50:38 | LL | extern "rust-intrinsic" fn im1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:49:42 + --> $DIR/feature-gate-abi.rs:52:42 | LL | extern "platform-intrinsic" fn im2() {} | ^^ diff --git a/src/test/ui/issues/issue-12127.rs b/src/test/ui/issues/issue-12127.rs index 8b30ddc2de67..199d542e816f 100644 --- a/src/test/ui/issues/issue-12127.rs +++ b/src/test/ui/issues/issue-12127.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_once>(f: F) -> F { f } +fn to_fn_once>(f: F) -> F { f } fn do_it(x: &isize) { } fn main() { diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr index 73f93c51d34e..dc8b34a70c32 100644 --- a/src/test/ui/issues/issue-23024.stderr +++ b/src/test/ui/issues/issue-23024.stderr @@ -16,7 +16,7 @@ LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); note: trait defined here, with 1 generic parameter: `Args` --> $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { +LL | pub trait Fn: FnMut { | ^^ ---- help: add missing generic argument | diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr index ecff8b42b0ea..f1ab0ad26d70 100644 --- a/src/test/ui/issues/issue-7607-1.stderr +++ b/src/test/ui/issues/issue-7607-1.stderr @@ -6,8 +6,8 @@ LL | impl Fo { | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here error: aborting due to previous error diff --git a/src/test/ui/lang-items/lang-item-missing-generator.rs b/src/test/ui/lang-items/lang-item-missing-generator.rs index 0c329542928c..9b9aff38e524 100644 --- a/src/test/ui/lang-items/lang-item-missing-generator.rs +++ b/src/test/ui/lang-items/lang-item-missing-generator.rs @@ -1,12 +1,14 @@ // error-pattern: requires `generator` lang_item -#![feature(no_core, lang_items, unboxed_closures)] +#![feature(no_core, lang_items, unboxed_closures, tuple_trait)] #![no_core] #[lang = "sized"] pub trait Sized { } +#[lang = "tuple_trait"] pub trait Tuple { } + #[lang = "fn_once"] #[rustc_paren_sugar] -pub trait FnOnce { +pub trait FnOnce { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; diff --git a/src/test/ui/lang-items/lang-item-missing-generator.stderr b/src/test/ui/lang-items/lang-item-missing-generator.stderr index fa13bf0b1271..a24fdb5fb650 100644 --- a/src/test/ui/lang-items/lang-item-missing-generator.stderr +++ b/src/test/ui/lang-items/lang-item-missing-generator.stderr @@ -1,8 +1,15 @@ +error[E0635]: unknown feature `tuple_trait` + --> $DIR/lang-item-missing-generator.rs:2:51 + | +LL | #![feature(no_core, lang_items, unboxed_closures, tuple_trait)] + | ^^^^^^^^^^^ + error: requires `generator` lang_item - --> $DIR/lang-item-missing-generator.rs:15:17 + --> $DIR/lang-item-missing-generator.rs:17:17 | LL | pub fn abc() -> impl FnOnce(f32) { | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0635`. diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index 8dbe3472ea89..307104e47a18 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -1,8 +1,8 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures,tuple_trait)] use std::ops::FnMut; -fn to_fn_mut>(f: F) -> F { f } +fn to_fn_mut>(f: F) -> F { f } fn call_it isize>(y: isize, mut f: F) -> isize { //~^ NOTE required by this bound in `call_it` diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs index 76b7aab542de..490d91ac118c 100644 --- a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs +++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn>(f: F) -> F { f } +fn to_fn>(f: F) -> F { f } fn test(_x: Box) {} diff --git a/src/test/ui/overloaded/overloaded-calls-nontuple.rs b/src/test/ui/overloaded/overloaded-calls-nontuple.rs index 07d44ff82b13..32a3b93e0a1e 100644 --- a/src/test/ui/overloaded/overloaded-calls-nontuple.rs +++ b/src/test/ui/overloaded/overloaded-calls-nontuple.rs @@ -8,22 +8,23 @@ struct S { } impl FnMut for S { + //~^ ERROR type parameter to bare `FnMut` trait must be a tuple extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument self.x + self.y + z } - //~^^^ ERROR functions with the "rust-call" ABI must take a single non-self argument } impl FnOnce for S { + //~^ ERROR type parameter to bare `FnOnce` trait must be a tuple type Output = isize; - extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) } - //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument + extern "rust-call" fn call_once(mut self, z: isize) -> isize { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + self.call_mut(z) + } } fn main() { - let mut s = S { - x: 1, - y: 2, - }; - drop(s(3)) //~ ERROR cannot use call notation + let mut s = S { x: 1, y: 2 }; + drop(s(3)) } diff --git a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr index 8f299bc9434f..794535aeb110 100644 --- a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr +++ b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr @@ -1,21 +1,40 @@ -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/overloaded-calls-nontuple.rs:11:5 +error[E0059]: type parameter to bare `FnMut` trait must be a tuple + --> $DIR/overloaded-calls-nontuple.rs:10:6 + | +LL | impl FnMut for S { + | ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | +note: required by a bound in `FnMut` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait FnMut: FnOnce { + | ^^^^^ required by this bound in `FnMut` + +error[E0059]: type parameter to bare `FnOnce` trait must be a tuple + --> $DIR/overloaded-calls-nontuple.rs:18:6 + | +LL | impl FnOnce for S { + | ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | +note: required by a bound in `FnOnce` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait FnOnce { + | ^^^^^ required by this bound in `FnOnce` + +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/overloaded-calls-nontuple.rs:12:5 | LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` -error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple - --> $DIR/overloaded-calls-nontuple.rs:19:5 +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/overloaded-calls-nontuple.rs:21:5 | -LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` -error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit - --> $DIR/overloaded-calls-nontuple.rs:28:10 - | -LL | drop(s(3)) - | ^^^^ +error: aborting due to 4 previous errors -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0059`. +Some errors have detailed explanations: E0059, E0277. +For more information about an error, try `rustc --explain E0059`. diff --git a/src/test/ui/span/issue-11925.rs b/src/test/ui/span/issue-11925.rs index d9c08fbdd0f1..cac9fd5bfb68 100644 --- a/src/test/ui/span/issue-11925.rs +++ b/src/test/ui/span/issue-11925.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_once>(f: F) -> F { f } +fn to_fn_once>(f: F) -> F { f } fn main() { let r = { diff --git a/src/test/ui/typeck/issue-83693.stderr b/src/test/ui/typeck/issue-83693.stderr index 0d8bbf1ce98c..1e45c2d35dfd 100644 --- a/src/test/ui/typeck/issue-83693.stderr +++ b/src/test/ui/typeck/issue-83693.stderr @@ -6,8 +6,8 @@ LL | impl F { | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here error[E0412]: cannot find type `TestResult` in this scope --> $DIR/issue-83693.rs:9:22 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs index ed8d72114613..7377359b6b0c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs @@ -1,12 +1,12 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] // Tests that we can't move out of an unboxed closure environment // if the upvar is captured by ref or the closure takes self by // reference. -fn to_fn>(f: F) -> F { f } -fn to_fn_mut>(f: F) -> F { f } -fn to_fn_once>(f: F) -> F { f } +fn to_fn>(f: F) -> F { f } +fn to_fn_mut>(f: F) -> F { f } +fn to_fn_once>(f: F) -> F { f } fn main() { // By-ref cases diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs index 57e6d30658ce..c57312b43874 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs @@ -2,12 +2,12 @@ // as `mut` through a closure. Also test that we CAN mutate a moved copy, // unless this is a `Fn` closure. Issue #16749. -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] use std::mem; -fn to_fn>(f: F) -> F { f } -fn to_fn_mut>(f: F) -> F { f } +fn to_fn>(f: F) -> F { f } +fn to_fn_mut>(f: F) -> F { f } fn a() { let n = 0; diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr index d6e74b5b8b91..26f97b51913d 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr @@ -28,8 +28,8 @@ LL | n += 1; error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure --> $DIR/unboxed-closures-mutate-upvar.rs:53:9 | -LL | fn to_fn>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` ... LL | let mut f = to_fn(move || { | ----- ------- in this closure diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs index 0e727b11cd21..7289d9322d05 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs @@ -1,6 +1,6 @@ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, tuple_trait)] -fn to_fn_mut>(f: F) -> F { f } +fn to_fn_mut>(f: F) -> F { f } fn main() { let mut_ = to_fn_mut(|x| x); From 29dccfe9e498f41169c120e515494cdd9b5b3e11 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Jul 2022 05:43:26 +0000 Subject: [PATCH 093/221] Bless chalk tests --- .../src/traits/error_reporting/mod.rs | 3 +- src/test/ui/chalkify/closure.rs | 5 +- src/test/ui/chalkify/closure.stderr | 74 +++++++++---------- src/test/ui/chalkify/trait-objects.rs | 3 +- src/test/ui/chalkify/trait-objects.stderr | 28 +++++++ 5 files changed, 72 insertions(+), 41 deletions(-) create mode 100644 src/test/ui/chalkify/trait-objects.stderr 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 46c03757e600..54281f912054 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -867,7 +867,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } - let is_fn_trait = ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some(); + let is_fn_trait = + ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some(); let is_target_feature_fn = if let ty::FnDef(def_id, _) = *trait_ref.skip_binder().self_ty().kind() { diff --git a/src/test/ui/chalkify/closure.rs b/src/test/ui/chalkify/closure.rs index 81114d491d78..408e8802d862 100644 --- a/src/test/ui/chalkify/closure.rs +++ b/src/test/ui/chalkify/closure.rs @@ -1,4 +1,5 @@ -// check-fail +// known-bug: unknown +// FIXME(chalk): Chalk needs support for the Tuple trait // compile-flags: -Z chalk fn main() -> () { @@ -25,7 +26,7 @@ fn main() -> () { let mut c = b; c(); - b(); //~ ERROR + b(); // FIXME: reenable when this is fixed ~ ERROR // FIXME(chalk): this doesn't quite work /* diff --git a/src/test/ui/chalkify/closure.stderr b/src/test/ui/chalkify/closure.stderr index ca62ad834bc7..bcee0cab96ae 100644 --- a/src/test/ui/chalkify/closure.stderr +++ b/src/test/ui/chalkify/closure.stderr @@ -1,5 +1,5 @@ error[E0277]: `()` is not a tuple - --> $DIR/closure.rs:6:5 + --> $DIR/closure.rs:7:5 | LL | t(); | ^^^ the trait `Tuple` is not implemented for `()` @@ -10,7 +10,7 @@ LL | fn main() -> () where (): Tuple { | +++++++++++++++ error[E0277]: `()` is not a tuple - --> $DIR/closure.rs:12:5 + --> $DIR/closure.rs:13:5 | LL | b(); | ^^^ the trait `Tuple` is not implemented for `()` @@ -20,42 +20,9 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn main() -> () where (): Tuple { | +++++++++++++++ -error[E0277]: `()` is not a tuple - --> $DIR/closure.rs:16:5 - | -LL | c(); - | ^^^ the trait `Tuple` is not implemented for `()` - | -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement - | -LL | fn main() -> () where (): Tuple { - | +++++++++++++++ - error[E0277]: `()` is not a tuple --> $DIR/closure.rs:17:5 | -LL | b(); - | ^^^ the trait `Tuple` is not implemented for `()` - | -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement - | -LL | fn main() -> () where (): Tuple { - | +++++++++++++++ - -error[E0277]: `()` is not a tuple - --> $DIR/closure.rs:23:5 - | -LL | b(); - | ^^^ the trait `Tuple` is not implemented for `()` - | -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement - | -LL | fn main() -> () where (): Tuple { - | +++++++++++++++ - -error[E0277]: `()` is not a tuple - --> $DIR/closure.rs:27:5 - | LL | c(); | ^^^ the trait `Tuple` is not implemented for `()` | @@ -64,11 +31,44 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn main() -> () where (): Tuple { | +++++++++++++++ +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:18:5 + | +LL | b(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:24:5 + | +LL | b(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + error[E0277]: `()` is not a tuple --> $DIR/closure.rs:28:5 | -LL | b(); - | ^^^ `()` is not a tuple +LL | c(); + | ^^^ the trait `Tuple` is not implemented for `()` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() -> () where (): Tuple { + | +++++++++++++++ + +error[E0277]: `()` is not a tuple + --> $DIR/closure.rs:29:5 + | +LL | b(); // FIXME: reenable when this is fixed ~ ERROR + | ^^^ the trait `Tuple` is not implemented for `()` | help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | diff --git a/src/test/ui/chalkify/trait-objects.rs b/src/test/ui/chalkify/trait-objects.rs index d56abc42bf54..30929e943bd7 100644 --- a/src/test/ui/chalkify/trait-objects.rs +++ b/src/test/ui/chalkify/trait-objects.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: unknown +// FIXME(chalk): Chalk needs support for the Tuple trait // compile-flags: -Z chalk use std::fmt::Display; diff --git a/src/test/ui/chalkify/trait-objects.stderr b/src/test/ui/chalkify/trait-objects.stderr new file mode 100644 index 000000000000..098bd2d3226e --- /dev/null +++ b/src/test/ui/chalkify/trait-objects.stderr @@ -0,0 +1,28 @@ +error: the type `&dyn Fn(i32) -> _` is not well-formed (chalk) + --> $DIR/trait-objects.rs:11:12 + | +LL | let f: &dyn Fn(i32) -> _ = &|x| x + x; + | ^^^^^^^^^^^^^^^^^ + +error[E0277]: `(i32,)` is not a tuple + --> $DIR/trait-objects.rs:12:5 + | +LL | f(2); + | ^^^^ the trait `Tuple` is not implemented for `(i32,)` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() where (i32,): Tuple { + | +++++++++++++++++++ + +error[E0277]: expected a `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32` + --> $DIR/trait-objects.rs:12:5 + | +LL | f(2); + | ^^^^ expected an `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32` + | + = help: the trait `Fn<(i32,)>` is not implemented for `dyn Fn(i32) -> i32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. From d9891563d30375df1854dd2ec0271ac3d058e10c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Oct 2022 06:57:01 +0000 Subject: [PATCH 094/221] Merge conflicts and rebase onto master --- library/core/src/const_closure.rs | 30 +++++++++++++++++++ library/core/src/ops/function.rs | 3 -- src/test/ui/function-pointer/unsized-ret.rs | 3 +- .../ui/function-pointer/unsized-ret.stderr | 12 ++++---- src/test/ui/parser/kw-in-trait-bounds.stderr | 16 +++++----- .../non-tupled-arg-mismatch.rs | 2 +- .../non-tupled-arg-mismatch.stderr | 20 ++++++------- 7 files changed, 56 insertions(+), 30 deletions(-) diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index 9e9c02093be2..151c8e6d8986 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -1,4 +1,6 @@ use crate::marker::Destruct; +#[cfg(not(bootstrap))] +use crate::marker::Tuple; /// Struct representing a closure with mutably borrowed data. /// @@ -44,6 +46,7 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, macro_rules! impl_fn_mut_tuple { ($($var:ident)*) => { + #[cfg(bootstrap)] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const FnOnce for ConstFnMutClosure<($(&'a mut $var),*), Function> @@ -56,6 +59,7 @@ macro_rules! impl_fn_mut_tuple { self.call_mut(args) } } + #[cfg(bootstrap)] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const FnMut for ConstFnMutClosure<($(&'a mut $var),*), Function> @@ -68,6 +72,32 @@ macro_rules! impl_fn_mut_tuple { (self.func)(($($var),*), args) } } + #[cfg(not(bootstrap))] + #[allow(unused_parens)] + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnOnce for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct, + { + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } + } + #[cfg(not(bootstrap))] + #[allow(unused_parens)] + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnMut for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, + { + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + #[allow(non_snake_case)] + let ($($var),*) = &mut self.data; + (self.func)(($($var),*), args) + } + } }; } impl_fn_mut_tuple!(A); diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 7c93fd30d4ec..8d4b0a7ccacd 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -75,7 +75,6 @@ use crate::marker::Tuple; )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), const_trait)] pub trait Fn: FnMut { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -245,7 +244,6 @@ pub trait Fn: FnMut { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), const_trait)] pub trait FnMut: FnOnce { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -415,7 +413,6 @@ pub trait FnMut: FnOnce { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), const_trait)] pub trait FnOnce { /// The returned type after the call operator is used. #[lang = "fn_once_output"] diff --git a/src/test/ui/function-pointer/unsized-ret.rs b/src/test/ui/function-pointer/unsized-ret.rs index 60af5769d6dd..79009c5cb6c0 100644 --- a/src/test/ui/function-pointer/unsized-ret.rs +++ b/src/test/ui/function-pointer/unsized-ret.rs @@ -1,7 +1,8 @@ #![feature(fn_traits)] #![feature(unboxed_closures)] +#![feature(tuple_trait)] -fn foo, T>(f: Option, t: T) { +fn foo, T:std::marker::Tuple>(f: Option, t: T) { let y = (f.unwrap()).call(t); } diff --git a/src/test/ui/function-pointer/unsized-ret.stderr b/src/test/ui/function-pointer/unsized-ret.stderr index bec3e2aa3fe6..40bf7a3898ac 100644 --- a/src/test/ui/function-pointer/unsized-ret.stderr +++ b/src/test/ui/function-pointer/unsized-ret.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/unsized-ret.rs:9:27 + --> $DIR/unsized-ret.rs:10:27 | LL | foo:: str, _>(None, ()); | --------------------- ^^^^ doesn't have a size known at compile-time @@ -9,13 +9,13 @@ LL | foo:: str, _>(None, ()); = help: within `fn() -> str`, the trait `Sized` is not implemented for `str` = note: required because it appears within the type `fn() -> str` note: required by a bound in `foo` - --> $DIR/unsized-ret.rs:4:11 + --> $DIR/unsized-ret.rs:5:11 | -LL | fn foo, T>(f: Option, t: T) { +LL | fn foo, T:std::marker::Tuple>(f: Option, t: T) { | ^^^^^ required by this bound in `foo` error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time - --> $DIR/unsized-ret.rs:12:66 + --> $DIR/unsized-ret.rs:13:66 | LL | foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); | ------------------------------------------------------------ ^^^^ doesn't have a size known at compile-time @@ -25,9 +25,9 @@ LL | foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&() = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)` = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)` note: required by a bound in `foo` - --> $DIR/unsized-ret.rs:4:11 + --> $DIR/unsized-ret.rs:5:11 | -LL | fn foo, T>(f: Option, t: T) { +LL | fn foo, T:std::marker::Tuple>(f: Option, t: T) { | ^^^^^ required by this bound in `foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr index 28196c7ce2de..546ad84eeee7 100644 --- a/src/test/ui/parser/kw-in-trait-bounds.stderr +++ b/src/test/ui/parser/kw-in-trait-bounds.stderr @@ -94,8 +94,8 @@ LL | fn _f(_: impl fn(), _: &dyn fn()) | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#fn` in this scope --> $DIR/kw-in-trait-bounds.rs:17:4 @@ -105,8 +105,8 @@ LL | G: fn(), | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#fn` in this scope --> $DIR/kw-in-trait-bounds.rs:3:27 @@ -116,8 +116,8 @@ LL | fn _f(_: impl fn(), _: &dyn fn()) | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#fn` in this scope --> $DIR/kw-in-trait-bounds.rs:3:41 @@ -127,8 +127,8 @@ LL | fn _f(_: impl fn(), _: &dyn fn()) | ::: $SRC_DIR/core/src/ops/function.rs:LL:COL | -LL | pub trait Fn: FnMut { - | ------------------------------- similarly named trait `Fn` defined here +LL | pub trait Fn: FnMut { + | -------------------------------------- similarly named trait `Fn` defined here error[E0405]: cannot find trait `r#struct` in this scope --> $DIR/kw-in-trait-bounds.rs:24:10 diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs index 925463d6deed..d2e486002272 100644 --- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs +++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs @@ -1,8 +1,8 @@ #![feature(unboxed_closures)] fn a>(f: F) {} +//~^ ERROR type parameter to bare `Fn` trait must be a tuple fn main() { a(|_: usize| {}); - //~^ ERROR mismatched types } diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr index 9a24fb8c2bee..1c18eb0fc490 100644 --- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr +++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr @@ -1,17 +1,15 @@ -error[E0308]: mismatched types - --> $DIR/non-tupled-arg-mismatch.rs:6:5 - | -LL | a(|_: usize| {}); - | ^ types differ - | - = note: expected trait `Fn` - found trait `Fn<(usize,)>` -note: required by a bound in `a` +error[E0059]: type parameter to bare `Fn` trait must be a tuple --> $DIR/non-tupled-arg-mismatch.rs:3:9 | LL | fn a>(f: F) {} - | ^^^^^^^^^ required by this bound in `a` + | ^^^^^^^^^ the trait `Tuple` is not implemented for `usize` + | +note: required by a bound in `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn: FnMut { + | ^^^^^ required by this bound in `Fn` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0059`. From ff8f84ccf6b208e41713da911333f20676472a48 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Oct 2022 19:41:54 +0000 Subject: [PATCH 095/221] Bless more tests --- src/test/codegen/avr/avr-func-addrspace.rs | 16 +++++----------- src/test/incremental/hashes/extern_mods.rs | 4 ++-- .../by-value-trait-objects-rust-call.rs | 3 ++- .../by-value-trait-objects-rust-call2.rs | 3 ++- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/test/codegen/avr/avr-func-addrspace.rs b/src/test/codegen/avr/avr-func-addrspace.rs index a038dfe76f70..cbbcfad3ef48 100644 --- a/src/test/codegen/avr/avr-func-addrspace.rs +++ b/src/test/codegen/avr/avr-func-addrspace.rs @@ -19,6 +19,8 @@ pub trait Sized { } pub trait Copy { } #[lang = "receiver"] pub trait Receiver { } +#[lang = "tuple_trait"] +pub trait Tuple { } pub struct Result { _a: T, _b: E } @@ -29,7 +31,7 @@ impl Copy for &usize {} pub unsafe fn drop_in_place(_: *mut T) {} #[lang = "fn_once"] -pub trait FnOnce { +pub trait FnOnce { #[lang = "fn_once_output"] type Output; @@ -37,24 +39,16 @@ pub trait FnOnce { } #[lang = "fn_mut"] -pub trait FnMut : FnOnce { +pub trait FnMut : FnOnce { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } #[lang = "fn"] -pub trait Fn: FnOnce { +pub trait Fn: FnOnce { /// Performs the call operation. extern "rust-call" fn call(&self, args: Args) -> Self::Output; } -impl<'a, A, R> FnOnce for &'a fn(A) -> R { - type Output = R; - - extern "rust-call" fn call_once(self, args: A) -> R { - (*self)(args) - } -} - pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box; pub static mut STORAGE_BAR: u32 = 12; diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index ff79acc7f639..3121abbea369 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -128,7 +128,7 @@ extern "C" { // Change calling convention --------------------------------------------------- #[cfg(any(cfail1,cfail4))] extern "C" { - pub fn change_calling_convention(c: i32); + pub fn change_calling_convention(c: (i32,)); } #[cfg(not(any(cfail1,cfail4)))] @@ -137,7 +137,7 @@ extern "C" { #[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "rust-call" { - pub fn change_calling_convention(c: i32); + pub fn change_calling_convention(c: (i32,)); } // Make function public -------------------------------------------------------- diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs index 7f365ce2bbaf..ece4dea9aaf6 100644 --- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs @@ -1,7 +1,8 @@ #![feature(unsized_locals)] #![feature(unboxed_closures)] +#![feature(tuple_trait)] -pub trait FnOnce { +pub trait FnOnce { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs index a78b897d1941..94df2b0b83f0 100644 --- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs @@ -1,7 +1,8 @@ #![feature(unsized_locals)] #![feature(unboxed_closures)] +#![feature(tuple_trait)] -pub trait FnOnce { +pub trait FnOnce { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } From 13d4c61b5f732f17b66c7610588e113844fc5e08 Mon Sep 17 00:00:00 2001 From: Tanner Davies Date: Sat, 5 Nov 2022 15:07:10 -0600 Subject: [PATCH 096/221] Place config.toml in current working directory if config not found --- src/bootstrap/bin/main.rs | 2 +- src/bootstrap/config.rs | 4 ++-- src/bootstrap/setup.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index 9b4861ccd95f..be69f819c642 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -35,7 +35,7 @@ fn main() { // NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the // changelog warning, not the `x.py setup` message. - let suggest_setup = !config.config.exists() && !matches!(config.cmd, Subcommand::Setup { .. }); + let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. }); if suggest_setup { println!("warning: you have not made a `config.toml`"); println!( diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 21dc11c48081..c086d248e5ce 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -80,7 +80,7 @@ pub struct Config { pub keep_stage_std: Vec, pub src: PathBuf, /// defaults to `config.toml` - pub config: PathBuf, + pub config: Option, pub jobs: Option, pub cmd: Subcommand, pub incremental: bool, @@ -942,7 +942,7 @@ impl Config { } config.changelog_seen = toml.changelog_seen; - config.config = toml_path; + config.config = if toml_path.exists() { Some(toml_path) } else { None }; let build = toml.build.unwrap_or_default(); diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index eb7da1bda73c..04480277fe04 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -82,7 +82,7 @@ impl fmt::Display for Profile { } pub fn setup(config: &Config, profile: Profile) { - let path = &config.config; + let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml")); if path.exists() { eprintln!( From 21894801c66709f6b16d16a8598f9c99fd4c998c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 5 Nov 2022 10:14:31 -0700 Subject: [PATCH 097/221] rustdoc: add test case for huge logo --- src/test/rustdoc-gui/huge-logo.goml | 21 +++++++++++++++++++ src/test/rustdoc-gui/search-filter.goml | 2 ++ src/test/rustdoc-gui/sidebar-source-code.goml | 2 +- src/test/rustdoc-gui/source-code-page.goml | 2 +- src/test/rustdoc-gui/src/huge_logo/Cargo.lock | 7 +++++++ src/test/rustdoc-gui/src/huge_logo/Cargo.toml | 8 +++++++ src/test/rustdoc-gui/src/huge_logo/src/lib.rs | 17 +++++++++++++++ 7 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc-gui/huge-logo.goml create mode 100644 src/test/rustdoc-gui/src/huge_logo/Cargo.lock create mode 100644 src/test/rustdoc-gui/src/huge_logo/Cargo.toml create mode 100644 src/test/rustdoc-gui/src/huge_logo/src/lib.rs diff --git a/src/test/rustdoc-gui/huge-logo.goml b/src/test/rustdoc-gui/huge-logo.goml new file mode 100644 index 000000000000..01f06771c15a --- /dev/null +++ b/src/test/rustdoc-gui/huge-logo.goml @@ -0,0 +1,21 @@ +// huge_logo crate has a custom 712x860 logo +// test to ensure the maximum size in the layout works correctly +goto: "file://" + |DOC_PATH| + "/huge_logo/index.html" + +size: (1280, 1024) +// offsetWidth = width of sidebar +assert-property: (".sidebar .logo-container", {"offsetWidth": "200", "offsetHeight": 100}) +assert-property: (".sidebar .logo-container img", {"offsetWidth": "100", "offsetHeight": 100}) + +size: (400, 600) +// offset = size + margin +assert-property: (".mobile-topbar .logo-container", {"offsetWidth": "55", "offsetHeight": 45}) +assert-property: (".mobile-topbar .logo-container img", {"offsetWidth": "35", "offsetHeight": 35}) + +goto: "file://" + |DOC_PATH| + "/src/huge_logo/lib.rs.html" + +size: (1280, 1024) +assert-property: (".sub-logo-container", {"offsetWidth": "60", "offsetHeight": 60}) + +size: (400, 600) +assert-property: (".sub-logo-container", {"offsetWidth": "35", "offsetHeight": 35}) diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml index 27db816e6851..e0228694eec5 100644 --- a/src/test/rustdoc-gui/search-filter.goml +++ b/src/test/rustdoc-gui/search-filter.goml @@ -14,6 +14,7 @@ click: "#crate-search" // We select "lib2" option then press enter to change the filter. press-key: "ArrowDown" press-key: "ArrowDown" +press-key: "ArrowDown" press-key: "Enter" // Waiting for the search results to appear... wait-for: "#titles" @@ -37,6 +38,7 @@ assert-property: ("#crate-search", {"value": "lib2"}) click: "#crate-search" press-key: "ArrowUp" press-key: "ArrowUp" +press-key: "ArrowUp" press-key: "Enter" // Waiting for the search results to appear... wait-for: "#titles" diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 9ba663687729..e9a987d52bbd 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -28,7 +28,7 @@ assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']" // Only "another_folder" should be "open" in "lib2". assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']" // All other trees should be collapsed. -assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 5) +assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 6) // We now switch to mobile mode. size: (600, 600) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index a2dac2aa681d..3c4db978d5fb 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -78,7 +78,7 @@ assert: ".source-sidebar-expanded" // We check that the first entry of the sidebar is collapsed assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) -assert-text: ("#source-sidebar details:first-of-type > summary", "implementors") +assert-text: ("#source-sidebar details:first-of-type > summary", "huge_logo") // We now click on it. click: "#source-sidebar details:first-of-type > summary" assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) diff --git a/src/test/rustdoc-gui/src/huge_logo/Cargo.lock b/src/test/rustdoc-gui/src/huge_logo/Cargo.lock new file mode 100644 index 000000000000..142805750642 --- /dev/null +++ b/src/test/rustdoc-gui/src/huge_logo/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "huge_logo" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/huge_logo/Cargo.toml b/src/test/rustdoc-gui/src/huge_logo/Cargo.toml new file mode 100644 index 000000000000..3f10d09c80ad --- /dev/null +++ b/src/test/rustdoc-gui/src/huge_logo/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "huge_logo" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/test/rustdoc-gui/src/huge_logo/src/lib.rs b/src/test/rustdoc-gui/src/huge_logo/src/lib.rs new file mode 100644 index 000000000000..ec137fb9a88f --- /dev/null +++ b/src/test/rustdoc-gui/src/huge_logo/src/lib.rs @@ -0,0 +1,17 @@ +// ignore-tidy-linelength +#![doc(html_logo_url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsgAAANcCAQAAADoIpEcAAAAAmJLR0QA/4ePzL8AAHSISURBVHja7Z15vFbT/sefzNflXtzr+qHOXvs5p051KtVJIg1IhqRoQlHKVKbKUBkaRQiRpEhKkqIQkURyJJUkQxNKs4bTPJ7h8/uj5Ax772fvZ6+999r7+bzXP14vPXufs9b3+znr+a7v+n5jMUIIIYQQ95zxTz1Tr6e10Dpp3bX+4nkxRrwnZonvxW/iN/Gb2CpyRa7YIyAgIHaLXJErcsVqsUxfoM0QU7Sx+ouij9ZFuyZ+oZ6ZeTLnkxBCbJJ1XLy8uEx01p4Wb4vZYrnYfVhqZY1csVC8qz+j3y0u1zXONyGEFCPt1PiF4nZtqJgpVol8yQJsObRdYp4YrT+gXZTxL64DISRlySirXSsGielirZ8SbDoKxBJtrH63qB47imtDCEkJxAnaRdrD4j2xXgkZNg5qvCe6UpgJIdHlmLRs0UObIfYpK8QlwxmbxUT9pvi/uXSEkMig6frdYnp4hLjE2C+m67ee/R+uIyEkzBwVv1AMEj+FVIiLj4PiI/0mHvwRQkJIWpboK36LhBQXHfvExHijWBmuLyEkFIiK+sAISnHR8YvolnYqV5oQojAZx+uttBmiMNJi/Hf+8ghRkWtOCFFyXyyeF7mpIMXFMpenaBdw7QkhChG/UEz0936dSkPPEQ1pA4SQwMk+Vr9RfJ+qUlxkTIufS2sghAQpxjdpKyjGh0ehmKjptApCiP8cpbcSyynDJcYB8Tzv9RFCfEW7Riyj/JqM9XprWgghxB8xriG+oOwmGJ/HK9BSCCGeIv5PvCYKKLg2xh6tO2vFEUK8oox+k9hCqXUwvk7PoNkQQqSjZ4ovKbGOxw5xM22HECKTo7WHQls6M/gxPuskmhAhRM7eWOPe2OVYGq9KOyKEuEa0Fzsoqa7Hbq0tbYkQ4oKsk8QEiqm08QSzLgghSRKvoP1IGZU6PmK/EUJIEmgtxE5KqPSxqNxZtC1CiBPK6I+lRpH5AMbv8fI0MEKITTKO18dROD0cW0QdWhkhxAYV/qvnUDS9vi6i16OlEUISIARLavrTj4+STAixJF5BrKZY+lZ86CJaHCHETI6rig0USj93ydr5tDpCiAFaTVZy833kpleh5RFCSqBnio0UyADGOnbhI4QUD1aUZ7AisLE843RaICHkMELwKC/IoedkHE8rJITEYrGyp4mlFMWAx4RYGVoiISlPxvGsdaxExsXDtEVCUp0y2liKoRKjUDSnORKS0oi+lEJ1UuCYb0FICqM3FQUUQpVKc551Iq2SkJQkXkFspwgqNkbQLglJQbJOYjcQJVPgWtM2CUm96PEYip+akeR4Gq2TkNSS4zaUPmXHTLZCJSSFyCgrtlL4FA5b3EUbJSRVOErMpugpXpaTCXCEpEi4ohslT/nxOa9SE5ICpMXFbgpeCHbJnWirhESdMuJTil0oxtYK/6W5EhJp9FsodaHZI79CeyUkyuGKU8UmCl1oRgE77hES5f3xMMpcqPbI85mRTEhESa+i5VHkQpaRfCPtlpBIwkL0IRyry/6DlktI5IhfRXljJxFCiAocLX6iuIVybE87leZLSKTQOlLaQjv60H4JiRBZx4k/KGyhHdvi/6YNExIZ9Fspa6EevWnDhEQnfrycohbuOLI4hWZMSCQQ7Slpoc9HfoR2TEgUKCN+oaCFv9RQxr9oyoSEHq0J5SwS+cgP0ZYJCX/AYibFLBJjffaxtGZCQk28qiikmEVktKE9ExLu/fFrFLLIBC2+oj0TEub98b/FHgpZdEZaNm2akNCi300RYw8RQogSaD9SxCI19p79H1o1IeGU4wsoYZHbI99HuyYklIiXKWCRG7+xqRMhISTrOLGFAhbB0ZC2TUj4AhYtKF482COEqBGwmELximZ1ZHECrZuQUJF5sthH8Ypo5beWtG9CwhWwuIHCFdkxhfZNSKjQ36FwRXYcYDYyISHirBPFbgpXhMfttHFCwrM/vpqiFekxmzZOSHgEeRhFK9KjsOzZtHJCQoL4laLFoAUhRAE0nYIV+dS3D2nnhIRjf9yZghX5sT/rJFo6IWEQZN7RS4XRjJZOiPocI7ZTrlIgaPEqTZ0Q5dHrUaxSYvzJQpyEKI82gGKVIuM8WjshqkeQZ1OqUiRo8RitnRClyT6WfaZTZsylvROidsCiJoUqZUrV52X8ixZPiMoBC+Ygp5IkN6HFE6KyIL9OmUqhKPJgWjwhKgvyUspUCo3vaPGEqCvHp4gCylQKjYK0U2n1hKgqyJdRpHiBmhCihiD3pkSl2BhCqydEVUGeTIlKsbGIVk+IqoK8jBKValHkzJNp94QoSMbxWh4lKuVGA1o+IQqin0N5SsFc5Ado+YQoiHYD5SkFx0RaPiEq7pAfozyl4FhFyydEQdi6KUWDFmfQ9glRT5CZY5GagtyUtk+IanJ8gsinOKVkzbf+tH5CFCMti9KUouNjWj8hiqFdSWlK0bGW1k+IaiELlqZP2XH2f2j/hKglyIMoTCl7rFef9k+IWoL8FoUpZY/1utD+CVFLkOdQmFJ2vET7J0QtQV5HYUrZHfJXtH9CFCLrODZvSuGxPVaGPkCIMpRLpyyl8sgoSx8gRJ2ARQOKUkoHLa6gDxCiDHprilJKj3voA4Qog3YnRSlhti7qoAXaojO6oAs6oA0aoEJUfrvn6QOEqBOy6EvBNRuX4FG8g+U4ACPWYjoGowXSw/3H5kP6ACHqCPJLFF4jKR6O32GPXLyD66CH9XddSh8gRJ2QxSTKb/HwRGfMRSGcshL9UCmMv/GB2NH0AkJU2SHPogj/PW7FL0ieLXgcmeH7rQW9gBBVBPlnyvCh0RBfwj3r0T1kv3e8Eb2AEFVCFpspxQIZeAEHIYvPUDtMv/0d9AJC1OAotm8SaIBFkEsu7grP1ZCn6QaEKEHmyZTjztgNLxgXllzlifQDQtQIWJwpOR6JZngaH2MZcgEAediM7zEJPXCBmvFTDE0io8Iui1AnDII8h35AiBLEK8hz7Dp4ERtNxakQC/GAYjkIFTAN3rIBjdUPWayhHxCixg65phynzsYY5NkQqM3ojQxFhKgyvoL37EAb1SU5P3YMPYEQBZBT663L4QCFPVbheiXkeAH8Ya/ykswSnISosUNu4l7YPnAsUQUYHnAFiPKYBf/Yi9ZqBy3OpycQosIO+Tp3rlwXS5IUqfmoFeBR3nT4y3ZcovJ18Vb0BEIUQL/FjSNfjPWuDryuDEiAhsF/ViNb3R1yd3oCISrskLsm78aNsMX1gVfzAOTnLg8T3ayYq26hzmfpCYSoIMg9k3Xi+tggQaR2oYXP4lPfo2sgdnheVUEeT08gRIWQxaPJuXAVLJckUrtwha81KxYhOAqUyC8xiCF/Rk8gRAG0/sk4cDpmS7084d99tucRLGtRWUVJXkxPIESFkMUTyTjwc5Jl6nufqj5cZNKMyU9GqyjIG+kJhKgQsnjGuftea+tOnjPG+NIL5BsET0EgB5kJ7+odRV8gJPiQxQvOr1Ss8ESobvZcdu6BGixUsP9exun0BUKCD1kMd+q6T3kkUxtxjsd381ZBFdSrlZxWmb5ASPCCPMppESHvksbe8FRy+kAdVqO8apLckL5ASPAhi7HOHHeMp9HVZp4JTkVshkr0VC3xrTV9gZDgBfkNJ257vsS+c0bM8UxwekMt/lDt1l5n+gIhIdshj/RcqLypipaOP6Aa96lVzeIh+gIhwceQxzi5nbfLc5n62qPqFerxi1o75CfpC4QEL8iv23faHr4IlRd75HlQEaXK1o+gLxASvCCPtu+0/lyryJEuNo2hJh+rJMhv0xcICV6QX7N/oFfgk1A1kSw2YxQV5LwAS/SXGp/SFwgJXpBt5yE/6ZtQyb1GneGo35+/DFBHkOfRFwgJHP1Vuy671DeZ2olKEqXmZkk50ovxKcbhNXyKn6WVKFLoYG85fYGQwNFesdusyU+6SpSaKa5/msXojprFnlkV3ZAj5TdtpIogb6IvEBJ8yOIlFS9WzJGYgbzD1U+yCreYlgJqj19d/6ZPqSLIB+gLhAQvyEPsOezHvgpyIRpIEprWrn6Oj1AtQcGiSa4rQasStMg+lt5ASNAhi6fs7TO3+Xzc1T/w/tIF6G3zsLPQ1Z8eVXpRx/9NbyAkYPTH7DhrU9/zD76UJDOLk3x/PrrZfsdjrn7TOxUR5HJn0RsICTpk0duOsw5Kaoe5DhuSzkfYLyXTolKSvU0KHR4ruqnxMU6VHXJ5egMhQQtyTzvOOs2hFH+Ctsg65OZogTFJyXJHCSLTJkmRHOG4OdQXSQvyClWiyNXpDYQEHUPubsdZlzsQmDW4ttTn6ybRpVrG9ZBBSUlkThKlMc9LOspecPhPV+A9Q+rSGwgJOoZ8l527bva/+P9o0ogpjucdCtWvEkTmvSQEcg8uSOpdXZPeI7dSo0R9Y3oDIUEL8i2JXbWRAxGtafGcAQ53jpVdi8wvScjjoKTftihJQe6rRkXka+kNhAQdsmib2FU72xSWfWic4EnPOBKqa1xfCtnvWBx/ddHt7qYkBfkNNXbI7egNhAQtyNckdtXBNoWlt43Dr88cCNVDLiXmwiTEsZurN85XpOBoUjvkjvQGQoIOWTSWVb5yma2jsHOwybedYyvH0rgeGa7eeG9SgryaXfUIIbFYLBa/MLGrfmBLVm636fjdbQvVApcSc7djaezj8o2Z2J7UJRQlGp52pTcQEnTIokZiV51lqwiPbjtnd4FNodruUmKc3qDbKyEBLbli+EoUqu9BbyAk6JBFZmJX/cGGpAz25PDL3W29oQ5l8T0JstYiKUG+XAVB7k1vICRgMsomdtWVNiSlricVJuq5kpjXHcpiBynlPpPpT9JWhSyLgfQGQgKm7GmJXTXXxoGeN4df17qSmMmORDFXUiT3/SQE+Q4VBPkZegMhAZN1XGJXTXwp+BXHh187fBAqZxU4PpQkbN2TEORuKgjyi/QGQgJH7E3kqps9KAQ03pZQPepKYj51JIoPSxK2ZJpdPaRCDHkEfYGQ4AX5z0SuusGDLIEbbAnV864k5jNHonixrDKW2O1YkJ9Q4WLIK/QFQoIX5OWJXHVtAjnZkIT7Z2CnB2Uwi4+ZjiLI8qTtW8eCPESFHfIo+gIhgaPNd5tlMcuzCO/rvgnyfInSNs6xIA9WQZBH0xcICX6HPDORq65IICdvJiUAfWwI1Zu+HepNkChtzzgW5CdVEOQx9AVCghfkyW4vhjyblABcY0Oo3nElMU46Qj8mUdoedCzIA1WIIb9BXyAkeEEe7fZwrGeSdR8Sl73/wLdrzDJbjbZ3LMi9VNghv0lfICR4QX7ebYpaslm0vycUqimuJGZYQHflWoaz8/Rb9AVCAkfrn8hVhySQk7uSlIDEjUHddWTu70ASm0iUtmscC3I7FQT5bfoCIYGj35/IVR/y6D5d4pDCSFcSc6cDSbxQorRd5ViQr1Lhpt479AVCghfkWxO56i0J5KRrkhLwlMf5uU5CBzUkStsVjgW5pgo75Mn0BUKCjyG3SeSqTRLIySNJSkDfhEL1uCuJqeOgXLxMSbzeoRzvs11L2tPxHn2BkOAF+XK3+RDJ9mnuYVksfjruQzXX15ivwkB8buMy83kSpa2zQ0H+XY0WTh/QFwgJHO38xM66zFJQXk5SAu4xfFoB5uA+VJYqNulog5H4zacY8kMOBfkzNbpOf0hfICRw0rISO+sUS0GZmqQE3FrqSZsxxGGpe2ejAQbgGxQY/A4NJb7lKYeCPEyNHfI0+gIhgWOnZ8hAS0FZlKQEdCz2lCW4HxV8kZ46GIifSvwOzSU+f7RDQb5XDUGeTl8gJHCyTkrsrO08qZTW7cgTfrFZUbkyLsdt6I9hGIXx+BAfYSrGYwyGYwA6o6mjo7lGGIp1nlzN+NKhIF+qhCBrM+gLhCiAOJjIWasbfs3/mzouLm6sxF2IW/67LNyAwfgMf9oQtz2Yj9HohkYJnvnXoV8n5EjI5yg+1jmS4+22flIfxkx6AiEqCPKmxO66yFJUbkuyK/R+DLEMU9RHf8yxUfPCiF2Yjl64wMbP0RSTMUqasFVGoaOfc6YacgzxKT2BEBUEeVlid7W+Pv1iklkWDUz/X1U8ip8hg2UYYSNCnClN2FqFsfQmBMTH9ARCVBDkb93WZ1gkVRqaYjz2QC6/YQjq+yJsQxz+ZE0UEWSmvRGihiB/YieTN9dCVAqS6KpnlnmxGF5RgDno7nkmxzxHP9OfatzS48UQQpQR5LfsOOz7lsLygJSylXPhPVswRGrlipIR5IOOfpq3VZFjiCn0BEJUEOThdhz2dkth+dp1mOIr+MdevCH1Ksjfo6vDn+RmZQSZ1d4IUUOQH7d3/XiThbAUuojQVsaryIffFGAaGkmXtVmOfoZcZKizQ2Y9ZEKUEOQH7bnsCEtxGZqkEHTAGgRFAT6yyPRwPrIdpui9oY4cs2MIIWqQuCLyoXGRZYbtTlR1LAJVE1TJ8IMDGI1sSaL2tMN3t1BIkPVx9ARCVBDkVnaddr6lvDzhUAKuxh9Qgz0YgooS9sfbHL11iUr7Y4gx9ARCFCDeyHn1CeOIqJPshV4O8xG85g+b9TTMr2F/6vCNj6olyK/REwhRQZBr2XXajATx3rdsH+NNh4p86qIu8gjHV7urKCXI+qv0BEIUoFy6fbd9JMEh2Q22yl/+mECs8vEtnsGduBpN0RYP4ytH9SE2YCg6oiWuwo3ojSmOAgn7MCSpa9R9HIv/y2rtjyFG0BMIUYCM0+27bQVsSHDtIlHlt5bYYvmElRhgcMh2m+0Ax7RSd/HScRM+TVCvrnhLpfaOe4QUOpTjA1KbRkkZL9ETCFEAcYLzopnmLLbshHcPDlh8diPuNy1G+blNqatjWv/YSY7wdNSzPSO9HcsxME41OYY2lJ5AiBqSfNDJHvn3BGLzo+nhXh/Lfeosi6hqA+yQUD3tQQcXUPbheVuJfN0c7L3/Yr+tsqA+j+fpB4SoIci5ybdeMuJXXGLwuUGWn1mDSoZvq4J2eMtR9bd5eND03uBQR8K5G8NxToLZaIxhjq+2DFdPjiGepR8QooYgr3bmvJ8lEJwfSrUqjWNcgs+MNris3RPfJn2pej1exfkG8umUnRhm8JzStThGY7PtC9NVFRRk7Wn6ASFqCPLPzpy3PvZZCM6oUhUa0jExoUx9WeIz9fC96zS2Xehe6nAwuSvWOeiC9IRJgR0xBXsTPu0RFffHEIPoB4SoIchznbrvw6Z33u4yEKoPbZairFHk8G8b5PD2kUPGOLpaVnVOfHVkiI3KF1XQC79YPOU7VXrolRyP0w8IUQJthnMHnmIYO25scAg4w7bk5WE+JuA1yUXqczERYzANWyU8qxAL8IiNG4lNMd5wr3zAgwpzkkIWA+gHhKixQ57s3IGzsLKE2ExB5VL/qhJmI3rkIwfdkZWwV/cA/FrikwMVlWMB0Zd+QIgaO+SxybhwY2wvUvK9h2G5nfmILnsxFbcmaAml4zq8fyT3eqY6DZtKj970A0KUQB+WnBM3w24AwApcZvi1fT2iz3ZMwA0J4sLZGIJcrPOwdZSEkMXD9ANC1AhZDEq+D94eTDbMIH4E+5E6bMCLuMhypiqqeBmk6OhJPyBEjZDFw8k78nmGheenIhVZjH5K74ItgysP0A8IUWOH3FWma7fEOqQuezEJzUIoyNp99ANC1Igh3yXLreMY7LCvXFT3yj0Mck6UHl3pB4SosUO+XY5Tn4scanGRS9evK5t1bBCyuJt+QIgaMeSOMlz6BvxJFS7FfHRSOdnt75BFF/oBIWqELG50687peDGJMpSpwlJ0Vl+U76AfEKJGyOI6d858fqQvgMjhe1yntiDfTj8gRI0dcms3rtzJVcmeVOIjg+ZU3CETQorHkNsm68bl8WoSDYxSl224V1VB7kw/IESNkEWH5Jy4Lr6jxjpmsklvlIAP9e6kHxCixg65UzIufCd2Ul2TzFKuxbQ3QojJDvkOp+6bidHUVResRkNenSaEGAryPc6c9xIspaa6LkekWLGhvvQDQtQIWfR34rr3O+oBTcxYoVQhIjY5JUSVHfJwu25bGZOppNL4XKHrIvow+gEhauyQJ9lz2jr4mSoqlcfU2SG/QT8gRI0d8pd2XLYpNlJBJbMX56siydPoB4SoIcg/J3bYy7CD+ukB76siyPPoB4SoIcibEgcr1lM7bVKId9ERbfEoltj41wVooIYg/0Y/IEQFjhL5iWq5/UidtUk+7izS3soOr6ohyDvoCIQogHZmImcdTJ21zePFuk3bYaMiuRaZJ9MXCAmctGxrR62HA9RZm8wsJq6P2fzU1WrkWVSiLxASOHpTa0d9jTpr+/Zd0aseNbDF5uf6qJGJ3Ji+QEjgWHfUq4JdVFpb5KFNUXnDdNuffFuNHXIn+gIhwQtyX+uabqWZjevwNDZTg4tlSxSvdPyCg89+qYYgD6AvEBI42kgrNx1rkNZV+/BX8kXU4cMcRPdis9bDUdn+xWrkWUygLxASfAz5Qys3LZ1L+8eR/1eTfaYBALkl+uV1d9jwVRFB/p6+QEjwO+Qfrdy0dL+8VUX+bxeqMeajTrEZexD5jp+ghCDvjpWhNxAStCDvMnfSuIG4HEBmkX+R2v2mC/EaMorNWN8kegx+qMj16fRy9AZCAiXjdOvOIEYU/YLeIoXleDPalbjROCqp57ysSsW3JvQHQoKNINe2dlKjYvQfFfsXH6SoHOfg3GLzUA2zknzS3aoI8kP0B0KCFeTW1k662rBeQ+Mi/6IWNqRgxYpnEC82Txfh16SfpkwJzrfpD4QEiuhh7aQ5hhLyCyoU+TdXGBz9RftGXusSs9QO25N+2q/qNHJaRn8gJFhBftnaSc0uOEwqtkNslEK75M9L9cLrizwXzxuqjiAXVvgvPYKQIAX5c2snvdFUSD4oll9QF7+nxPXo50qEKrLwvstnNlap93QzegQhQQry+kRtTc17TM8olgBXK/Id91aheYnZuRIrXT7zG5XkGPpgegQhgZHxr8ROOslCTuaiSrE8gyhnJb+LrBIz0w17XT/1VqUEWXxLnyAkuP3xeYmdtE2Ca79FI6qV8EVEL0ffXqoK3lQJz12sSHH6I4lveVkn0SsICUqQ29v4GotllqKyotjV4QzLHXU4mXW4nNLf42rXoYpD3KTW/hgCaZfQKwgJSpAft+OktyWQlTVoWEzAh0ZIjPegd4ldbHkMdZVV8TcfKyfHAqIvvYKQoAR5iq2jHixMeIn4ymKf6CVJsoLm01KXNprY6iVth90lihIpMj6nVxASlCCvtOemrRKWzNmDDtKuSqjBRnQr1X17EA5Ke/4DKsoxxD5GkQkJRo5PEYV2HfV1Gzm6PYt9ogFWhFaMCzC+VE5FYyyW+IZpasoxBLRr6RmEBIB2kX03rWTj4kchBpcot/NlSA/xLi+Vjf2SxL0x8CuqKivIYgw9g5AgBLm7E0e9xlZceEqxyyLpeN5h94ygWYy2pX7z27FO6ju2FzsEVW5sjR1D3yDEf0Ee68xVH7IlNwtLJIm1w5aQiPFq3FsqL7iJSXml5DmA60u8o4ZqktyQvkGI/4L8o1NXtVeAfQOaFvvUefg2BBXcHkb5Er/tBXhH+v4+H11KSf7nqgnyc/QNQnzmrBO1PMdNfjDTluzsR98SraD64oCyYrwVg1CxxG9aE8OxX/qb8nFfifdUx2ocRGW1BPl3egchPiMaJuOslfGNTfGZXEJm5GYpyGILnkClEr9jNl7BPk9qxd1Tqmfhl0re2NOr0T8I8VeQeyXnrJXwtU0B+g2XlcrjVWmfvBZ9S4lxdTyHXZ68bZ9BIaGRh//fSNUEeSD9gxB/I8hTk3XXivjKpgjtxSMljskuSbrznFyWoVuJftECVTHEIzEGctGy1DwOOPJ/f1Itirw2djQ9hBD/KCM2Je+wmfjYthTloG6JT3fCqkDFeC5uKZVNURlPY5uH8t+g1Bz2LpbBna2aJF9GFyHEN/RMl19qMSjhdeq/2IWeJQSwAgZhRyClgsYZdOiohIHY6uFb3zc4tOteIn/jbtUEeQJ9hBD/Isjt3TvtPQ7yEL4stUesisG+Nkf9FX2KldP/6zbh057mSe/DowYzdz/yS/y7CcrVtCh7Gr2EEL8EebQMt22O9Q4uRAwvVR+iMh7HZs+leBcm4QaDUvDnYrhnMeND/IhLDWbN6LvFWvVqWnShlxDilyCvluO25zjqnPEnupcSxop40LPWTwcwHV2KXeb+a9THOA/yjItyEC+UumoikIG3Tf79RaoJ8nx6CSGhiCAXH10cxYMX4gaDZ1yCEVL3yvvxFXrgHMPod1tMLxUykM18w27SWZht+on+yu2RmY1MiC9od8p13foO97gLSlRP/mv32BETXMvyb3gNHUrlF/8liL19KAq6weB7wKGrMVbNsGarV2ZoBD2FED8CFpNlO28cPR2mjS3GbYayFcfVeAJfYKdDGVyF9/EQLjT9CRtjDHb7kMcxxOQidPcEt/8OqHaBGmK/fgZ9hRCvOVrkupXfqobx5NEOi/EsxwDUNE2sa4A7MRRTsdgkKW0/1uAbjEM/tEN1i5/2fDyOX3xJqhtdqh3qXzNjJ2/7VvX2yH3oLIR4vT8+z62j1sB6g7rBAgItsdTx4dfH6Ij0hGWNzkVjNEULtMU1aIoGtopWVkcvfOtLReYdGG56ueNmrLX1jPHqCfKf4gT6CyGeog9066gXAyjEeMMv2enohz1JxF1fRgvEJUa1e2OW1C4fVnWUB6Gayc9RG5MdzIGu3sHeLfQXQjzFeR3kkqPFYQn5A60N/39D2wWIStZem4SurroxZ6MLxuJXny6bHMRHuMn0z0gcvRzmOV+u3h55aawMPYYQ7wIWwr2bdixS4XeU4T5Zx2Mu9qcrMQWP4TrbvTRq4wYMxAf43fZ1brcUYgH6msa/BQRuSKLc6FMqtnS6nD5DiHeCfI97J72vmIxsxB2G/+oqG41RE7EdP+ADvIbB6IEuuANt0RZt0Rld0BPPYAym4UcfcieKsxQDcYHl/DSzWci/JPNUFOSZ9BlCvBPkme6ddEApKZmKcw3zfj9DlMjFaFyVYG4a49Ok9+l5ltki7LFHSNTk+BRx0L2LjjDcy/Y0OJTSMSQiYrwW/Uyum/w9rsMnLnM6uqooyLPpN4R4I8gdZLjo+6YXhhsZBjgOhFyMV6F7qXL2okRB0e5Scp2nqSjIiDei5xDihSBPl+Ggcy1qSDxmsE++1oeabl6xDYNQwXI2GmCotHrKewxLIQU+5jHXghDppP/Peadpo2Hd8SPHIJ58oWUdB1XJwwjDO4l/X5DphfmSMzs6KrlH1q6k9xAiGf1uOe6ZqCfzRjQzKAU/L2RyPNewYtuhUQUPIMeTmnFvKSnI+gLukQmRHbD4WoZzVrfVKeMug+aoM0Ijxptxr+nv3wbvYq+Hb44rKcmiOf2HEJn7Y00UynDNpjavTgwvFU1Ox1uhkOOPTK6k6OiERZ6/vYWaQYsVWcfRhwiRhvawHNe807a0vF/qiEr9NLg/0M7k974dy335CV5Wc4cM0ZU+RIgsymgr5Djm0w7EZaFBDbQ+nvfrSP4Q72VUNLl7518E/DdVBTm3wn/pRoTICVhcKssx33ZYl6J+qSd0SqIenPcsRhOTgkXv+FYj4xCNFJVkbSj9iBApiImy3PJbh/KyCVeWesbl2KCUGO9EP8OazHE8iu2+/zRPqbpHzk+vQk8ixDUV/iv2y3JL51K6y6CxaR38rIwcz8T5hr/pFT4c4Rnxo6qCDP0z+hIh7gMW98tyyaykvr4fxN2lnlTVogezf/xu0vukIob4VODeiAbKSjKviBDiPmDxiyyHbJ6kxBRggEF3kSG+NFgyv+g9xOSqcjv8EeifiSfUFeQVbOtEiLv98aXyHLKHC5mZYFCi52bkBiJ5hfjQ4LjxUEvS8T4f4pXmB2UFWUDrT48ixM3+eJo8d3zFldDMQpVST6yFT30XvO/Q0uTqx4MB/YEo+efiQnUl+UBaZfoUIcnujzNFgTx3/NKl1CxDXcN99w4fxbiDye92OeYrc9A4UOE9spjNyhaEJLs/HiHTGde7lpo/cbVhhYzRPlwYmY9OpuWCRiFPoUS8hSoLMrSO9CtCkqDsaWK3PEesLiW6uh8PmXTh+9yz6O0BTME1pr/XPdio2DWVQpNUPEXG1vT/0bcIcYysChaHRltpgjPFsFu1QBNMk5558QcGWXSIvgQ5Sl7k7q/2HnksfYsQh2QcL9bLdMPHpWYAX2vyljoYhJVS3rEeo9HSoIfJX+NcjFMqUFE8vCLUluQr6F+EOIsfd5brhB9IlZx8jDBtWaSjBV7E4iR3y3uRg2fQ3EKKBbIwRMmaGn9nbtdRW5LXpZ1KDyPENtnHipVynfB3D2qb3Wz5xhrojKGYgTW2rmgvwiQ8jpYon+D3qIrBSqS3hTjTAgLidfoYIbbRb5HrgFU8ulc3C5fYurTdCNejKwZiOIZjOEZjPMbjZTyBHrgdrW0fgtXAkAAKBiXDYtUFGdq19DJC7HG0WC7X/dp4Jj15mIiLfRCQJngb+xEeGqouyRvO/g8djRA78eP2st1vkMcx0w9NKhLLKYrUXaFrH3YZrPweWbxJTyPEzv54qWzn86NJ6XLLFLVkRjraYrLSx3fm/Kq+IEO7hs5GSKL48Y3yXW+zTzJ0ANPwAM5z/fNegJ6Y5uOlbC+4TH1B3qydSX8jxIKs48Rvsh2vnu931X7By7jVcZmdDFyFXngLKxAFhoVgjyw+ZW0LQizQust3u3sDE6Ud+AavYwDuRWtcXOqGXzXUwqXogIcwDO/hBxxAlPjDMpdamdGNPkeICfF/iy3yne51hWRqP7YjF9tDlTGRLM3DIMj7RXX6HSHG8eOBXjjdUpAgGBUGQYb45awT6XmElA5XnCmzvttfo2bgXTRSlT8N+2ErOF6i7xFSCrn1j/8ad1IZA6NdOAS5UL+a3kdIMdKytDwv3G0cdTEw3g2HIEPkajo9kJCi++MvvHG236mLgbHHpHa0gmNe1nH0QUL+kuM23jjaeVTFQLk3LIIMMYReSEgsFovFyv5DrPLGzbpREwPli/AIMvSW9ERCYrGY1t8rJ5tITQyUPJwbGkHWdomK9EWS8sTTxB6vnGwNNTFg+oVojywWl/0H/ZGkevx4ilcOVp96GDg/hEmQoY2kP5LUDldc6Z179aAeKkDjUEmyfhN9kqQsmSeL1d451xSqoQIMDZUgi91plemXJFX3x0M93OvgT6qhAqxBPFySvDTzZHomSUH02iLfO8dqSi1UhLbhEmSIt+ibJPU4RnzvpVsNoRIqwpSwCTL0W+meJNXCFQ9761SLqYSKsA/VwibJ+7Sa9FCSQsQriH1eulRtlt1UiIdDt0fWVohT6KUkVThKzPbWoXpSBRViUegEWUBMjx1NRyUpgejptTvNoAoqxeVhlOS+9FSSCtHjSt6GKwQqYg81UClGhlGQC7Vr6a0k6hwj5nntSh2pgIqxBRlhlOSdWiU6LIl2uKKv9470BhVQOW4LoyBDLMn4F32WRDdcUUMc9N6N1lL/lGNGOAUZYnKsDP2WRHN3fIL4yXsXupLqpyB5qB1SSda603NJNAV5lB8ONJjqpySPh3WPnK83pu+SyKE/4I8DLaL2KcmKsAoyxBYh6L8kWnLc2MtSQn+PC3hHT1muCa8kL2Q3ERIlOc4U2/xxncepe8oyPryCDDGGXkwiQsa/xM9+Oc4P1D1l2YVKIZZk1oAj0eBoMc0vp7mQAQul6RbmPfJ+cR6dmYQ/XDHYP6dhwEJt5oRZkCE2pJejP5Nwy/GNfroMAxZqU4gG4ZbkhWf8kz5NQktattjrn7swYKE+z4dbkKG/w5t7JKRoZ4q1fjrLE9Q75dmA9JBLsuhNzyYhRJwg5vrrKgxYhIEbwy7IhaINvZuET5BH+eso9RiwCAUfh12QIfbGz6V/k3DJ8YN+uwkDFuEgD3XCL8nryp5NHyfhkePL/LkozT7TYeTZ8AsytPm8TE1Cgn8Xpf8eDRiw4MGev5I8lp5OQkDWSf5dlP57DKHOhYhbIyDIAuJBejtRnTLapACyQ7GKKhciZkVDkAv0q+nwhId5pUZLalyoCP2NvSNtUNOy6PNEWbSLtbwgHONNalzIGB4NQYZYLk6h3xMlSS8nNgXhFOWRS4ULGbmoEBVJ/iB2FH2fKEfG8WJeMC7RmfoWQu6JiiBDf5TeT9QLV4wMyiFmUN1CyLeREWRRoF1J/ydK4W+ZzaKjBg5S3UJJ4+hIcm65dGoAUWd3XFPsC8oZelPZQsro6AgyxPdnnUgdIEqQebJYGpwrLKKyhZSdqBwlSX6TSkBUoIz+TnBu0JBXpkNMjygJMvS7KQYkcES3IJ1gKFUtxPwQKUEWB/X61AMS7GFebXEgOBeIYy1VLdQ0jZYkb2RZThIgaaeKlUE6wM1UtJAzIVqCDPFN1nHUBRJQ9Fi8F6z5f0xFCzl7cU7EJFkbSmEgwUSPewZr+rWQR0ULPX2itkeGfiO1gfgfPa4fTCGhv8fjVLMIsDxygix2a5WoD8RXMk4X64I2/BVUs0hwQ/QkeTEbPBF/o8fvB230ralkEWFG9AQZ4mWKBPEN7b7gTf5dKllEKMBFEZRkrS11gvhCWnaQuceHRlXspZJFhteiKMi74hWoFcRzsk4Sy4I390epYhFiN6pGUJL1BRnHUy+I19kV41Qw9h+pYpGiXxTjyBDPUS+It3J8iwqGfjkVLGKsRnoUBblQNKdmEM+IV9B2qWDoY6lgkeOWaO6Rc4WgbhBPECeIRSoYeWXson5Fjq+jKcgQc7OPpXYQL8IVw9QwcR7oRZMroirJT1A7iPz98eWiUA0DX0rtiiTuK79dgv5orWATVL0x9YNIJeN0sUEN825F5Yoo+1DDlWWciwMADuJO9ST5z3JnUUOIPMqID1Qx7g+oXJFlsCvLqH34Kfl4WD1JnhU7mjJCJKHdqYph18QB6lZk2Yjyrqxj4ZEnDVdPkntRR4gcOa4k9qhi1oOpWpHmXlfW0anIk15W7Sp1nl6bWkJck32smKeKUaezh17EWezSQiYXedYrqu2Rl5x1IvWEuN0fP6WOSd9KxYo817osOrWqyLNGqFbd4kXqCXGFXk/kq2PQs6lXkWeqSxtpgFx1d8mFWhNqCkmatFPFanXMuSEKqVeRJw91XNrJ9cUOfhU73ttQ4b/UFZIk4k2VjPkVqlVK8JJrS7mlWPvbQWpJ8nvUFZJc9LiFSoZcGdupVSnBNmS5tpbORSS5EL3UyrfoRG0hjsk4XWxUyYwfolKlDI9JsJe7ikhyPu5SSZJ36Br1hTg9zntHqfNpLKdOpQwbXF4QKS3JB9FeJUmeGStDhSFOosft1UoYupEqlVI8IMVqigYu9qK5SmGLLtQYYpuyZ4tctQR5JjUqpfgNcemSvAl11bHo3ekZ1BlijzJimhyzq415uF/CcxqggBqVYtwuSfruLZIsuQzV1AnC5bDcELEXrugsy+g+hNvqBIfGaOpTyrFImvQ9UeSpc1FBnV1yV2oNSZzspoudcgyuHQDgMtfPqcKWTSnJddKkb0yRp74LXRVB3pdWmXpDrDlKzJZjbuXxG4BVEp7Uj9qUknwhTfri+KTIc59UZ4/8dewoSg6xClfcK8vYngEAPC8h4e13alOK0kSa9FXEd0eeWoCO6kSS76bmEFN0Tdslx9DqYx8A4FLXT+pIXUpZ3pMofdnYcOS5O3GxMtkWaXHqDjHbH0+Xm6b2rYQn5VCXUpZ8NJAofs2KFB36XZ18i4+pO8T4OK+jLCO77bDZd3b9pMas8JbSjJEqfr2KPPlzSZnOEsIW7ag9pPTu+P9kXQapjHUAgHVId/2st6lJKc0+ZEsVv6L29IIqe+Qt6f+j/pCSgvyuLAMbftjgn3D9pFrYT01KcYZKFb9M/FDkcE+Z+hbjqT+k+HFea1nGdTEOAgD2orrrZw2lHqU82yUU4yw66hbpKJLruhi+tNGMGkSOcPZ/5JXa/PKwsb8mIfSxjXpEMFCy+HUsci6xABlqCPLqrJOoQ+Sv47w3ZB/nHZSw9+hNLSKQVYyz6Bhb5OmqdN3TB1OHyCE5vkJehG71YTOf4PpZ6cX6B5NU5iHJ4lcJK448uxC3qVGQM09UpxaR2Bn/FH/IMqpnj+SPNpRQOJEQHM7Xkb1HbnL4pAMAduACXqQmyhznDZZlUOdjz2ETf1/C076jDpEj9JAuf8VrwKmRk8xueylPvKo4KMucph35Eui+BkFLahApwlrpe+Q4vvbw4DDJsTXjdGpSKnOUmCPLmNoeMe7pEp72CTWIeLxHPh87jjz9AK5UQ5Jfoyil8nFeF1mGlI6lR/bHV0goTZRPBSIe75EFehZ5/gpUUkGQC0VD6lKqyvGZYpssQ+p/xLA/kpyWRMghHvSgl/ncIs8fo0Yc+cfYMdSmlERMkFfacOdhoy5AY9dPq4G9VB9SilUSaqOUvle6v0gC3A1qhC3uoTalohxfJs+E3jxi1DIq2D5L7SE+xZEFBhd5/hrJ17STHLk82ks5yv5D/CrLgBodabWej0tcP60CNlF5iCEbUFG6/KXjZ+XCFuJlKlSq7Y8fl2c+s46Y8zuSD1oIKU5/D+SvWZEj5AK0UUGQC+K1qFEpRFplcUCW8dxwxJjzcZGEY5blVB1iSq4nQYWiXalXo7IKkvwlVSqV9sfT5X3hW3rElCdIeB476BFrBnsgf1WKhcleVaPYUGvqVIqgt/KiKc5+nC/hed9QcYglOyXU2S49ehR5QwGaq5D+tuaMf1KrUuM4b6Uso6mMP4+Y8UgJz2tKvSEJGeaB/MWxuMgbFnuQYJfE6Eu1SgG0/vJM5u+OHrul9D57n2pDErLPkz4f1xV7x6MqCPKesmdTryJOPE3skWUwdYpc4HhGyvPyqDbEBt4kp00v8oZdqK2CJI+iYkX9OO89eeYy+Yj5bpFy9v0KlYbY4iDqeyB/DYvUSAamKJH+ptWgZkV5f9xIZonvgiPG21fC887BbioNsclkTwSw+JZAiYvU06hakSX7WLFEnqn8XU12LSpIeN7TVBliGxk1U0qPakU6UgMrlGiAql9K5Ypqutv98sykbRHDvV9KN77NVBnigE89kb8+xd7RV4U98iI2doqmHJ8htsszk4VHjPY3KSlCj1BhiEOu9UD+KmBDkTdsRw0V9sjtqF5RPM57XZ6J3FLEaO+Qct+PHaaJU+Z4In+9i71DiVt7q8QJ1K+oZR/XFAXykuiXHDHYH6FLeOKdVBeSBG093yMflNA/XcIe+X4qWNQCFp/JM497ixjszVKeuJjaQpJgvg975Okq7JG3ZPyLGhalcEUzmfVjfztirD9I2R+3pbKQJLnB8z2yN/twx3vkR6li0eEY8bM3ZVjkmOpX1BWSJPN82CMvlrLtcDm2lz2NQhaV+PGdMncP644Y6lxJF0wIUXuPfIcCe2RtAJUsEmSeLDbKM4t+0l1hKjWFKB5HXoZ48IK8K/1/VLMoxI8HyTOKykWubyyU8sT6RdrnEKLKHjmzSGFZAOiqwh75KapZ6MkoK6+6W/HrzZ2kPPEN6glRco88uNg7VqlQIXkvy3GGf3/8pjyDqIrtRwx0iZSDjmzso54QJffINYoUlwWAHiqkvz1PRQs18VqiUJ45PFPEPO+WXOCeENX2yGOLvWOdlBJaLse+jLJUtTDvj2fJM4asIpWwVkr5AlcZ26glRAqtPamPXFDsHY+osEceQlULb7rbFTJN4YkiptlLyhP7U0eIJD73RP5mFnvHHyrEkfdknE5lCydlxLfyDKESthwxzG2oJOGJGUUymglxy5UeyF/HEu+4V4Vci/6UtnDuj1vINIMBRcxyqJQn3kcNIRLxoodIHKuLvWOJEnf24v+muoWPo8QP3txcypPS81fHMmoIkUge6nogf4NKvKWjCnHkHpS30KHfKNMEeknfiXSkghDJvOZJ8tuBYu+Yp4Igbyz7DypcqMg+Vvwq84vbyiIm2VTKM7+lfhDJ7PWkv8dHJd7SUoU48p3UuHClu90uc/nvKGKOcgoKXU31IB7wrAfi16HEOz5TYY+8Ous4qlx45PgEbY3M5f+uiDl29mTXQYgMclFZuvill6j8VqhEDxHRnjoXHkHuJnPp2xQxxs1SGqPXQx61g3hCbw/E7+US7xipQtDix1gZKl0oOOOfMsttFk+OHy7lia9TN4hHrPbg8kajEu/YhooqSPJF1Lpw5B8/LHPZL0VhkS9rDSQ8sTr2UDeIZ9zjgfj9XOIdD6oQtHifWhcCMv4lcmUu+1tFzPArD8oaEiKX7z0QvydLvONnFQS5ID2Deqd+/LinzEU/p9huVsaBXgVsomYQT2kmXfzqFfmeeIhrWYyT2MmvEOu9uqck50CvJ/WCeMy7HojfDyXeMUUFQd7JS9SqC3JXuQk/Rcv/vCzlwvQK6gXxmAPIli5+A0u94xwVDva6U/MUJus48YfM5e5SzAQvk/DEW6gWxAcGS5e++qXe8bAKe+RVsWOoe8qi3yZ3uecXMb8lUp44j1pBfGCjlPBa8bG8xDu+U0GQoV1L3VOVo7UVMpf6ymLmN0jCE5tRKYhPdJEufcNLveMiBQRZ/4zCp2r8uL3cpR5XxPQKcaGEJ06jThCf+Fa69LUs9Y6hKuyRC+PlqX0qcpT4SeZCV8YuyeZdH/nUCeIbl0uvabG1xBvWIa6CJA+i+KkYP24td5mLp6fJ6KE3hhpBfOQt6dL3fql3XK9CFHlzxvHUP9UoI77zLu/yIKrzwjQJGXslWG3x8WCpd0xS4mBPb0UBVIz4VXKXuEkxs5NRAZYXponfDJQsfHVLvWG7B9kcSeyRZ1ABVTvQm+XdgZ6MUirleWGa+M5q6THelaXe0U6Jgz1WtVAKrYbcBa5U7ECvALUkXzEhxB86SJa+N0q94Q0lghbicaqgSoI8Vu7ydi1mcgskPDGH2kACYJpk4bu71Bs2qZFpsTH7WOqgKnJ8pjggd3m/KmZyT0qolVVAbSABkIdzPY4iK1L3Ddo1VEJVEt4Gyl3a80rkC1/q+okvUhlIQDwuWfg2lHrDCDWCFu9SCZXgrBPFFrlLO6iYua2SkFC/kbpAAuJ36FK9Y5rB0aESgnzg7P9QDVXIr7hD9tIuK2Zuo1w/7zaqAgmQVp6W4QSAxmpkI99GNVThQsgvcpe1aQljc38X6XNqAgkQueXqWxq8ob8ae+TZlMPgD/SayF7WUcVMbY/rxPcLWMGCBMpeZEn0jyqlmjkBM9UQ5EJNpyIGfaD3meSvPVhfzNS+dP3EIVQEEjAPSPWR1aWev1uJ+3oC2sNUxEBJryIK5S5pixKm9pTL58WLNYEiJAjmSPWR6QZvaKnGHnkJNTHYgMVIbwMW7nMsO1INSOAUop5EHzH6zjdEDUGGqE5VDIzMk8VO2QGLdZIjyJ9SDYgCyOyxd4fB8+crIsjaAOpicAlvnWUv5zUlzGy2y+fVQB61gCjASonZyI0Nnp+HKmpI8jLqYnCC/J3s5RxZwsyedvm8h6gERBGukVh6q9Dg+R0U2SOnZVEZg8mvqC1/MVdLPqqYSx0gijDW0+vTCkWRe1Mbg9kfj5K9lCW/iu1FeZc1MVhSiKhCLtKlecq3Bs//QhVB/oHaGADxf4vdspfyiRIm5rax6QCqAFGIG6V5ytuGgq8rIsl6JvXR/4S3LvIXsmSA4XWJXfkICZq3pXnKM4bPb6DKHrkX9dH/gMVC2ctYtVRGhLv7TQ0Mjz4ICYodqOBJR/a/uFcVQZ5DffRbjuvIX8a7ShnYVR7sIggJjk6SfKWT4dNHqSLIBen/o0b6K8ivyV/Gd0qYV57L/cQy+j9RjCkeVUQ8xAJVBBlaW2qkvwd6e6QfBGBLCfNa6up5l9H7iXLsRkUp3lLHJCSiiiCLN6mSfmYg3yp/CUvfPprs6nnD6P1EQTpL8ZYMk/OR81QR5K2xo6mT/gUsZslfwj6ljOsxV/vt1fR9EuGgxV7Dp9+gTtDiAuqkT6SXEwXyF7B0p7C2Lp7WnJ5PlGSHy8tOf43Nhk/vrY4gs8iQb/vjBz1IJcfWUsaVzS7TJILcJMVjVhk+e4w6UeSFVEq/BHmxHxHkXcywIJFknBSPWWL47K/VEeTCCv+lVvpAWmUvlq93KdP6ycXT6tLribL8ibgEj5lv8myhTtCiBdXSj/3xIC8W76NSpvWRVHknRB1aSPCYHJNnV1RHkIdSLb2njFjpxeKVLic4zMXTvqTPE4UZKcFjvjZ5dgN19sg/US69z0Cu78XS1TIwrIeTflplHKDPE4VZ6eEOuY1CUWT9DCqm1wGLEV4snVEj0uRv/d9OjyeK09CzHfK9CkWR9dZUTE/JOk5s8WLhjLroNpVaK5YQlejnmSA/rpAgi+HUTG8DFld7s3AzDQwr2UugcWyivxPFme3aZ+aYPPk1lQR5CTXTU7Sx3ixc6VtH+Um3u2lGbyfKsx+VXfrMQpMnT1NJkJmL7ClHexOwuMDArHKTftoL9HYSAtxWRl5u8tz5KgkytCspm97tjy/2ZtE6ST2H/om+TkLAGy69Zr3Jc5cqJciiL3XTuwyL571ZtMcNzGpR0nVi2baJhIG1Lr1mp8lz16glyB9TN70T5N+9WbQJEg89utPTSUi41FUxrnyTp+aqJchbY2WonN7IcXWvFm2egVl9mOSz3qWfk5DgJvWtiulTD6glyIiXp3Z6I8h9vFqyrQZmNUnaFWxC1ORTFz7TyOK55dU61mN3PY8EeaE3C3aOoVGNl26mhKjFzqRTOwXaWjy3ulqC/AK10wPiaaLQmwW7xtCokiu0zSpvJEw0T9prulk89UKlBFnPoXp6sT++x6sFMz6GeyWpZ02nj5MQ8VTSXvOkxVMbqBVF3s5jPS8EeaZXC/a0oVENT+rS9Db6OAkROUl7zZjQ7JAF0stRPyWTdZI44NVyGZvWCCltoAhRmf3ITNJrPrd46vmKCbLWhAoq+47eFd4t18eGRvVqEk96hB5OQsZ1SXrNGotnnqeYIIseVFDJ6IO9W64F0g713qN/k5DxfFI+UwkFFs88V7Ud8htUUNkR5O+9Wy7jv/XJ3PRfT/8mKRFFbmr5zJqq7ZAXUUGlcvZ/RIF3y7XP0KjedvycC+ndJHTsSSoXuavlM2uoJsj7Y8dQRWUGLFp6t1jVTIxqmmQjJURNrkrCa4ZZPjFLNUGGnkkVlRmwGO7dUjWQ9lVuDH2bhJA+EhucAkAedOUEWbuCKipTkJd7t1SXmZjVYsdPWkzfJiHkgyTy7XdZPG+zcnIsoN1JFZVGejkvl6qZiVk5LVCfiYP0bRJCNjj2mcstn7dcQUHWB1NH5e2PO3i5VG1MzGqbw+dcS88mIcXpRY6elk+br6Agi8nUUXmXQt7wcqnamxpWRUfPGUC/JiHlLoc+M9HyaZ+qKMhMfJO4Q17t5VLdbmpYzkqkfEC/JiFllEOfWWn5tEkqCvJO6qis/fGZ3i6VebKas0ulq+jXJKTMc2Tp9RI8baSKgoyM06mlcvbHzbxdqAdNDaurg6dkWV4lJURldiMuseb3ACUFWa9NLZVzKWSgtwtl3pT0aQdPaUWvJiHmEge2PjPBs25RUpBFM2qpnJDFDG8X6i5Tw5rs4Cl96dMkxNxr29IrYE+CZ12q5g75NmqpDMqIbd4u1K2mhrVY2rkzIWpjvz/OjQmeVJB0hWWPBflRiqmMCHJFrxeqvalp7XFwBfQX+jQJMd/YtvTxCZ60Xs2ABfQXqaYyIsg3er1Q11kYl92E+Qze0iOhZqfNzUcGcqVJu8+C/A7VVEYE+QWvF8rqht3NNp9xKT2ahJyGtiy9Y8LnTFBUkLWvqKYyQhZzvV6oJhbG9ZzNZ3ShP5OQswQ5yEEOZmEyRuIxdEUrg7rGiXviPKGoIIvlVFPXZB0n9nm9UFZl5T+3+Yzn6M8kkmzBHLyB+3ExBAQqJ8ywANqqKsg7qKeuScv2fqEqoNDUuLbafMaH9FwScXLxGaYk/FeFqKaqIBfGjqaiug1YdPBjqayOKerZesJy+ishAH5VVY4hkHkyFdXtkd7TfizUEgsD68YcC0JsM0VhQdbOpKK63SF/7MdCfWFhYO/a+PzF9ENCACTXDsqvES9PRXUryKv9WKgJFga20UZ+Zkf6ISEAgGtU3iHXoKK6IuNfotCPhXrB0sQS38zvRz8kBECew6YOPu+QL6SmurulV9ufhephaWT92G2aEFvkYwquUneHzM7TLo/0bvBnoZpZGllOws/PoicScoT56IJ0FS9Pt6SmutshP+rPQlVEvuVf/Wz2CiHEEavQD5VVE+R21FR3R3pj/Fqq3yyNq4flZ9ORR/8jpBTbMBTVVRLkG6mp7gT5a7+W6iNLw/rS8rMX0PMIMWEPhuMcCnJEBHmjX0s1OMHZsdXf+Zb0OhKZPe0vWIzF+B45WIQ1NipX2GEnhihxoVq/iZrqRo5P8CfpTUCgUwKT6p1U12pCwrCH/QrPoTOuMhTNCqiDVngIo5GDDS7esgPPoQoFOczEy/u3VOcnMKefLT77FH2ahJJ9mIyOjhou1UJnvIbFlofg5mxFX5SnIIc26e1iPxdrbQJjamr6yXH0bBI6tmKQizBCFm7C61iTxHv/wD0OGqNJHu2pqm6S3m7yc7HeTWBIb5p+8nN6NwkVBzBUUkraZXgaC1Hg8P0/oh0FOYQ75If8XKwHExjRLlMT/pkeTkLET7hEsu/UwUDLiolGfI6LKMgh2yEP83Ox6iY0of4mn9xEHyehYQIqeORBl2OEo2O/g3gZWf7GkFtRVd3skCf5+/dzWQIDWocMo4IlSR5wEOI/g70u34P2+MyBR2xENx8jyqxl4S7tbZa/gvxSQvPpavCpbHo5CQnP+ORJF+IlbLX9U823UU9R0g65HlXVjSD/5K8gJ77gscTgr/nl9HMSCsb56k0V0BU/2D5kfNaXdDitJlXVjSD/6XO1VGxMaDodS32qHT2dhID5hgE3r8f1+NLmz7cMzb338ApU1eQpo+X5bT6jE5rNL4jznh4JHbttNuv1YjTBB7aiyvl41dElFeej3FmU1aTJ+Jf/ptPChtmUjCP3obcT5ekd8KXl+phgqybiMjT2cof8b+pq0pQ9O4CrlTYqG68pkTb0LL2dKM4yJcrF17MlyvvR27O8i9jR1NXks5AzgzCap22Yd/GWTqPo70RxOilTkdieKM9EDS/evoOq6qa0UK0gDOY8G+aSW8xc3qG/E8X3x7oygiwg0BDTUJjgZ16LK+W/eSlV1U2ORcNgzOVTGyb+dpF/P4MeT5Smh4Ld7a7BvAQ/9R50kf3WWVRVN/f0mgRjKtfbMPFCtDzy7+fR44nC7FGus91f4xb8nsDLhpbKaXI13qaquhHka4IylJ9sfQ38K6vzF/o8UZh3FJXjQ5dHnkrQk+QDmdnTz1FV3RzqtQrKTLrZMvRBh//1Svo8UZhbFRbkQx0ppyU44Kso6109qapuYsjXB2UiGbYKb+8/nDG5kT5PlGUfKikuyAICHSyrxM2V1fqJxTdd7ZDbBWcgPWwZ+y+oAIEd9HqiLF+HQI4FBKpigkXmxfdy4uCXUVXd7JDbB2ceGVhty9xHQuAgvZ4oy5CQCLKAQHuLffKXEmLJ+jlUVTeC3CFI47jflrkX4Eb6PFGYm0IkyAI1MMv0N5nsNpu6MOskqmpIQxYCcZuNmbbQ54nC1A6VIAvoeMr0atZL7p69jprqbofcJljTuIHeTEJObsjk+NC4DtsMf5tCd1fAeS3EZR7ytUEbxmf0aBJq5oVSkAUuNinylYs6yRenf4Wa6i5k0TT4Qih76dMkxLwdUkEWqInvDH+jucnXrXuQmuouZHFZ8GYxiD5NQsyToRVkgUr4xvB3Srays3YNNdUV8QuDN4p0m0d7hKhI5xALskBlfGvwO21PsjRnWhY11V3IopoKRtHUVp8DQtRjAxqEWpAFqhrWlRmdzLMKyv6DmuouZCHUMIpn6NkkZOThU3RUokuI+0oXWw1+u/rOAxYrqKguKXuaGiaRju/p4SQ07MfrLnIRVEyCK/0ddaTz50ygorrlGFVMogF20s9JCNiH13BehMT40Bhc6vfc5rwCHHMsJAQtdqhiEp0TtpwhJGimoW7kxFhAoDyWlfpdH3B687YR9dS9IC9XxyjYypSozO+4IZJifGi0QEGJ33emwzoWZU+jnrq/q/eVOiaRgfn0eqIkhRgTiqrHMjtd7nZW/e13qqkMQZ6k1t2h1fR9ohxbcWPExfjQHrkkrZzkWEyimsoQ5KFqGUVj7KL/E6X4AeengBwLCCwo8ZsPdvLpXlRTGVdDHlGv1QyviRB1mIIKKSLHAn1L/O6O6nSwV4gUQb5RPbPoWup4gZBgGI14ysixQN0Sv7395lRaXsa/qKYRqWZRegygEhAFeCKFxPjQ+LXY77/a/ifnUkulUO4sNQ1jKNWABMyglJNjgY+LzYCD4vtPUEvlUEbsUdM0hlERSIA8Y8NGr8W0iAnySyWySxhB9v9qyM/OlqwCzsOlaIm2uA5N0RCZnhnHi1QFEhDjE1rneZiMQhRK6NSs0nik2Cxsth1BzjyZSion7a2G2GZv0uujL97BUoMciE1YgHF4CI3d9qwtNV6gMpAA+DJBFTcdfbDn8L+tHSlB7llsHjbY/dwcKqkcOa4ptti5rjEIi20Z8mZMwa1S98z9mHFBfGYVqibYG+cU+ddXRkqQexSbiUU2P6UPpJbKyLCoJbYmmuo6eM1x17tdeAOXSzORe3GQGkF8Yx+usLTH1thU7N/fHClB7l3sd3vfriBfSjWVkfCWoNJbJp7HgaQNew7aSjKSm3h7j/hGT0tbfKBUyK5vpAR5ZLHfbai9T+0960TqqVs5rpoodnwdfndt3N+hpaQL1axxQfzgM0s7fMqgROyYSAnytGK/W3d7n3qfeuqSjLLaGsvKpnhOUuy2ENOkVAKoyUpwxHO2WR7RPWf4mVmREuTiVZHttXHSOlFRXVH2NLHEaoJrYJZUM9+NvhJ6j1XABCoG8RSrHeETJp9ZEyE5rlnsG8A6e58qEP9HTXWTd3yCnmN9n/1XD0x9oZTuvN2OJBsRIpv5Fmmbd5r2sylEjcgI8p3FfrN3mfLmiyCPsprey7HRI3Pfgc4STOZyrKRyEA/IQ2NTq2uG/RafbBsZQW6NQUVGM3bS80GOu1lNblPs8NDkC/GChKsjVTCF6kGkY344VznB8XbqlSAqlvKWSVVNmrRLtDzzqb0CuZ6b/UxUkdIQdRsVhEhkD2qZWtukBJ+dlsJyrK2gqiZ/L0+3upfX2Ac5BoCfcYEEQzgfc6giRBrPW/zxT0RuStVMLjGGU1eTJPtY8Y2VwG3wzfg3J7gLZfOrEnphN5WESGA3qplek95u4/NXpHLIIkdvFTuG+uo8evy8VVz2F18dYIfdA4OEFbdmUE2Ia0aZWtg7tj4/IKWjyAJilX4bRdnZzbyrRKHZdGYUK5biDztxjSRjuM/WHoYQM/JQz8S2rrJ5PerzVBdkCIhleqtYGSqtvd2xELnmU/l2IG6wE9dKMoVamExVIUkz1dSy7G5UDkg5qo7AEd9X8QpUWzvR4znmk/hogJG7FtJMoSPWUVlIUjQ3sanbHTzjbsrxobFP9IgdTc213h8/a9WEJsjilttwiTRTqIThyKe6EIfMMz00Xu7gKR9Siv8e38TTqLrmyW5NzKPH55Wo7eo/q3GuRFNoUaI4CiGJuNfElto7esoeVKYQ/z22xBtReQ3RNfMi9PEADvNK86NUU87AIBc1nEmqYS6ksx0+6YFQS2gGzkEd1EcTND0yLkZ9nJtkjrWWJ7pSfR1Gj4co4hRfSKgFV3Q04KURYpPJptekCh0+aX4ohfhVbE1QLiEff+JnTMcL6IwGzkofvMxocsno8ZPm03W9QhHX8ZLNLI6H2WWE2OAmEwtKptRro9DJ8VDHv+NWTEYXZNndJ0/KOJ4q/LccXy4KzCufblTKMXpKN7a6+IZ6QyzZYvLd7BzL6m5mjA6ZHD+W9LztxVsWtfGKjfd4YeQw5c4Sm8yvHX+mmGscwNXyL3WiH+PJxIJRtnov249HVw+RHA90HJQpTiG+sld49HVeF4nFYrGj9M/MJ+lJBZ1jnSeFvi/z+VI4CRNmF/iTPYMYHBo5HiRpBmfiwsRv6005jol+wqLcdp6S7pEj+XDvr/PjIcxPJobx0LhJMmiy/SS3oGIYygGV6C3tjr0YjPLWbywUzVNdjhuIfLPpqY61yrrIUI9M8Fqsov6QEkw2/TKfPE8qL8cVPGjwsBh1rd+6XYhUvgpyplhv/tdR5fpoBbjKIzPMwngqEClGVxNbWezimTsV77BXA996Mpe5aGf95tkpmwKXfayY7cXJqj9846Ex3ootVCFy5I9/tkllcG8OClUYl3r4TTEfj1u/vVuqhitGmE/K1YFWrrBHBw8NMluJu4lEBRZLzbD4m4PK5iPf5XnP9tFW9/r2pGTYQtxuviDVsDoEjrLCk6O9v0Y6hiR9ZEOihNl5xTTXT16oYEundAz3ZVbHWl4TSb3o8cXigHn0+JOQuMqDHhtnB5+6BxKVaW0iXDL6rj+imBzXxXzf5vUxi58jrW5qyXENsdN8MvqHxlU2el45q46PBkpUJA+VTOoFymCXnexc30Y37PR1ZptbHe2lDhlltTXhjh7/zWAfvsIxdJHK/GBiFy9Ie34FJcS4qgdJbolYZ3FjMWX2yOkZYrlVssuaULnLLtT0wVg7YhuVKUUxqzsh75vTGAXk+LaAKtZMsaptkRJHeXW0zVa7wa9D5zBjfIqtfU9tSknuMbSH8kkVFTKjW6BiXFvC8WSyFJr3yyzUKkVfjtuLfVZLMyaUMb6GPt1bmkh1SkGMb5Y1l/qOg4kuS3g24nhIyuFk8nxvWjlZGxlpMT77P9ok68W5L6QuM8038+2laG0P4hV/mlhCP8nv2Y2mAchxa/yowBx3NW2DWva06O6Nm5lfkj40rgttAcpCiT2pEyfC7aRKpRCfmNjBVOlv2oIrfRXjC/GRInP8m3k29h3RTHKrKT5PtDyNsT3EbrPQWcMYV6MhfqVOpQzPmljBOg/etROtfLLhbLwqNQbullvMbkTkRG9nXFEba94N5O9s23Uhd5w7fNxbnMNr1SnD7SZlN71hH271oWjQS55fjHbKt6YHe+XSI3X9QxtrXlyzqMAsC73j/I6MCF4vJUHT0CQN0rvw2zAPCwLUxouKdpC8Otol68v+Q79JfG3368tPkXCd3j4fiPTkAV/k2Wsijt720ZmHOh7Y6xV4R+ErX6bNi5eEP0hRXTwvcu0u0wX4LSLOs8V2h1tZoy12U7MijVmdtykev3cn+kncJ2fiLuXvF+xAplliXvnQSnG5s8S94jsnS3Ul1kfIfYb6njZ0NbZStSLMRJN196P74lJcL8FCm2JMSI7ru0SpOrI4Rb9Jm6rlOVus+7EvYl8w6/guyQ3Y8inCDDDpvehXguh36Jxkgc44mmEYlodormea/S4zwyXFJ+hNxUTzUpoqlRLxngkBJNefh6VUrohyk0k3DT9ZhSG4wpE93onx+DN0c52Hqsa/0UFxSkgaMOlNxZtidzIicn2kQhV/k4/LApDkah51HyNB08Ckn4b//IHR6I7LTXKJ4qiLtuiNyaFoLGHGPWbZyC2VF+O0ymKQ2JhsHuLYCJeT/Dyg/rwfUb0iR56J/D0b4M90AEvxNT7BRIzCOEzBdORgmVKXPJLnA7OaFkMVluIz/inucHZwVzz61SvyPTDaBtT4ZgIVLGKsMlnrdzk1nrAT5Y1nfLGqFz3OFH3FluTrOt0RmRQ3KxYH1KdMD2WtPGLOl55XQia2NlOFFf6rnhhXEm85zaIoujPuHqoTV3d0DaiUISU5Wpi14dzMqfGIF818q7lSYqxrYkTyYlwNfbE2pZZ1TWBNcXSMpVdFBuMmnJVRyKnxiO/MPOs5ZcS4wn/Fy+Jg8mnh45UrJOIHAwPrvkBJjg7GNcgu58R4Rp7ZbduFquyNW4lNyXZLHpjC+bHbLZonei/J4+lZkeByw/W9nRPjIe2NvSpfgVzktLiYnlz32PuRk/J9kkcG2KOMu+RocI7h6g7kxHjIy2apb02CvoF3s9jrVAgqohMmYy9XFcBBk6R+vyT5HS5ByNlrsravcWo8ZJGZID8VoBhnHK+NdHoxoRMms/ZYMd4LtJNvOj7lEoSa301WdhqnxkPyUc143r8NTI7Ty4m5Thz/RrzDPm8GFAbSNvLvUQnfcRFCzNcm67qQU+MpHY13yHlZJwUTqjhP22zX5S/BEKzhCpoyN1BBFqiREhdxosq7Jqu6gVPjKWanP2mXBHH94yKx096+uBP7uiX919a/UR+buAghZZiJ57FPjLf8YOZNfXyX43gjsc9OB7xnQ1hcLxiWedifzG4m+B4uQyjpbZJOSrwlD5WMgxYz/M45rif2JHLvLAzCDq6ZA3oELMgCN3FPFUqM+00348R4ThtjQd4VO8bP2HHFRH3wMvCEoh1jVWYjKgcuyX25DCHkWsO1vI0T4zlPmZVHq+XnBelfrZ26JZZxpZLimcAFWWASlyF0GOexP8yJ8ZzPAu+ud5T4xMqdy+N1FjRJmt2oFbggZ2IxFyJkGFdVeI4T4zm50I2vW73jV7iil3VVCuazumOsAnvkupFvDBAt9pmsIy/F+8HFxrO/KVbGj1S3mlalNdvQkV2TZ7bAvo62yOdShIa1vKcXIA+YlSTI9F6Pj7FqyNSaSVNS+EQBQRZ4igsRGsyyYdnO1g/eMvOhzt6HK3pSjv2gpQKCrONzLkRIMGuWy7uXfrDMzIfe9bpuxf/EDjP3vQb7uDLS+M7koMDfUZsBqJAwyWQFt3FqfKDArJ75ttjR3saPXzGvg8AqFXLprETYguXNw8EIk7sAzHbyh9uCyEXWKol8sw7Rs7kmkvnDrMm4z+N9LkUIeMrkGw7xh1FmdZEf9lKQ3zBz2he4Ih7QRwlBrob1XArlechw7RpzYnziFzP/meuZHJdLN9sfN8QBrogH5KKqEpLcjl98ledOw5VrxYnxiULUMPaeAvF/Xu2PnzZz2FlcD494UQlBFnibS6E47QzXrRMnxjfMzny0Tp7IcdZx4k/jF3bmWnjGPlyghCBns2af4lxluG73c2J8Y6KZ97zvTf5xM7Oabsyu8JJJiuyRH+NSKE09rlrAbEHc2Hf2p53qhSCPMXbUrlwJTylAEyUEOZ3V+5TG+LRhKCfGR5qbXbC6xYsL01uMX7aI6+AxsxTZI3fgUihLvsk1IpYW8pMXzHxnlvxmTbWMX9WCq+ADbRWR5JlcCkXZzhxyBVhi5jkF8TTZAYtuxq8axVXwgV/MolM+j0tQwMVQErNab6xF4i+Xm/nO47JT3iYZv4hxRX/opsgemcUcw7U3m8+p8ZURZp6z9awT5e6Qlxu95lxeGPCJDSadbf0eV3MplGS+yXot4dT4ykbzrvEyC3GedaIoMHrJPVwB33hCkT1yDpdCQcyKb67l1PiM6XnPMok9qPVzWMEiaHaYXc30/Ro1UY8PWHxTET409x15e2S9qfErPuD8+8goRfbIbH+qHuNN1iqPU+Mz+SbdvwXEpvi/ZUWQ7zB+xY+cfx85gDpKCPJ9XArlGGm4UpU5MQEwxtRztKdkCXIP4xewm4S/vKGEIFfGbi6FYjzLasjKsBc1zQQ5T68nJ+mtP78QqUCeScUC1n5LdfobrtPFnJhAeM7cdzZIKcapP2P08EzOvO9MVEKQb+RCKIZxG/pmnJhA2I1sc++ZLqHLnnjZ6NE1OfO+U4CmCghyBk/vFcO4Fm9bTkxAjLbyn5c9at10Iec9AOYosUeewoVQihvZoFYp8nCZlf/c43aH/KbRY+tw3gPhVgUEmYXP1aI5V0kxFpnf2YMoEM3dxZBfNXpsLc56IKxD5cAF+QIug1I0MlylvpyYAHnMyoP2ivPcCPKLRg+tzjkPiFcV2CNv4DIohHGG+jOcmAA5YN1aYoOuSW5vyrTzoMhX4GiPtZFVIstwjUZwYgLld1Sz8qGfxSnJCvIAw8YkzEMOjCXICFiQ2RxIHQpM+oW8yakJmK+sIskQX2Qdl5wg32f8wC2c8cAYGLAgP8glUAb2C1GX0dZ+9FJyMeR2xo9bwfkOjL2oH6ggM8dVHZabrNEsTo0C9LH2pJuTEeRLjR82j7MdIME2P72MC6AMOWDxL5UDSpaJqvvSsp0LcjXjh33M2Q6UhwIU5PqcfmV4l5kwin+bbWblS6sq/NepIJ9h/KhXONcBL/TFgQkyK4mpw8swPnQ/wKlRhI3WpXM/dVrf4iixz+hBvTnTAfMjygckyPU4+crQG7y4pTrLUNXKn/o6vTy9xOgxHTnPgTM0IEFuzKlXBuM+bs05MUoxy/IytXals8S3qUaPacRZDpwCXMfeeimO8dfhuzgxivG6lUdtLXeWkx3yEOOKyIWc5cBZj3MCEOQenHhF2GVyLWQQp0Y5ulpHksvYP9a72/ghGznHCjAlAEF+ndOuCN+brNBkTo1y7LOub3GH/ZDFlcaPWMA5VoL7fRfkhZx0RZhkskI/c2oUZKXV4d7ueHm7O+RMFipXmf24wlc5roaDnHRFML4Jls6kN0WZYRJiEhAQc2wmwGUdJ/KNHvAC51cRfkcVHwW5GydcGa4xXKFLOTHK8riVb/W0e6y3ko6pNu/5KMg5nG5FyENF5liEbs3amPvWfr2avaDFZ+xrqzoP+ZaDzOwaVfjZZI1e5NQozAarzKhvYkfZ2SEPN/pwFbqmQhzAVb4I8iecamUYb7JGn3FqlGaShX/pt9gR5G4sYKI+q6wvaEoZ13GaFaKnySqt4dQozi3mPrbFRrmh+FWMJoaB6VZnuBJGZazkJCvEJaxjEVK2Itt8j/xiYkGuYPzRMZxZxRjsoRzrmMoJVsqpjf/83sGpCcXmyczPtDytUiJFPkYcZMW3MFCAjp4J8jBOr1J8YrJOIzk1oeAuc1+bnDiKvJStfMLBbjTyRI5ZHUE1+pus1PecmlCw2eL2QLxWUhXf6nBWFeRX6ddEMjGR06ocTQ3XqiLvUYaGYeY+916iTOTBxh/cxVlVMj4l83DvEvZnU5BdJhV2W3FqQsNBNDTzusIE3fbE7cYfXMxZVZKnJIlxJQxhXQQlmWGyYk9yakK1dTI9Qh9nHbK4yPhjH3JOlaQAN0tIcuuHTZxKReltsmozOTWh4iYz/zsg/s8qZKHx5D1cbEcDF2LcFOOxm5OoMBeZ1HnbzqkJFYvNvbCPZeKblsfeEeFiRRKHew3QA5N5A1N51pqs39WcmtDR1swb/7Csa2Fc8a0N51NhPrE83KuMy9EMbXELumMIJmMBtnLKQsJbJmv6FKcmdOSY+2gDK0H+wugjdTmfSvOEhSBn4VdOUEjpzNKoEaKp2Z29kVaC/LrRR8qz4pvSFKCDhSRfhj2cohCSj+omOcj7OTkh5EMzD91oEbQQjxt/KJfzqTTbLA/37uEEhRCz1qa8ORtO8kxLDVnc2BP3Gn9kCedTcZagMjtIR4qhJmv5EqcmpJi1l9AfNU98a238kVmcTeV530KQMzCPExQyWoPXtKLFHDP//NhckOsbf2QyZzMEDLSQ5HOxkRMUInYjw3AdqyOfkxNS8nGusXdujZUxEeS0LGN3HsfZDMWCWx3utWBBmhAxg+cBEaSHWaaFbhZDFqy+GmasD/cGcIJCg9ml6SmcmhAzziyK3NhEkDNON/7AC5zLkGB9uMfQU1gw/sMaxxZOTYhZZLZD7mIiyGX/wcLlYedji5t7lbGMExQCfjVZv2s5NaFmv8nJgP6YeeJbodEH+nMuQ8TjFnvkhtjJCVKekSarN5RTE8lvPvow87563CGHnny0s5DkW3jvUnnMStGwiUDYucZZXWRxgrEhDOFMhoptqGchycM5QUqzG+UN1602/5SGntbOBDnzZGMXfpkzGTJ+RkVTQU7HfE6Qwph1mmYZ3PDTwnhtXzcR5PT/GZvCaM5k6HjLYo9ch9VJFMYsW/UTTk3oqW28ti+ZNXGqYWwK7EccRh60kOSO/PqrKIWoA+Oai+zuEnb2mGRAaQ+bCHL8KmP3/YZzGUL2m9ZgFRAYxQlSkp9Z5S2ymLZyutlsh9zF+APrOJehZB1qWBQcWsgJUpAXTdbrVU5N6HnOrADnuWZZFs8Zuy4LmoSVHKSbSnJ95iQrSEuT1fqNUxN6LjUOWOSV/YfZDnm+cVNMEr2/ygICnTk9irHd5A8ofTD8/GLmh/NM5DjrJOOu0x05lyEmH9dZSPIbnCClMKtq3ZdTE3o6mXlhP7OAxeW8sBlFNpvVYYVABfzECVKGj3COyTp9yckJOfNNfVCvbRawGMkut9HkC4uCQxezCaoSbMGtFkWh2Ng03Bw0z3haZlKePvtYbbNxl9u9nM/QY1Vw6BFOjwJ/Mmtb1h8h4aav+eo+6DBg0YGzGQHyzC5tQkDH55ygANmO+yzEWEDgTU5SqLEoibsj7VQzQX6Nxz5RZg2qmTp8NgufB8ZMk5t5vAcQFRZYNY143CzD4jix1bgQDV01KkyzcPnbOD0BsAXdE4qxwJWcqBCzEFnma7u17Glm/aabGn+kHWc0QvSwcPt3OT0+M8XiHmXR8TSnKrTMR1Wrtb3DtFOIPs74IxM4pxFij0UT1KrYwAnyjVW4yZYYCwh8x+kKKVMtiuAK6Dmxo80L0+8wvjTNMo1R+4udblEBjvjBPgxBBdtyXJ2FC0JJIYZYJJsKaLvKpZvvj682/tDNnNfIMdDCSKZyejxnpmU3l9KjK6cshGxBxwTrqt0QM0e8xLhiqnAAl5kaSU1+I/KU3xK6aenxAactdHxlmVUuIKANjVkhfjO+VstqYFHkJ5OebQICt/NOmEfswACTJvBWI51/IkPGHvS2DFUICIgpsWMs5DhenjHF1OIFC2NpwHYE0inAZGQ7FmMBgeacvFDxBS5MuKbajIzjLffH+l3GHxzL+Y0oebjawmDi6MP6FhKZgcZJibGAwLOcvtCwDb3srOmcrJNi1mhTjT+6inMcWZYk+Pp8IWZzkiSwEG2SFmMBwf7godnijEZ1Oyv6dfzfCeQ46zhtl9FH63GWI82AhMZzH29puvyj19GVGAtUQR6nMQTk2P0O9K5pb5Ai++OLjT/8KOc50uy1Ee2qhlGUhKRYhrsRdynHAndwIkOw0u3trufzsaNiidEHGn/8U851xPnElhldhC84VQ5dtLvF9RsnYzwnU2nWoZfNldbyROeYPcRM43QbprxFn1ts79RWc7Jshik6S9gZ/zU46+qSi0H271v+kVbXphzHyohtRo9oxRlPAdZaFQYsNjIxAFs5YZbMRcfEGagOxsWcUkXZhIG2PUdATDat6WY/B3kwZz0lGOFAICpjEHZwygwowExcK1GKD43enFgF2YC+liWDSoy9FhXdDI/02ho/6BPOfEqQh4sciUQNjMQ+TlsR9mCsRQ09N2MaJ1cx1qGfEzGG9pWoGHOGeM74USzFmCpMcywUdTCKF0cAAL+jL6p4IsYCOpMOlWIt+iHTyQpuF/fayqoosUP+yuhhtTj/KUSLpDJk++HPlA5S5KCT1IhxydGYhqkMq9HLaR2SyeXOiiXB0WI3q1ikOvOSlIwK6J6Stzk3YDjqeyjFjCCrxDJ0dZrE+LPeOJYc5dKNHzmE65BSJH+jLAN34hsUpsg87cd7aCsxrY0RZLX5xXlGea7okXVcLFn0xrwUQoClLi8yNMLrEc9bL8Bc9LLo280IctSY7zwkdVB7wUGCm2EE+U7jRy/leqQY97uWkMroie8jOTeL8Rjq+CbFjCCrIMZtna5YoZiYnhFziz7Y+PG8pZdqrLMoWu9kXITnIxNXLsQPeNphWiAjyGFf85lo5ny9PtVqxmQg3jQuKUNSjwckft1ugbGh7nRxELPxiO+74qLjPRqk7+RjSjKVq79OuyQmC/G50Suu4NqkIL9JPqxKRxu8Errd8jpMQBdUDVCKWYs8CArwES5xvk7f6E1jMhE/Gb3mFq5PSnK7R9HQp7BQ+Vb2e/AF+qFR4EJ8aFRPmbwVVcIUTZyv0hxxWUw2Yq3Rq3pyjVKSeR5KTGW0xXAsVk5odiEHg9BSUgRd1uhAY/SNHFwV/M74iCBvN3pdH65SitLEc6nJxt14HQsD7m19AD/gDTyIRp7etUt+sJOeX2J8tTpiHIvFYlqe0SsHcqVSlDd9k5wMNMUjmIRfcMC33y4X8/AmeuEqp9dgfR8zaYo+iHES2RTfaFfEvEQUGr32Sa5WirIHWb6LTzoa4jY8hSlYLD0zYx+WYybG4BFcj2zFRbjo2ExT9JSv0dJ57lCOhzvjI4Kcz4vTpCj3BSxFlXApOuAhDMUEfIr5WIEttg4EC7Adq7EQn+FtvIj+uAvNUStEEly84zfxjhXooqYYx2KxmDhg9PpnuGop/EVORYk6B9VRHw3QFFejLdqiLZoeHpehPqo7K4uo/OhMM/SIDXjAcXKnNkM7P+YXYqvRj9CLK5eyFAR6HYKD31C9C8cNcVRcXkAUalP12jE/0VYwD5kUpzclMeDxIY1Q+jZjAmo6W4UCbWpadsxvxLdGP0wzrmAK8wUlMeCxjEYolcVO+x0WiLe0SrEgEJONW/SQ1GU/KlEUAxzpPiYCRp9c9HMWNS7Upmo1YkGhPWX8Y23iSqYwHSiLAY6GNEBJ5GOUw6ok2owAwhTFym/exm4FpCRDKYsBjltpgFJY4vTix8fxc2NBo9c2/uH6cz1TmBzKYoCD17JkhN2GOKpOoueIhjEVyDpO7Ge/AlKc3T51jeMwGu/SAF0yz1khTZn1jCUc631j/GMu5LqmMMxFDm7Mo/m5YA96OikYtciDEpouBbmv8Y96H9c2hbmewsjS9CFkERraP8Bbo98WOzqmGuI84x+3IgucpDAPURgDG3tofkmRh+H2q/jlih5l/xFTkqPESuMfuivXOGUZTGEMaFSh8SXFGtv127Q87YWyp8XURetv9qN/xXVOUV6mNAY0LqbxJcEkVLY7w1/Eq8bUJi1uXIRToB62cq1TkjcpjQGN62h8DjmAfnZnd6XWIhYGxESzX6EpI1oUZA4fxz00PkesR3N7M7tP9FE1alx6j5xt3DlEQKATDnLVU45XKI0BjcdofA6YY7cPzCw9MxYmxNvmv0wrBi5SjhcojQGNoTQ+mxRgiL0LTNvEvbGjYuFCCLHP/Feqh6Vc/5SiH6UxoDGKxmczcny3vRmdmP6/WBgRPa1+rQwMCrhxO/GT2ymNAY3xND4bbEMrO7O50adOeB7lI89OlJCTQ0tIEZpRGgMaU2h8CVmJBnbmcpp2ZizM6JrYlOiXbImZKKRFRJ7alMaAxgc0vgQstHOQt1O/LRZ+tIu1vMQm0wQTsIt2EWHyWO0tsPEezc+SaXY6jM/W9Fg00NuJAjtmUxFdMRt5tI9IsoLCyJCFkkxFeqIZLBTPZx8biw6is3lOcslRGZ0wHhtpJxHjAwojqyEryOTEcpwb5mM8813yQScmFMeV6IOp2ECLiQhPUxgDG2/Q/Ex4L7EcL0yLx6KI3lhsTcaY6qIzhmIm1tN6Qk1HCmNg4yWanyETEp9rvJxxfCyqpMXF927MqjraoCdGYiZWMtIcOtgvJLjxFM3PgPGJuoDk63fFok32saKvWRU4p+McNEUXDMJ4zMRi7KZ9Kc1KymKAoycNsBQfJtod745g5Nikm8h3XhjduWiGzhiAUfgIC7Cee2ilYKW3IEd7GmAJvk2U6LZOqxlLGY4Wd2hrvDbCOGqjGW5DHwzHFMzFakp0gNwZLgnbJ9aJJdp8bYaYoo8TI8QoMVFMFBPFFG2GvkAs0dZYVWlRb7Dfe3GW4xzrGfshvVwstcg4XtwhVvlrlumoizbojucwCd9QoH2kADXVlKrdYomYLd7WXtAf0TrqTeMXpmWVO8tehdvMk+MV0uqK5vpd2tPibTFXbFBXkLN4E7YIG3GB5WxpX2X8K5aKZB+rdRK/BGemhwT6PgzFh/gZe2mpHn5BVESa9oif9Q/1F/X79ZbxWhX+KzkYd4KeqV+q36IN0MaKOYlLBvg51tIID7MbV1rP1RdZJ8VSGe18baTYEbzJ6rgA7dAb47CAl7gl80hgq6rt0uZrY0VPvbVe2++SifF/x2uJ6/RHxBgxR9scrHXPoBECAPLQ1tpeZpx1YoycdaJ+o/hI7FVnR1EPt2AwPsJq2rAEJ/A5YLFVz9FGat3FZboWK6PMYfYp8VriOu1h8Zr4Uqy1f3OVJerlUYjuCWq5haYhk0+yfLU2UqxTK/5WEx0xBF8gl/acJLP8WKeD4gcxRuuedol+RihyjU5Iy9Kbiq7aUDFNLPP+iLADzRDAM9a746kRvgTigjLxqloX8aZYrdrRSAM8iMm8zO2YW71bk23iCzFE3KzVyDou5Ifcp+vVtCb6baKvGCU+Fj+JXLkzVZldLDHBOmSZw91xohhcmnaD9rQ2Q2xRTZh7YArLH9lkpfyym6vF+6KfaC5ExL8vZooG2jVaJ/0BMUgbKSZqM8RsfYFYJlaKXJErcrVdRbJFcrU14jfxg77A7BvmvJT/nlaqakXRGpRLyp5GxbVNern4VaKXNlabL3aqlN05CPNRQM314UBPyxM/izf1B+KNzv4P/cEyGNLeeAYfT2krXIQso6KaBw7/1/po/3H3WpwbiTvEk2KiNl+FvXMtPIiPsYfKa8hWVHIzuyv1D8Ugra2ozuieXcqdZXxgeB7yU9YKl6K6WZ3j3aJQ7NRq0G5kxd7+pZ8jmotu2gvaVPGT2B2ULGeiEz5inK4UvZ3O5AbxjXhLPK7fop2foun57hNJfzSe229SNmh2rnVOzqW0Gc9IOzVeNX6V6Cwe18aKL8XvR76U+DKqoTtmpvBOpCS/I8Nsrv4Qv+oL9AXaDDFBH6b117poV6ZV5rGKlKBFP+M5vzMlbXAd6lr3AulAi/E1Z0M7U5yntdDu04ZqU8VPYo/3snw+BjMXAwBwm9kcLVYnPziCm5Iss5upq1LOAjegvrW39qG9BB2D/p9eW28tHhTDxcdiiVcZoOm4HTkpXkHgC/MUo1a0wyCCFg+nmAWuQQNrP32NGwPldtC6pl+qddFeEJ+I3+01Y3WSIDc8ZS+U7DAvSf9T7CganqdBi3uMZ748/kghC1yNetb++UmkGpdGkbNOjNfSOopntRlio7yU/IHYlIKCfK/5nDSnpXksyKeYhea6pYz9/ZqoR833mSfTUkIV2tCuEL21qTLKKlZE3xSLKr9nPhszaVs+BC1GmlUJ/zEl7O/nRPVTlon/o5WEVZrLaddoT4tvtTw3olwe3VPmUOUn8+zjfP0cWpT3lEs3a5XWPgXs7xtUs/bGVSlXgD6KZJ0kLtMH6jnJp9JloEcK1I/70+LLov4i7cgf9HFma/BlxO1vKipY++H69AzaR4Q445/61eLlZIsfRV2Ud6GZxc27FC/+7SPx8uKg8SrUjfS90tEJaqdom9OyaB3R3INUEz3E7GS6aGegO1ZG0h32oI1FEj7vRPlqny+arcSgiIpxIZ5I5Hvb07JpGdE+PjlT3Cu+cV5wPAP3Y1nEHGI3WloVOBxGa/H17ON/ZqW40vFTBOV4t/lFpCPXpOO1aBepYfzlxL16jvO2UTdHqMLAJqtgBcQPvBjt+x75UbPVaBq5uiu/45JE/vYnD5RTbbdcU3vFtMBRoblzfBiB+hdLrHv57oiXp334f9oh1putyMBIyfGsRHkVEOu0SrSIVDxM+bd+t0Ev7ULroMb5GIrNIXaI6Ub1ZouWAm9Gywhkj3yj+bezzyMTOX4xcROEP5hZkdKIhuL9ohJsJ4e5PLqEsv7FPvSDbn2y3Z0WEZglfmLeLTIKl5VycXPi4OBSXaMlcHdyjph4uDpGvv0qGZdjdKjqX/yAixP9Ti/RFgIUZGFeJfxa7Au5HM/BeYl9ag67zJDDpFXWxmp5TmvKpaNtKMrd70C/0p3KSu6OJ8WOph0EKsndzFenc4hbkOVjSELrExDvnXUibYAUjSqX115J5tp1TfTDd8qGMAowHjUS/xZTYsfQAgLmaDHXfIWeDG1WRQs7eUzDuB0gBpRLF6OTq4VRB/2Ua6VagI8SJxlBQExhLzwVSM8Q281XaVzoxLgAr6BiYusrFD259sQqmjci2QJFddAHX2K/Ekd4ExKV/f5rjOHuWJnzjJZW2fBjQyXHf1jdBv07VLZLu4brThLulPVXxf7ky3i2xWisDcwVfsMgO2GKQ+MJdmNQSpJftJLkN0MixgcxzFYfc21FWmWuObH3BfJ/oq/Y6qaU5yV4CO/jTx8dYT1es7wWXWLsZ+tI1cg4Xl9gJcljQiDHOfYCZRCfpJ3KFScOyDxZu09b47bw/UXoibex1MN7fgX4CS+jeYI845J3osR5XGElQ2aWzRZ6IU9hMf4T3e1ZYaH2FA/ySBJkH6u3szr/dtImqiX6YzIWY68k88/DTxiHLvYDFH/vtT7MOJ1rqyZp2douq7Vrj11KivEeDEcVe/a3RW/KdSaunES8JvbK6uCnox46YCDGYCaWYIcjs9+PFZiJ19ADV6F8cu/fp9/NyLHKaE2sj5WvwK/KRY3HINum/WlfsRMIkUDZ0/T7xa9yO14fGlVwCVqiE+7HY3gRwzEa4zEeUzEe4/E6huMF9ENXtEdTnOcsLGE0vtQzuZbKBy5uT/Rt6y1lxDgPU+xm9EAU6I8xq4fI4yjtIjHG/Jqr4iNXv41745BIcq9Eq9lZgcv7BzDevhhDrI434soS+Xvlf+ittBnOy90HOg6KEen/49qFKHBxX6I1rY7xAV5G2oNRFn0ZDcbEsqdxVYlnlEvXHhaLQiHGBdqkeAWuWOh2yfck/qN/NX4IQIx/RR9UdWKBa7UruZ7EB+IVFJflAjEhvQrXKaSS3DlxBUIdt/nY7OkgpqGt05OM18UpXEviqyyLB8WsZK9cezZ2iOe5Mw65JDezToL7S5RvwULPS8zPx8Oo7tQGf9Eu5iqSYJznFNFGjBGbVBBjbb7WJfNkrkn40c8Rf9hb8yswFjs9KaG5AE/iQudWuFv0zDqOK0iC5ai0bO0+bapV7S5Px0rxBGsEREqSzxBz7F8/uhtTpV0dycVUdE3i4pGAgJgcT+PaEXU4Oi1bu0+8J9b5dnQ3X3+UPXujSMbx4jknWT0V0B6v4vukr1n/gcnohUuTz3r/VruIq0YUpezZopn+mJgutniU0LZIe0G7hklFEQ+IXWbendq88mBrDMCbmJOwyNU+/IYcjMFDaOksf6L0WKa3ZLY7CcdO53TRUNyhvaDNEH+4OwLUNou54mX9tngtlpdPIet5L3mLqYjz0RQdcC96HRl3oRPa4vJkgxJGJavuyD6WK0XCyDHxtPiFWlvRSzyvvSE+Et+IZWKLwZn6XpErVovvxMfaG+I50VNvpdWM/5vTl6L75OvEWkUTLH8Tt3NzQKLpdieknZp2atqp/OpHSpJ5sva0OKiYGP+kt2ONCkJISpJWWXysiBQXiul609hRXBNCSCp/i6qjTQ24nsp2MSItiytBCCGxWEzUER8FIsoFYpbW8awTuQKEEFKE9AwxyNfboT+LvmlxzjshhBjvlE/QbxSzRL7Hu+JvRe94Vc42IYQk3iv/T79NfOJBBkaumCjas5o2IYQ4JO1UvaX2gliUuHBnwrFKe0PckV6FORSEEOIujHFK/Cr9UTFBLBYHHIjwHm2+eE27T29c7izOISGEyOYYPVNcpt+kPyCe1ceJ97UZ2gztK32BmKvNEJPFeDFCPKHfpV+t1dTP4GQRQghJYf4fTci7RwYvH54AAAAASUVORK5CYII=")] + +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} From 87de9bd1088ec0f1a2e8893a517cde2005a546a0 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 18 Sep 2022 18:45:36 +0100 Subject: [PATCH 098/221] Prevent auto-application of associated functions with placeholders --- .../rustc_hir_typeck/src/method/suggest.rs | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 04ecd2757b42..613acd3d705c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -18,7 +18,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; @@ -392,28 +392,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { custom_span_label = true; } if static_candidates.len() == 1 { - let ty_str = - if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) { - // When the "method" is resolved through dereferencing, we really want the - // original type that has the associated function for accurate suggestions. - // (#61411) - let ty = tcx.at(span).type_of(*impl_did); - match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { - (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { - // Use `actual` as it will have more `substs` filled in. - self.ty_to_value_string(actual.peel_refs()) - } - _ => self.ty_to_value_string(ty.peel_refs()), + let (ty_str, placeholders) = if let Some(CandidateSource::Impl(impl_did)) = + static_candidates.get(0) + { + // When the "method" is resolved through dereferencing, we really want the + // original type that has the associated function for accurate suggestions. + // (#61411) + let ty = tcx.at(span).type_of(*impl_did); + match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { + (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => { + // If there are any inferred arguments, (`{integer}`), we shouldn't mark + // this as machine-applicable. + let placeholders = substs + .iter() + .filter_map(|arg| { + if let GenericArgKind::Type(ty) = arg.unpack() { + Some(ty) + } else { + None + } + }) + .any(|ty| matches!(ty.kind(), ty::Infer(_))); + // Use `actual` as it will have more `substs` filled in. + (self.ty_to_value_string(actual.peel_refs()), placeholders) } - } else { - self.ty_to_value_string(actual.peel_refs()) - }; + _ => (self.ty_to_value_string(ty.peel_refs()), true), + } + } else { + (self.ty_to_value_string(actual.peel_refs()), true) + }; + let applicability = match placeholders { + true => Applicability::HasPlaceholders, + false => Applicability::MachineApplicable, + }; if let SelfSource::MethodCall(expr) = source { err.span_suggestion( expr.span.to(span), "use associated function syntax instead", format!("{}::{}", ty_str, item_name), - Applicability::MachineApplicable, + applicability, ); } else { err.help(&format!("try with `{}::{}`", ty_str, item_name,)); From a3b5ca7b6d8a1aa42544f5bb1b854f357678e612 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 19 Sep 2022 00:53:41 +0100 Subject: [PATCH 099/221] Allow inferring generic arguments for associated methods --- .../rustc_hir_typeck/src/method/suggest.rs | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 613acd3d705c..85c003ff605c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -14,7 +14,11 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{ + type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, + RegionVariableOrigin, +}; +use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; @@ -392,7 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { custom_span_label = true; } if static_candidates.len() == 1 { - let (ty_str, placeholders) = if let Some(CandidateSource::Impl(impl_did)) = + let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) { // When the "method" is resolved through dereferencing, we really want the @@ -401,36 +405,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = tcx.at(span).type_of(*impl_did); match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => { - // If there are any inferred arguments, (`{integer}`), we shouldn't mark - // this as machine-applicable. - let placeholders = substs - .iter() - .filter_map(|arg| { - if let GenericArgKind::Type(ty) = arg.unpack() { - Some(ty) - } else { - None - } + // If there are any inferred arguments, (`{integer}`), we should replace + // them with underscores to allow the compiler to infer them + let substs = substs + .into_iter() + .filter(|arg| !arg.is_suggestable(tcx, true)) + .map(|arg| match arg.unpack() { + GenericArgKind::Lifetime(_) => self + .next_region_var(RegionVariableOrigin::MiscVariable( + rustc_span::DUMMY_SP, + )) + .into(), + GenericArgKind::Type(_) => self + .next_ty_var(TypeVariableOrigin { + span: rustc_span::DUMMY_SP, + kind: TypeVariableOriginKind::MiscVariable, + }) + .into(), + GenericArgKind::Const(arg) => self + .next_const_var( + arg.ty(), + ConstVariableOrigin { + span: rustc_span::DUMMY_SP, + kind: ConstVariableOriginKind::MiscVariable, + }, + ) + .into(), }) - .any(|ty| matches!(ty.kind(), ty::Infer(_))); - // Use `actual` as it will have more `substs` filled in. - (self.ty_to_value_string(actual.peel_refs()), placeholders) + .collect::>(); + format!( + "{}", + ty::Instance::new(def_actual.did(), tcx.intern_substs(&substs)) + ) } - _ => (self.ty_to_value_string(ty.peel_refs()), true), + _ => self.ty_to_value_string(ty.peel_refs()), } } else { - (self.ty_to_value_string(actual.peel_refs()), true) - }; - let applicability = match placeholders { - true => Applicability::HasPlaceholders, - false => Applicability::MachineApplicable, + self.ty_to_value_string(actual.peel_refs()) }; if let SelfSource::MethodCall(expr) = source { err.span_suggestion( expr.span.to(span), "use associated function syntax instead", format!("{}::{}", ty_str, item_name), - applicability, + Applicability::MachineApplicable, ); } else { err.help(&format!("try with `{}::{}`", ty_str, item_name,)); From d1ec75da7cc466bb4fa61896489e5709ac12c0f5 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 19 Sep 2022 01:54:11 +0100 Subject: [PATCH 100/221] Update UI test --- .../ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr index 3fb418b1c0aa..199454ee228e 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -8,7 +8,7 @@ LL | x.default_hello(); | --^^^^^^^^^^^^^ | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::::default_hello` + | help: use associated function syntax instead: `GenericAssocMethod::default_hello` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `GenericAssocMethod` From 02025b54eade665d32ab9b507bb5a0376d639785 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 23 Sep 2022 12:40:20 +0100 Subject: [PATCH 101/221] Use `FmtPrinter` instead of creating `Instance` --- .../rustc_hir_typeck/src/method/suggest.rs | 63 ++++++----- compiler/rustc_middle/src/ty/print/pretty.rs | 6 + .../suggest-assoc-fn-call-with-turbofish.rs | 17 ++- ...uggest-assoc-fn-call-with-turbofish.stderr | 103 +++++++++++++++++- 4 files changed, 156 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 85c003ff605c..52099102dc20 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -22,7 +22,9 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{ + self, DefIdTree, GenericArg, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable, +}; use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; @@ -283,7 +285,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { return None; } - span = item_name.span; // Don't show generic arguments when the method can't be found in any implementation (#81576). @@ -407,35 +408,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => { // If there are any inferred arguments, (`{integer}`), we should replace // them with underscores to allow the compiler to infer them - let substs = substs + let infer_substs: Vec> = substs .into_iter() - .filter(|arg| !arg.is_suggestable(tcx, true)) - .map(|arg| match arg.unpack() { - GenericArgKind::Lifetime(_) => self - .next_region_var(RegionVariableOrigin::MiscVariable( - rustc_span::DUMMY_SP, - )) - .into(), - GenericArgKind::Type(_) => self - .next_ty_var(TypeVariableOrigin { - span: rustc_span::DUMMY_SP, - kind: TypeVariableOriginKind::MiscVariable, - }) - .into(), - GenericArgKind::Const(arg) => self - .next_const_var( - arg.ty(), - ConstVariableOrigin { + .map(|arg| { + if !arg.is_suggestable(tcx, true) { + match arg.unpack() { + GenericArgKind::Lifetime(_) => self + .next_region_var(RegionVariableOrigin::MiscVariable( + rustc_span::DUMMY_SP, + )) + .into(), + GenericArgKind::Type(_) => self + .next_ty_var(TypeVariableOrigin { span: rustc_span::DUMMY_SP, - kind: ConstVariableOriginKind::MiscVariable, - }, - ) - .into(), + kind: TypeVariableOriginKind::MiscVariable, + }) + .into(), + GenericArgKind::Const(arg) => self + .next_const_var( + arg.ty(), + ConstVariableOrigin { + span: rustc_span::DUMMY_SP, + kind: ConstVariableOriginKind::MiscVariable, + }, + ) + .into(), + } + } else { + arg + } }) .collect::>(); - format!( - "{}", - ty::Instance::new(def_actual.did(), tcx.intern_substs(&substs)) + + tcx.value_path_str_with_substs( + def_actual.did(), + tcx.intern_substs(&infer_substs), ) } _ => self.ty_to_value_string(ty.peel_refs()), @@ -1861,7 +1868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Print out the type for use in value namespace. fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String { match ty.kind() { - ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)), + ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs), _ => self.ty_to_string(ty), } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fab85c39d253..a0efff14f1c8 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1659,6 +1659,12 @@ impl<'t> TyCtxt<'t> { debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer() } + + pub fn value_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String { + let ns = guess_def_namespace(self, def_id); + debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns); + FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer() + } } impl fmt::Write for FmtPrinter<'_, '_> { diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs index 2a829db53839..213d1c72f9ae 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -2,10 +2,25 @@ struct GenericAssocMethod(T); impl GenericAssocMethod { fn default_hello() {} + fn self_ty_hello(_: T) {} + fn self_ty_ref_hello(_: &T) {} } fn main() { - let x = GenericAssocMethod(33i32); + // Test for inferred types + let x = GenericAssocMethod(33); x.default_hello(); //~^ ERROR no method named `default_hello` found + x.self_ty_ref_hello(); + //~^ ERROR no method named `self_ty_ref_hello` found + x.self_ty_hello(); + //~^ ERROR no method named `self_ty_hello` found + // Test for known types + let y = GenericAssocMethod(33i32); + y.default_hello(); + //~^ ERROR no method named `default_hello` found + y.self_ty_ref_hello(); + //~^ ERROR no method named `self_ty_ref_hello` found + y.self_ty_hello(); + //~^ ERROR no method named `self_ty_hello` found } diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr index 199454ee228e..c6d9122228ac 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -1,5 +1,5 @@ -error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 +error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:12:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `default_hello` not found for this struct @@ -8,7 +8,7 @@ LL | x.default_hello(); | --^^^^^^^^^^^^^ | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::default_hello` + | help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `GenericAssocMethod` @@ -17,6 +17,101 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod` LL | fn default_hello() {} | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:14:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_ref_hello` not found for this struct +... +LL | x.self_ty_ref_hello(); + | --^^^^^^^^^^^^^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5 + | +LL | fn self_ty_ref_hello(_: &T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_hello` not found for this struct +... +LL | x.self_ty_hello(); + | --^^^^^^^^^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:5:5 + | +LL | fn self_ty_hello(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `default_hello` not found for this struct +... +LL | y.default_hello(); + | --^^^^^^^^^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::default_hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5 + | +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_ref_hello` not found for this struct +... +LL | y.self_ty_ref_hello(); + | --^^^^^^^^^^^^^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_ref_hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5 + | +LL | fn self_ty_ref_hello(_: &T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_hello` not found for this struct +... +LL | y.self_ty_hello(); + | --^^^^^^^^^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:5:5 + | +LL | fn self_ty_hello(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0599`. From de0ab1cee60804caea065e332d84858042157890 Mon Sep 17 00:00:00 2001 From: BlackHoleFox Date: Sun, 23 Oct 2022 16:41:36 -0500 Subject: [PATCH 102/221] Merge apple_base and apple_sdk_base into one module --- .../src/spec/aarch64_apple_darwin.rs | 9 +- .../src/spec/aarch64_apple_ios.rs | 8 +- .../src/spec/aarch64_apple_ios_macabi.rs | 2 +- .../src/spec/aarch64_apple_ios_sim.rs | 8 +- .../src/spec/aarch64_apple_tvos.rs | 2 +- .../src/spec/aarch64_apple_watchos_sim.rs | 8 +- compiler/rustc_target/src/spec/apple_base.rs | 98 ++++++++++++++++--- .../rustc_target/src/spec/apple_sdk_base.rs | 81 --------------- .../src/spec/arm64_32_apple_watchos.rs | 2 +- .../rustc_target/src/spec/armv7_apple_ios.rs | 7 +- .../src/spec/armv7k_apple_watchos.rs | 2 +- .../rustc_target/src/spec/armv7s_apple_ios.rs | 2 +- .../rustc_target/src/spec/i386_apple_ios.rs | 7 +- .../src/spec/i686_apple_darwin.rs | 7 +- compiler/rustc_target/src/spec/mod.rs | 1 - .../src/spec/x86_64_apple_darwin.rs | 11 ++- .../rustc_target/src/spec/x86_64_apple_ios.rs | 7 +- .../src/spec/x86_64_apple_ios_macabi.rs | 2 +- .../src/spec/x86_64_apple_tvos.rs | 2 +- .../src/spec/x86_64_apple_watchos_sim.rs | 4 +- 20 files changed, 134 insertions(+), 136 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/apple_sdk_base.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 6d919a4c2ad2..13a13f2f073c 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,20 +1,21 @@ +use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let arch = "arm64"; - let mut base = super::apple_base::opts("macos", arch, ""); + let arch = Arch::Arm64; + let mut base = opts("macos", arch); base.cpu = "apple-a14".into(); base.max_atomic_width = Some(128); // FIXME: The leak sanitizer currently fails the tests, see #88132. base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); + base.link_env_remove.to_mut().extend(macos_link_env_remove()); // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - let llvm_target = super::apple_base::macos_llvm_target(arch); + let llvm_target = macos_llvm_target(arch.target_name()); Target { llvm_target: llvm_target.into(), diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index beb9042390b7..1f9ac7ce59b0 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { @@ -6,8 +6,8 @@ pub fn target() -> Target { // IPHONEOS_DEPLOYMENT_TARGET. // This is required for the target to pick the right // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::ios_llvm_target(arch); + let arch = Arch::Arm64; + let llvm_target = ios_llvm_target(arch); Target { llvm_target: llvm_target.into(), @@ -30,7 +30,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..opts("ios", Arch::Arm64) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs index 2d2671549cf5..c2106b456bec 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs index b4e135f66e94..097b92f2e8fd 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -1,15 +1,15 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::Arm64_sim); + let arch = Arch::Arm64_sim; + let base = opts("ios", arch); // Clang automatically chooses a more specific target based on // IPHONEOS_DEPLOYMENT_TARGET. // This is required for the simulator target to pick the right // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::ios_sim_llvm_target(arch); + let llvm_target = ios_sim_llvm_target(arch); Target { llvm_target: llvm_target.into(), diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index 2e31d16dc76c..8cf24e4bf1f6 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs index 3059f42140be..b6c8cd46c050 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs @@ -1,15 +1,15 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::Arm64_sim); + let arch = Arch::Arm64_sim; + let base = opts("watchos", arch); // Clang automatically chooses a more specific target based on // WATCHOS_DEPLOYMENT_TARGET. // This is required for the simulator target to pick the right // MACH-O commands, so we do too. - let arch = "arm64"; - let llvm_target = super::apple_base::watchos_sim_llvm_target(arch); + let llvm_target = watchos_sim_llvm_target(arch); Target { llvm_target: llvm_target.into(), diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 40bc59ca145e..eb7f457d60bc 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -3,6 +3,75 @@ use std::{borrow::Cow, env}; use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs}; use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, TargetOptions}; +#[cfg(test)] +#[path = "apple/tests.rs"] +mod tests; + +use Arch::*; +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum Arch { + Armv7, + Armv7k, + Armv7s, + Arm64, + Arm64_32, + I386, + X86_64, + X86_64_sim, + X86_64_macabi, + Arm64_macabi, + Arm64_sim, +} + +impl Arch { + pub fn target_name(self) -> &'static str { + match self { + Armv7 => "armv7", + Armv7k => "armv7k", + Armv7s => "armv7s", + Arm64 | Arm64_macabi | Arm64_sim => "arm64", + Arm64_32 => "arm64_32", + I386 => "i386", + X86_64 | X86_64_sim | X86_64_macabi => "x86_64", + } + } + + fn target_abi(self) -> &'static str { + match self { + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "", + X86_64_macabi | Arm64_macabi => "macabi", + // x86_64-apple-ios is a simulator target, even though it isn't + // declared that way in the target like the other ones... + Arm64_sim | X86_64_sim => "sim", + } + } + + fn target_cpu(self) -> &'static str { + match self { + Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher + Armv7k => "cortex-a8", + Armv7s => "cortex-a9", + Arm64 => "apple-a7", + Arm64_32 => "apple-s4", + I386 => "yonah", + X86_64 | X86_64_sim => "core2", + X86_64_macabi => "core2", + Arm64_macabi => "apple-a12", + Arm64_sim => "apple-a12", + } + } + + fn link_env_remove(self) -> StaticCow<[StaticCow]> { + match self { + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | X86_64_sim | Arm64_sim => { + cvs!["MACOSX_DEPLOYMENT_TARGET"] + } + X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], + } + } +} + fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs { let platform_name: StaticCow = match abi { "sim" => format!("{}-simulator", os).into(), @@ -35,30 +104,35 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin args } -pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOptions { - // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 +pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { + // Static TLS is only available in macOS 10.7+. If you try to compile for 10.6 // either the linker will complain if it is used or the binary will end up // segfaulting at runtime when run on 10.6. Rust by default supports macOS // 10.7+, but there is a standard environment variable, // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older // versions of macOS. For example compiling on 10.10 with // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate - // warnings about the usage of ELF TLS. + // warnings about the usage of static TLS. // - // Here we detect what version is being requested, defaulting to 10.7. ELF + // Here we detect what version is being requested, defaulting to 10.7. Static // TLS is flagged as enabled if it looks to be supported. The architecture // only matters for default deployment target which is 11.0 for ARM64 and // 10.7 for everything else. - let has_thread_local = macos_deployment_target("x86_64") >= (10, 7); + let has_thread_local = os == "macos" && macos_deployment_target("x86_64") >= (10, 7); + + let abi = arch.target_abi(); TargetOptions { + abi: abi.into(), os: os.into(), + cpu: arch.target_cpu().into(), + link_env_remove: arch.link_env_remove(), vendor: "apple".into(), linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No), // macOS has -dead_strip, which doesn't rely on function_sections function_sections: false, dynamic_linking: true, - pre_link_args: pre_link_args(os, arch, abi), + pre_link_args: pre_link_args(os, arch.target_name(), abi), families: cvs!["unix"], is_like_osx: true, default_dwarf_version: 2, @@ -142,7 +216,7 @@ fn ios_deployment_target() -> (u32, u32) { deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0)) } -pub fn ios_llvm_target(arch: &str) -> String { +pub fn ios_llvm_target(arch: Arch) -> String { // Modern iOS tooling extracts information about deployment target // from LC_BUILD_VERSION. This load command will only be emitted when // we build with a version specific `llvm_target`, with the version @@ -150,7 +224,7 @@ pub fn ios_llvm_target(arch: &str) -> String { // to pick it up (since std and core are still built with the fallback // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION). let (major, minor) = ios_deployment_target(); - format!("{}-apple-ios{}.{}.0", arch, major, minor) + format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor) } fn ios_lld_platform_version() -> String { @@ -158,9 +232,9 @@ fn ios_lld_platform_version() -> String { format!("{}.{}", major, minor) } -pub fn ios_sim_llvm_target(arch: &str) -> String { +pub fn ios_sim_llvm_target(arch: Arch) -> String { let (major, minor) = ios_deployment_target(); - format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor) + format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor) } fn tvos_deployment_target() -> (u32, u32) { @@ -181,7 +255,7 @@ fn watchos_lld_platform_version() -> String { format!("{}.{}", major, minor) } -pub fn watchos_sim_llvm_target(arch: &str) -> String { +pub fn watchos_sim_llvm_target(arch: Arch) -> String { let (major, minor) = watchos_deployment_target(); - format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor) + format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor) } diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs deleted file mode 100644 index 148031b15697..000000000000 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::spec::{cvs, TargetOptions}; -use std::borrow::Cow; - -#[cfg(test)] -#[path = "apple/tests.rs"] -mod tests; - -use Arch::*; -#[allow(non_camel_case_types)] -#[derive(Copy, Clone)] -pub enum Arch { - Armv7, - Armv7k, - Armv7s, - Arm64, - Arm64_32, - I386, - #[allow(dead_code)] // Some targets don't use this enum... - X86_64, - X86_64_sim, - X86_64_macabi, - Arm64_macabi, - Arm64_sim, -} - -fn target_arch_name(arch: Arch) -> &'static str { - match arch { - Armv7 => "armv7", - Armv7k => "armv7k", - Armv7s => "armv7s", - Arm64 | Arm64_macabi | Arm64_sim => "arm64", - Arm64_32 => "arm64_32", - I386 => "i386", - X86_64 | X86_64_sim | X86_64_macabi => "x86_64", - } -} - -fn target_abi(arch: Arch) -> &'static str { - match arch { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "", - X86_64_macabi | Arm64_macabi => "macabi", - // x86_64-apple-ios is a simulator target, even though it isn't - // declared that way in the target like the other ones... - Arm64_sim | X86_64_sim => "sim", - } -} - -fn target_cpu(arch: Arch) -> &'static str { - match arch { - Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher - Armv7k => "cortex-a8", - Armv7s => "cortex-a9", - Arm64 => "apple-a7", - Arm64_32 => "apple-s4", - I386 => "yonah", - X86_64 | X86_64_sim => "core2", - X86_64_macabi => "core2", - Arm64_macabi => "apple-a12", - Arm64_sim => "apple-a12", - } -} - -fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> { - match arch { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | X86_64_sim | Arm64_sim => { - cvs!["MACOSX_DEPLOYMENT_TARGET"] - } - X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], - } -} - -pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { - let abi = target_abi(arch); - TargetOptions { - abi: abi.into(), - cpu: target_cpu(arch).into(), - link_env_remove: link_env_remove(arch), - has_thread_local: false, - ..super::apple_base::opts(os, target_arch_name(arch), abi) - } -} diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs index cb7f5f2a5830..2cf2cbc75100 100644 --- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs index 57fd74a36b65..5167af3e7f22 100644 --- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs @@ -1,8 +1,9 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let llvm_target = super::apple_base::ios_llvm_target("armv7"); + let arch = Arch::Armv7; + let llvm_target = super::apple_base::ios_llvm_target(arch); Target { llvm_target: llvm_target.into(), @@ -12,7 +13,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v7,+vfp3,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", Arch::Armv7) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs index af5d1c2ff458..7e9c9b5c2687 100644 --- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs index cc17265b2b8d..30851564523b 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs index b85214a9c6b4..21635642c18a 100644 --- a/compiler/rustc_target/src/spec/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs @@ -1,9 +1,10 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::I386); - let llvm_target = super::apple_base::ios_sim_llvm_target("i386"); + let arch = Arch::I386; + let base = opts("ios", arch); + let llvm_target = super::apple_base::ios_sim_llvm_target(arch); Target { llvm_target: llvm_target.into(), diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 15607c12ea90..84dae68877df 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,12 +1,13 @@ +use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { // ld64 only understand i386 and not i686 - let mut base = super::apple_base::opts("macos", "i386", ""); + let mut base = opts("macos", Arch::I386); base.cpu = "yonah".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); + base.link_env_remove.to_mut().extend(macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.frame_pointer = FramePointer::Always; @@ -14,7 +15,7 @@ pub fn target() -> Target { // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. let arch = "i686"; - let llvm_target = super::apple_base::macos_llvm_target(&arch); + let llvm_target = macos_llvm_target(arch); Target { llvm_target: llvm_target.into(), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 72b088d663b1..9baf7655595b 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -59,7 +59,6 @@ pub mod crt_objects; mod android_base; mod apple_base; -mod apple_sdk_base; mod avr_gnu_base; mod bpf_base; mod dragonfly_base; diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index 087be1b957b1..6112ef7ec1f9 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,14 +1,15 @@ +use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let arch = "x86_64"; - let mut base = super::apple_base::opts("macos", arch, ""); + let arch = Arch::X86_64; + let mut base = opts("macos", arch); base.cpu = "core2".into(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); - base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove()); + base.link_env_remove.to_mut().extend(macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; @@ -16,14 +17,14 @@ pub fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - let llvm_target = super::apple_base::macos_llvm_target(&arch); + let llvm_target = macos_llvm_target(arch.target_name()); Target { llvm_target: llvm_target.into(), pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: arch.into(), + arch: "x86_84".into(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs index db23f01c2332..032ba0763b4c 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs @@ -1,9 +1,10 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::X86_64_sim); - let llvm_target = super::apple_base::ios_sim_llvm_target("x86_64"); + let arch = Arch::X86_64_sim; + let base = opts("ios", arch); + let llvm_target = ios_sim_llvm_target(arch); Target { llvm_target: llvm_target.into(), diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs index 13259205ac0f..6647c1d29217 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs index c1fd8e1c8b90..cb70717b3c42 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs index 550566b2aa75..03ea66499db1 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs @@ -1,10 +1,10 @@ -use super::apple_sdk_base::{opts, Arch}; +use super::apple_base::{opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { + let arch = Arch::X86_64_sim; let base = opts("watchos", Arch::X86_64_sim); - let arch = "x86_64"; let llvm_target = super::apple_base::watchos_sim_llvm_target(arch); Target { From da588e6df7afb80e210e62dea7e43c5687f088a5 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 23 Sep 2022 17:09:32 +0100 Subject: [PATCH 103/221] Attempt to fix arguments of associated functions --- .../rustc_hir_typeck/src/method/suggest.rs | 62 ++++++++++- src/test/ui/issues/issue-3707.stderr | 4 +- ...n-call-with-turbofish-through-deref.stderr | 4 +- ...suggest-assoc-fn-call-with-turbofish.fixed | 29 +++++ .../suggest-assoc-fn-call-with-turbofish.rs | 11 +- ...uggest-assoc-fn-call-with-turbofish.stderr | 105 +++++++----------- 6 files changed, 140 insertions(+), 75 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 52099102dc20..7ec3d4536606 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -13,7 +13,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, Node, QPath}; +use rustc_hir::{Expr, ExprKind, Node, QPath}; use rustc_infer::infer::{ type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, RegionVariableOrigin, @@ -397,6 +397,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { custom_span_label = true; } if static_candidates.len() == 1 { + let mut has_unsuggestable_args = false; let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) { @@ -412,6 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .map(|arg| { if !arg.is_suggestable(tcx, true) { + has_unsuggestable_args = true; match arg.unpack() { GenericArgKind::Lifetime(_) => self .next_region_var(RegionVariableOrigin::MiscVariable( @@ -450,12 +452,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { self.ty_to_value_string(actual.peel_refs()) }; - if let SelfSource::MethodCall(expr) = source { + if let SelfSource::MethodCall(_) = source { + let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) && + let Some(assoc) = self.associated_value(*impl_did, item_name) { + let sig = self.tcx.fn_sig(assoc.def_id); + if let Some(first) = sig.inputs().skip_binder().get(0) { + if first.peel_refs() == rcvr_ty.peel_refs() { + None + } else { + Some(if first.is_region_ptr() { + if first.is_mutable_ptr() { "&mut " } else { "&" } + } else { + "" + }) + } + } else { + None + } + } else { + None + }; + let mut applicability = Applicability::MachineApplicable; + let args = if let Some((receiver, args)) = args { + // The first arg is the same kind as the receiver + let it = if first_arg.is_some() { + Box::new(std::iter::once(receiver).chain(args.iter())) + as Box>> + } else { + // There is no `Self` kind to infer the arguments from + if has_unsuggestable_args { + applicability = Applicability::HasPlaceholders; + } + Box::new(args.iter()) as _ + }; + format!( + "({}{})", + first_arg.unwrap_or(""), + it.map(|arg| tcx + .sess + .source_map() + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { + applicability = Applicability::HasPlaceholders; + "_".to_owned() + })) + .collect::>() + .join(", "), + ) + } else { + applicability = Applicability::HasPlaceholders; + "(...)".to_owned() + }; err.span_suggestion( - expr.span.to(span), + sugg_span, "use associated function syntax instead", - format!("{}::{}", ty_str, item_name), - Applicability::MachineApplicable, + format!("{}::{}{}", ty_str, item_name, args), + applicability, ); } else { err.help(&format!("try with `{}::{}`", ty_str, item_name,)); diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr index 6ca2deee377a..07c8101cbc68 100644 --- a/src/test/ui/issues/issue-3707.stderr +++ b/src/test/ui/issues/issue-3707.stderr @@ -2,10 +2,10 @@ error[E0599]: no method named `boom` found for reference `&Obj` in the current s --> $DIR/issue-3707.rs:10:14 | LL | self.boom(); - | -----^^^^ + | -----^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `Obj::boom` + | help: use associated function syntax instead: `Obj::boom()` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `Obj` diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr index 996d57731187..7c9f0b6c212e 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr @@ -2,10 +2,10 @@ error[E0599]: no method named `hello` found for struct `RefMut<'_, HasAssocMetho --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11 | LL | state.hello(); - | ------^^^^^ + | ------^^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `HasAssocMethod::hello` + | help: use associated function syntax instead: `HasAssocMethod::hello()` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `HasAssocMethod` diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed new file mode 100644 index 000000000000..0398c510feac --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed @@ -0,0 +1,29 @@ +// run-rustfix + +struct GenericAssocMethod(T); + +impl GenericAssocMethod { + fn default_hello() {} + fn self_ty_hello(_: Self) {} + fn self_ty_ref_hello(_: &Self) {} +} + +fn main() { + // Test for inferred types + let x = GenericAssocMethod(33); + // This particular case is unfixable without more information by the user, + // but `cargo fix --broken-code` reports a bug if + // x.default_hello(); + GenericAssocMethod::<_>::self_ty_ref_hello(&x); + //~^ ERROR no method named `self_ty_ref_hello` found + GenericAssocMethod::<_>::self_ty_hello(x); + //~^ ERROR no method named `self_ty_hello` found + // Test for known types + let y = GenericAssocMethod(33i32); + GenericAssocMethod::::default_hello(); + //~^ ERROR no method named `default_hello` found + GenericAssocMethod::::self_ty_ref_hello(&y); + //~^ ERROR no method named `self_ty_ref_hello` found + GenericAssocMethod::::self_ty_hello(y); + //~^ ERROR no method named `self_ty_hello` found +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs index 213d1c72f9ae..8bafc83bdd0b 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -1,16 +1,19 @@ +// run-rustfix + struct GenericAssocMethod(T); impl GenericAssocMethod { fn default_hello() {} - fn self_ty_hello(_: T) {} - fn self_ty_ref_hello(_: &T) {} + fn self_ty_hello(_: Self) {} + fn self_ty_ref_hello(_: &Self) {} } fn main() { // Test for inferred types let x = GenericAssocMethod(33); - x.default_hello(); - //~^ ERROR no method named `default_hello` found + // This particular case is unfixable without more information by the user, + // but `cargo fix --broken-code` reports a bug if + // x.default_hello(); x.self_ty_ref_hello(); //~^ ERROR no method named `self_ty_ref_hello` found x.self_ty_hello(); diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr index c6d9122228ac..e2f2d46b9e8b 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -1,117 +1,98 @@ -error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:12:7 - | -LL | struct GenericAssocMethod(T); - | ---------------------------- method `default_hello` not found for this struct -... -LL | x.default_hello(); - | --^^^^^^^^^^^^^ - | | | - | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello` - | - = note: found the following associated functions; to be used as methods, functions must have a `self` parameter -note: the candidate is defined in an impl for the type `GenericAssocMethod` - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5 - | -LL | fn default_hello() {} - | ^^^^^^^^^^^^^^^^^^ - error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:14:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:17:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `self_ty_ref_hello` not found for this struct ... LL | x.self_ty_ref_hello(); - | --^^^^^^^^^^^^^^^^^ + | --^^^^^^^^^^^^^^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello` + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello(&x)` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `GenericAssocMethod` - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5 | -LL | fn self_ty_ref_hello(_: &T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn self_ty_ref_hello(_: &Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:19:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `self_ty_hello` not found for this struct ... LL | x.self_ty_hello(); - | --^^^^^^^^^^^^^ + | --^^^^^^^^^^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello` + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello(x)` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `GenericAssocMethod` - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:5:5 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5 | -LL | fn self_ty_hello(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | fn self_ty_hello(_: Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:23:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `default_hello` not found for this struct ... LL | y.default_hello(); - | --^^^^^^^^^^^^^ + | --^^^^^^^^^^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::::default_hello` - | - = note: found the following associated functions; to be used as methods, functions must have a `self` parameter -note: the candidate is defined in an impl for the type `GenericAssocMethod` - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5 - | -LL | fn default_hello() {} - | ^^^^^^^^^^^^^^^^^^ - -error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7 - | -LL | struct GenericAssocMethod(T); - | ---------------------------- method `self_ty_ref_hello` not found for this struct -... -LL | y.self_ty_ref_hello(); - | --^^^^^^^^^^^^^^^^^ - | | | - | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_ref_hello` + | help: use associated function syntax instead: `GenericAssocMethod::::default_hello()` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `GenericAssocMethod` --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5 | -LL | fn self_ty_ref_hello(_: &T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:25:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_ref_hello` not found for this struct +... +LL | y.self_ty_ref_hello(); + | --^^^^^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_ref_hello(&y)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5 + | +LL | fn self_ty_ref_hello(_: &Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:27:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `self_ty_hello` not found for this struct ... LL | y.self_ty_hello(); - | --^^^^^^^^^^^^^ + | --^^^^^^^^^^^^^-- | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_hello` + | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_hello(y)` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `GenericAssocMethod` - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:5:5 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5 | -LL | fn self_ty_hello(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | fn self_ty_hello(_: Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0599`. From cef19b80f7145f99d2f91818c687781a0dc4004d Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 26 Sep 2022 00:33:08 +0100 Subject: [PATCH 104/221] Split non-fixable case to different test --- ...ssoc-fn-call-with-turbofish-placeholder.rs | 11 ++++++++++ ...-fn-call-with-turbofish-placeholder.stderr | 22 +++++++++++++++++++ ...suggest-assoc-fn-call-with-turbofish.fixed | 3 --- .../suggest-assoc-fn-call-with-turbofish.rs | 3 --- ...uggest-assoc-fn-call-with-turbofish.stderr | 10 ++++----- 5 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs new file mode 100644 index 000000000000..a39b8711dd87 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs @@ -0,0 +1,11 @@ +struct GenericAssocMethod(T); + +impl GenericAssocMethod { + fn default_hello() {} +} + +fn main() { + let x = GenericAssocMethod(33); + x.default_hello(); + //~^ ERROR no method named `default_hello` found +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr new file mode 100644 index 000000000000..c247e73b39cb --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr @@ -0,0 +1,22 @@ +error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:9:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `default_hello` not found for this struct +... +LL | x.default_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:4:5 + | +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed index 0398c510feac..02dd0715c801 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed @@ -11,9 +11,6 @@ impl GenericAssocMethod { fn main() { // Test for inferred types let x = GenericAssocMethod(33); - // This particular case is unfixable without more information by the user, - // but `cargo fix --broken-code` reports a bug if - // x.default_hello(); GenericAssocMethod::<_>::self_ty_ref_hello(&x); //~^ ERROR no method named `self_ty_ref_hello` found GenericAssocMethod::<_>::self_ty_hello(x); diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs index 8bafc83bdd0b..1d0ca8e780ab 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -11,9 +11,6 @@ impl GenericAssocMethod { fn main() { // Test for inferred types let x = GenericAssocMethod(33); - // This particular case is unfixable without more information by the user, - // but `cargo fix --broken-code` reports a bug if - // x.default_hello(); x.self_ty_ref_hello(); //~^ ERROR no method named `self_ty_ref_hello` found x.self_ty_hello(); diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr index e2f2d46b9e8b..92b03fc77142 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:17:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:14:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `self_ty_ref_hello` not found for this struct @@ -18,7 +18,7 @@ LL | fn self_ty_ref_hello(_: &Self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:19:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `self_ty_hello` not found for this struct @@ -37,7 +37,7 @@ LL | fn self_ty_hello(_: Self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:23:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `default_hello` not found for this struct @@ -56,7 +56,7 @@ LL | fn default_hello() {} | ^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:25:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `self_ty_ref_hello` not found for this struct @@ -75,7 +75,7 @@ LL | fn self_ty_ref_hello(_: &Self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod` in the current scope - --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:27:7 + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7 | LL | struct GenericAssocMethod(T); | ---------------------------- method `self_ty_hello` not found for this struct From 2553a9590c5980a0013789209f928ec065e44ca6 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 26 Sep 2022 00:43:52 +0100 Subject: [PATCH 105/221] Replace boxed iterator with vec collect --- .../rustc_hir_typeck/src/method/suggest.rs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7ec3d4536606..237701b5e6fe 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -13,7 +13,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{Expr, ExprKind, Node, QPath}; +use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::{ type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, RegionVariableOrigin, @@ -475,29 +475,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut applicability = Applicability::MachineApplicable; let args = if let Some((receiver, args)) = args { // The first arg is the same kind as the receiver - let it = if first_arg.is_some() { - Box::new(std::iter::once(receiver).chain(args.iter())) - as Box>> + let explicit_args = if first_arg.is_some() { + std::iter::once(receiver).chain(args.iter()).collect::>() } else { // There is no `Self` kind to infer the arguments from if has_unsuggestable_args { applicability = Applicability::HasPlaceholders; } - Box::new(args.iter()) as _ + args.iter().collect() }; format!( "({}{})", first_arg.unwrap_or(""), - it.map(|arg| tcx - .sess - .source_map() - .span_to_snippet(arg.span) - .unwrap_or_else(|_| { - applicability = Applicability::HasPlaceholders; - "_".to_owned() - })) - .collect::>() - .join(", "), + explicit_args + .iter() + .map(|arg| tcx + .sess + .source_map() + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { + applicability = Applicability::HasPlaceholders; + "_".to_owned() + })) + .collect::>() + .join(", "), ) } else { applicability = Applicability::HasPlaceholders; From 7e38c8a750de95f66a6792c0cfe6fb25b8c5260a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 10 Oct 2022 15:08:40 +0100 Subject: [PATCH 106/221] Update UI test --- src/test/ui/suggestions/inner_type2.rs | 2 +- src/test/ui/suggestions/inner_type2.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs index c56ea7c030d8..fac68c053eb4 100644 --- a/src/test/ui/suggestions/inner_type2.rs +++ b/src/test/ui/suggestions/inner_type2.rs @@ -22,5 +22,5 @@ fn main() { let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 }); item.method(); //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599] - //~| HELP if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value + //~| HELP if this `MaybeUninit>` has been initialized, use one of the `assume_init` methods to access the inner value } diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr index eddfd9d63409..984366123c82 100644 --- a/src/test/ui/suggestions/inner_type2.stderr +++ b/src/test/ui/suggestions/inner_type2.stderr @@ -17,7 +17,7 @@ error[E0599]: no method named `method` found for union `MaybeUninit` in the curr LL | item.method(); | ^^^^^^ method not found in `MaybeUninit>` | - = help: if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value + = help: if this `MaybeUninit>` has been initialized, use one of the `assume_init` methods to access the inner value note: the method `method` exists on the type `Struct` --> $DIR/inner_type2.rs:6:5 | From ae948c63808d06d6ae5994a2c3d943dbc440c0b2 Mon Sep 17 00:00:00 2001 From: BlackHoleFox Date: Sun, 23 Oct 2022 17:22:54 -0500 Subject: [PATCH 107/221] Cleanup Apple target specifications --- .../src/spec/aarch64_apple_darwin.rs | 12 +++--- .../src/spec/aarch64_apple_ios.rs | 14 +++---- .../src/spec/aarch64_apple_ios_macabi.rs | 5 ++- .../src/spec/aarch64_apple_ios_sim.rs | 18 ++++----- .../src/spec/aarch64_apple_tvos.rs | 5 ++- .../src/spec/aarch64_apple_watchos_sim.rs | 18 ++++----- compiler/rustc_target/src/spec/apple_base.rs | 39 +++++++++++++------ .../rustc_target/src/spec/armv7_apple_ios.rs | 12 +++--- .../src/spec/armv7k_apple_watchos.rs | 6 +-- .../rustc_target/src/spec/armv7s_apple_ios.rs | 5 ++- .../rustc_target/src/spec/i386_apple_ios.rs | 15 +++---- .../src/spec/i686_apple_darwin.rs | 21 +++++----- .../src/spec/x86_64_apple_darwin.rs | 15 +++---- .../rustc_target/src/spec/x86_64_apple_ios.rs | 9 ++--- .../src/spec/x86_64_apple_ios_macabi.rs | 5 ++- .../src/spec/x86_64_apple_tvos.rs | 6 +-- .../src/spec/x86_64_apple_watchos_sim.rs | 12 ++---- 17 files changed, 108 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 13a13f2f073c..0f6bbc323174 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -12,16 +12,14 @@ pub fn target() -> Target { base.link_env_remove.to_mut().extend(macos_link_env_remove()); - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - let llvm_target = macos_llvm_target(arch.target_name()); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), frame_pointer: FramePointer::NonLeaf, diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index 1f9ac7ce59b0..b5f9eb1259da 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -2,18 +2,16 @@ use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the target to pick the right - // MACH-O commands, so we do too. let arch = Arch::Arm64; - let llvm_target = ios_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs index c2106b456bec..0009972cf425 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -4,14 +4,15 @@ use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { let llvm_target = "arm64-apple-ios14.0-macabi"; - let mut base = opts("ios", Arch::Arm64_macabi); + let arch = Arch::Arm64_macabi; + let mut base = opts("ios", arch); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]); Target { llvm_target: llvm_target.into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".into(), max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs index 097b92f2e8fd..3374755e2dd8 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -3,19 +3,15 @@ use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::Arm64_sim; - let base = opts("ios", arch); - - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - let llvm_target = ios_sim_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the simulator target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -32,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index 8cf24e4bf1f6..bb7c39ff26bd 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -2,17 +2,18 @@ use super::apple_base::{opts, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { + let arch = Arch::Arm64; Target { llvm_target: "arm64-apple-tvos".into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), forces_embed_bitcode: true, frame_pointer: FramePointer::NonLeaf, - ..opts("tvos", Arch::Arm64) + ..opts("tvos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs index b6c8cd46c050..e4af4127c222 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs @@ -3,19 +3,15 @@ use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::Arm64_sim; - let base = opts("watchos", arch); - - // Clang automatically chooses a more specific target based on - // WATCHOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - let llvm_target = watchos_sim_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // WATCHOS_DEPLOYMENT_TARGET. + // This is required for the simulator target to pick the right + // MACH-O commands, so we do too. + llvm_target: watchos_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), - arch: "aarch64".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), @@ -32,7 +28,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index eb7f457d60bc..23c826cb1bda 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -17,6 +17,7 @@ pub enum Arch { Arm64, Arm64_32, I386, + I686, X86_64, X86_64_sim, X86_64_macabi, @@ -33,13 +34,23 @@ impl Arch { Arm64 | Arm64_macabi | Arm64_sim => "arm64", Arm64_32 => "arm64_32", I386 => "i386", + I686 => "i686", X86_64 | X86_64_sim | X86_64_macabi => "x86_64", } } + pub fn target_arch(self) -> Cow<'static, str> { + Cow::Borrowed(match self { + Armv7 | Armv7k | Armv7s => "arm", + Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64", + I386 | I686 => "x86", + X86_64 | X86_64_sim | X86_64_macabi => "x86_64", + }) + } + fn target_abi(self) -> &'static str { match self { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "", + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 => "", X86_64_macabi | Arm64_macabi => "macabi", // x86_64-apple-ios is a simulator target, even though it isn't // declared that way in the target like the other ones... @@ -54,7 +65,7 @@ impl Arch { Armv7s => "cortex-a9", Arm64 => "apple-a7", Arm64_32 => "apple-s4", - I386 => "yonah", + I386 | I686 => "yonah", X86_64 | X86_64_sim => "core2", X86_64_macabi => "core2", Arm64_macabi => "apple-a12", @@ -64,7 +75,8 @@ impl Arch { fn link_env_remove(self) -> StaticCow<[StaticCow]> { match self { - Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | X86_64_sim | Arm64_sim => { + Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim + | Arm64_sim => { cvs!["MACOSX_DEPLOYMENT_TARGET"] } X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], @@ -72,7 +84,7 @@ impl Arch { } } -fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs { +fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { let platform_name: StaticCow = match abi { "sim" => format!("{}-simulator", os).into(), "macabi" => "mac-catalyst".into(), @@ -88,6 +100,8 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin } .into(); + let arch = arch.target_name(); + let mut args = TargetOptions::link_args( LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch, "-platform_version"], @@ -118,7 +132,7 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { // TLS is flagged as enabled if it looks to be supported. The architecture // only matters for default deployment target which is 11.0 for ARM64 and // 10.7 for everything else. - let has_thread_local = os == "macos" && macos_deployment_target("x86_64") >= (10, 7); + let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7); let abi = arch.target_abi(); @@ -132,7 +146,7 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { // macOS has -dead_strip, which doesn't rely on function_sections function_sections: false, dynamic_linking: true, - pre_link_args: pre_link_args(os, arch.target_name(), abi), + pre_link_args: pre_link_args(os, arch, abi), families: cvs!["unix"], is_like_osx: true, default_dwarf_version: 2, @@ -177,23 +191,24 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> { .and_then(|(a, b)| a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok()) } -fn macos_default_deployment_target(arch: &str) -> (u32, u32) { - if arch == "arm64" { (11, 0) } else { (10, 7) } +fn macos_default_deployment_target(arch: Arch) -> (u32, u32) { + // Note: Arm64_sim is not included since macOS has no simulator. + if matches!(arch, Arm64 | Arm64_macabi) { (11, 0) } else { (10, 7) } } -fn macos_deployment_target(arch: &str) -> (u32, u32) { +fn macos_deployment_target(arch: Arch) -> (u32, u32) { deployment_target("MACOSX_DEPLOYMENT_TARGET") .unwrap_or_else(|| macos_default_deployment_target(arch)) } -fn macos_lld_platform_version(arch: &str) -> String { +fn macos_lld_platform_version(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); format!("{}.{}", major, minor) } -pub fn macos_llvm_target(arch: &str) -> String { +pub fn macos_llvm_target(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); - format!("{}-apple-macosx{}.{}.0", arch, major, minor) + format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor) } pub fn macos_link_env_remove() -> Vec> { diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs index 5167af3e7f22..3259c854791c 100644 --- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs @@ -1,15 +1,17 @@ -use super::apple_base::{opts, Arch}; +use super::apple_base::{ios_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::Armv7; - let llvm_target = super::apple_base::ios_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_llvm_target(arch).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp3,+neon".into(), max_atomic_width: Some(64), diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs index 7e9c9b5c2687..45ead8d65aba 100644 --- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs @@ -2,12 +2,12 @@ use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = opts("watchos", Arch::Armv7k); + let arch = Arch::Armv7k; Target { llvm_target: "armv7k-apple-watchos".into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), @@ -22,7 +22,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs index 30851564523b..be4bc6758443 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs @@ -2,15 +2,16 @@ use super::apple_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { + let arch = Arch::Armv7s; Target { llvm_target: "armv7s-apple-ios".into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), - arch: "arm".into(), + arch: arch.target_arch(), options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", Arch::Armv7s) + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs index 21635642c18a..5819981612e8 100644 --- a/compiler/rustc_target/src/spec/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs @@ -1,22 +1,23 @@ -use super::apple_base::{opts, Arch}; +use super::apple_base::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::I386; - let base = opts("ios", arch); - let llvm_target = super::apple_base::ios_sim_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // IPHONEOS_DEPLOYMENT_TARGET. + // This is required for the target to pick the right + // MACH-O commands, so we do too. + llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: "x86".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 84dae68877df..8b968af5eccf 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -2,28 +2,27 @@ use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - // ld64 only understand i386 and not i686 - let mut base = opts("macos", Arch::I386); - base.cpu = "yonah".into(); + // ld64 only understands i386 and not i686 + let arch = Arch::I386; + let mut base = opts("macos", arch); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); base.link_env_remove.to_mut().extend(macos_link_env_remove()); base.stack_probes = StackProbeType::X86; base.frame_pointer = FramePointer::Always; - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - let arch = "i686"; - let llvm_target = macos_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + // + // While ld64 doesn't understand i686, LLVM does. + llvm_target: macos_llvm_target(Arch::I686).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: "x86".into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index 6112ef7ec1f9..c053031612ce 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -5,8 +5,7 @@ use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::X86_64; let mut base = opts("macos", arch); - base.cpu = "core2".into(); - base.max_atomic_width = Some(128); // core2 support cmpxchg16b + base.max_atomic_width = Some(128); // core2 supports cmpxchg16b base.frame_pointer = FramePointer::Always; base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); base.link_env_remove.to_mut().extend(macos_link_env_remove()); @@ -14,17 +13,15 @@ pub fn target() -> Target { base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - let llvm_target = macos_llvm_target(arch.target_name()); - Target { - llvm_target: llvm_target.into(), + // Clang automatically chooses a more specific target based on + // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work + // correctly, we do too. + llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_84".into(), + arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs index 032ba0763b4c..fbd3ebd4d043 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs @@ -3,19 +3,16 @@ use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::X86_64_sim; - let base = opts("ios", arch); - let llvm_target = ios_sim_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("ios", arch) }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs index 6647c1d29217..0f3f85199637 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs @@ -4,7 +4,8 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let llvm_target = "x86_64-apple-ios13.0-macabi"; - let mut base = opts("ios", Arch::X86_64_macabi); + let arch = Arch::X86_64_macabi; + let mut base = opts("ios", arch); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]); Target { @@ -12,7 +13,7 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs index cb70717b3c42..550ce0b9ce57 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs @@ -2,16 +2,16 @@ use super::apple_base::{opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("tvos", Arch::X86_64_sim); + let arch = Arch::X86_64_sim; Target { llvm_target: "x86_64-apple-tvos".into(), pointer_width: 64, data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..base + ..opts("tvos", arch) }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs index 03ea66499db1..75ce02cba1de 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs @@ -1,18 +1,14 @@ -use super::apple_base::{opts, Arch}; +use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::X86_64_sim; - let base = opts("watchos", Arch::X86_64_sim); - - let llvm_target = super::apple_base::watchos_sim_llvm_target(arch); - Target { - llvm_target: llvm_target.into(), + llvm_target: watchos_sim_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_64".into(), + arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, @@ -28,7 +24,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..base + ..opts("watchos", arch) }, } } From 7df4b0b66252748108b5d7edee27ee5776222f64 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 5 Nov 2022 23:06:58 +0000 Subject: [PATCH 108/221] Rebase and update test --- compiler/rustc_hir_typeck/src/method/suggest.rs | 4 ++-- src/test/ui/suggestions/issue-102354.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 237701b5e6fe..22007d5eb683 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -399,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if static_candidates.len() == 1 { let mut has_unsuggestable_args = false; let ty_str = if let Some(CandidateSource::Impl(impl_did)) = - static_candidates.get(0) + static_candidates.get(0) { // When the "method" is resolved through dereferencing, we really want the // original type that has the associated function for accurate suggestions. @@ -453,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.ty_to_value_string(actual.peel_refs()) }; if let SelfSource::MethodCall(_) = source { - let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) && + let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) && let Some(assoc) = self.associated_value(*impl_did, item_name) { let sig = self.tcx.fn_sig(assoc.def_id); if let Some(first) = sig.inputs().skip_binder().get(0) { diff --git a/src/test/ui/suggestions/issue-102354.stderr b/src/test/ui/suggestions/issue-102354.stderr index 4f76c5f2e75b..b17c4dc5dfb5 100644 --- a/src/test/ui/suggestions/issue-102354.stderr +++ b/src/test/ui/suggestions/issue-102354.stderr @@ -13,7 +13,7 @@ LL | fn func() {} help: use associated function syntax instead | LL | i32::func(); - | ~~~~~~~~~ + | ~~~~~~~~~~~ help: disambiguate the associated function for the candidate | LL | ::func(x); From e410cd25b2fc8180cd16b908c331363f8f81c803 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 5 Nov 2022 16:55:40 -0700 Subject: [PATCH 109/221] rustdoc: print usize with less string manipulation --- src/librustdoc/clean/utils.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 4e1f39cf87b9..e3df367774be 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -242,19 +242,13 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { s } - _ => { - let mut s = n.to_string(); - // array lengths are obviously usize - if s.ends_with("_usize") { - let n = s.len() - "_usize".len(); - s.truncate(n); - if s.ends_with(": ") { - let n = s.len() - ": ".len(); - s.truncate(n); - } - } - s + // array lengths are obviously usize + ty::ConstKind::Value(ty::ValTree::Leaf(scalar)) + if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) => + { + scalar.to_string() } + _ => n.to_string(), } } From 84fe2ee9d24cd2b8a44e15ae3214c302e4c3117f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 6 Nov 2022 01:22:31 +0100 Subject: [PATCH 110/221] Add more nonsense to weird-exprs.rs. --- src/test/ui/weird-exprs.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/ui/weird-exprs.rs b/src/test/ui/weird-exprs.rs index 4066bcf3badd..d65703ef5cae 100644 --- a/src/test/ui/weird-exprs.rs +++ b/src/test/ui/weird-exprs.rs @@ -8,6 +8,7 @@ #![allow(unreachable_code)] #![allow(unused_braces, unused_must_use, unused_parens)] #![allow(uncommon_codepoints, confusable_idents)] +#![allow(unreachable_patterns)] #![recursion_limit = "256"] @@ -194,6 +195,15 @@ fn bathroom_stall() { assert_eq!(i, 13); } +fn closure_matching() { + let x = |_| Some(1); + let (|x| x) = match x(..) { + |_| Some(2) => |_| Some(3), + |_| _ => unreachable!(), + }; + assert!(matches!(x(..), |_| Some(4))); +} + pub fn main() { strange(); funny(); @@ -216,4 +226,5 @@ pub fn main() { 𝚌𝚘𝚗𝚝𝚒𝚗𝚞𝚎(); function(); bathroom_stall(); + closure_matching(); } From 9a1043eac7dbd7177ce032c0f777b5ee2f636621 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Nov 2022 01:59:03 +0000 Subject: [PATCH 111/221] Normalize signature when deducing closure signature from supertraits --- compiler/rustc_hir_typeck/src/closure.rs | 10 +++++++--- .../supertrait-hint-references-assoc-ty.rs | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/closures/supertrait-hint-references-assoc-ty.rs diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 09df50c76b73..3001e7994767 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -10,6 +10,7 @@ use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; +use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty}; @@ -22,7 +23,7 @@ use std::cmp; use std::iter; /// What signature do we *expect* the closure to have from context? -#[derive(Debug)] +#[derive(Debug, Clone, TypeFoldable, TypeVisitable)] struct ExpectedSig<'tcx> { /// Span that gave us this expectation, if we know that. cause_span: Option, @@ -241,9 +242,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if expected_sig.is_none() && let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() { - expected_sig = self.deduce_sig_from_projection( + expected_sig = self.normalize_associated_types_in( + obligation.cause.span, + self.deduce_sig_from_projection( Some(obligation.cause.span), - bound_predicate.rebind(proj_predicate), + bound_predicate.rebind(proj_predicate), + ), ); } diff --git a/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs b/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs new file mode 100644 index 000000000000..270bf14c35ec --- /dev/null +++ b/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs @@ -0,0 +1,17 @@ +// check-pass + +pub trait Fn0: Fn(i32) -> Self::Out { + type Out; +} + +impl ()> Fn0 for F { + type Out = (); +} + +pub fn closure_typer(_: impl Fn0) {} + +fn main() { + closure_typer(move |x| { + let _: i64 = x.into(); + }); +} From 28d82ddfc22bcbcef2ade0a3c75e6711475a9098 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 5 Nov 2022 19:33:12 -0700 Subject: [PATCH 112/221] Fix typo --- compiler/rustc_parse/src/parser/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 338e6a8e2895..4a1162b95998 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2880,7 +2880,7 @@ impl<'a> Parser<'a> { }; while self.token != token::CloseDelim(close_delim) { - if self.eat(&token::DotDot) || self.recover_struct_fileds_dots(close_delim) { + if self.eat(&token::DotDot) || self.recover_struct_field_dots(close_delim) { let exp_span = self.prev_token.span; // We permit `.. }` on the left-hand side of a destructuring assignment. if self.check(&token::CloseDelim(close_delim)) { @@ -3027,7 +3027,7 @@ impl<'a> Parser<'a> { self.recover_stmt(); } - fn recover_struct_fileds_dots(&mut self, close_delim: Delimiter) -> bool { + fn recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool { if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim)) && self.eat(&token::DotDotDot) { From bc345d7bd0c1d7ff7608bff504255842467c3d3c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Nov 2022 01:34:17 +0000 Subject: [PATCH 113/221] Move fallback_has_occurred to FnCtxt --- .../src/region_infer/opaque_types.rs | 2 +- .../src/transform/check_consts/check.rs | 3 +-- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_method.rs | 10 +++---- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/coherence/builtin.rs | 4 +-- .../src/impl_wf_check/min_specialization.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 4 +-- compiler/rustc_hir_typeck/src/coercion.rs | 7 +---- compiler/rustc_hir_typeck/src/expr.rs | 4 +-- compiler/rustc_hir_typeck/src/fallback.rs | 26 +++++++++---------- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 13 +++------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 9 ++++++- compiler/rustc_hir_typeck/src/lib.rs | 4 +-- compiler/rustc_hir_typeck/src/op.rs | 2 +- .../src/infer/error_reporting/mod.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 4 +-- .../src/traits/error_reporting/mod.rs | 11 ++------ .../rustc_trait_selection/src/traits/misc.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- 21 files changed, 52 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 95ea42b584a3..103c7ed8ef70 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -299,7 +299,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { if errors.is_empty() { definition_ty } else { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); self.tcx.ty_error() } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index b1ad22b899e3..5a8b3e30b9fc 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -765,7 +765,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } } @@ -831,7 +831,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { obligation.clone(), &obligation, &e, - false, ); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 133bbd52b914..3170f8feffc6 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -471,7 +471,7 @@ fn check_opaque_meets_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } match origin { // Checked when type checking the function containing them. diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index c6b497e9b9fc..0e8ac17fb71b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -405,7 +405,7 @@ fn compare_predicate_entailment<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } @@ -538,7 +538,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( // RPITs. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } @@ -1431,7 +1431,7 @@ pub(crate) fn raw_compare_const_impl<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None, false)); + return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None)); } // FIXME return `ErrorReported` if region obligations error? @@ -1549,7 +1549,7 @@ fn compare_type_predicate_entailment<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } @@ -1769,7 +1769,7 @@ pub fn check_type_bounds<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0117bdd0ba81..64e4b3267d2b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -104,7 +104,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( f(&mut wfcx); let errors = wfcx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); return; } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index b6c91d425dff..6f74ef3ccad6 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -321,7 +321,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: }), ); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. @@ -561,7 +561,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]); let errors = traits::fully_solve_obligation(&infcx, predicate); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } // Finally, resolve all regions. diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index e806e94879d9..267077cdab4e 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -155,7 +155,7 @@ fn get_impl_substs<'tcx>( let errors = ocx.select_all_or_error(); if !errors.is_empty() { - ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None); return None; } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index bd1a461b9352..664d3a3a1db8 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -173,7 +173,7 @@ fn require_same_types<'tcx>( match &errors[..] { [] => true, errors => { - infcx.err_ctxt().report_fulfillment_errors(errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(errors, None); false } } @@ -336,7 +336,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ocx.register_bound(cause, param_env, norm_return_ty, term_did); let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); error = true; } // now we can take the return type of the given main function diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index e8bf299b0378..25306ebf3567 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -705,12 +705,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Object safety violations or miscellaneous. Err(err) => { - self.err_ctxt().report_selection_error( - obligation.clone(), - &obligation, - &err, - false, - ); + self.err_ctxt().report_selection_error(obligation.clone(), &obligation, &err); // Treat this like an obligation and follow through // with the unsizing - the lack of a coercion should // be silent, as it causes a type mismatch later. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 682dbab56bc1..89b5e5161a9c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -843,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // Point any obligations that were registered due to opaque type // inference at the return expression. - self.select_obligations_where_possible(false, |errors| { + self.select_obligations_where_possible(|errors| { self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty); }); } @@ -2738,7 +2738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some((index_ty, element_ty)) => { // two-phase not needed because index_ty is never mutable self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); - self.select_obligations_where_possible(false, |errors| { + self.select_obligations_where_possible(|errors| { self.point_at_index_if_possible(errors, idx.span) }); element_ty diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 747ecb036b2a..5d44092a5f68 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -7,16 +7,16 @@ use rustc_data_structures::{ use rustc_middle::ty::{self, Ty}; impl<'tcx> FnCtxt<'_, 'tcx> { - /// Performs type inference fallback, returning true if any fallback - /// occurs. - pub(super) fn type_inference_fallback(&self) -> bool { + /// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred` + /// if fallback has occurred. + pub(super) fn type_inference_fallback(&self) { debug!( "type-inference-fallback start obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations() ); // All type checking constraints were added, try to fallback unsolved variables. - self.select_obligations_where_possible(false, |_| {}); + self.select_obligations_where_possible(|_| {}); debug!( "type-inference-fallback post selection obligations: {:#?}", @@ -26,18 +26,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // Check if we have any unsolved variables. If not, no need for fallback. let unsolved_variables = self.unsolved_variables(); if unsolved_variables.is_empty() { - return false; + return; } let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables); - let mut fallback_has_occurred = false; // We do fallback in two passes, to try to generate // better error messages. // The first time, we do *not* replace opaque types. for ty in unsolved_variables { debug!("unsolved_variable = {:?}", ty); - fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback); + self.fallback_if_possible(ty, &diverging_fallback); } // We now see if we can make progress. This might cause us to @@ -63,9 +62,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // If we had tried to fallback the opaque inference variable to `MyType`, // we will generate a confusing type-check error that does not explicitly // refer to opaque types. - self.select_obligations_where_possible(fallback_has_occurred, |_| {}); - - fallback_has_occurred + self.select_obligations_where_possible(|_| {}); } // Tries to apply a fallback to `ty` if it is an unsolved variable. @@ -81,12 +78,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // Fallback becomes very dubious if we have encountered // type-checking errors. In that case, fallback to Error. // - // The return value indicates whether fallback has occurred. + // Sets `FnCtxt::fallback_has_occurred` if fallback is performed + // during this call. fn fallback_if_possible( &self, ty: Ty<'tcx>, diverging_fallback: &FxHashMap, Ty<'tcx>>, - ) -> bool { + ) { // Careful: we do NOT shallow-resolve `ty`. We know that `ty` // is an unsolved variable, and we determine its fallback // based solely on how it was created, not what other type @@ -111,7 +109,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64, _ => match diverging_fallback.get(&ty) { Some(&fallback_ty) => fallback_ty, - None => return false, + None => return, }, }; debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback); @@ -122,7 +120,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .map(|origin| origin.span) .unwrap_or(rustc_span::DUMMY_SP); self.demand_eqtype(span, ty, fallback); - true + self.fallback_has_occurred.set(true); } /// The "diverging fallback" system is rather complicated. This is diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 7563c543d3f1..35323137e2d5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // possible. This can help substantially when there are // indirect dependencies that don't seem worth tracking // precisely. - self.select_obligations_where_possible(false, mutate_fulfillment_errors); + self.select_obligations_where_possible(mutate_fulfillment_errors); self.resolve_vars_if_possible(ty) } @@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) { let mut generators = self.deferred_generator_interiors.borrow_mut(); for (body_id, interior, kind) in generators.drain(..) { - self.select_obligations_where_possible(false, |_| {}); + self.select_obligations_where_possible(|_| {}); crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind); } } @@ -611,25 +611,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !errors.is_empty() { self.adjust_fulfillment_errors_for_expr_obligation(&mut errors); - self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id, false); + self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id); } } /// Select as many obligations as we can at present. pub(in super::super) fn select_obligations_where_possible( &self, - fallback_has_occurred: bool, mutate_fulfillment_errors: impl Fn(&mut Vec>), ) { let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self); if !result.is_empty() { mutate_fulfillment_errors(&mut result); self.adjust_fulfillment_errors_for_expr_obligation(&mut result); - self.err_ctxt().report_fulfillment_errors( - &result, - self.inh.body_id, - fallback_has_occurred, - ); + self.err_ctxt().report_fulfillment_errors(&result, self.inh.body_id); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e1955d838f25..62347f3d7e0f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -344,7 +344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // an "opportunistic" trait resolution of any trait bounds on // the call. This helps coercions. if check_closures { - self.select_obligations_where_possible(false, |_| {}) + self.select_obligations_where_possible(|_| {}) } // Check each argument, to satisfy the input it was provided for diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 72388baa261e..75984243aa73 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -115,6 +115,8 @@ pub struct FnCtxt<'a, 'tcx> { pub(super) enclosing_breakables: RefCell>, pub(super) inh: &'a Inherited<'tcx>, + + pub(super) fallback_has_occurred: Cell, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -138,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { by_id: Default::default(), }), inh, + fallback_has_occurred: Cell::new(false), } } @@ -159,7 +162,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { - TypeErrCtxt { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()) } + TypeErrCtxt { + infcx: &self.infcx, + typeck_results: Some(self.typeck_results.borrow()), + fallback_has_occurred: self.fallback_has_occurred.get(), + } } pub fn errors_reported_since_creation(&self) -> bool { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index d1762598a520..0bfbd98bab2d 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -316,12 +316,12 @@ fn typeck_with_fallback<'tcx>( fcx }; - let fallback_has_occurred = fcx.type_inference_fallback(); + fcx.type_inference_fallback(); // Even though coercion casts provide type hints, we check casts after fallback for // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. fcx.check_casts(); - fcx.select_obligations_where_possible(fallback_has_occurred, |_| {}); + fcx.select_obligations_where_possible(|_| {}); // Closure and generator analysis may run after fallback // because they don't constrain other type variables. diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 8598369e884b..c3bcbcc993b7 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -772,7 +772,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match (method, trait_did) { (Some(ok), _) => { let method = self.register_infer_ok_obligations(ok); - self.select_obligations_where_possible(false, |_| {}); + self.select_obligations_where_possible(|_| {}); Ok(method) } (None, None) => Err(vec![]), diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 9ff703e521ff..12ea05480ca4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -91,6 +91,7 @@ pub mod nice_region_error; pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub typeck_results: Option>>, + pub fallback_has_occurred: bool, } impl TypeErrCtxt<'_, '_> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c2eecd9e87a3..d5be9983ea7c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -677,9 +677,9 @@ pub struct CombinedSnapshot<'tcx> { impl<'tcx> InferCtxt<'tcx> { /// Creates a `TypeErrCtxt` for emitting various inference errors. - /// During typeck, use `FnCtxt::infer_err` instead. + /// During typeck, use `FnCtxt::err_ctxt` instead. pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { - TypeErrCtxt { infcx: self, typeck_results: None } + TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false } } /// calls `tcx.try_unify_abstract_consts` after 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 dacce5cd2f60..fc1d0c760e9a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -101,7 +101,6 @@ pub trait TypeErrCtxtExt<'tcx> { &self, errors: &[FulfillmentError<'tcx>], body_id: Option, - fallback_has_occurred: bool, ) -> ErrorGuaranteed; fn report_overflow_error( @@ -124,7 +123,6 @@ pub trait TypeErrCtxtExt<'tcx> { obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - fallback_has_occurred: bool, ); } @@ -375,7 +373,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, errors: &[FulfillmentError<'tcx>], body_id: Option, - fallback_has_occurred: bool, ) -> ErrorGuaranteed { #[derive(Debug)] struct ErrorDescriptor<'tcx> { @@ -452,7 +449,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { for (error, suppressed) in iter::zip(errors, is_suppressed) { if !suppressed { - self.report_fulfillment_error(error, body_id, fallback_has_occurred); + self.report_fulfillment_error(error, body_id); } } @@ -534,7 +531,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { mut obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - fallback_has_occurred: bool, ) { self.set_tainted_by_errors(); let tcx = self.tcx; @@ -1000,7 +996,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // variable that used to fallback to `()` now falling back to `!`. Issue a // note informing about the change in behaviour. if trait_predicate.skip_binder().self_ty().is_never() - && fallback_has_occurred + && self.fallback_has_occurred { let predicate = trait_predicate.map_bound(|mut trait_pred| { trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( @@ -1366,7 +1362,6 @@ trait InferCtxtPrivExt<'tcx> { &self, error: &FulfillmentError<'tcx>, body_id: Option, - fallback_has_occurred: bool, ); fn report_projection_error( @@ -1516,7 +1511,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, error: &FulfillmentError<'tcx>, body_id: Option, - fallback_has_occurred: bool, ) { match error.code { FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { @@ -1524,7 +1518,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { error.obligation.clone(), &error.root_obligation, selection_error, - fallback_has_occurred, ); } FulfillmentErrorCode::CodeProjectionError(ref e) => { diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index be603c609cb3..b6ded4ce5a39 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -70,7 +70,7 @@ pub fn can_type_implement_copy<'tcx>( } } Err(errors) => { - infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + infcx.err_ctxt().report_fulfillment_errors(&errors, None); } }; } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 9ee6e0a2bf3a..bdcb2321d4ff 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -238,7 +238,7 @@ fn do_normalize_predicates<'tcx>( let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) { Ok(predicates) => predicates, Err(errors) => { - let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false); + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); return Err(reported); } }; From 299bc61035466b3e6ce0af78d19996a5eef6e294 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sun, 6 Nov 2022 14:01:46 +0530 Subject: [PATCH 114/221] Add type_array to BaseTypeMethods Moved type_array function to rustc_codegen_ssa::BaseTypeMethods trait. This allows using normal alloca function to create arrays as suggested in https://github.com/rust-lang/rust/pull/104022. Signed-off-by: Ayush Singh --- compiler/rustc_codegen_gcc/src/type_.rs | 42 +++++++++---------- compiler/rustc_codegen_llvm/src/type_.rs | 8 ++-- .../rustc_codegen_ssa/src/traits/type_.rs | 1 + 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 68bdb8d4e55f..862ed62c68b2 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -201,6 +201,27 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> { value.get_type() } + + fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> { + if let Some(struct_type) = ty.is_struct() { + if struct_type.get_field_count() == 0 { + // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a + // size of usize::MAX in test_binary_search, we workaround this by setting the size to + // zero for ZSTs. + // FIXME(antoyo): fix gccjit API. + len = 0; + } + } + + // NOTE: see note above. Some other test uses usize::MAX. + if len == u64::MAX { + len = 0; + } + + let len: i32 = len.try_into().expect("array len"); + + self.context.new_array_type(None, ty, len) + } } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -227,27 +248,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.context.new_opaque_struct_type(None, name) } - pub fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> { - if let Some(struct_type) = ty.is_struct() { - if struct_type.get_field_count() == 0 { - // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a - // size of usize::MAX in test_binary_search, we workaround this by setting the size to - // zero for ZSTs. - // FIXME(antoyo): fix gccjit API. - len = 0; - } - } - - // NOTE: see note above. Some other test uses usize::MAX. - if len == u64::MAX { - len = 0; - } - - let len: i32 = len.try_into().expect("array len"); - - self.context.new_array_type(None, ty, len) - } - pub fn type_bool(&self) -> Type<'gcc> { self.context.new_type::() } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index eeb38d4ecf59..5eec7dc61302 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -127,10 +127,6 @@ impl<'ll> CodegenCx<'ll, '_> { pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) } } - - pub(crate) fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { - unsafe { llvm::LLVMRustArrayType(ty, len) } - } } impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -231,6 +227,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn val_ty(&self, v: &'ll Value) -> &'ll Type { common::val_ty(v) } + + fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { + unsafe { llvm::LLVMRustArrayType(ty, len) } + } } impl Type { diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index bdc6a91cf6ab..86481d5d758d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -22,6 +22,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_f32(&self) -> Self::Type; fn type_f64(&self) -> Self::Type; + fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type; fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type; fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type; fn type_kind(&self, ty: Self::Type) -> TypeKind; From df3187260fdcd71d46da7b02b1a1488ae939abbd Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:20:38 +0100 Subject: [PATCH 115/221] Remove one lifetime from `QueryKeyStringBuilder` --- .../rustc_query_impl/src/profiling_support.rs | 51 ++++++------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 2cc311d48c8f..81114f2cd82c 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -19,18 +19,18 @@ impl QueryKeyStringCache { } } -struct QueryKeyStringBuilder<'p, 'c, 'tcx> { +struct QueryKeyStringBuilder<'p, 'tcx> { profiler: &'p SelfProfiler, tcx: TyCtxt<'tcx>, - string_cache: &'c mut QueryKeyStringCache, + string_cache: &'p mut QueryKeyStringCache, } -impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { +impl<'p, 'tcx> QueryKeyStringBuilder<'p, 'tcx> { fn new( profiler: &'p SelfProfiler, tcx: TyCtxt<'tcx>, - string_cache: &'c mut QueryKeyStringCache, - ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> { + string_cache: &'p mut QueryKeyStringCache, + ) -> QueryKeyStringBuilder<'p, 'tcx> { QueryKeyStringBuilder { profiler, tcx, string_cache } } @@ -99,7 +99,7 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { } trait IntoSelfProfilingString { - fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId; + fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId; } // The default implementation of `IntoSelfProfilingString` just uses `Debug` @@ -109,7 +109,7 @@ trait IntoSelfProfilingString { impl IntoSelfProfilingString for T { default fn to_self_profile_string( &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, + builder: &mut QueryKeyStringBuilder<'_, '_>, ) -> StringId { let s = format!("{:?}", self); builder.profiler.alloc_string(&s[..]) @@ -117,60 +117,42 @@ impl IntoSelfProfilingString for T { } impl IntoSelfProfilingString for T { - fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId { + fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { self.spec_to_self_profile_string(builder) } } #[rustc_specialization_trait] trait SpecIntoSelfProfilingString: Debug { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId; + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId; } impl SpecIntoSelfProfilingString for DefId { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(*self) } } impl SpecIntoSelfProfilingString for CrateNum { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(self.as_def_id()) } } impl SpecIntoSelfProfilingString for DefIndex { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self }) } } impl SpecIntoSelfProfilingString for LocalDefId { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index }) } } impl SpecIntoSelfProfilingString for WithOptConstParam { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { // We print `WithOptConstParam` values as tuples to make them shorter // and more readable, without losing information: // @@ -205,10 +187,7 @@ where T0: SpecIntoSelfProfilingString, T1: SpecIntoSelfProfilingString, { - fn spec_to_self_profile_string( - &self, - builder: &mut QueryKeyStringBuilder<'_, '_, '_>, - ) -> StringId { + fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId { let val0 = self.0.to_self_profile_string(builder); let val1 = self.1.to_self_profile_string(builder); From 3da576804af9c1fb141c94d28efc63919200e046 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:26:41 +0100 Subject: [PATCH 116/221] Rename `incremental_verify_ich_cold` to `incremental_verify_ich_failed` --- .../rustc_query_system/src/query/plumbing.rs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 0f7abe84231b..f2abbdae5837 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -585,7 +585,11 @@ fn incremental_verify_ich( debug!("END verify_ich({:?})", dep_node); if Some(new_hash) != old_hash { - incremental_verify_ich_cold(tcx.sess(), DebugArg::from(&dep_node), DebugArg::from(&result)); + incremental_verify_ich_failed( + tcx.sess(), + DebugArg::from(&dep_node), + DebugArg::from(&result), + ); } } @@ -631,13 +635,7 @@ impl std::fmt::Debug for DebugArg<'_> { // different implementations for LLVM to chew on (and filling up the final // binary, too). #[cold] -fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: DebugArg<'_>) { - let run_cmd = if let Some(crate_name) = &sess.opts.crate_name { - format!("`cargo clean -p {}` or `cargo clean`", crate_name) - } else { - "`cargo clean`".to_string() - }; - +fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: DebugArg<'_>) { // When we emit an error message and panic, we try to debug-print the `DepNode` // and query result. Unfortunately, this can cause us to run additional queries, // which may result in another fingerprint mismatch while we're in the middle @@ -653,6 +651,12 @@ fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: D if old_in_panic { sess.emit_err(crate::error::Reentrant); } else { + let run_cmd = if let Some(crate_name) = &sess.opts.crate_name { + format!("`cargo clean -p {}` or `cargo clean`", crate_name) + } else { + "`cargo clean`".to_string() + }; + sess.emit_err(crate::error::IncrementCompilation { run_cmd, dep_node: format!("{:?}", dep_node), From 91971f293cba3bcbe20bb93236254cc1550e1049 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:40:42 +0100 Subject: [PATCH 117/221] Improve tracing logging --- .../rustc_query_system/src/dep_graph/graph.rs | 53 +++++-------------- .../rustc_query_system/src/dep_graph/mod.rs | 3 +- .../rustc_query_system/src/query/plumbing.rs | 4 +- 3 files changed, 17 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 8ff56132749d..7109c1ac9a20 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -598,6 +598,7 @@ impl DepGraph { } } + #[instrument(skip(self, tcx, data, parent_dep_node_index), level = "debug")] fn try_mark_parent_green>( &self, tcx: Ctxt, @@ -613,11 +614,7 @@ impl DepGraph { // This dependency has been marked as green before, we are // still fine and can continue with checking the other // dependencies. - debug!( - "try_mark_previous_green({:?}) --- found dependency {:?} to \ - be immediately green", - dep_node, dep_dep_node, - ); + debug!("dependency {dep_dep_node:?} was immediately green"); return Some(()); } Some(DepNodeColor::Red) => { @@ -625,10 +622,7 @@ impl DepGraph { // compared to the previous compilation session. We cannot // mark the DepNode as green and also don't need to bother // with checking any of the other dependencies. - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} was immediately red", - dep_node, dep_dep_node, - ); + debug!("dependency {dep_dep_node:?} was immediately red"); return None; } None => {} @@ -638,33 +632,24 @@ impl DepGraph { // an eval_always node, let's try to mark it green recursively. if !tcx.dep_context().is_eval_always(dep_dep_node.kind) { debug!( - "try_mark_previous_green({:?}) --- state of dependency {:?} ({}) \ - is unknown, trying to mark it green", - dep_node, dep_dep_node, dep_dep_node.hash, + "state of dependency {:?} ({}) is unknown, trying to mark it green", + dep_dep_node, dep_dep_node.hash, ); let node_index = self.try_mark_previous_green(tcx, data, parent_dep_node_index, dep_dep_node); + if node_index.is_some() { - debug!( - "try_mark_previous_green({:?}) --- managed to MARK dependency {:?} as green", - dep_node, dep_dep_node - ); + debug!("managed to MARK dependency {dep_dep_node:?} as green",); return Some(()); } } // We failed to mark it green, so we try to force the query. - debug!( - "try_mark_previous_green({:?}) --- trying to force dependency {:?}", - dep_node, dep_dep_node - ); + debug!("trying to force dependency {dep_dep_node:?}"); if !tcx.dep_context().try_force_from_dep_node(*dep_dep_node) { // The DepNode could not be forced. - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} could not be forced", - dep_node, dep_dep_node - ); + debug!("dependency {dep_dep_node:?} could not be forced"); return None; } @@ -672,17 +657,11 @@ impl DepGraph { match dep_dep_node_color { Some(DepNodeColor::Green(_)) => { - debug!( - "try_mark_previous_green({:?}) --- managed to FORCE dependency {:?} to green", - dep_node, dep_dep_node - ); + debug!("managed to FORCE dependency {dep_dep_node:?} to green"); return Some(()); } Some(DepNodeColor::Red) => { - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} was red after forcing", - dep_node, dep_dep_node - ); + debug!("dependency {dep_dep_node:?} was red after forcing",); return None; } None => {} @@ -702,14 +681,12 @@ impl DepGraph { // invalid state will not be persisted to the // incremental compilation cache because of // compilation errors being present. - debug!( - "try_mark_previous_green({:?}) - END - dependency {:?} resulted in compilation error", - dep_node, dep_dep_node - ); + debug!("dependency {dep_dep_node:?} resulted in compilation error",); return None; } /// Try to mark a dep-node which existed in the previous compilation session as green. + #[instrument(skip(self, tcx, data, prev_dep_node_index), level = "debug")] fn try_mark_previous_green>( &self, tcx: Ctxt, @@ -717,8 +694,6 @@ impl DepGraph { prev_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode, ) -> Option { - debug!("try_mark_previous_green({:?}) - BEGIN", dep_node); - #[cfg(not(parallel_compiler))] { debug_assert!(!self.dep_node_exists(dep_node)); @@ -772,7 +747,7 @@ impl DepGraph { // Multiple threads can all write the same color here data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index)); - debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node); + debug!("successfully marked {dep_node:?} as green"); Some(dep_node_index) } diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index da2075fd5aad..e370c6990a41 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -52,9 +52,8 @@ pub trait DepContext: Copy { } /// Try to force a dep node to execute and see if it's green. + #[instrument(skip(self), level = "debug")] fn try_force_from_dep_node(self, dep_node: DepNode) -> bool { - debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); - let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { f(self, dep_node); diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index f2abbdae5837..e9972a542094 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -563,6 +563,7 @@ where Some((result, dep_node_index)) } +#[instrument(skip(tcx, result, query), level = "debug")] fn incremental_verify_ich( tcx: CTX::DepContext, result: &V, @@ -577,12 +578,11 @@ fn incremental_verify_ich( dep_node, ); - debug!("BEGIN verify_ich({:?})", dep_node); let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| { tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) }); + let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); - debug!("END verify_ich({:?})", dep_node); if Some(new_hash) != old_hash { incremental_verify_ich_failed( From 16558bd26740085c5ae3dd27ae1d01cc39d18f2f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 20:58:10 +0100 Subject: [PATCH 118/221] Rename `tcx` to `qcx` when it's a `QueryContext` --- .../rustc_query_system/src/dep_graph/graph.rs | 38 ++--- compiler/rustc_query_system/src/query/job.rs | 4 +- .../rustc_query_system/src/query/plumbing.rs | 146 +++++++++--------- 3 files changed, 94 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 7109c1ac9a20..e856e39bf212 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -573,10 +573,10 @@ impl DepGraph { /// a node index can be found for that node. pub fn try_mark_green>( &self, - tcx: Ctxt, + qcx: Ctxt, dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind)); + debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); // Return None if the dep graph is disabled let data = self.data.as_ref()?; @@ -592,16 +592,16 @@ impl DepGraph { // in the previous compilation session too, so we can try to // mark it as green by recursively marking all of its // dependencies green. - self.try_mark_previous_green(tcx, data, prev_index, &dep_node) + self.try_mark_previous_green(qcx, data, prev_index, &dep_node) .map(|dep_node_index| (prev_index, dep_node_index)) } } } - #[instrument(skip(self, tcx, data, parent_dep_node_index), level = "debug")] + #[instrument(skip(self, qcx, data, parent_dep_node_index), level = "debug")] fn try_mark_parent_green>( &self, - tcx: Ctxt, + qcx: Ctxt, data: &DepGraphData, parent_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode, @@ -630,14 +630,14 @@ impl DepGraph { // We don't know the state of this dependency. If it isn't // an eval_always node, let's try to mark it green recursively. - if !tcx.dep_context().is_eval_always(dep_dep_node.kind) { + if !qcx.dep_context().is_eval_always(dep_dep_node.kind) { debug!( "state of dependency {:?} ({}) is unknown, trying to mark it green", dep_dep_node, dep_dep_node.hash, ); let node_index = - self.try_mark_previous_green(tcx, data, parent_dep_node_index, dep_dep_node); + self.try_mark_previous_green(qcx, data, parent_dep_node_index, dep_dep_node); if node_index.is_some() { debug!("managed to MARK dependency {dep_dep_node:?} as green",); @@ -647,7 +647,7 @@ impl DepGraph { // We failed to mark it green, so we try to force the query. debug!("trying to force dependency {dep_dep_node:?}"); - if !tcx.dep_context().try_force_from_dep_node(*dep_dep_node) { + if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node) { // The DepNode could not be forced. debug!("dependency {dep_dep_node:?} could not be forced"); return None; @@ -667,7 +667,7 @@ impl DepGraph { None => {} } - if !tcx.dep_context().sess().has_errors_or_delayed_span_bugs() { + if !qcx.dep_context().sess().has_errors_or_delayed_span_bugs() { panic!("try_mark_previous_green() - Forcing the DepNode should have set its color") } @@ -686,10 +686,10 @@ impl DepGraph { } /// Try to mark a dep-node which existed in the previous compilation session as green. - #[instrument(skip(self, tcx, data, prev_dep_node_index), level = "debug")] + #[instrument(skip(self, qcx, data, prev_dep_node_index), level = "debug")] fn try_mark_previous_green>( &self, - tcx: Ctxt, + qcx: Ctxt, data: &DepGraphData, prev_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode, @@ -701,14 +701,14 @@ impl DepGraph { } // We never try to mark eval_always nodes as green - debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind)); + debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node); let prev_deps = data.previous.edge_targets_from(prev_dep_node_index); for &dep_dep_node_index in prev_deps { - self.try_mark_parent_green(tcx, data, dep_dep_node_index, dep_node)? + self.try_mark_parent_green(qcx, data, dep_dep_node_index, dep_node)? } // If we got here without hitting a `return` that means that all @@ -720,7 +720,7 @@ impl DepGraph { // We allocating an entry for the node in the current dependency graph and // adding all the appropriate edges imported from the previous graph let dep_node_index = data.current.promote_node_and_deps_to_current( - tcx.dep_context().profiler(), + qcx.dep_context().profiler(), &data.previous, prev_dep_node_index, ); @@ -729,7 +729,7 @@ impl DepGraph { // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere // Maybe store a list on disk and encode this fact in the DepNodeState - let side_effects = tcx.load_side_effects(prev_dep_node_index); + let side_effects = qcx.load_side_effects(prev_dep_node_index); #[cfg(not(parallel_compiler))] debug_assert!( @@ -740,7 +740,7 @@ impl DepGraph { ); if !side_effects.is_empty() { - self.emit_side_effects(tcx, data, dep_node_index, side_effects); + self.emit_side_effects(qcx, data, dep_node_index, side_effects); } // ... and finally storing a "Green" entry in the color map. @@ -757,7 +757,7 @@ impl DepGraph { #[inline(never)] fn emit_side_effects>( &self, - tcx: Ctxt, + qcx: Ctxt, data: &DepGraphData, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects, @@ -769,9 +769,9 @@ impl DepGraph { // must process side effects // Promote the previous diagnostics to the current session. - tcx.store_side_effects(dep_node_index, side_effects.clone()); + qcx.store_side_effects(dep_node_index, side_effects.clone()); - let handle = tcx.dep_context().sess().diagnostic(); + let handle = qcx.dep_context().sess().diagnostic(); for mut diagnostic in side_effects.diagnostics { handle.emit_diagnostic(&mut diagnostic); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index ed65393f57e4..bd21b5465e2f 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -597,7 +597,7 @@ pub(crate) fn report_cycle<'a>( } pub fn print_query_stack( - tcx: CTX, + qcx: CTX, mut current_query: Option, handler: &Handler, num_frames: Option, @@ -606,7 +606,7 @@ pub fn print_query_stack( // a panic hook, which means that the global `Handler` may be in a weird // state if it was responsible for triggering the panic. let mut i = 0; - let query_map = tcx.try_collect_active_jobs(); + let query_map = qcx.try_collect_active_jobs(); while let Some(query) = current_query { if Some(i) == num_frames { diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index e9972a542094..6348bc6b3afa 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -64,7 +64,7 @@ where pub fn try_collect_active_jobs( &self, - tcx: CTX, + qcx: CTX, make_query: fn(CTX, K) -> QueryStackFrame, jobs: &mut QueryMap, ) -> Option<()> { @@ -76,7 +76,7 @@ where for shard in shards.iter() { for (k, v) in shard.iter() { if let QueryResult::Started(ref job) = *v { - let query = make_query(tcx, k.clone()); + let query = make_query(qcx, k.clone()); jobs.insert(job.id, QueryJobInfo { query, job: job.clone() }); } } @@ -90,7 +90,7 @@ where // really hurt much.) for (k, v) in self.active.try_lock()?.iter() { if let QueryResult::Started(ref job) = *v { - let query = make_query(tcx, k.clone()); + let query = make_query(qcx, k.clone()); jobs.insert(job.id, QueryJobInfo { query, job: job.clone() }); } } @@ -120,7 +120,7 @@ where #[cold] #[inline(never)] fn mk_cycle( - tcx: CTX, + qcx: CTX, cycle_error: CycleError, handler: HandleCycleError, cache: &dyn crate::query::QueryStorage, @@ -130,8 +130,8 @@ where V: std::fmt::Debug + Value, R: Clone, { - let error = report_cycle(tcx.dep_context().sess(), &cycle_error); - let value = handle_cycle_error(*tcx.dep_context(), &cycle_error, error, handler); + let error = report_cycle(qcx.dep_context().sess(), &cycle_error); + let value = handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler); cache.store_nocache(value) } @@ -177,7 +177,7 @@ where /// for some compile-time benchmarks. #[inline(always)] fn try_start<'b, CTX>( - tcx: &'b CTX, + qcx: &'b CTX, state: &'b QueryState, span: Span, key: K, @@ -193,8 +193,8 @@ where match lock.entry(key) { Entry::Vacant(entry) => { - let id = tcx.next_job_id(); - let job = tcx.current_query_job(); + let id = qcx.next_job_id(); + let job = qcx.current_query_job(); let job = QueryJob::new(id, span, job); let key = entry.key().clone(); @@ -213,8 +213,8 @@ where // If we are single-threaded we know that we have cycle error, // so we just return the error. return TryGetJob::Cycle(id.find_cycle_in_stack( - tcx.try_collect_active_jobs().unwrap(), - &tcx.current_query_job(), + qcx.try_collect_active_jobs().unwrap(), + &qcx.current_query_job(), span, )); } @@ -223,7 +223,7 @@ where // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the // self-profiler. - let query_blocked_prof_timer = tcx.dep_context().profiler().query_blocked(); + let query_blocked_prof_timer = qcx.dep_context().profiler().query_blocked(); // Get the latch out let latch = job.latch(); @@ -232,7 +232,7 @@ where // With parallel queries we might just have to wait on some other // thread. - let result = latch.wait_on(tcx.current_query_job(), span); + let result = latch.wait_on(qcx.current_query_job(), span); match result { Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer), @@ -357,7 +357,7 @@ where } fn try_execute_query( - tcx: CTX, + qcx: CTX, state: &QueryState, cache: &C, span: Span, @@ -371,14 +371,14 @@ where C::Value: Value, CTX: QueryContext, { - match JobOwner::<'_, C::Key>::try_start(&tcx, state, span, key.clone()) { + match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) { TryGetJob::NotYetStarted(job) => { - let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id); + let (result, dep_node_index) = execute_job(qcx, key, dep_node, query, job.id); let result = job.complete(cache, result, dep_node_index); (result, Some(dep_node_index)) } TryGetJob::Cycle(error) => { - let result = mk_cycle(tcx, error, query.handle_cycle_error, cache); + let result = mk_cycle(qcx, error, query.handle_cycle_error, cache); (result, None) } #[cfg(parallel_compiler)] @@ -387,8 +387,8 @@ where .lookup(&key, |value, index| (value.clone(), index)) .unwrap_or_else(|_| panic!("value must be in cache after waiting")); - if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) { - tcx.dep_context().profiler().query_cache_hit(index.into()); + if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) { + qcx.dep_context().profiler().query_cache_hit(index.into()); } query_blocked_prof_timer.finish_with_query_invocation_id(index.into()); @@ -398,7 +398,7 @@ where } fn execute_job( - tcx: CTX, + qcx: CTX, key: K, mut dep_node_opt: Option>, query: &QueryVTable, @@ -409,13 +409,13 @@ where V: Debug, CTX: QueryContext, { - let dep_graph = tcx.dep_context().dep_graph(); + let dep_graph = qcx.dep_context().dep_graph(); // Fast path for when incr. comp. is off. if !dep_graph.is_fully_enabled() { - let prof_timer = tcx.dep_context().profiler().query_provider(); - let result = tcx.start_query(job_id, query.depth_limit, None, || { - query.compute(*tcx.dep_context(), key) + let prof_timer = qcx.dep_context().profiler().query_provider(); + let result = qcx.start_query(job_id, query.depth_limit, None, || { + query.compute(*qcx.dep_context(), key) }); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -425,33 +425,33 @@ where if !query.anon && !query.eval_always { // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.get_or_insert_with(|| query.to_dep_node(*tcx.dep_context(), &key)); + dep_node_opt.get_or_insert_with(|| query.to_dep_node(*qcx.dep_context(), &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. - if let Some(ret) = tcx.start_query(job_id, false, None, || { - try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query) + if let Some(ret) = qcx.start_query(job_id, false, None, || { + try_load_from_disk_and_cache_in_memory(qcx, &key, &dep_node, query) }) { return ret; } } - let prof_timer = tcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.dep_context().profiler().query_provider(); let diagnostics = Lock::new(ThinVec::new()); let (result, dep_node_index) = - tcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || { + qcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || { if query.anon { - return dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || { - query.compute(*tcx.dep_context(), key) + return dep_graph.with_anon_task(*qcx.dep_context(), query.dep_kind, || { + query.compute(*qcx.dep_context(), key) }); } // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.unwrap_or_else(|| query.to_dep_node(*tcx.dep_context(), &key)); + dep_node_opt.unwrap_or_else(|| query.to_dep_node(*qcx.dep_context(), &key)); - dep_graph.with_task(dep_node, *tcx.dep_context(), key, query.compute, query.hash_result) + dep_graph.with_task(dep_node, *qcx.dep_context(), key, query.compute, query.hash_result) }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -461,9 +461,9 @@ where if std::intrinsics::unlikely(!side_effects.is_empty()) { if query.anon { - tcx.store_side_effects_for_anon_node(dep_node_index, side_effects); + qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { - tcx.store_side_effects(dep_node_index, side_effects); + qcx.store_side_effects(dep_node_index, side_effects); } } @@ -471,7 +471,7 @@ where } fn try_load_from_disk_and_cache_in_memory( - tcx: CTX, + qcx: CTX, key: &K, dep_node: &DepNode, query: &QueryVTable, @@ -484,32 +484,32 @@ where // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. - let dep_graph = tcx.dep_context().dep_graph(); - let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(tcx, &dep_node)?; + let dep_graph = qcx.dep_context().dep_graph(); + let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(qcx, &dep_node)?; debug_assert!(dep_graph.is_green(dep_node)); // First we try to load the result from the on-disk cache. // Some things are never cached on disk. if let Some(try_load_from_disk) = query.try_load_from_disk { - let prof_timer = tcx.dep_context().profiler().incr_cache_loading(); + let prof_timer = qcx.dep_context().profiler().incr_cache_loading(); // The call to `with_query_deserialization` enforces that no new `DepNodes` // are created during deserialization. See the docs of that method for more // details. let result = - dep_graph.with_query_deserialization(|| try_load_from_disk(tcx, prev_dep_node_index)); + dep_graph.with_query_deserialization(|| try_load_from_disk(qcx, prev_dep_node_index)); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); if let Some(result) = result { if std::intrinsics::unlikely( - tcx.dep_context().sess().opts.unstable_opts.query_dep_graph, + qcx.dep_context().sess().opts.unstable_opts.query_dep_graph, ) { dep_graph.mark_debug_loaded_from_disk(*dep_node) } - let prev_fingerprint = tcx + let prev_fingerprint = qcx .dep_context() .dep_graph() .prev_fingerprint_of(dep_node) @@ -523,9 +523,9 @@ where // give us some coverage of potential bugs though. let try_verify = prev_fingerprint.as_value().1 % 32 == 0; if std::intrinsics::unlikely( - try_verify || tcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, + try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, ) { - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query); } return Some((result, dep_node_index)); @@ -534,7 +534,7 @@ where // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !tcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), + !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), "missing on-disk cache entry for {:?}", dep_node ); @@ -542,10 +542,10 @@ where // We could not load a result from the on-disk cache, so // recompute. - let prof_timer = tcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.dep_context().profiler().query_provider(); // The dep-graph for this computation is already in-place. - let result = dep_graph.with_ignore(|| query.compute(*tcx.dep_context(), key.clone())); + let result = dep_graph.with_ignore(|| query.compute(*qcx.dep_context(), key.clone())); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -558,14 +558,14 @@ where // // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query); Some((result, dep_node_index)) } -#[instrument(skip(tcx, result, query), level = "debug")] +#[instrument(skip(qcx, result, query), level = "debug")] fn incremental_verify_ich( - tcx: CTX::DepContext, + qcx: CTX::DepContext, result: &V, dep_node: &DepNode, query: &QueryVTable, @@ -573,20 +573,20 @@ fn incremental_verify_ich( CTX: QueryContext, { assert!( - tcx.dep_graph().is_green(dep_node), + qcx.dep_graph().is_green(dep_node), "fingerprint for green query instance not loaded from cache: {:?}", dep_node, ); let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| { - tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) + qcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) }); - let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); + let old_hash = qcx.dep_graph().prev_fingerprint_of(dep_node); if Some(new_hash) != old_hash { incremental_verify_ich_failed( - tcx.sess(), + qcx.sess(), DebugArg::from(&dep_node), DebugArg::from(&result), ); @@ -677,7 +677,7 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: /// Note: The optimization is only available during incr. comp. #[inline(never)] fn ensure_must_run( - tcx: CTX, + qcx: CTX, key: &K, query: &QueryVTable, ) -> (bool, Option>) @@ -692,10 +692,10 @@ where // Ensuring an anonymous query makes no sense assert!(!query.anon); - let dep_node = query.to_dep_node(*tcx.dep_context(), key); + let dep_node = query.to_dep_node(*qcx.dep_context(), key); - let dep_graph = tcx.dep_context().dep_graph(); - match dep_graph.try_mark_green(tcx, &dep_node) { + let dep_graph = qcx.dep_context().dep_graph(); + match dep_graph.try_mark_green(qcx, &dep_node) { None => { // A None return from `try_mark_green` means that this is either // a new dep node or that the dep node has already been marked red. @@ -707,7 +707,7 @@ where } Some((_, dep_node_index)) => { dep_graph.read_index(dep_node_index); - tcx.dep_context().profiler().query_cache_hit(dep_node_index.into()); + qcx.dep_context().profiler().query_cache_hit(dep_node_index.into()); (false, None) } } @@ -719,16 +719,16 @@ pub enum QueryMode { Ensure, } -pub fn get_query(tcx: CTX, span: Span, key: Q::Key, mode: QueryMode) -> Option +pub fn get_query(qcx: CTX, span: Span, key: Q::Key, mode: QueryMode) -> Option where Q: QueryConfig, Q::Key: DepNodeParams, Q::Value: Value, CTX: QueryContext, { - let query = Q::make_vtable(tcx, &key); + let query = Q::make_vtable(qcx, &key); let dep_node = if let QueryMode::Ensure = mode { - let (must_run, dep_node) = ensure_must_run(tcx, &key, &query); + let (must_run, dep_node) = ensure_must_run(qcx, &key, &query); if !must_run { return None; } @@ -738,21 +738,21 @@ where }; let (result, dep_node_index) = try_execute_query( - tcx, - Q::query_state(tcx), - Q::query_cache(tcx), + qcx, + Q::query_state(qcx), + Q::query_cache(qcx), span, key, dep_node, &query, ); if let Some(dep_node_index) = dep_node_index { - tcx.dep_context().dep_graph().read_index(dep_node_index) + qcx.dep_context().dep_graph().read_index(dep_node_index) } Some(result) } -pub fn force_query(tcx: CTX, key: Q::Key, dep_node: DepNode) +pub fn force_query(qcx: CTX, key: Q::Key, dep_node: DepNode) where Q: QueryConfig, Q::Key: DepNodeParams, @@ -761,10 +761,10 @@ where { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - let cache = Q::query_cache(tcx); + let cache = Q::query_cache(qcx); let cached = cache.lookup(&key, |_, index| { - if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) { - tcx.dep_context().profiler().query_cache_hit(index.into()); + if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) { + qcx.dep_context().profiler().query_cache_hit(index.into()); } }); @@ -773,9 +773,9 @@ where Err(()) => {} } - let query = Q::make_vtable(tcx, &key); - let state = Q::query_state(tcx); + let query = Q::make_vtable(qcx, &key); + let state = Q::query_state(qcx); debug_assert!(!query.anon); - try_execute_query(tcx, state, cache, DUMMY_SP, key, Some(dep_node), &query); + try_execute_query(qcx, state, cache, DUMMY_SP, key, Some(dep_node), &query); } From 6d26ea86dac0eb987b338bf3ba5f3900fd68f000 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 5 Nov 2022 21:04:19 +0100 Subject: [PATCH 119/221] Rename `Ctxt` and `CTX` to `Tcx` and `Qcx` This makes it consistent and clear which context is used. --- compiler/rustc_query_system/src/cache.rs | 4 +- .../src/dep_graph/dep_node.rs | 36 +++--- .../rustc_query_system/src/dep_graph/graph.rs | 22 ++-- .../rustc_query_system/src/query/config.rs | 32 ++--- compiler/rustc_query_system/src/query/job.rs | 4 +- .../rustc_query_system/src/query/plumbing.rs | 112 +++++++++--------- compiler/rustc_query_system/src/values.rs | 8 +- 7 files changed, 109 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs index d592812f79b6..7cc885be2ba6 100644 --- a/compiler/rustc_query_system/src/cache.rs +++ b/compiler/rustc_query_system/src/cache.rs @@ -26,7 +26,7 @@ impl Cache { } impl Cache { - pub fn get(&self, key: &Key, tcx: CTX) -> Option { + pub fn get(&self, key: &Key, tcx: Tcx) -> Option { Some(self.hashmap.borrow().get(key)?.get(tcx)) } @@ -46,7 +46,7 @@ impl WithDepNode { WithDepNode { dep_node, cached_value } } - pub fn get(&self, tcx: CTX) -> T { + pub fn get(&self, tcx: Tcx) -> T { tcx.dep_graph().read_index(self.dep_node); self.cached_value.clone() } diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 5c6ce0556eb8..d79c5816a9c4 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -61,18 +61,18 @@ impl DepNode { /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. - pub fn new_no_params(tcx: Ctxt, kind: K) -> DepNode + pub fn new_no_params(tcx: Tcx, kind: K) -> DepNode where - Ctxt: super::DepContext, + Tcx: super::DepContext, { debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); DepNode { kind, hash: Fingerprint::ZERO.into() } } - pub fn construct(tcx: Ctxt, kind: K, arg: &Key) -> DepNode + pub fn construct(tcx: Tcx, kind: K, arg: &Key) -> DepNode where - Ctxt: super::DepContext, - Key: DepNodeParams, + Tcx: super::DepContext, + Key: DepNodeParams, { let hash = arg.to_fingerprint(tcx); let dep_node = DepNode { kind, hash: hash.into() }; @@ -93,9 +93,9 @@ impl DepNode { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - pub fn from_def_path_hash(tcx: Ctxt, def_path_hash: DefPathHash, kind: K) -> Self + pub fn from_def_path_hash(tcx: Tcx, def_path_hash: DefPathHash, kind: K) -> Self where - Ctxt: super::DepContext, + Tcx: super::DepContext, { debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } @@ -108,18 +108,18 @@ impl fmt::Debug for DepNode { } } -pub trait DepNodeParams: fmt::Debug + Sized { +pub trait DepNodeParams: fmt::Debug + Sized { fn fingerprint_style() -> FingerprintStyle; /// This method turns the parameters of a DepNodeConstructor into an opaque /// Fingerprint to be used in DepNode. /// Not all DepNodeParams support being turned into a Fingerprint (they /// don't need to if the corresponding DepNode is anonymous). - fn to_fingerprint(&self, _: Ctxt) -> Fingerprint { + fn to_fingerprint(&self, _: Tcx) -> Fingerprint { panic!("Not implemented. Accidentally called on anonymous node?") } - fn to_debug_str(&self, _: Ctxt) -> String { + fn to_debug_str(&self, _: Tcx) -> String { format!("{:?}", self) } @@ -129,10 +129,10 @@ pub trait DepNodeParams: fmt::Debug + Sized { /// `fingerprint_style()` is not `FingerprintStyle::Opaque`. /// It is always valid to return `None` here, in which case incremental /// compilation will treat the query as having changed instead of forcing it. - fn recover(tcx: Ctxt, dep_node: &DepNode) -> Option; + fn recover(tcx: Tcx, dep_node: &DepNode) -> Option; } -impl DepNodeParams for T +impl DepNodeParams for T where T: for<'a> HashStable> + fmt::Debug, { @@ -142,7 +142,7 @@ where } #[inline(always)] - default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { + default fn to_fingerprint(&self, tcx: Tcx) -> Fingerprint { tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); self.hash_stable(&mut hcx, &mut hasher); @@ -151,12 +151,12 @@ where } #[inline(always)] - default fn to_debug_str(&self, _: Ctxt) -> String { + default fn to_debug_str(&self, _: Tcx) -> String { format!("{:?}", *self) } #[inline(always)] - default fn recover(_: Ctxt, _: &DepNode) -> Option { + default fn recover(_: Tcx, _: &DepNode) -> Option { None } } @@ -166,7 +166,7 @@ where /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual /// jump table instead of large matches. -pub struct DepKindStruct { +pub struct DepKindStruct { /// Anonymous queries cannot be replayed from one compiler invocation to the next. /// When their result is needed, it is recomputed. They are useful for fine-grained /// dependency tracking, and caching within one compiler invocation. @@ -216,10 +216,10 @@ pub struct DepKindStruct { /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` /// is actually a `DefPathHash`, and can therefore just look up the corresponding /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: Option) -> bool>, + pub force_from_dep_node: Option) -> bool>, /// Invoke a query to put the on-disk cached value in memory. - pub try_load_from_on_disk_cache: Option)>, + pub try_load_from_on_disk_cache: Option)>, } /// A "work product" corresponds to a `.o` (or other) file that we diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index e856e39bf212..d86c0bebdcdf 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -377,9 +377,9 @@ impl DepGraph { /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. - pub fn with_anon_task, OP, R>( + pub fn with_anon_task, OP, R>( &self, - cx: Ctxt, + cx: Tcx, dep_kind: K, op: OP, ) -> (R, DepNodeIndex) @@ -571,9 +571,9 @@ impl DepGraph { /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub fn try_mark_green>( + pub fn try_mark_green>( &self, - qcx: Ctxt, + qcx: Qcx, dep_node: &DepNode, ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); @@ -599,9 +599,9 @@ impl DepGraph { } #[instrument(skip(self, qcx, data, parent_dep_node_index), level = "debug")] - fn try_mark_parent_green>( + fn try_mark_parent_green>( &self, - qcx: Ctxt, + qcx: Qcx, data: &DepGraphData, parent_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode, @@ -687,9 +687,9 @@ impl DepGraph { /// Try to mark a dep-node which existed in the previous compilation session as green. #[instrument(skip(self, qcx, data, prev_dep_node_index), level = "debug")] - fn try_mark_previous_green>( + fn try_mark_previous_green>( &self, - qcx: Ctxt, + qcx: Qcx, data: &DepGraphData, prev_dep_node_index: SerializedDepNodeIndex, dep_node: &DepNode, @@ -755,9 +755,9 @@ impl DepGraph { /// This may be called concurrently on multiple threads for the same dep node. #[cold] #[inline(never)] - fn emit_side_effects>( + fn emit_side_effects>( &self, - qcx: Ctxt, + qcx: Qcx, data: &DepGraphData, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects, @@ -799,7 +799,7 @@ impl DepGraph { // // This method will only load queries that will end up in the disk cache. // Other queries will not be executed. - pub fn exec_cache_promotions>(&self, tcx: Ctxt) { + pub fn exec_cache_promotions>(&self, tcx: Tcx) { let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion"); let data = self.data.as_ref().unwrap(); diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index db3ae559ad15..f40e174b7e79 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use std::fmt::Debug; use std::hash::Hash; -pub trait QueryConfig { +pub trait QueryConfig { const NAME: &'static str; type Key: Eq + Hash + Clone + Debug; @@ -21,47 +21,47 @@ pub trait QueryConfig { type Cache: QueryCache; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(tcx: CTX) -> &'a QueryState + fn query_state<'a>(tcx: Qcx) -> &'a QueryState where - CTX: 'a; + Qcx: 'a; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(tcx: CTX) -> &'a Self::Cache + fn query_cache<'a>(tcx: Qcx) -> &'a Self::Cache where - CTX: 'a; + Qcx: 'a; // Don't use this method to compute query results, instead use the methods on TyCtxt - fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVTable; + fn make_vtable(tcx: Qcx, key: &Self::Key) -> QueryVTable; - fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool; + fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool; // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(tcx: CTX::DepContext, k: Self::Key) -> Self::Stored; + fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Stored; } #[derive(Copy, Clone)] -pub struct QueryVTable { +pub struct QueryVTable { pub anon: bool, - pub dep_kind: CTX::DepKind, + pub dep_kind: Qcx::DepKind, pub eval_always: bool, pub depth_limit: bool, - pub compute: fn(CTX::DepContext, K) -> V, + pub compute: fn(Qcx::DepContext, K) -> V, pub hash_result: Option, &V) -> Fingerprint>, pub handle_cycle_error: HandleCycleError, // NOTE: this is also `None` if `cache_on_disk()` returns false, not just if it's unsupported by the query - pub try_load_from_disk: Option Option>, + pub try_load_from_disk: Option Option>, } -impl QueryVTable { - pub(crate) fn to_dep_node(&self, tcx: CTX::DepContext, key: &K) -> DepNode +impl QueryVTable { + pub(crate) fn to_dep_node(&self, tcx: Qcx::DepContext, key: &K) -> DepNode where - K: crate::dep_graph::DepNodeParams, + K: crate::dep_graph::DepNodeParams, { DepNode::construct(tcx, self.dep_kind, key) } - pub(crate) fn compute(&self, tcx: CTX::DepContext, key: K) -> V { + pub(crate) fn compute(&self, tcx: Qcx::DepContext, key: K) -> V { (self.compute)(tcx, key) } } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index bd21b5465e2f..49bbcf578045 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -596,8 +596,8 @@ pub(crate) fn report_cycle<'a>( cycle_diag.into_diagnostic(&sess.parse_sess.span_diagnostic) } -pub fn print_query_stack( - qcx: CTX, +pub fn print_query_stack( + qcx: Qcx, mut current_query: Option, handler: &Handler, num_frames: Option, diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 6348bc6b3afa..f8d93a27d1c2 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -62,10 +62,10 @@ where } } - pub fn try_collect_active_jobs( + pub fn try_collect_active_jobs( &self, - qcx: CTX, - make_query: fn(CTX, K) -> QueryStackFrame, + qcx: Qcx, + make_query: fn(Qcx, K) -> QueryStackFrame, jobs: &mut QueryMap, ) -> Option<()> { #[cfg(parallel_compiler)] @@ -119,15 +119,15 @@ where #[cold] #[inline(never)] -fn mk_cycle( - qcx: CTX, +fn mk_cycle( + qcx: Qcx, cycle_error: CycleError, handler: HandleCycleError, cache: &dyn crate::query::QueryStorage, ) -> R where - CTX: QueryContext, - V: std::fmt::Debug + Value, + Qcx: QueryContext, + V: std::fmt::Debug + Value, R: Clone, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); @@ -135,15 +135,15 @@ where cache.store_nocache(value) } -fn handle_cycle_error( - tcx: CTX, +fn handle_cycle_error( + tcx: Tcx, cycle_error: &CycleError, mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, handler: HandleCycleError, ) -> V where - CTX: DepContext, - V: Value, + Tcx: DepContext, + V: Value, { use HandleCycleError::*; match handler { @@ -176,14 +176,14 @@ where /// This function is inlined because that results in a noticeable speed-up /// for some compile-time benchmarks. #[inline(always)] - fn try_start<'b, CTX>( - qcx: &'b CTX, + fn try_start<'b, Qcx>( + qcx: &'b Qcx, state: &'b QueryState, span: Span, key: K, ) -> TryGetJob<'b, K> where - CTX: QueryContext, + Qcx: QueryContext, { #[cfg(parallel_compiler)] let mut state_lock = state.active.get_shard_by_value(&key).lock(); @@ -335,8 +335,8 @@ where /// which will be used if the query is not in the cache and we need /// to compute it. #[inline] -pub fn try_get_cached<'a, CTX, C, R, OnHit>( - tcx: CTX, +pub fn try_get_cached<'a, Tcx, C, R, OnHit>( + tcx: Tcx, cache: &'a C, key: &C::Key, // `on_hit` can be called while holding a lock to the query cache @@ -344,7 +344,7 @@ pub fn try_get_cached<'a, CTX, C, R, OnHit>( ) -> Result where C: QueryCache, - CTX: DepContext, + Tcx: DepContext, OnHit: FnOnce(&C::Stored) -> R, { cache.lookup(&key, |value, index| { @@ -356,20 +356,20 @@ where }) } -fn try_execute_query( - qcx: CTX, +fn try_execute_query( + qcx: Qcx, state: &QueryState, cache: &C, span: Span, key: C::Key, - dep_node: Option>, - query: &QueryVTable, + dep_node: Option>, + query: &QueryVTable, ) -> (C::Stored, Option) where C: QueryCache, - C::Key: Clone + DepNodeParams, - C::Value: Value, - CTX: QueryContext, + C::Key: Clone + DepNodeParams, + C::Value: Value, + Qcx: QueryContext, { match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) { TryGetJob::NotYetStarted(job) => { @@ -397,17 +397,17 @@ where } } -fn execute_job( - qcx: CTX, +fn execute_job( + qcx: Qcx, key: K, - mut dep_node_opt: Option>, - query: &QueryVTable, + mut dep_node_opt: Option>, + query: &QueryVTable, job_id: QueryJobId, ) -> (V, DepNodeIndex) where - K: Clone + DepNodeParams, + K: Clone + DepNodeParams, V: Debug, - CTX: QueryContext, + Qcx: QueryContext, { let dep_graph = qcx.dep_context().dep_graph(); @@ -470,15 +470,15 @@ where (result, dep_node_index) } -fn try_load_from_disk_and_cache_in_memory( - qcx: CTX, +fn try_load_from_disk_and_cache_in_memory( + qcx: Qcx, key: &K, - dep_node: &DepNode, - query: &QueryVTable, + dep_node: &DepNode, + query: &QueryVTable, ) -> Option<(V, DepNodeIndex)> where K: Clone, - CTX: QueryContext, + Qcx: QueryContext, V: Debug, { // Note this function can be called concurrently from the same query @@ -564,13 +564,13 @@ where } #[instrument(skip(qcx, result, query), level = "debug")] -fn incremental_verify_ich( - qcx: CTX::DepContext, +fn incremental_verify_ich( + qcx: Qcx::DepContext, result: &V, - dep_node: &DepNode, - query: &QueryVTable, + dep_node: &DepNode, + query: &QueryVTable, ) where - CTX: QueryContext, + Qcx: QueryContext, { assert!( qcx.dep_graph().is_green(dep_node), @@ -676,14 +676,14 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run( - qcx: CTX, +fn ensure_must_run( + qcx: Qcx, key: &K, - query: &QueryVTable, -) -> (bool, Option>) + query: &QueryVTable, +) -> (bool, Option>) where - K: crate::dep_graph::DepNodeParams, - CTX: QueryContext, + K: crate::dep_graph::DepNodeParams, + Qcx: QueryContext, { if query.eval_always { return (true, None); @@ -719,12 +719,12 @@ pub enum QueryMode { Ensure, } -pub fn get_query(qcx: CTX, span: Span, key: Q::Key, mode: QueryMode) -> Option +pub fn get_query(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option where - Q: QueryConfig, - Q::Key: DepNodeParams, - Q::Value: Value, - CTX: QueryContext, + Q: QueryConfig, + Q::Key: DepNodeParams, + Q::Value: Value, + Qcx: QueryContext, { let query = Q::make_vtable(qcx, &key); let dep_node = if let QueryMode::Ensure = mode { @@ -752,12 +752,12 @@ where Some(result) } -pub fn force_query(qcx: CTX, key: Q::Key, dep_node: DepNode) +pub fn force_query(qcx: Qcx, key: Q::Key, dep_node: DepNode) where - Q: QueryConfig, - Q::Key: DepNodeParams, - Q::Value: Value, - CTX: QueryContext, + Q: QueryConfig, + Q::Key: DepNodeParams, + Q::Value: Value, + Qcx: QueryContext, { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs index 67fbf14e6129..214656abed4d 100644 --- a/compiler/rustc_query_system/src/values.rs +++ b/compiler/rustc_query_system/src/values.rs @@ -1,12 +1,12 @@ use crate::dep_graph::DepContext; use crate::query::QueryInfo; -pub trait Value: Sized { - fn from_cycle_error(tcx: CTX, cycle: &[QueryInfo]) -> Self; +pub trait Value: Sized { + fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo]) -> Self; } -impl Value for T { - default fn from_cycle_error(tcx: CTX, _: &[QueryInfo]) -> T { +impl Value for T { + default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo]) -> T { tcx.sess().abort_if_errors(); // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's // non-trivial to define it earlier. From c0889a6005ecac3d304009e734baa97b37b534d2 Mon Sep 17 00:00:00 2001 From: Boxy Date: Sun, 6 Nov 2022 13:39:13 +0000 Subject: [PATCH 120/221] fixyfixfix --- .../src/collect/lifetimes.rs | 92 ++++++++++++++++++- src/test/ui/issues/issue-47511.stderr | 18 ---- .../downgraded_to_early_through_alias.rs | 24 +++++ .../issue-47511.rs | 7 +- .../mismatched_arg_count.rs | 12 +++ .../mismatched_arg_count.stderr | 17 ++++ 6 files changed, 141 insertions(+), 29 deletions(-) delete mode 100644 src/test/ui/issues/issue-47511.stderr create mode 100644 src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs rename src/test/ui/{issues => late-bound-lifetimes}/issue-47511.rs (52%) create mode 100644 src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs create mode 100644 src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index 3d07f3fbc674..b9583bd2244b 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -18,7 +18,7 @@ use rustc_middle::bug; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime::*; -use rustc_middle::ty::{self, DefIdTree, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -1781,7 +1781,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< let mut late_bound = FxIndexSet::default(); - let mut constrained_by_input = ConstrainedCollector::default(); + let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx }; for arg_ty in decl.inputs { constrained_by_input.visit_ty(arg_ty); } @@ -1834,12 +1834,44 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< debug!(?late_bound); return Some(tcx.arena.alloc(late_bound)); - #[derive(Default)] - struct ConstrainedCollector { + struct ConstrainedCollectorPostAstConv { + arg_is_constrained: Box<[bool]>, + } + + use std::ops::ControlFlow; + use ty::Ty; + impl<'tcx> TypeVisitor<'tcx> for ConstrainedCollectorPostAstConv { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + match t.kind() { + ty::Param(param_ty) => { + self.arg_is_constrained[param_ty.index as usize] = true; + } + ty::Projection(_) => return ControlFlow::Continue(()), + _ => (), + } + t.super_visit_with(self) + } + + fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow { + ControlFlow::Continue(()) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + debug!("r={:?}", r.kind()); + if let ty::RegionKind::ReEarlyBound(region) = r.kind() { + self.arg_is_constrained[region.index as usize] = true; + } + + ControlFlow::Continue(()) + } + } + + struct ConstrainedCollector<'tcx> { + tcx: TyCtxt<'tcx>, regions: FxHashSet, } - impl<'v> Visitor<'v> for ConstrainedCollector { + impl<'v> Visitor<'v> for ConstrainedCollector<'_> { fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { match ty.kind { hir::TyKind::Path( @@ -1850,6 +1882,56 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< // (defined above) } + hir::TyKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, + )) => { + // If this is a top level type alias attempt to "look through" it to see if the args + // are constrained, instead of assuming they are and inserting all the lifetimes. + // This is necessary for the following case: + // ``` + // type Alias<'a, T> = >::Assoc; + // fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... } + // ``` + // If we considered `'a` constrained then it would become late bound causing an error + // during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` + // but appears in the output type `<() as Trait<'a>>::Assoc`. + + let generics = self.tcx.generics_of(alias_def); + let mut walker = ConstrainedCollectorPostAstConv { + arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(), + }; + walker.visit_ty(self.tcx.type_of(alias_def)); + + match segments.last() { + Some(hir::PathSegment { args: Some(args), .. }) => { + let tcx = self.tcx; + for constrained_arg in + args.args.iter().enumerate().flat_map(|(n, arg)| { + match walker.arg_is_constrained.get(n) { + Some(true) => Some(arg), + Some(false) => None, + None => { + tcx.sess.delay_span_bug( + *span, + format!( + "Incorrect generic arg count for alias {:?}", + alias_def + ), + ); + None + } + } + }) + { + self.visit_generic_arg(constrained_arg); + } + } + Some(_) => (), + None => bug!("Path with no segments or self type"), + } + } + hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { // consider only the lifetimes on the final // segment; I am not sure it's even currently diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr deleted file mode 100644 index 9998ee0e8d0c..000000000000 --- a/src/test/ui/issues/issue-47511.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types - --> $DIR/issue-47511.rs:8:15 - | -LL | fn f(_: X) -> X { - | ^ - | - = note: lifetimes appearing in an associated or opaque type are not considered constrained - = note: consider introducing a named lifetime parameter - -error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types - --> $DIR/issue-47511.rs:12:23 - | -LL | fn g<'a>(_: X<'a>) -> X<'a> { - | ^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0581`. diff --git a/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs new file mode 100644 index 000000000000..e56a34218e23 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs @@ -0,0 +1,24 @@ +// check-pass + +trait Gats<'a> { + type Assoc; + type Assoc2; +} + +trait Trait: for<'a> Gats<'a> { + fn foo<'a>(_: &mut >::Assoc) -> >::Assoc2; +} + +impl<'a> Gats<'a> for () { + type Assoc = &'a u32; + type Assoc2 = (); +} + +type GatsAssoc<'a, T> = >::Assoc; +type GatsAssoc2<'a, T> = >::Assoc2; + +impl Trait for () { + fn foo<'a>(_: &mut GatsAssoc<'a, Self>) -> GatsAssoc2<'a, Self> {} +} + +fn main() {} diff --git a/src/test/ui/issues/issue-47511.rs b/src/test/ui/late-bound-lifetimes/issue-47511.rs similarity index 52% rename from src/test/ui/issues/issue-47511.rs rename to src/test/ui/late-bound-lifetimes/issue-47511.rs index eb4860e75d75..789443515408 100644 --- a/src/test/ui/issues/issue-47511.rs +++ b/src/test/ui/late-bound-lifetimes/issue-47511.rs @@ -1,9 +1,4 @@ -// check-fail -// known-bug: #47511 - -// Regression test for #47511: anonymous lifetimes can appear -// unconstrained in a return type, but only if they appear just once -// in the input, as the input to a projection. +// check-pass fn f(_: X) -> X { unimplemented!() diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs new file mode 100644 index 000000000000..0b331e2039f2 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs @@ -0,0 +1,12 @@ +// ensures that we don't ICE when there are too many args supplied to the alias. + +trait Trait<'a> { + type Assoc; +} + +type Alias<'a, T> = >::Assoc; + +fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} +//~^ error: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + +fn main() {} diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr new file mode 100644 index 000000000000..3704d9bb957e --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr @@ -0,0 +1,17 @@ +error[E0107]: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/mismatched_arg_count.rs:9:29 + | +LL | fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} + | ^^^^^ -- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: type alias defined here, with 1 lifetime parameter: `'a` + --> $DIR/mismatched_arg_count.rs:7:6 + | +LL | type Alias<'a, T> = >::Assoc; + | ^^^^^ -- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. From 743726e352b41ea6a8370ab16cd81152b3b28a53 Mon Sep 17 00:00:00 2001 From: ripytide <62516857+ripytide@users.noreply.github.com> Date: Sun, 6 Nov 2022 15:25:00 +0000 Subject: [PATCH 121/221] Vec: IntoIterator signature consistency Also makes the code dryer. --- library/alloc/src/vec/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 834c8f58cb2a..766006939fa4 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2780,7 +2780,7 @@ impl IntoIterator for Vec { /// assert_eq!(v_iter.next(), None); /// ``` #[inline] - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> Self::IntoIter { unsafe { let mut me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); @@ -2808,7 +2808,7 @@ impl<'a, T, A: Allocator> IntoIterator for &'a Vec { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; - fn into_iter(self) -> slice::Iter<'a, T> { + fn into_iter(self) -> Self::IntoIter { self.iter() } } @@ -2818,7 +2818,7 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; - fn into_iter(self) -> slice::IterMut<'a, T> { + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } From e15c406deb29933e5aa6b3d1497978776ca275ea Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 6 Nov 2022 11:22:29 -0500 Subject: [PATCH 122/221] fix: typo --- compiler/rustc_middle/src/lint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 79522bd0b2b2..51df42f6d14e 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -276,7 +276,7 @@ pub fn explain_lint_level_source( /// The innermost function for emitting lints. /// -/// If you are loocking to implement a lint, look for higher level functions, +/// If you are looking to implement a lint, look for higher level functions, /// for example: /// - [`TyCtxt::emit_spanned_lint`] /// - [`TyCtxt::struct_span_lint_hir`] From b34fdd32bb0eb7bf0796186fb94ee10b1e6134b3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 6 Nov 2022 09:55:16 -0700 Subject: [PATCH 123/221] rustdoc: remove unused CSS `#sidebar-filler` This hack was removed in 6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c, but the CSS was left in. --- src/librustdoc/html/static/css/rustdoc.css | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 66e48ba8cf1a..ee3f4e7c471b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1804,21 +1804,6 @@ in storage.js display: block; } - /* Because of ios, we need to actually have a full height sidebar title so the - * actual sidebar can show up. But then we need to make it transparent so we don't - * hide content. The filler just allows to create the background for the sidebar - * title. But because of the absolute position, I had to lower the z-index. - */ - #sidebar-filler { - position: fixed; - left: 45px; - width: calc(100% - 45px); - top: 0; - height: 45px; - z-index: -1; - border-bottom: 1px solid; - } - #main-content > details.rustdoc-toggle > summary::before, #main-content > div > details.rustdoc-toggle > summary::before { left: -11px; From 24d86a1c086371aa9185a231d37e0ed71fa27e34 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 6 Nov 2022 18:20:28 +0100 Subject: [PATCH 124/221] Migrate rust logo filter to CSS variables --- src/librustdoc/html/static/css/rustdoc.css | 4 ++++ src/librustdoc/html/static/css/themes/ayu.css | 11 ++++------- src/librustdoc/html/static/css/themes/dark.css | 11 ++++------- src/librustdoc/html/static/css/themes/light.css | 7 +------ 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 66e48ba8cf1a..33505a366997 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -378,6 +378,10 @@ img { object-fit: contain; } +.rust-logo { + filter: var(--rust-logo-filter); +} + .sidebar, .mobile-topbar, .sidebar-menu-toggle { background-color: var(--sidebar-background-color); } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 4b88c42f2df0..bf8a60affaa2 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -63,6 +63,10 @@ Original by Dempfi (https://github.com/dempfi/ayu) --test-arrow-background-color: rgba(57, 175, 215, 0.09); --test-arrow-hover-color: #c5c5c5; --test-arrow-hover-background-color: rgba(57, 175, 215, 0.368); + --rust-logo-filter: drop-shadow(1px 0 0px #fff) + drop-shadow(0 1px 0 #fff) + drop-shadow(-1px 0 0 #fff) + drop-shadow(0 -1px 0 #fff); } .slider { @@ -104,13 +108,6 @@ pre, .rustdoc.source .example-wrap { color: #e6e1cf; } -.rust-logo { - filter: drop-shadow(1px 0 0px #fff) - drop-shadow(0 1px 0 #fff) - drop-shadow(-1px 0 0 #fff) - drop-shadow(0 -1px 0 #fff); -} - .sidebar .current, .sidebar a:hover { color: #ffb44c; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 8edd8fee78d0..ac6e527848f6 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -58,6 +58,10 @@ --test-arrow-background-color: rgba(78, 139, 202, 0.2); --test-arrow-hover-color: #dedede; --test-arrow-hover-background-color: #4e8bca; + --rust-logo-filter: drop-shadow(1px 0 0px #fff) + drop-shadow(0 1px 0 #fff) + drop-shadow(-1px 0 0 #fff) + drop-shadow(0 -1px 0 #fff); } .slider { @@ -70,13 +74,6 @@ input:focus + .slider { box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); } -.rust-logo { - filter: drop-shadow(1px 0 0px #fff) - drop-shadow(0 1px 0 #fff) - drop-shadow(-1px 0 0 #fff) - drop-shadow(0 -1px 0 #fff) -} - .content .item-info::before { color: #ccc; } body.source .example-wrap pre.rust a { diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 797be8754f8d..608fc5aba7fd 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -58,6 +58,7 @@ --test-arrow-background-color: rgba(78, 139, 202, 0.2); --test-arrow-hover-color: #f5f5f5; --test-arrow-hover-background-color: #4e8bca; + --rust-logo-filter: initial; } .slider { @@ -70,12 +71,6 @@ input:focus + .slider { box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); } -.rust-logo { - /* This rule exists to force other themes to explicitly style the logo. - * Rustdoc has a custom linter for this purpose. - */ -} - .content .item-info::before { color: #ccc; } body.source .example-wrap pre.rust a { From f414715ebfda201f91f80ef9f28d9923d614d1c4 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 6 Nov 2022 19:03:22 +0000 Subject: [PATCH 125/221] LLVM 16: Update RISCV data layout --- compiler/rustc_codegen_llvm/src/context.rs | 4 ++++ compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs | 2 +- compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs | 2 +- .../rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs | 2 +- compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs | 2 +- compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs | 2 +- .../rustc_target/src/spec/riscv64imac_unknown_none_elf.rs | 2 +- 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 79ddfd884dfa..c22ec128dacb 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -158,6 +158,10 @@ pub unsafe fn create_module<'ll>( if sess.target.arch == "s390x" { target_data_layout = target_data_layout.replace("-v128:64", ""); } + + if sess.target.arch == "riscv64" { + target_data_layout = target_data_layout.replace("-n32:64-", "-n64-"); + } } // Ensure the data-layout values hardcoded remain the defaults. diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs index 0539eca6c1fc..8281bac10f88 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-freebsd".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs index 7d1bf228c370..90dccb28063d 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-gnu".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs index f04f8a48bc81..1a56c78e6852 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs index 67806d578c8e..409b0b269615 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), llvm_target: "riscv64".into(), pointer_width: 64, arch: "riscv64".into(), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs index cd10f3afaac0..ade9d77624bd 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs @@ -4,7 +4,7 @@ pub fn target() -> Target { Target { llvm_target: "riscv64-unknown-openbsd".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), options: TargetOptions { code_model: Some(CodeModel::Medium), diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs index f371e09bed74..87aba9171b41 100644 --- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { - data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), llvm_target: "riscv64".into(), pointer_width: 64, arch: "riscv64".into(), From 0e23d90e26571fc53f0263858d9558d03de6cd30 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 6 Nov 2022 20:20:43 +0100 Subject: [PATCH 126/221] Extend rust-logo GUI test to check there is no filter for other logos --- src/test/rustdoc-gui/rust-logo.goml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml index 6c8dc8594193..816cc9abd693 100644 --- a/src/test/rustdoc-gui/rust-logo.goml +++ b/src/test/rustdoc-gui/rust-logo.goml @@ -17,6 +17,15 @@ define-function: ( ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), ("reload"), ("assert-css", (".rust-logo", {"filter": |filter|})), + // Now we check that the non-rust logos don't have a CSS filter set. + ("goto", "file://" + |DOC_PATH| + "/huge_logo/index.html"), + // Changing theme on the new page (again...). + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + // Check there is no rust logo + ("assert-false", ".rust-logo"), + // Check there is no filter. + ("assert-css", (".sidebar .logo-container img", {"filter": "none"})), ], ) From b97ec85e96ae4d724bf12ad0d1acb05c80158891 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 3 Sep 2022 18:06:25 -0400 Subject: [PATCH 127/221] Add a codegen test for rust-lang/rust#96152 --- src/test/assembly/strict_provenance.rs | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/test/assembly/strict_provenance.rs diff --git a/src/test/assembly/strict_provenance.rs b/src/test/assembly/strict_provenance.rs new file mode 100644 index 000000000000..01f1957d5f66 --- /dev/null +++ b/src/test/assembly/strict_provenance.rs @@ -0,0 +1,37 @@ +// assembly-output: emit-asm +// compile-flags: -Copt-level=1 +// only-x86_64 +// min-llvm-version: 15.0 +#![crate_type = "rlib"] + +// CHECK-LABEL: old_style +// CHECK: movq %{{.*}}, %rax +// CHECK: orq $1, %rax +// CHECK: retq +#[no_mangle] +pub fn old_style(a: *mut u8) -> *mut u8 { + (a as usize | 1) as *mut u8 +} + +// CHECK-LABEL: cheri_compat +// CHECK: movq %{{.*}}, %rax +// CHECK: orq $1, %rax +// CHECK: retq +#[no_mangle] +pub fn cheri_compat(a: *mut u8) -> *mut u8 { + let old = a as usize; + let new = old | 1; + let diff = new.wrapping_sub(old); + a.wrapping_add(diff) +} + +// CHECK-LABEL: definitely_not_a_null_pointer +// CHECK: movq %{{.*}}, %rax +// CHECK: orq $1, %rax +// CHECK: retq +#[no_mangle] +pub fn definitely_not_a_null_pointer(a: *mut u8) -> *mut u8 { + let old = a as usize; + let new = old | 1; + a.wrapping_sub(old).wrapping_add(new) +} From 16edaa56bafca405f4bae43d3f18480af13dfc90 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 5 Nov 2022 14:26:54 -0400 Subject: [PATCH 128/221] Limit efiapi calling convention to supported arches Supported architectures in UEFI are described here: https://uefi.org/specs/UEFI/2.10/02_Overview.html#calling-conventions Changes to tests modeled on 8240e7aa101815e2009c7d03b33dd2566d843e73. https://github.com/rust-lang/rust/issues/65815 --- compiler/rustc_target/src/spec/mod.rs | 4 +- .../feature-gates/feature-gate-abi-efiapi.rs | 33 +++++ .../feature-gate-abi-efiapi.stderr | 66 ++++++++++ src/test/ui/feature-gates/feature-gate-abi.rs | 8 -- .../ui/feature-gates/feature-gate-abi.stderr | 119 +++++------------- 5 files changed, 130 insertions(+), 100 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-abi-efiapi.rs create mode 100644 src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 72b088d663b1..0fe600bd0588 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1941,8 +1941,10 @@ impl Target { | PlatformIntrinsic | Unadjusted | Cdecl { .. } - | EfiApi | RustCold => true, + EfiApi => { + ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..]) + } X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), Aapcs { .. } => "arm" == self.arch, CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), diff --git a/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs b/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs new file mode 100644 index 000000000000..0c0d736acd04 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs @@ -0,0 +1,33 @@ +// needs-llvm-components: x86 +// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +// Functions +extern "efiapi" fn f1() {} //~ ERROR efiapi ABI is experimental + +// Methods in trait defintion +trait Tr { + extern "efiapi" fn f2(); //~ ERROR efiapi ABI is experimental + extern "efiapi" fn f3() {} //~ ERROR efiapi ABI is experimental +} + +struct S; + +// Methods in trait impl +impl Tr for S { + extern "efiapi" fn f2() {} //~ ERROR efiapi ABI is experimental +} + +// Methods in inherent impl +impl S { + extern "efiapi" fn f4() {} //~ ERROR efiapi ABI is experimental +} + +// Function pointer types +type A = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental + +// Foreign modules +extern "efiapi" {} //~ ERROR efiapi ABI is experimental diff --git a/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr b/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr new file mode 100644 index 000000000000..5b01dcc6d859 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr @@ -0,0 +1,66 @@ +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:9:8 + | +LL | extern "efiapi" fn f1() {} + | ^^^^^^^^ + | + = note: see issue #65815 for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:13:12 + | +LL | extern "efiapi" fn f2(); + | ^^^^^^^^ + | + = note: see issue #65815 for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:14:12 + | +LL | extern "efiapi" fn f3() {} + | ^^^^^^^^ + | + = note: see issue #65815 for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:21:12 + | +LL | extern "efiapi" fn f2() {} + | ^^^^^^^^ + | + = note: see issue #65815 for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:26:12 + | +LL | extern "efiapi" fn f4() {} + | ^^^^^^^^ + | + = note: see issue #65815 for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:30:17 + | +LL | type A = extern "efiapi" fn(); + | ^^^^^^^^ + | + = note: see issue #65815 for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error[E0658]: efiapi ABI is experimental and subject to change + --> $DIR/feature-gate-abi-efiapi.rs:33:8 + | +LL | extern "efiapi" {} + | ^^^^^^^^ + | + = note: see issue #65815 for more information + = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs index 15b674c62e44..712655f9775d 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.rs +++ b/src/test/ui/feature-gates/feature-gate-abi.rs @@ -1,6 +1,5 @@ // gate-test-intrinsics // gate-test-platform_intrinsics -// gate-test-abi_efiapi // compile-flags: --crate-type=rlib #![feature(no_core, lang_items)] @@ -18,7 +17,6 @@ extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change -extern "efiapi" fn f10() {} //~ ERROR efiapi ABI is experimental and subject to change // Methods in trait definition trait Tr { @@ -27,10 +25,8 @@ trait Tr { extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn dm10() {} //~ ERROR efiapi ABI is experimental and subject to change } struct S; @@ -42,7 +38,6 @@ impl Tr for S { extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn m10() {} //~ ERROR efiapi ABI is experimental and subject to change } // Methods in inherent impl @@ -52,17 +47,14 @@ impl S { extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to change } // Function pointer types type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change -type A10 = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental and subject to change // Foreign modules extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental extern "rust-call" {} //~ ERROR rust-call ABI is subject to change -extern "efiapi" {} //~ ERROR efiapi ABI is experimental and subject to change diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index 33ec250f0906..e9791b9513f4 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -1,5 +1,5 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:16:8 + --> $DIR/feature-gate-abi.rs:15:8 | LL | extern "rust-intrinsic" fn f1() {} | ^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:18:8 + --> $DIR/feature-gate-abi.rs:17:8 | LL | extern "platform-intrinsic" fn f2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | extern "platform-intrinsic" fn f2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:20:8 + --> $DIR/feature-gate-abi.rs:19:8 | LL | extern "rust-call" fn f4(_: ()) {} | ^^^^^^^^^^^ @@ -24,17 +24,8 @@ LL | extern "rust-call" fn f4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:21:8 - | -LL | extern "efiapi" fn f10() {} - | ^^^^^^^^ - | - = note: see issue #65815 for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:25:12 + --> $DIR/feature-gate-abi.rs:23:12 | LL | extern "rust-intrinsic" fn m1(); | ^^^^^^^^^^^^^^^^ @@ -42,7 +33,7 @@ LL | extern "rust-intrinsic" fn m1(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:27:12 + --> $DIR/feature-gate-abi.rs:25:12 | LL | extern "platform-intrinsic" fn m2(); | ^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +42,7 @@ LL | extern "platform-intrinsic" fn m2(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:29:12 + --> $DIR/feature-gate-abi.rs:27:12 | LL | extern "rust-call" fn m4(_: ()); | ^^^^^^^^^^^ @@ -59,17 +50,8 @@ LL | extern "rust-call" fn m4(_: ()); = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:30:12 - | -LL | extern "efiapi" fn m10(); - | ^^^^^^^^ - | - = note: see issue #65815 for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:32:12 + --> $DIR/feature-gate-abi.rs:29:12 | LL | extern "rust-call" fn dm4(_: ()) {} | ^^^^^^^^^^^ @@ -77,17 +59,8 @@ LL | extern "rust-call" fn dm4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:33:12 - | -LL | extern "efiapi" fn dm10() {} - | ^^^^^^^^ - | - = note: see issue #65815 for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:40:12 + --> $DIR/feature-gate-abi.rs:36:12 | LL | extern "rust-intrinsic" fn m1() {} | ^^^^^^^^^^^^^^^^ @@ -95,7 +68,7 @@ LL | extern "rust-intrinsic" fn m1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:42:12 + --> $DIR/feature-gate-abi.rs:38:12 | LL | extern "platform-intrinsic" fn m2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +77,7 @@ LL | extern "platform-intrinsic" fn m2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:44:12 + --> $DIR/feature-gate-abi.rs:40:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -112,17 +85,8 @@ LL | extern "rust-call" fn m4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:45:12 - | -LL | extern "efiapi" fn m10() {} - | ^^^^^^^^ - | - = note: see issue #65815 for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:50:12 + --> $DIR/feature-gate-abi.rs:45:12 | LL | extern "rust-intrinsic" fn im1() {} | ^^^^^^^^^^^^^^^^ @@ -130,7 +94,7 @@ LL | extern "rust-intrinsic" fn im1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:52:12 + --> $DIR/feature-gate-abi.rs:47:12 | LL | extern "platform-intrinsic" fn im2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +103,7 @@ LL | extern "platform-intrinsic" fn im2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:54:12 + --> $DIR/feature-gate-abi.rs:49:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -147,17 +111,8 @@ LL | extern "rust-call" fn im4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:55:12 - | -LL | extern "efiapi" fn im10() {} - | ^^^^^^^^ - | - = note: see issue #65815 for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:59:18 + --> $DIR/feature-gate-abi.rs:53:18 | LL | type A1 = extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^ @@ -165,7 +120,7 @@ LL | type A1 = extern "rust-intrinsic" fn(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:60:18 + --> $DIR/feature-gate-abi.rs:54:18 | LL | type A2 = extern "platform-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +129,7 @@ LL | type A2 = extern "platform-intrinsic" fn(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:61:18 + --> $DIR/feature-gate-abi.rs:55:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -182,17 +137,8 @@ LL | type A4 = extern "rust-call" fn(_: ()); = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:62:19 - | -LL | type A10 = extern "efiapi" fn(); - | ^^^^^^^^ - | - = note: see issue #65815 for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:65:8 + --> $DIR/feature-gate-abi.rs:58:8 | LL | extern "rust-intrinsic" {} | ^^^^^^^^^^^^^^^^ @@ -200,7 +146,7 @@ LL | extern "rust-intrinsic" {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:66:8 + --> $DIR/feature-gate-abi.rs:59:8 | LL | extern "platform-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +155,7 @@ LL | extern "platform-intrinsic" {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:67:8 + --> $DIR/feature-gate-abi.rs:60:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -217,63 +163,54 @@ LL | extern "rust-call" {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:68:8 - | -LL | extern "efiapi" {} - | ^^^^^^^^ - | - = note: see issue #65815 for more information - = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable - error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:25:32 + --> $DIR/feature-gate-abi.rs:23:32 | LL | extern "rust-intrinsic" fn m1(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:27:36 + --> $DIR/feature-gate-abi.rs:25:36 | LL | extern "platform-intrinsic" fn m2(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:16:33 + --> $DIR/feature-gate-abi.rs:15:33 | LL | extern "rust-intrinsic" fn f1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:18:37 + --> $DIR/feature-gate-abi.rs:17:37 | LL | extern "platform-intrinsic" fn f2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:40:37 + --> $DIR/feature-gate-abi.rs:36:37 | LL | extern "rust-intrinsic" fn m1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:42:41 + --> $DIR/feature-gate-abi.rs:38:41 | LL | extern "platform-intrinsic" fn m2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:50:38 + --> $DIR/feature-gate-abi.rs:45:38 | LL | extern "rust-intrinsic" fn im1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:52:42 + --> $DIR/feature-gate-abi.rs:47:42 | LL | extern "platform-intrinsic" fn im2() {} | ^^ -error: aborting due to 34 previous errors +error: aborting due to 27 previous errors For more information about this error, try `rustc --explain E0658`. From a398e09e42b9b3263dd20d45b1c6f1fd4fe8ce3b Mon Sep 17 00:00:00 2001 From: yancy Date: Sun, 6 Nov 2022 23:05:16 +0100 Subject: [PATCH 129/221] rustdoc: Add an example for round that is different from truncate --- library/std/src/f32.rs | 2 ++ library/std/src/f64.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index dafcd8767441..4127c4056f24 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -77,9 +77,11 @@ impl f32 { /// ``` /// let f = 3.3_f32; /// let g = -3.3_f32; + /// let h = -3.7_f32; /// /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); + /// assert_eq!(h.round(), -4.0); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 77048f9a28f2..cc64258da60d 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -77,9 +77,11 @@ impl f64 { /// ``` /// let f = 3.3_f64; /// let g = -3.3_f64; + /// let h = -3.7_f64; /// /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); + /// assert_eq!(h.round(), -4.0); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] From dba6fc3ef529824d9fc3248001089364888f3490 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2022 12:02:33 +1100 Subject: [PATCH 130/221] Make underscore_literal_suffix a hard error. It's been a warning for 5.5 years. Time to make it a hard error. Closes #42326. --- compiler/rustc_lexer/src/lib.rs | 9 ++++++--- compiler/rustc_parse/src/lexer/mod.rs | 12 +----------- .../ui/parser/underscore-suffix-for-string.rs | 17 +++++++++++++---- .../parser/underscore-suffix-for-string.stderr | 13 ++++++++----- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 51515976e4ee..dd2c09cae02f 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -88,7 +88,9 @@ pub enum TokenKind { /// tokens. UnknownPrefix, - /// Examples: `"12_u8"`, `"1.0e-40"`, `b"123`. + /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid + /// suffix, but may be present here on string and float literals. Users of + /// this type will need to check for and reject that case. /// /// See [LiteralKind] for more details. Literal { kind: LiteralKind, suffix_start: u32 }, @@ -840,12 +842,13 @@ impl Cursor<'_> { self.eat_decimal_digits() } - // Eats the suffix of the literal, e.g. "_u8". + // Eats the suffix of the literal, e.g. "u8". fn eat_literal_suffix(&mut self) { self.eat_identifier(); } - // Eats the identifier. + // Eats the identifier. Note: succeeds on `_`, which isn't a valid + // identifer. fn eat_identifier(&mut self) { if !is_id_start(self.first()) { return; diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 462bce16ad71..de8f1c00c129 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -175,20 +175,10 @@ impl<'a> StringReader<'a> { if string == "_" { self.sess .span_diagnostic - .struct_span_warn( + .struct_span_err( self.mk_sp(suffix_start, self.pos), "underscore literal suffix is not allowed", ) - .warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ) - .note( - "see issue #42326 \ - \ - for more information", - ) .emit(); None } else { diff --git a/src/test/ui/parser/underscore-suffix-for-string.rs b/src/test/ui/parser/underscore-suffix-for-string.rs index 2e0ebe2cfa44..bd260752e04d 100644 --- a/src/test/ui/parser/underscore-suffix-for-string.rs +++ b/src/test/ui/parser/underscore-suffix-for-string.rs @@ -1,8 +1,17 @@ -// check-pass +macro_rules! sink { + ($tt:tt) => {()} +} fn main() { let _ = "Foo"_; - //~^ WARNING underscore literal suffix is not allowed - //~| WARNING this was previously accepted - //~| NOTE issue #42326 + //~^ ERROR underscore literal suffix is not allowed + + // This is ok, because `__` is a valid identifier and the macro consumes it + // before proper parsing happens. + let _ = sink!("Foo"__); + + // This is not ok, even as an input to a macro, because the `_` suffix is + // never allowed. + sink!("Foo"_); + //~^ ERROR underscore literal suffix is not allowed } diff --git a/src/test/ui/parser/underscore-suffix-for-string.stderr b/src/test/ui/parser/underscore-suffix-for-string.stderr index 00c7657f17bd..2fe2c130eb21 100644 --- a/src/test/ui/parser/underscore-suffix-for-string.stderr +++ b/src/test/ui/parser/underscore-suffix-for-string.stderr @@ -1,11 +1,14 @@ -warning: underscore literal suffix is not allowed - --> $DIR/underscore-suffix-for-string.rs:4:18 +error: underscore literal suffix is not allowed + --> $DIR/underscore-suffix-for-string.rs:6:18 | LL | let _ = "Foo"_; | ^ + +error: underscore literal suffix is not allowed + --> $DIR/underscore-suffix-for-string.rs:15:16 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: see issue #42326 for more information +LL | sink!("Foo"_); + | ^ -warning: 1 warning emitted +error: aborting due to 2 previous errors From 152646f23fababe13f9fdd852c9b4efb10f1e150 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Nov 2022 17:14:05 +0000 Subject: [PATCH 131/221] Don't normalize constants unless they need normalization --- compiler/rustc_trait_selection/src/traits/project.rs | 2 +- compiler/rustc_trait_selection/src/traits/query/normalize.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index daee5dd8f02e..7f829e46bbb1 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -647,7 +647,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { #[instrument(skip(self), level = "debug")] fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> { let tcx = self.selcx.tcx(); - if tcx.lazy_normalization() { + if tcx.lazy_normalization() || !needs_normalization(&constant, self.param_env.reveal()) { constant } else { let constant = constant.super_fold_with(self); diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 715f5be8e2f4..a7932b332c94 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -353,6 +353,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { &mut self, constant: ty::Const<'tcx>, ) -> Result, Self::Error> { + if !needs_normalization(&constant, self.param_env.reveal()) { + return Ok(constant); + } + let constant = constant.try_super_fold_with(self)?; debug!(?constant, ?self.param_env); Ok(crate::traits::project::with_replaced_escaping_bound_vars( From 6994651b6c52e010dc93efbe4f90aa3816d79f5c Mon Sep 17 00:00:00 2001 From: jeremyd2019 Date: Sun, 6 Nov 2022 11:51:12 -0800 Subject: [PATCH 132/221] fix debuginfo for windows_gnullvm_base.rs These lines (including the FIXME comment) were added to windows_gnu_base.rs in cf2c492ef8c87c049b4e3a62f43c841aafc88cba but windows_gnullvm_base.rs was not updated. This resulted in an error `LLVM ERROR: dwo only supported with ELF and Wasm` attempting to build on aarch64-pc-windows-gnullvm. Signed-off-by: Jeremy Drake --- compiler/rustc_target/src/spec/windows_gnullvm_base.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs index 58210c75a3da..cada28652f98 100644 --- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs @@ -1,4 +1,5 @@ -use crate::spec::{cvs, Cc, LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; +use std::borrow::Cow; pub fn opts() -> TargetOptions { // We cannot use `-nodefaultlibs` because compiler-rt has to be passed @@ -36,7 +37,10 @@ pub fn opts() -> TargetOptions { eh_frame_header: false, no_default_libraries: false, has_thread_local: true, - + // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to + // output DWO, despite using DWARF, doesn't use ELF.. + debuginfo_kind: DebuginfoKind::Pdb, + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..Default::default() } } From 6b2257b1b86985aec3b3d33977c78fdaa0c70096 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 6 Nov 2022 20:58:16 +0900 Subject: [PATCH 133/221] return `None` when def_kind is `DefKind::Use` --- src/librustdoc/passes/collect_intra_doc_links.rs | 3 ++- src/test/rustdoc-ui/issue-103997.rs | 6 ++++++ src/test/rustdoc-ui/issue-103997.stderr | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-ui/issue-103997.rs create mode 100644 src/test/rustdoc-ui/issue-103997.stderr diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0bd0dbbeb702..37a28b6b7bd8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -402,6 +402,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }) .and_then(|self_id| match tcx.def_kind(self_id) { DefKind::Impl => self.def_id_to_res(self_id), + DefKind::Use => None, def_kind => Some(Res::Def(def_kind, self_id)), }) } @@ -1772,7 +1773,6 @@ fn resolution_failure( // Otherwise, it must be an associated item or variant let res = partial_res.expect("None case was handled by `last_found_module`"); - let name = res.name(tcx); let kind = match res { Res::Def(kind, _) => Some(kind), Res::Primitive(_) => None, @@ -1814,6 +1814,7 @@ fn resolution_failure( } else { "associated item" }; + let name = res.name(tcx); let note = format!( "the {} `{}` has no {} named `{}`", res.descr(), diff --git a/src/test/rustdoc-ui/issue-103997.rs b/src/test/rustdoc-ui/issue-103997.rs new file mode 100644 index 000000000000..36f42fb15f7e --- /dev/null +++ b/src/test/rustdoc-ui/issue-103997.rs @@ -0,0 +1,6 @@ +// check-pass + +pub fn foo() {} + +/// [`foo`](Self::foo) //~ WARNING unresolved link to `Self::foo` +pub use foo as bar; diff --git a/src/test/rustdoc-ui/issue-103997.stderr b/src/test/rustdoc-ui/issue-103997.stderr new file mode 100644 index 000000000000..c06db91496f8 --- /dev/null +++ b/src/test/rustdoc-ui/issue-103997.stderr @@ -0,0 +1,10 @@ +warning: unresolved link to `Self::foo` + --> $DIR/issue-103997.rs:5:13 + | +LL | /// [`foo`](Self::foo) + | ^^^^^^^^^ no item named `Self` in scope + | + = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default + +warning: 1 warning emitted + From ee7a80211a066b8345119ce258361a8ad22986b4 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 7 Nov 2022 03:25:54 +0000 Subject: [PATCH 134/221] Migrate linker-plugin-lto.md compatibility table to show Rust ranges The helper shell script has been rewritten as a helper Python script that generates the range-based table. --- src/doc/rustc/src/linker-plugin-lto.md | 93 +++++++++++++------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 5730f95ad2b9..9272b9ac9b2d 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -131,24 +131,47 @@ able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS ## Toolchain Compatibility - @@ -166,37 +189,13 @@ The following table shows known good combinations of toolchain versions. | Rust Version | Clang Version | |--------------|---------------| -| Rust 1.34 | Clang 8 | -| Rust 1.35 | Clang 8 | -| Rust 1.36 | Clang 8 | -| Rust 1.37 | Clang 8 | -| Rust 1.38 | Clang 9 | -| Rust 1.39 | Clang 9 | -| Rust 1.40 | Clang 9 | -| Rust 1.41 | Clang 9 | -| Rust 1.42 | Clang 9 | -| Rust 1.43 | Clang 9 | -| Rust 1.44 | Clang 9 | -| Rust 1.45 | Clang 10 | -| Rust 1.46 | Clang 10 | -| Rust 1.47 | Clang 11 | -| Rust 1.48 | Clang 11 | -| Rust 1.49 | Clang 11 | -| Rust 1.50 | Clang 11 | -| Rust 1.51 | Clang 11 | -| Rust 1.52 | Clang 12 | -| Rust 1.53 | Clang 12 | -| Rust 1.54 | Clang 12 | -| Rust 1.55 | Clang 12 | -| Rust 1.56 | Clang 13 | -| Rust 1.57 | Clang 13 | -| Rust 1.58 | Clang 13 | -| Rust 1.59 | Clang 13 | -| Rust 1.60 | Clang 14 | -| Rust 1.61 | Clang 14 | -| Rust 1.62 | Clang 14 | -| Rust 1.63 | Clang 14 | -| Rust 1.64 | Clang 14 | -| Rust 1.65 | Clang 15 | +| 1.34 - 1.37 | 8 | +| 1.38 - 1.44 | 9 | +| 1.45 - 1.46 | 10 | +| 1.47 - 1.51 | 11 | +| 1.52 - 1.55 | 12 | +| 1.56 - 1.59 | 13 | +| 1.60 - 1.64 | 14 | +| 1.65 | 15 | Note that the compatibility policy for this feature might change in the future. From 009f80b987214aaae42c94d2fc8a33aaf689ab69 Mon Sep 17 00:00:00 2001 From: wanghaha-dev Date: Mon, 7 Nov 2022 14:33:33 +0800 Subject: [PATCH 135/221] Modify comment syntax error --- compiler/rustc_macros/src/diagnostics/error.rs | 4 ++-- library/alloc/src/collections/mod.rs | 2 +- .../ui/conditional-compilation/cfg_accessible-not_sure.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index 0b1ededa7751..4612f54e4b17 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -84,7 +84,7 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { } } -/// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration +/// Emit an error diagnostic for an invalid attribute (optionally performing additional decoration /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// /// For methods that return a `Result<_, DiagnosticDeriveError>`: @@ -126,7 +126,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag } } -/// Emit a error diagnostic for an invalid nested attribute (optionally performing additional +/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional /// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// /// For methods that return a `Result<_, DiagnosticDeriveError>`: diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 161a375736c6..3e0b0f735508 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -139,7 +139,7 @@ impl Display for TryReserveError { " because the computed capacity exceeded the collection's maximum" } TryReserveErrorKind::AllocError { .. } => { - " because the memory allocator returned a error" + " because the memory allocator returned an error" } }; fmt.write_str(reason) diff --git a/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs b/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs index d68acd2451fb..99a7949db173 100644 --- a/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs +++ b/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs @@ -46,7 +46,7 @@ const C: bool = true; trait Trait {} impl dyn Trait { fn existing() {} } -// FIXME: Should be a error for edition > 2015 +// FIXME: Should be an error for edition > 2015 #[cfg_accessible(Trait::existing)] //~ ERROR not sure const A: bool = true; #[cfg_accessible(Trait::unresolved)] //~ ERROR not sure From 80e4e72fcd180ef62baa3a5c2e03fad75e41848b Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Nov 2022 08:10:25 +0100 Subject: [PATCH 136/221] fully move `on_unimplemented` to error reporting --- .../rustc_hir_analysis/src/check/check.rs | 3 +- .../rustc_hir_typeck/src/method/suggest.rs | 3 +- .../src/traits/error_reporting/mod.rs | 16 +- .../error_reporting/on_unimplemented.rs | 398 +++++++++++++++++- .../rustc_trait_selection/src/traits/mod.rs | 2 - .../src/traits/on_unimplemented.rs | 393 ----------------- 6 files changed, 404 insertions(+), 411 deletions(-) delete mode 100644 compiler/rustc_trait_selection/src/traits/on_unimplemented.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 133bbd52b914..8f62df683cba 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -26,6 +26,7 @@ use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVE use rustc_span::symbol::sym; use rustc_span::{self, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -655,7 +656,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { // an error would be reported if this fails. - let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id()); + let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id()); } pub(super) fn check_specialization_validity<'tcx>( diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 04ecd2757b42..50e2b0f89267 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -23,10 +23,11 @@ use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span}; +use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote; use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ - FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote, + FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, }; use std::cmp::Ordering; 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 54281f912054..a871a2501371 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -3,14 +3,17 @@ pub mod suggestions; use super::{ FulfillmentContext, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, - Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, - OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation, - SelectionContext, SelectionError, TraitNotObjectSafe, + Obligation, ObligationCause, ObligationCauseCode, OutputTypeParameterMismatch, Overflow, + PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, }; - use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt, TyCtxtInferExt}; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use crate::traits::query::normalize::AtExt as _; +use crate::traits::specialize::to_pretty_impl_header; +use on_unimplemented::OnUnimplementedNote; +use on_unimplemented::TypeErrCtxtExt as _; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, @@ -40,11 +43,6 @@ use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; use std::iter; use std::ops::ControlFlow; - -use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::query::normalize::AtExt as _; -use crate::traits::specialize::to_pretty_impl_header; -use on_unimplemented::TypeErrCtxtExt as _; use suggestions::TypeErrCtxtExt as _; pub use rustc_infer::traits::error_reporting::*; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 5eef54c6330d..82f0440b3078 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -1,14 +1,22 @@ -use super::{ - ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation, -}; +use super::{ObligationCauseCode, PredicateObligation}; use crate::infer::error_reporting::TypeErrCtxt; +use rustc_ast::{MetaItem, NestedMetaItem}; +use rustc_attr as attr; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::SubstsRef; -use rustc_middle::ty::{self, GenericParamDefKind}; -use rustc_span::symbol::sym; +use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; +use rustc_parse_format::{ParseMode, Parser, Piece, Position}; +use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::{Span, DUMMY_SP}; use std::iter; +use crate::errors::{ + EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, +}; + use super::InferCtxtPrivExt; pub trait TypeErrCtxtExt<'tcx> { @@ -276,3 +284,383 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } } + +#[derive(Clone, Debug)] +pub struct OnUnimplementedFormatString(Symbol); + +#[derive(Debug)] +pub struct OnUnimplementedDirective { + pub condition: Option, + pub subcommands: Vec, + pub message: Option, + pub label: Option, + pub note: Option, + pub parent_label: Option, + pub append_const_msg: Option>, +} + +/// For the `#[rustc_on_unimplemented]` attribute +#[derive(Default)] +pub struct OnUnimplementedNote { + pub message: Option, + pub label: Option, + pub note: Option, + pub parent_label: Option, + /// Append a message for `~const Trait` errors. `None` means not requested and + /// should fallback to a generic message, `Some(None)` suggests using the default + /// appended message, `Some(Some(s))` suggests use the `s` message instead of the + /// default one.. + pub append_const_msg: Option>, +} + +impl<'tcx> OnUnimplementedDirective { + fn parse( + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + items: &[NestedMetaItem], + span: Span, + is_root: bool, + ) -> Result { + let mut errored = None; + let mut item_iter = items.iter(); + + let parse_value = |value_str| { + OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some) + }; + + let condition = if is_root { + None + } else { + let cond = item_iter + .next() + .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))? + .meta_item() + .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?; + attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| { + if let Some(value) = cfg.value && let Err(guar) = parse_value(value) { + errored = Some(guar); + } + true + }); + Some(cond.clone()) + }; + + let mut message = None; + let mut label = None; + let mut note = None; + let mut parent_label = None; + let mut subcommands = vec![]; + let mut append_const_msg = None; + + for item in item_iter { + if item.has_name(sym::message) && message.is_none() { + if let Some(message_) = item.value_str() { + message = parse_value(message_)?; + continue; + } + } else if item.has_name(sym::label) && label.is_none() { + if let Some(label_) = item.value_str() { + label = parse_value(label_)?; + continue; + } + } else if item.has_name(sym::note) && note.is_none() { + if let Some(note_) = item.value_str() { + note = parse_value(note_)?; + continue; + } + } else if item.has_name(sym::parent_label) && parent_label.is_none() { + if let Some(parent_label_) = item.value_str() { + parent_label = parse_value(parent_label_)?; + continue; + } + } else if item.has_name(sym::on) + && is_root + && message.is_none() + && label.is_none() + && note.is_none() + { + if let Some(items) = item.meta_item_list() { + match Self::parse(tcx, item_def_id, &items, item.span(), false) { + Ok(subcommand) => subcommands.push(subcommand), + Err(reported) => errored = Some(reported), + }; + continue; + } + } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() { + if let Some(msg) = item.value_str() { + append_const_msg = Some(Some(msg)); + continue; + } else if item.is_word() { + append_const_msg = Some(None); + continue; + } + } + + // nothing found + tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() }); + } + + if let Some(reported) = errored { + Err(reported) + } else { + Ok(OnUnimplementedDirective { + condition, + subcommands, + message, + label, + note, + parent_label, + append_const_msg, + }) + } + } + + pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result, ErrorGuaranteed> { + let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) else { + return Ok(None); + }; + + let result = if let Some(items) = attr.meta_item_list() { + Self::parse(tcx, item_def_id, &items, attr.span, true).map(Some) + } else if let Some(value) = attr.value_str() { + Ok(Some(OnUnimplementedDirective { + condition: None, + message: None, + subcommands: vec![], + label: Some(OnUnimplementedFormatString::try_parse( + tcx, + item_def_id, + value, + attr.span, + )?), + note: None, + parent_label: None, + append_const_msg: None, + })) + } else { + let reported = + tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str"); + return Err(reported); + }; + debug!("of_item({:?}) = {:?}", item_def_id, result); + result + } + + pub fn evaluate( + &self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + options: &[(Symbol, Option)], + ) -> OnUnimplementedNote { + let mut message = None; + let mut label = None; + let mut note = None; + let mut parent_label = None; + let mut append_const_msg = None; + info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); + + let options_map: FxHashMap = + options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); + + for command in self.subcommands.iter().chain(Some(self)).rev() { + if let Some(ref condition) = command.condition && !attr::eval_condition( + condition, + &tcx.sess.parse_sess, + Some(tcx.features()), + &mut |cfg| { + let value = cfg.value.map(|v| { + OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map) + }); + + options.contains(&(cfg.name, value)) + }, + ) { + debug!("evaluate: skipping {:?} due to condition", command); + continue; + } + debug!("evaluate: {:?} succeeded", command); + if let Some(ref message_) = command.message { + message = Some(message_.clone()); + } + + if let Some(ref label_) = command.label { + label = Some(label_.clone()); + } + + if let Some(ref note_) = command.note { + note = Some(note_.clone()); + } + + if let Some(ref parent_label_) = command.parent_label { + parent_label = Some(parent_label_.clone()); + } + + append_const_msg = command.append_const_msg; + } + + OnUnimplementedNote { + label: label.map(|l| l.format(tcx, trait_ref, &options_map)), + message: message.map(|m| m.format(tcx, trait_ref, &options_map)), + note: note.map(|n| n.format(tcx, trait_ref, &options_map)), + parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), + append_const_msg, + } + } +} + +impl<'tcx> OnUnimplementedFormatString { + fn try_parse( + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + from: Symbol, + err_sp: Span, + ) -> Result { + let result = OnUnimplementedFormatString(from); + result.verify(tcx, item_def_id, err_sp)?; + Ok(result) + } + + fn verify( + &self, + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + span: Span, + ) -> Result<(), ErrorGuaranteed> { + let trait_def_id = if tcx.is_trait(item_def_id) { + item_def_id + } else { + tcx.trait_id_of_impl(item_def_id) + .expect("expected `on_unimplemented` to correspond to a trait") + }; + let trait_name = tcx.item_name(trait_def_id); + let generics = tcx.generics_of(item_def_id); + let s = self.0.as_str(); + let parser = Parser::new(s, None, None, false, ParseMode::Format); + let mut result = Ok(()); + for token in parser { + match token { + Piece::String(_) => (), // Normal string, no need to check it + Piece::NextArgument(a) => match a.position { + Position::ArgumentNamed(s) => { + match Symbol::intern(s) { + // `{Self}` is allowed + kw::SelfUpper => (), + // `{ThisTraitsName}` is allowed + s if s == trait_name => (), + // `{from_method}` is allowed + sym::from_method => (), + // `{from_desugaring}` is allowed + sym::from_desugaring => (), + // `{ItemContext}` is allowed + sym::ItemContext => (), + // `{integral}` and `{integer}` and `{float}` are allowed + sym::integral | sym::integer_ | sym::float => (), + // So is `{A}` if A is a type parameter + s => match generics.params.iter().find(|param| param.name == s) { + Some(_) => (), + None => { + let reported = struct_span_err!( + tcx.sess, + span, + E0230, + "there is no parameter `{}` on {}", + s, + if trait_def_id == item_def_id { + format!("trait `{}`", trait_name) + } else { + "impl".to_string() + } + ) + .emit(); + result = Err(reported); + } + }, + } + } + // `{:1}` and `{}` are not to be used + Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { + let reported = struct_span_err!( + tcx.sess, + span, + E0231, + "only named substitution parameters are allowed" + ) + .emit(); + result = Err(reported); + } + }, + } + } + + result + } + + pub fn format( + &self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + options: &FxHashMap, + ) -> String { + let name = tcx.item_name(trait_ref.def_id); + let trait_str = tcx.def_path_str(trait_ref.def_id); + let generics = tcx.generics_of(trait_ref.def_id); + let generic_map = generics + .params + .iter() + .filter_map(|param| { + let value = match param.kind { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + trait_ref.substs[param.index as usize].to_string() + } + GenericParamDefKind::Lifetime => return None, + }; + let name = param.name; + Some((name, value)) + }) + .collect::>(); + let empty_string = String::new(); + + let s = self.0.as_str(); + let parser = Parser::new(s, None, None, false, ParseMode::Format); + let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); + parser + .map(|p| match p { + Piece::String(s) => s, + Piece::NextArgument(a) => match a.position { + Position::ArgumentNamed(s) => { + let s = Symbol::intern(s); + match generic_map.get(&s) { + Some(val) => val, + None if s == name => &trait_str, + None => { + if let Some(val) = options.get(&s) { + val + } else if s == sym::from_desugaring || s == sym::from_method { + // don't break messages using these two arguments incorrectly + &empty_string + } else if s == sym::ItemContext { + &item_context + } else if s == sym::integral { + "{integral}" + } else if s == sym::integer_ { + "{integer}" + } else if s == sym::float { + "{float}" + } else { + bug!( + "broken on_unimplemented {:?} for {:?}: \ + no argument matching {:?}", + self.0, + trait_ref, + s + ) + } + } + } + } + _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0), + }, + }) + .collect() + } +} diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a33534f5747f..408dc7d3bd8f 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -12,7 +12,6 @@ pub mod error_reporting; mod fulfill; pub mod misc; mod object_safety; -mod on_unimplemented; pub mod outlives_bounds; mod project; pub mod query; @@ -58,7 +57,6 @@ pub use self::object_safety::astconv_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::ObjectSafetyViolation; -pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; pub use self::project::{normalize, normalize_projection_type, normalize_to}; pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs deleted file mode 100644 index fb062ea71c4c..000000000000 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ /dev/null @@ -1,393 +0,0 @@ -use rustc_ast::{MetaItem, NestedMetaItem}; -use rustc_attr as attr; -use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, ErrorGuaranteed}; -use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; -use rustc_parse_format::{ParseMode, Parser, Piece, Position}; -use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{Span, DUMMY_SP}; - -use crate::errors::{ - EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, -}; - -#[derive(Clone, Debug)] -pub struct OnUnimplementedFormatString(Symbol); - -#[derive(Debug)] -pub struct OnUnimplementedDirective { - pub condition: Option, - pub subcommands: Vec, - pub message: Option, - pub label: Option, - pub note: Option, - pub parent_label: Option, - pub append_const_msg: Option>, -} - -#[derive(Default)] -/// For the `#[rustc_on_unimplemented]` attribute -pub struct OnUnimplementedNote { - pub message: Option, - pub label: Option, - pub note: Option, - pub parent_label: Option, - /// Append a message for `~const Trait` errors. `None` means not requested and - /// should fallback to a generic message, `Some(None)` suggests using the default - /// appended message, `Some(Some(s))` suggests use the `s` message instead of the - /// default one.. - pub append_const_msg: Option>, -} - -impl<'tcx> OnUnimplementedDirective { - fn parse( - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - items: &[NestedMetaItem], - span: Span, - is_root: bool, - ) -> Result { - let mut errored = None; - let mut item_iter = items.iter(); - - let parse_value = |value_str| { - OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some) - }; - - let condition = if is_root { - None - } else { - let cond = item_iter - .next() - .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))? - .meta_item() - .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?; - attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| { - if let Some(value) = cfg.value && let Err(guar) = parse_value(value) { - errored = Some(guar); - } - true - }); - Some(cond.clone()) - }; - - let mut message = None; - let mut label = None; - let mut note = None; - let mut parent_label = None; - let mut subcommands = vec![]; - let mut append_const_msg = None; - - for item in item_iter { - if item.has_name(sym::message) && message.is_none() { - if let Some(message_) = item.value_str() { - message = parse_value(message_)?; - continue; - } - } else if item.has_name(sym::label) && label.is_none() { - if let Some(label_) = item.value_str() { - label = parse_value(label_)?; - continue; - } - } else if item.has_name(sym::note) && note.is_none() { - if let Some(note_) = item.value_str() { - note = parse_value(note_)?; - continue; - } - } else if item.has_name(sym::parent_label) && parent_label.is_none() { - if let Some(parent_label_) = item.value_str() { - parent_label = parse_value(parent_label_)?; - continue; - } - } else if item.has_name(sym::on) - && is_root - && message.is_none() - && label.is_none() - && note.is_none() - { - if let Some(items) = item.meta_item_list() { - match Self::parse(tcx, item_def_id, &items, item.span(), false) { - Ok(subcommand) => subcommands.push(subcommand), - Err(reported) => errored = Some(reported), - }; - continue; - } - } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() { - if let Some(msg) = item.value_str() { - append_const_msg = Some(Some(msg)); - continue; - } else if item.is_word() { - append_const_msg = Some(None); - continue; - } - } - - // nothing found - tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() }); - } - - if let Some(reported) = errored { - Err(reported) - } else { - Ok(OnUnimplementedDirective { - condition, - subcommands, - message, - label, - note, - parent_label, - append_const_msg, - }) - } - } - - pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result, ErrorGuaranteed> { - let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) else { - return Ok(None); - }; - - let result = if let Some(items) = attr.meta_item_list() { - Self::parse(tcx, item_def_id, &items, attr.span, true).map(Some) - } else if let Some(value) = attr.value_str() { - Ok(Some(OnUnimplementedDirective { - condition: None, - message: None, - subcommands: vec![], - label: Some(OnUnimplementedFormatString::try_parse( - tcx, - item_def_id, - value, - attr.span, - )?), - note: None, - parent_label: None, - append_const_msg: None, - })) - } else { - let reported = - tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str"); - return Err(reported); - }; - debug!("of_item({:?}) = {:?}", item_def_id, result); - result - } - - pub fn evaluate( - &self, - tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - options: &[(Symbol, Option)], - ) -> OnUnimplementedNote { - let mut message = None; - let mut label = None; - let mut note = None; - let mut parent_label = None; - let mut append_const_msg = None; - info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); - - let options_map: FxHashMap = - options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); - - for command in self.subcommands.iter().chain(Some(self)).rev() { - if let Some(ref condition) = command.condition && !attr::eval_condition( - condition, - &tcx.sess.parse_sess, - Some(tcx.features()), - &mut |cfg| { - let value = cfg.value.map(|v| { - OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map) - }); - - options.contains(&(cfg.name, value)) - }, - ) { - debug!("evaluate: skipping {:?} due to condition", command); - continue; - } - debug!("evaluate: {:?} succeeded", command); - if let Some(ref message_) = command.message { - message = Some(message_.clone()); - } - - if let Some(ref label_) = command.label { - label = Some(label_.clone()); - } - - if let Some(ref note_) = command.note { - note = Some(note_.clone()); - } - - if let Some(ref parent_label_) = command.parent_label { - parent_label = Some(parent_label_.clone()); - } - - append_const_msg = command.append_const_msg; - } - - OnUnimplementedNote { - label: label.map(|l| l.format(tcx, trait_ref, &options_map)), - message: message.map(|m| m.format(tcx, trait_ref, &options_map)), - note: note.map(|n| n.format(tcx, trait_ref, &options_map)), - parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), - append_const_msg, - } - } -} - -impl<'tcx> OnUnimplementedFormatString { - fn try_parse( - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - from: Symbol, - err_sp: Span, - ) -> Result { - let result = OnUnimplementedFormatString(from); - result.verify(tcx, item_def_id, err_sp)?; - Ok(result) - } - - fn verify( - &self, - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - span: Span, - ) -> Result<(), ErrorGuaranteed> { - let trait_def_id = if tcx.is_trait(item_def_id) { - item_def_id - } else { - tcx.trait_id_of_impl(item_def_id) - .expect("expected `on_unimplemented` to correspond to a trait") - }; - let trait_name = tcx.item_name(trait_def_id); - let generics = tcx.generics_of(item_def_id); - let s = self.0.as_str(); - let parser = Parser::new(s, None, None, false, ParseMode::Format); - let mut result = Ok(()); - for token in parser { - match token { - Piece::String(_) => (), // Normal string, no need to check it - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => { - match Symbol::intern(s) { - // `{Self}` is allowed - kw::SelfUpper => (), - // `{ThisTraitsName}` is allowed - s if s == trait_name => (), - // `{from_method}` is allowed - sym::from_method => (), - // `{from_desugaring}` is allowed - sym::from_desugaring => (), - // `{ItemContext}` is allowed - sym::ItemContext => (), - // `{integral}` and `{integer}` and `{float}` are allowed - sym::integral | sym::integer_ | sym::float => (), - // So is `{A}` if A is a type parameter - s => match generics.params.iter().find(|param| param.name == s) { - Some(_) => (), - None => { - let reported = struct_span_err!( - tcx.sess, - span, - E0230, - "there is no parameter `{}` on {}", - s, - if trait_def_id == item_def_id { - format!("trait `{}`", trait_name) - } else { - "impl".to_string() - } - ) - .emit(); - result = Err(reported); - } - }, - } - } - // `{:1}` and `{}` are not to be used - Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { - let reported = struct_span_err!( - tcx.sess, - span, - E0231, - "only named substitution parameters are allowed" - ) - .emit(); - result = Err(reported); - } - }, - } - } - - result - } - - pub fn format( - &self, - tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - options: &FxHashMap, - ) -> String { - let name = tcx.item_name(trait_ref.def_id); - let trait_str = tcx.def_path_str(trait_ref.def_id); - let generics = tcx.generics_of(trait_ref.def_id); - let generic_map = generics - .params - .iter() - .filter_map(|param| { - let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - trait_ref.substs[param.index as usize].to_string() - } - GenericParamDefKind::Lifetime => return None, - }; - let name = param.name; - Some((name, value)) - }) - .collect::>(); - let empty_string = String::new(); - - let s = self.0.as_str(); - let parser = Parser::new(s, None, None, false, ParseMode::Format); - let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); - parser - .map(|p| match p { - Piece::String(s) => s, - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => { - let s = Symbol::intern(s); - match generic_map.get(&s) { - Some(val) => val, - None if s == name => &trait_str, - None => { - if let Some(val) = options.get(&s) { - val - } else if s == sym::from_desugaring || s == sym::from_method { - // don't break messages using these two arguments incorrectly - &empty_string - } else if s == sym::ItemContext { - &item_context - } else if s == sym::integral { - "{integral}" - } else if s == sym::integer_ { - "{integer}" - } else if s == sym::float { - "{float}" - } else { - bug!( - "broken on_unimplemented {:?} for {:?}: \ - no argument matching {:?}", - self.0, - trait_ref, - s - ) - } - } - } - } - _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0), - }, - }) - .collect() - } -} From 397e5bb8c84acb58c7f3bf21be5a85e6f615af1a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Nov 2022 09:14:49 +0100 Subject: [PATCH 137/221] add FIXME to replace this env var in the future --- src/bootstrap/sanity.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 9890480709bd..bdfd5fe5c421 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -156,6 +156,9 @@ than building it. } // Some environments don't want or need these tools, such as when testing Miri. + // FIXME: it would be better to refactor this code to split necessary setup from pure sanity + // checks, and have a regular flag for skipping the latter. Also see + // . if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { continue; } @@ -218,6 +221,9 @@ than building it. } // Some environments don't want or need these tools, such as when testing Miri. + // FIXME: it would be better to refactor this code to split necessary setup from pure sanity + // checks, and have a regular flag for skipping the latter. Also see + // . if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { continue; } From 17044c1d008e2d7c776e33a1e16d291dabd6520e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Nov 2022 09:29:14 +0100 Subject: [PATCH 138/221] disable btree size tests on Miri --- library/alloc/src/collections/btree/node/tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index aadb0dc9c40d..64bce0ff8c04 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -94,6 +94,7 @@ fn test_partial_eq() { #[test] #[cfg(target_arch = "x86_64")] +#[cfg_attr(miri, ignore)] // We'd like to run Miri with layout randomization fn test_sizes() { assert_eq!(core::mem::size_of::>(), 16); assert_eq!(core::mem::size_of::>(), 16 + CAPACITY * 2 * 8); From 780952f922a52db435aff7b73cfdb6cb541083b8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Nov 2022 10:33:54 +0100 Subject: [PATCH 139/221] run alloc benchmarks in Miri and fix UB --- library/alloc/src/alloc/tests.rs | 1 - .../alloc/src/collections/vec_deque/tests.rs | 34 +++++++++++-------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/src/alloc/tests.rs index b2f0194599b2..1a5938fd34cf 100644 --- a/library/alloc/src/alloc/tests.rs +++ b/library/alloc/src/alloc/tests.rs @@ -22,7 +22,6 @@ fn allocate_zeroed() { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn alloc_owned_small(b: &mut Bencher) { b.iter(|| { let _: Box<_> = Box::new(10); diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 1f2daef213c3..a103531a20f2 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -3,7 +3,6 @@ use core::iter::TrustedLen; use super::*; #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_push_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -16,7 +15,6 @@ fn bench_push_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_push_front_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -29,12 +27,15 @@ fn bench_push_front_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_pop_back_100(b: &mut test::Bencher) { - let mut deq = VecDeque::::with_capacity(101); + let size = 100; + let mut deq = VecDeque::::with_capacity(size+1); + // We'll mess with private state to pretend like `deq` is filled. + // Make sure the buffer is initialized so that we don't read uninit memory. + unsafe { deq.ptr().write_bytes(0u8, size+1) }; b.iter(|| { - deq.head = 100; + deq.head = size; deq.tail = 0; while !deq.is_empty() { test::black_box(deq.pop_back()); @@ -43,9 +44,9 @@ fn bench_pop_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_retain_whole_10000(b: &mut test::Bencher) { - let v = (1..100000).collect::>(); + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::>(); b.iter(|| { let mut v = v.clone(); @@ -54,9 +55,9 @@ fn bench_retain_whole_10000(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_retain_odd_10000(b: &mut test::Bencher) { - let v = (1..100000).collect::>(); + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::>(); b.iter(|| { let mut v = v.clone(); @@ -65,23 +66,26 @@ fn bench_retain_odd_10000(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_retain_half_10000(b: &mut test::Bencher) { - let v = (1..100000).collect::>(); + let size = if cfg!(miri) { 1000 } else { 100000 }; + let v = (1..size).collect::>(); b.iter(|| { let mut v = v.clone(); - v.retain(|x| *x > 50000) + v.retain(|x| *x > size/2) }) } #[bench] -#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_pop_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::::with_capacity(101); + let size = 100; + let mut deq = VecDeque::::with_capacity(size+1); + // We'll mess with private state to pretend like `deq` is filled. + // Make sure the buffer is initialized so that we don't read uninit memory. + unsafe { deq.ptr().write_bytes(0u8, size+1) }; b.iter(|| { - deq.head = 100; + deq.head = size; deq.tail = 0; while !deq.is_empty() { test::black_box(deq.pop_front()); From 29d451ccb3adf8eecb42c68d532459e630e2096f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Nov 2022 15:24:49 +0100 Subject: [PATCH 140/221] fmt --- library/alloc/src/collections/vec_deque/tests.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index a103531a20f2..6e0f83020f95 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -29,10 +29,10 @@ fn bench_push_front_100(b: &mut test::Bencher) { #[bench] fn bench_pop_back_100(b: &mut test::Bencher) { let size = 100; - let mut deq = VecDeque::::with_capacity(size+1); + let mut deq = VecDeque::::with_capacity(size + 1); // We'll mess with private state to pretend like `deq` is filled. // Make sure the buffer is initialized so that we don't read uninit memory. - unsafe { deq.ptr().write_bytes(0u8, size+1) }; + unsafe { deq.ptr().write_bytes(0u8, size + 1) }; b.iter(|| { deq.head = size; @@ -72,17 +72,17 @@ fn bench_retain_half_10000(b: &mut test::Bencher) { b.iter(|| { let mut v = v.clone(); - v.retain(|x| *x > size/2) + v.retain(|x| *x > size / 2) }) } #[bench] fn bench_pop_front_100(b: &mut test::Bencher) { let size = 100; - let mut deq = VecDeque::::with_capacity(size+1); + let mut deq = VecDeque::::with_capacity(size + 1); // We'll mess with private state to pretend like `deq` is filled. // Make sure the buffer is initialized so that we don't read uninit memory. - unsafe { deq.ptr().write_bytes(0u8, size+1) }; + unsafe { deq.ptr().write_bytes(0u8, size + 1) }; b.iter(|| { deq.head = size; From 4c3cad062014253452a15574868e49328486ec02 Mon Sep 17 00:00:00 2001 From: Kamil Koczurek Date: Mon, 7 Nov 2022 15:21:35 +0100 Subject: [PATCH 141/221] Add --print=split-debuginfo This option prints all supported values for -Csplit-debuginfo=.., i.e. only stable ones on stable/beta and all of them on nightly/dev. --- compiler/rustc_driver/src/lib.rs | 11 +++++++++++ compiler/rustc_session/src/config.rs | 2 ++ .../valid-print-requests/valid-print-requests.stderr | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index cf4bcc7c158f..423f0cdddfd5 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -736,6 +736,17 @@ fn print_crate_info( // Any output here interferes with Cargo's parsing of other printed output NativeStaticLibs => {} LinkArgs => {} + SplitDebuginfo => { + use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked}; + + for split in &[Off, Packed, Unpacked] { + let stable = sess.target.options.supported_split_debuginfo.contains(split); + let unstable_ok = sess.unstable_options(); + if stable || unstable_ok { + println!("{}", split); + } + } + } } } Compilation::Stop diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index aece29ca0cbf..be084adb7b72 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -548,6 +548,7 @@ pub enum PrintRequest { NativeStaticLibs, StackProtectorStrategies, LinkArgs, + SplitDebuginfo, } pub enum Input { @@ -1806,6 +1807,7 @@ fn collect_print_requests( ("stack-protector-strategies", PrintRequest::StackProtectorStrategies), ("target-spec-json", PrintRequest::TargetSpec), ("link-args", PrintRequest::LinkArgs), + ("split-debuginfo", PrintRequest::SplitDebuginfo), ]; prints.extend(matches.opt_strs("print").into_iter().map(|req| { diff --git a/src/test/run-make/valid-print-requests/valid-print-requests.stderr b/src/test/run-make/valid-print-requests/valid-print-requests.stderr index 85782866d125..5191e4676486 100644 --- a/src/test/run-make/valid-print-requests/valid-print-requests.stderr +++ b/src/test/run-make/valid-print-requests/valid-print-requests.stderr @@ -1,2 +1,2 @@ -error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args` +error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args`, `split-debuginfo` From d62582f92ac574f1998658ab2f9c85efa8c74396 Mon Sep 17 00:00:00 2001 From: yancy Date: Mon, 7 Nov 2022 16:51:23 +0100 Subject: [PATCH 142/221] rustdoc: Add mutable to the description --- library/core/src/slice/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 4f1bb17344b2..0fde931140fb 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3524,8 +3524,8 @@ impl [T] { } } - /// Transmute the slice to a slice of another type, ensuring alignment of the types is - /// maintained. + /// Transmute the mutable slice to a mutable slice of another type, ensuring alignment of the + /// types is maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest From f67ee43fe3675eed1a0d885a1ca196c9f73a8737 Mon Sep 17 00:00:00 2001 From: yancy Date: Mon, 7 Nov 2022 17:02:48 +0100 Subject: [PATCH 143/221] rustdoc: Add mutable to the description --- library/core/src/slice/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 4f1bb17344b2..c51e99b6627c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3667,7 +3667,8 @@ impl [T] { unsafe { self.align_to() } } - /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. + /// Split a mutable slice into a mutable prefix, a middle of aligned SIMD types, + /// and a mutable suffix. /// /// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak /// postconditions as that method. You're only assured that From 0c9896bfaa6c7bfd5d34119b7aecffbcc036b201 Mon Sep 17 00:00:00 2001 From: onestacked Date: Mon, 7 Nov 2022 17:41:58 +0100 Subject: [PATCH 144/221] Fix `const_fn_trait_ref_impl`, add test for it --- library/core/src/ops/function.rs | 25 ++++++++++++--------- src/test/ui/consts/fn_trait_refs.rs | 35 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/consts/fn_trait_refs.rs diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 8d4b0a7ccacd..11b43b621c7b 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -576,9 +576,10 @@ mod impls { use crate::marker::Tuple; #[stable(feature = "rust1", since = "1.0.0")] - impl Fn for &F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl const Fn for &F where - F: Fn, + F: ~const Fn, { extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) @@ -586,9 +587,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl const FnMut for &F where - F: Fn, + F: ~const Fn, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) @@ -596,9 +598,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl const FnOnce for &F where - F: Fn, + F: ~const Fn, { type Output = F::Output; @@ -608,9 +611,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &mut F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl const FnMut for &mut F where - F: FnMut, + F: ~const FnMut, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) @@ -618,9 +622,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &mut F + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + impl const FnOnce for &mut F where - F: FnMut, + F: ~const FnMut, { type Output = F::Output; extern "rust-call" fn call_once(self, args: A) -> F::Output { diff --git a/src/test/ui/consts/fn_trait_refs.rs b/src/test/ui/consts/fn_trait_refs.rs new file mode 100644 index 000000000000..57465c559258 --- /dev/null +++ b/src/test/ui/consts/fn_trait_refs.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(const_fn_trait_ref_impls)] +#![feature(fn_traits)] +#![feature(unboxed_closures)] +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] + +use std::marker::Destruct; + +const fn test(i: i32) -> i32 { + i + 1 +} + +const fn call i32 + ~const Destruct>(mut f: F) -> F::Output { + f(5) +} + +const fn use_fn i32 + ~const Destruct>(mut f: F) -> F::Output { + call(&mut f) +} + +const fn test_fn() {} + +const fn tester(_fn: T) +where + T: ~const Fn() + ~const Destruct, +{ +} + +const fn main() { + tester(test_fn); + let test_ref = &test_fn; + tester(test_ref); + assert!(use_fn(test) == 6); +} From d97fa2536f6fb583e2e7a49b90a33632da33443c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Nov 2022 17:46:46 +0100 Subject: [PATCH 145/221] Fix invalid background-image file name --- src/librustdoc/html/static/css/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a38c0e42ab45..f58d2c609426 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -854,7 +854,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ background-size: 20px; background-position: calc(100% - 2px) 56%; /* image is black color, themes should apply a "filter" property to change the color */ - background-image: url("down-arrow-2d685a4bae708e15.svg"); + background-image: url("down-arrow-927217e04c7463ac.svg"); } #crate-search > option { font-size: 1rem; From 87c190c4252ce2039400146bbdf6b7245a5499f0 Mon Sep 17 00:00:00 2001 From: onestacked Date: Mon, 7 Nov 2022 21:16:22 +0100 Subject: [PATCH 146/221] Reworked const fn ref tests --- src/test/ui/consts/fn_trait_refs.rs | 87 ++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/src/test/ui/consts/fn_trait_refs.rs b/src/test/ui/consts/fn_trait_refs.rs index 57465c559258..bc8766c74c60 100644 --- a/src/test/ui/consts/fn_trait_refs.rs +++ b/src/test/ui/consts/fn_trait_refs.rs @@ -1,35 +1,80 @@ -// run-pass +// build-pass + #![feature(const_fn_trait_ref_impls)] #![feature(fn_traits)] #![feature(unboxed_closures)] #![feature(const_trait_impl)] #![feature(const_mut_refs)] +#![feature(const_cmp)] +#![feature(const_refs_to_cell)] use std::marker::Destruct; +const fn tester_fn(f: T) -> T::Output +where + T: ~const Fn<()> + ~const Destruct, +{ + f() +} + +const fn tester_fn_mut(mut f: T) -> T::Output +where + T: ~const FnMut<()> + ~const Destruct, +{ + f() +} + +const fn tester_fn_once(f: T) -> T::Output +where + T: ~const FnOnce<()>, +{ + f() +} + +const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output) +where + T: ~const Fn<()> + ~const Destruct, +{ + ( + // impl const Fn for &F + tester_fn(&f), + // impl const FnMut for &F + tester_fn_mut(&f), + // impl const FnOnce for &F + tester_fn_once(&f), + ) +} + +const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) +where + T: ~const FnMut<()> + ~const Destruct, +{ + ( + // impl const FnMut for &mut F + tester_fn_mut(&mut f), + // impl const FnOnce for &mut F + tester_fn_once(&mut f), + ) +} const fn test(i: i32) -> i32 { i + 1 } -const fn call i32 + ~const Destruct>(mut f: F) -> F::Output { - f(5) -} - -const fn use_fn i32 + ~const Destruct>(mut f: F) -> F::Output { - call(&mut f) -} - -const fn test_fn() {} - -const fn tester(_fn: T) -where - T: ~const Fn() + ~const Destruct, -{ -} - const fn main() { - tester(test_fn); - let test_ref = &test_fn; - tester(test_ref); - assert!(use_fn(test) == 6); + const fn one() -> i32 { + 1 + }; + const fn two() -> i32 { + 2 + }; + + // FIXME(const_cmp_tuple) + let test_one = test_fn(one); + assert!(test_one.0 == 1); + assert!(test_one.1 == 1); + assert!(test_one.2 == 1); + + let test_two = test_fn_mut(two); + assert!(test_two.0 == 1); + assert!(test_two.1 == 1); } From b00666ed09f186d9891be463355d6f8c984dcd9e Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sun, 23 Oct 2022 19:16:49 +0200 Subject: [PATCH 147/221] add benchmark for iter::ArrayChunks::fold specialization This also updates the existing iter::Copied::next_chunk benchmark so that the thing it benches doesn't get masked by the ArrayChunks specialization --- library/core/benches/iter.rs | 23 +++++++++++++++++++++-- library/core/benches/lib.rs | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 38887f29af15..9193c79bee87 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -1,3 +1,4 @@ +use core::borrow::Borrow; use core::iter::*; use core::mem; use core::num::Wrapping; @@ -403,13 +404,31 @@ fn bench_trusted_random_access_adapters(b: &mut Bencher) { /// Exercises the iter::Copied specialization for slice::Iter #[bench] -fn bench_copied_array_chunks(b: &mut Bencher) { +fn bench_copied_chunks(b: &mut Bencher) { + let v = vec![1u8; 1024]; + + b.iter(|| { + let mut iter = black_box(&v).iter().copied(); + let mut acc = Wrapping(0); + // This uses a while-let loop to side-step the TRA specialization in ArrayChunks + while let Ok(chunk) = iter.next_chunk::<{ mem::size_of::() }>() { + let d = u64::from_ne_bytes(chunk); + acc += Wrapping(d.rotate_left(7).wrapping_add(1)); + } + acc + }) +} + +/// Exercises the TrustedRandomAccess specialization in ArrayChunks +#[bench] +fn bench_trusted_random_access_chunks(b: &mut Bencher) { let v = vec![1u8; 1024]; b.iter(|| { black_box(&v) .iter() - .copied() + // this shows that we're not relying on the slice::Iter specialization in Copied + .map(|b| *b.borrow()) .array_chunks::<{ mem::size_of::() }>() .map(|ary| { let d = u64::from_ne_bytes(ary); diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index 1e462e3fc3f8..cf5a7cada93c 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -5,6 +5,7 @@ #![feature(test)] #![feature(trusted_random_access)] #![feature(iter_array_chunks)] +#![feature(iter_next_chunk)] extern crate test; From eb3f001d3739e5e9f35e1a4b4e600889cf9980c6 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sun, 23 Oct 2022 19:17:41 +0200 Subject: [PATCH 148/221] make the array initialization guard available to other modules --- library/core/src/array/mod.rs | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index eae0e1c76186..24e5d0fba21b 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -865,24 +865,6 @@ where return Ok(Try::from_output(unsafe { mem::zeroed() })); } - struct Guard<'a, T, const N: usize> { - array_mut: &'a mut [MaybeUninit; N], - initialized: usize, - } - - impl Drop for Guard<'_, T, N> { - fn drop(&mut self) { - debug_assert!(self.initialized <= N); - - // SAFETY: this slice will contain only initialized objects. - unsafe { - crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( - &mut self.array_mut.get_unchecked_mut(..self.initialized), - )); - } - } - } - let mut array = MaybeUninit::uninit_array::(); let mut guard = Guard { array_mut: &mut array, initialized: 0 }; @@ -920,6 +902,24 @@ where Ok(Try::from_output(output)) } +pub(crate) struct Guard<'a, T, const N: usize> { + pub array_mut: &'a mut [MaybeUninit; N], + pub initialized: usize, +} + +impl Drop for Guard<'_, T, N> { + fn drop(&mut self) { + debug_assert!(self.initialized <= N); + + // SAFETY: this slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( + &mut self.array_mut.get_unchecked_mut(..self.initialized), + )); + } + } +} + /// Returns the next chunk of `N` items from the iterator or errors with an /// iterator over the remainder. Used for `Iterator::next_chunk`. #[inline] From cfcce8e684c5e1bb2f9a74e55debf801ef27706f Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sun, 23 Oct 2022 19:19:37 +0200 Subject: [PATCH 149/221] specialize iter::ArrayChunks::fold for TrustedRandomAccess iters This is fairly safe use of TRA since it consumes the iterator so no struct in an unsafe state will be left exposed to user code --- .../core/src/iter/adapters/array_chunks.rs | 89 ++++++++++++++++++- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index d4fb886101fe..3f0fad4ed336 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,6 +1,8 @@ use crate::array; -use crate::iter::{ByRefSized, FusedIterator, Iterator}; -use crate::ops::{ControlFlow, Try}; +use crate::const_closure::ConstFnMutClosure; +use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce}; +use crate::mem::{self, MaybeUninit}; +use crate::ops::{ControlFlow, NeverShortCircuit, Try}; /// An iterator over `N` elements of the iterator at a time. /// @@ -82,7 +84,13 @@ where } } - impl_fold_via_try_fold! { fold -> try_fold } + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + ::fold(self, init, f) + } } #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] @@ -168,3 +176,78 @@ where self.iter.len() < N } } + +trait SpecFold: Iterator { + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B; +} + +impl SpecFold for ArrayChunks +where + I: Iterator, +{ + #[inline] + default fn fold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp); + self.try_fold(init, fold).0 + } +} + +impl SpecFold for ArrayChunks +where + I: Iterator + TrustedRandomAccessNoCoerce, +{ + #[inline] + fn fold(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + if self.remainder.is_some() { + return init; + } + + let mut accum = init; + let inner_len = self.iter.size(); + let mut i = 0; + // Use a while loop because (0..len).step_by(N) doesn't optimize well. + while inner_len - i >= N { + let mut chunk = MaybeUninit::uninit_array(); + let mut guard = array::Guard { array_mut: &mut chunk, initialized: 0 }; + for j in 0..N { + // SAFETY: The method consumes the iterator and the loop condition ensures that + // all accesses are in bounds and only happen once. + guard.array_mut[j].write(unsafe { self.iter.__iterator_get_unchecked(i + j) }); + guard.initialized = j + 1; + } + mem::forget(guard); + // SAFETY: The loop above initialized all elements + let chunk = unsafe { MaybeUninit::array_assume_init(chunk) }; + accum = f(accum, chunk); + i += N; + } + + let remainder = inner_len % N; + + let mut tail = MaybeUninit::uninit_array(); + let mut guard = array::Guard { array_mut: &mut tail, initialized: 0 }; + for i in 0..remainder { + // SAFETY: the remainder was not visited by the previous loop, so we're still only + // accessing each element once + let val = unsafe { self.iter.__iterator_get_unchecked(inner_len - remainder + i) }; + guard.array_mut[i].write(val); + guard.initialized = i + 1; + } + mem::forget(guard); + // SAFETY: the loop above initialized elements up to the `remainder` index + self.remainder = Some(unsafe { array::IntoIter::new_unchecked(tail, 0..remainder) }); + + accum + } +} From 43c353fff73a1ee38d0ec29042e42bdeea05c191 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sun, 23 Oct 2022 21:29:15 +0200 Subject: [PATCH 150/221] simplification: do not process the ArrayChunks remainder in fold() --- .../core/src/iter/adapters/array_chunks.rs | 20 ++----------------- .../core/tests/iter/adapters/array_chunks.rs | 3 ++- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 3f0fad4ed336..9bd135007b4a 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -209,10 +209,6 @@ where Self: Sized, F: FnMut(B, Self::Item) -> B, { - if self.remainder.is_some() { - return init; - } - let mut accum = init; let inner_len = self.iter.size(); let mut i = 0; @@ -233,20 +229,8 @@ where i += N; } - let remainder = inner_len % N; - - let mut tail = MaybeUninit::uninit_array(); - let mut guard = array::Guard { array_mut: &mut tail, initialized: 0 }; - for i in 0..remainder { - // SAFETY: the remainder was not visited by the previous loop, so we're still only - // accessing each element once - let val = unsafe { self.iter.__iterator_get_unchecked(inner_len - remainder + i) }; - guard.array_mut[i].write(val); - guard.initialized = i + 1; - } - mem::forget(guard); - // SAFETY: the loop above initialized elements up to the `remainder` index - self.remainder = Some(unsafe { array::IntoIter::new_unchecked(tail, 0..remainder) }); + // unlike try_fold this method does not need to take care of the remainder + // since `self` will be dropped accum } diff --git a/library/core/tests/iter/adapters/array_chunks.rs b/library/core/tests/iter/adapters/array_chunks.rs index 4e9d89e1e580..ef4a7e53bdd3 100644 --- a/library/core/tests/iter/adapters/array_chunks.rs +++ b/library/core/tests/iter/adapters/array_chunks.rs @@ -139,7 +139,8 @@ fn test_iterator_array_chunks_fold() { let result = (0..10).map(|_| CountDrop::new(&count)).array_chunks::<3>().fold(0, |acc, _item| acc + 1); assert_eq!(result, 3); - assert_eq!(count.get(), 10); + // fold impls may or may not process the remainder + assert!(count.get() <= 10 && count.get() >= 9); } #[test] From 66e8a296403e80ea50b2217d40e7a31fbd2f2158 Mon Sep 17 00:00:00 2001 From: Tanner Davies Date: Mon, 7 Nov 2022 15:27:42 -0700 Subject: [PATCH 151/221] Only set config.config to None when using default path --- src/bootstrap/config.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index c086d248e5ce..ba50ce9ec242 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -926,8 +926,10 @@ impl Config { // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, // but not if `config.toml` hasn't been created. let mut toml = if !using_default_path || toml_path.exists() { + config.config = Some(toml_path.clone()); get_toml(&toml_path) } else { + config.config = None; TomlConfig::default() }; @@ -942,7 +944,6 @@ impl Config { } config.changelog_seen = toml.changelog_seen; - config.config = if toml_path.exists() { Some(toml_path) } else { None }; let build = toml.build.unwrap_or_default(); From 00e314d5edb735baef84c314c8c1a53587911887 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Mon, 17 Oct 2022 22:08:15 -0400 Subject: [PATCH 152/221] Add an optional Span to BrAnon and use it to print better error for HRTB error from generator interior --- .../src/diagnostics/bound_region_errors.rs | 3 + .../src/diagnostics/region_name.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 4 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 17 ++-- .../src/generator_interior/mod.rs | 88 ++++++++++++++----- compiler/rustc_hir_typeck/src/lib.rs | 1 + .../src/errors/note_and_explain.rs | 7 +- .../src/infer/canonical/canonicalizer.rs | 2 +- .../src/infer/error_reporting/mod.rs | 7 +- .../error_reporting/nice_region_error/mod.rs | 5 +- .../nice_region_error/named_anon_conflict.rs | 2 +- .../nice_region_error/placeholder_relation.rs | 78 ++++++++++++++++ compiler/rustc_middle/src/infer/canonical.rs | 6 +- compiler/rustc_middle/src/ty/fold.rs | 8 +- compiler/rustc_middle/src/ty/print/pretty.rs | 8 +- .../rustc_middle/src/ty/structural_impls.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_symbol_mangling/src/v0.rs | 4 +- .../src/traits/select/mod.rs | 1 + compiler/rustc_traits/src/chalk/db.rs | 2 +- compiler/rustc_traits/src/chalk/lowering.rs | 20 +++-- .../bugs/issue-100013.rs | 22 +++++ .../bugs/issue-100013.stderr | 23 +++++ 23 files changed, 251 insertions(+), 63 deletions(-) create mode 100644 compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs create mode 100644 src/test/ui/generic-associated-types/bugs/issue-100013.rs create mode 100644 src/test/ui/generic-associated-types/bugs/issue-100013.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index dac6abe37f58..897a161f7856 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -158,6 +158,7 @@ trait TypeOpInfo<'tcx> { error_region: Option>, ) -> Option>; + #[instrument(level = "debug", skip(self, mbcx))] fn report_error( &self, mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, @@ -167,6 +168,7 @@ trait TypeOpInfo<'tcx> { ) { let tcx = mbcx.infcx.tcx; let base_universe = self.base_universe(); + debug!(?base_universe); let Some(adjusted_universe) = placeholder.universe.as_u32().checked_sub(base_universe.as_u32()) @@ -389,6 +391,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( ) } +#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))] fn try_extract_error_from_region_constraints<'tcx>( infcx: &InferCtxt<'tcx>, placeholder_region: ty::Region<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index c044dbaba47e..f9741bacd170 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -355,7 +355,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { }) } - ty::BoundRegionKind::BrAnon(_) => None, + ty::BoundRegionKind::BrAnon(..) => None, }, ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 8b1cc50a3a1f..0e3d318dc4ca 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2976,7 +2976,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) { for br in referenced_regions.difference(&constrained_regions) { let br_name = match *br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) | ty::BrEnv => { + ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => { "an anonymous lifetime".to_string() } ty::BrNamed(_, name) => format!("lifetime `{}`", name), @@ -2984,7 +2984,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut err = generate_err(&br_name); - if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) = *br { + if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) = *br { // The only way for an anonymous lifetime to wind up // in the return type but **also** be unconstrained is // if it only appears in "associated types" in the diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 609095c9ceaa..69e54b41d4c0 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -134,15 +134,18 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let name_str = intrinsic_name.as_str(); let bound_vars = tcx.mk_bound_variable_kinds( - [ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)] - .iter() - .copied(), + [ + ty::BoundVariableKind::Region(ty::BrAnon(0, None)), + ty::BoundVariableKind::Region(ty::BrEnv), + ] + .iter() + .copied(), ); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { let region = tcx.mk_region(ty::ReLateBound( ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }, )); let env_region = tcx.mk_region(ty::ReLateBound( ty::INNERMOST, @@ -364,7 +367,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ); let discriminant_def_id = assoc_items[0]; - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; ( 1, vec![ @@ -418,7 +422,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), sym::raw_eq => { - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; let param_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)); (1, vec![param_ty; 2], tcx.types.bool) diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index b7dd599cd432..06f6d8409909 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -13,8 +13,9 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::HirIdSet; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; +use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData}; -use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -211,31 +212,52 @@ pub fn resolve_interior<'a, 'tcx>( debug!("types in generator {:?}, span = {:?}", types, body.value.span); - let mut counter = 0; + // We want to deduplicate if the lifetimes are the same modulo some non-informative counter. + // So, we need to actually do two passes: first by type to anonymize (preserving information + // required for diagnostics), then a second pass over all captured types to reassign disjoint + // region indices. let mut captured_tys = FxHashSet::default(); let type_causes: Vec<_> = types .into_iter() .filter_map(|mut cause| { - // Erase regions and canonicalize late-bound regions to deduplicate as many types as we - // can. - let ty = fcx.normalize_associated_types_in(cause.span, cause.ty); - let erased = fcx.tcx.erase_regions(ty); - if captured_tys.insert(erased) { - // Replace all regions inside the generator interior with late bound regions. - // Note that each region slot in the types gets a new fresh late bound region, - // which means that none of the regions inside relate to any other, even if - // typeck had previously found constraints that would cause them to be related. - let folded = fcx.tcx.fold_regions(erased, |_, current_depth| { - let br = ty::BoundRegion { - var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter), - }; - let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); - counter += 1; - r - }); + // Replace all regions inside the generator interior with late bound regions. + // Note that each region slot in the types gets a new fresh late bound region, + // which means that none of the regions inside relate to any other, even if + // typeck had previously found constraints that would cause them to be related. - cause.ty = folded; + let mut counter = 0; + let ty = fcx.normalize_associated_types_in(cause.span, cause.ty); + let ty = fcx.tcx.fold_regions(ty, |region, current_depth| { + let br = match region.kind() { + ty::ReVar(vid) => { + let origin = fcx.region_var_origin(vid); + match origin { + RegionVariableOrigin::EarlyBoundRegion(span, _) => { + let kind = ty::BrAnon(counter, Some(span)); + let var = ty::BoundVar::from_u32(counter); + counter += 1; + ty::BoundRegion { var, kind } + } + _ => { + let kind = ty::BrAnon(counter, None); + let var = ty::BoundVar::from_u32(counter); + counter += 1; + ty::BoundRegion { var, kind } + } + } + } + _ => { + let kind = ty::BrAnon(counter, None); + let var = ty::BoundVar::from_u32(counter); + counter += 1; + ty::BoundRegion { var, kind } + } + }; + let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); + r + }); + if captured_tys.insert(ty) { + cause.ty = ty; Some(cause) } else { None @@ -243,11 +265,29 @@ pub fn resolve_interior<'a, 'tcx>( }) .collect(); + let mut bound_vars: Vec = vec![]; + let mut counter = 0; + let type_causes = fcx.tcx.fold_regions(type_causes, |region, current_depth| { + let br = match region.kind() { + ty::ReLateBound(_, br) => { + let kind = match br.kind { + ty::BrAnon(_, span) => ty::BrAnon(counter, span), + _ => br.kind, + }; + let var = ty::BoundVar::from_usize(bound_vars.len()); + bound_vars.push(ty::BoundVariableKind::Region(kind)); + counter += 1; + ty::BoundRegion { var, kind } + } + _ => bug!("All regions should have been replaced by ReLateBound"), + }; + let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); + r + }); + // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); - let bound_vars = fcx.tcx.mk_bound_variable_kinds( - (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), - ); + let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter()); let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone())); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index d1762598a520..93c58475cfc7 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -209,6 +209,7 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T typeck_with_fallback(tcx, def_id, fallback) } +#[instrument(level = "debug", skip(tcx, fallback), ret)] fn typeck_with_fallback<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 6a29d85627a8..7aaa5ce2f424 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -89,10 +89,13 @@ impl<'a> DescriptionCtx<'a> { }; me.span = Some(sp); } - ty::BrAnon(idx) => { + ty::BrAnon(idx, span) => { me.kind = "anon_num_here"; me.num_arg = idx+1; - me.span = Some(tcx.def_span(scope)); + me.span = match span { + Some(_) => span, + None => Some(tcx.def_span(scope)), + } }, _ => { me.kind = "defined_here_reg"; diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index aa44d582fd6c..3dc0d60b1eb0 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -738,7 +738,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) }; + let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) }; let region = ty::ReLateBound(self.binder_index, br); self.tcx().mk_region(region) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 9ff703e521ff..8a509cb8287a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -206,9 +206,12 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( }; (text, sp) } - ty::BrAnon(idx) => ( + ty::BrAnon(idx, span) => ( format!("the anonymous lifetime #{} defined here", idx + 1), - tcx.def_span(scope) + match span { + Some(span) => span, + None => tcx.def_span(scope) + } ), _ => ( format!("the lifetime `{}` as defined here", region), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index aaf5a7af00af..8a0e332f9c70 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -10,6 +10,7 @@ pub mod find_anon_type; mod mismatched_static_lifetime; mod named_anon_conflict; mod placeholder_error; +mod placeholder_relation; mod static_impl_trait; mod trait_impl_difference; mod util; @@ -52,7 +53,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { pub fn try_report_from_nll(&self) -> Option> { // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of // the nice region errors are required when running under the MIR borrow checker. - self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict()) + self.try_report_named_anon_conflict() + .or_else(|| self.try_report_placeholder_conflict()) + .or_else(|| self.try_report_placeholder_relation()) } pub fn try_report(&self) -> Option { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 76cb76d9ff4e..3fe7c1598fc3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let is_impl_item = region_info.is_impl_item; match br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) => {} + ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {} _ => { /* not an anonymous region */ debug!("try_report_named_anon_conflict: not an anonymous region"); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs new file mode 100644 index 000000000000..7f39de1944fd --- /dev/null +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs @@ -0,0 +1,78 @@ +use crate::infer::{ + error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin, +}; +use rustc_data_structures::intern::Interned; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_middle::ty::{self, RePlaceholder, Region}; + +impl<'tcx> NiceRegionError<'_, 'tcx> { + /// Emitted wwhen given a `ConcreteFailure` when relating two placeholders. + pub(super) fn try_report_placeholder_relation( + &self, + ) -> Option> { + match &self.error { + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::RelateRegionParamBound(span), + Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)), + Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)), + )) => { + let msg = "lifetime bound not satisfied"; + let mut err = self.tcx().sess.struct_span_err(*span, msg); + let (sub_span, sub_symbol) = match sub_name { + ty::BrNamed(def_id, symbol) => { + (Some(self.tcx().def_span(def_id)), Some(symbol)) + } + ty::BrAnon(_, span) => (*span, None), + ty::BrEnv => (None, None), + }; + let (sup_span, sup_symbol) = match sup_name { + ty::BrNamed(def_id, symbol) => { + (Some(self.tcx().def_span(def_id)), Some(symbol)) + } + ty::BrAnon(_, span) => (*span, None), + ty::BrEnv => (None, None), + }; + match (sub_span, sup_span, sub_symbol, sup_symbol) { + (Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => { + err.span_note( + sub_span, + format!("the lifetime `{sub_symbol}` defined here..."), + ); + err.span_note( + sup_span, + format!("...must outlive the lifetime `{sup_symbol}` defined here"), + ); + } + (Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => { + err.span_note(sub_span, format!("the lifetime defined here...")); + err.span_note( + sup_span, + format!("...must outlive the lifetime `{sup_symbol}` defined here"), + ); + } + (Some(sub_span), Some(sup_span), Some(sub_symbol), _) => { + err.span_note( + sub_span, + format!("the lifetime `{sub_symbol}` defined here..."), + ); + err.span_note( + sup_span, + format!("...must outlive the lifetime defined here"), + ); + } + (Some(sub_span), Some(sup_span), _, _) => { + err.span_note(sub_span, format!("the lifetime defined here, ...")); + err.span_note( + sup_span, + format!("...must outlive the lifetime defined here"), + ); + } + _ => {} + } + Some(err) + } + + _ => None, + } + } +} diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 8d1ed4b2a522..0331d764b38a 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -336,8 +336,10 @@ impl<'tcx> CanonicalVarValues<'tcx> { tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() } GenericArgKind::Lifetime(..) => { - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(i), + kind: ty::BrAnon(i, None), + }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } GenericArgKind::Const(ct) => tcx diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index a329753726ef..2842b3c3102d 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -598,7 +598,7 @@ impl<'tcx> TyCtxt<'tcx> { .replace_late_bound_regions(sig, |_| { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter), + kind: ty::BrAnon(counter, None), }; let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); counter += 1; @@ -606,7 +606,7 @@ impl<'tcx> TyCtxt<'tcx> { }) .0; let bound_vars = self.mk_bound_variable_kinds( - (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))), ); Binder::bind_with_vars(inner, bound_vars) } @@ -626,7 +626,9 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(index as u32))) + .or_insert_with(|| { + ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None)) + }) .expect_region(); let br = ty::BoundRegion { var, kind }; self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fab85c39d253..c8815537835b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2115,7 +2115,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound match kind { - ty::BrAnon(_) | ty::BrEnv => r, + ty::BrAnon(..) | ty::BrEnv => r, _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; @@ -2226,10 +2226,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { let ty::BoundVariableKind::Region(var) = var else { // This doesn't really matter because it doesn't get used, // it's just an empty value - return ty::BrAnon(0); + return ty::BrAnon(0, None); }; match var { - ty::BrAnon(_) | ty::BrEnv => { + ty::BrAnon(..) | ty::BrEnv => { start_or_continue(&mut self, "for<", ", "); let name = next_name(&self); debug!(?name); @@ -2271,7 +2271,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { binder_level_idx: ty::DebruijnIndex, br: ty::BoundRegion| { let (name, kind) = match br.kind { - ty::BrAnon(_) | ty::BrEnv => { + ty::BrAnon(..) | ty::BrEnv => { let name = next_name(&self); if let Some(lt_idx) = lifetime_idx { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f2070869ce0c..9f0598d0ba86 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), + ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"), ty::BrNamed(did, name) => { if did.is_crate_root() { write!(f, "BrNamed({})", name) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5f108bf0ef30..49d82b503a4b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -59,7 +59,7 @@ pub struct FreeRegion { #[derive(HashStable)] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) - BrAnon(u32), + BrAnon(u32, Option), /// Named region parameters for functions (a in &'a T) /// diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 2109b3c24962..e540e2f2a219 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -218,7 +218,7 @@ impl<'tcx> SymbolMangler<'tcx> { let lifetimes = regions .into_iter() .map(|br| match br { - ty::BrAnon(i) => i, + ty::BrAnon(i, _) => i, _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value), }) .max() @@ -335,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { + ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i, _), .. }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + i; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 84be1ced520f..debf06593459 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1975,6 +1975,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Bar where struct Bar { x: T, y: u32 } -> [i32, u32] /// Zed where enum Zed { A(T), B(u32) } -> [i32, u32] /// ``` + #[instrument(level = "debug", skip(self), ret)] fn constituent_types_for_ty( &self, t: ty::Binder<'tcx, Ty<'tcx>>, diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 2035252fe39a..07f92299f72b 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -728,7 +728,7 @@ fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx ty::GenericParamDefKind::Lifetime => { let br = ty::BoundRegion { var: ty::BoundVar::from_usize(substs.len()), - kind: ty::BrAnon(substs.len() as u32), + kind: ty::BrAnon(substs.len() as u32, None), }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 0492e94b94e9..b64d53e60dee 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -498,13 +498,13 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime unimplemented!(), chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder { universe: ty::UniverseIndex::from_usize(p.ui.counter), - name: ty::BoundRegionKind::BrAnon(p.idx as u32), + name: ty::BoundRegionKind::BrAnon(p.idx as u32, None), }), chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static, chalk_ir::LifetimeData::Empty(_) => { @@ -933,7 +933,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { } } - ty::BoundRegionKind::BrAnon(var) => match self.parameters.entry(var) { + ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) { Entry::Vacant(entry) => { entry.insert(chalk_ir::VariableKind::Lifetime); } @@ -991,13 +991,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> { ty::ReLateBound(index, br) if index == self.binder_index => match br.kind { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { Some(idx) => { - let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) }; + let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) }; return self.tcx.mk_region(ty::ReLateBound(index, new_br)); } None => panic!("Missing `BrNamed`."), }, ty::BrEnv => unimplemented!(), - ty::BrAnon(_) => {} + ty::BrAnon(..) => {} }, _ => (), }; @@ -1072,14 +1072,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { Some(idx) => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(*idx), - kind: ty::BrAnon(*idx), + kind: ty::BrAnon(*idx, None), }; self.tcx.mk_region(ty::ReLateBound(self.binder_index, br)) } None => { let idx = self.named_regions.len() as u32; - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(idx), + kind: ty::BrAnon(idx, None), + }; self.named_regions.insert(_re.def_id, idx); self.tcx.mk_region(ty::ReLateBound(self.binder_index, br)) } @@ -1156,7 +1158,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector { fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { match *r { ty::RePlaceholder(p) if p.universe == self.universe_index => { - if let ty::BoundRegionKind::BrAnon(anon) = p.name { + if let ty::BoundRegionKind::BrAnon(anon, _) = p.name { self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon); } } diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.rs b/src/test/ui/generic-associated-types/bugs/issue-100013.rs new file mode 100644 index 000000000000..f995591d76ca --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-100013.rs @@ -0,0 +1,22 @@ +// check-fail +// known-bug +// edition: 2021 + +// We really should accept this, but we need implied bounds between the regions +// in a generator interior. + +pub trait FutureIterator { + type Future<'s, 'cx>: Send + where + 's: 'cx; +} + +fn call_2() -> impl Send { + async { // a generator checked for autotrait impl `Send` + //~^ lifetime bound not satisfied + let x = None::>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.stderr b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr new file mode 100644 index 000000000000..11d149faa8fb --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr @@ -0,0 +1,23 @@ +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:15:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | +LL | | let x = None::>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here, ... + --> $DIR/issue-100013.rs:17:38 + | +LL | let x = None::>; // a type referencing GAT + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:17:34 + | +LL | let x = None::>; // a type referencing GAT + | ^^ + +error: aborting due to previous error + From cececca7c7fdae8730027615c2e89120e40bac66 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Tue, 18 Oct 2022 20:08:13 -0400 Subject: [PATCH 153/221] Get spans for a couple more region types, add some optimizations, and extend test --- .../src/generator_interior/mod.rs | 82 +++++++++++-------- .../nice_region_error/placeholder_relation.rs | 2 +- .../bugs/issue-100013.rs | 19 ++++- .../bugs/issue-100013.stderr | 60 +++++++++++++- 4 files changed, 126 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 06f6d8409909..7bbfb70f2c3a 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -15,9 +15,11 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData}; +use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable}; use rustc_span::symbol::sym; use rustc_span::Span; +use smallvec::{smallvec, SmallVec}; mod drop_ranges; @@ -226,6 +228,12 @@ pub fn resolve_interior<'a, 'tcx>( // typeck had previously found constraints that would cause them to be related. let mut counter = 0; + let mut mk_bound_region = |span| { + let kind = ty::BrAnon(counter, span); + let var = ty::BoundVar::from_u32(counter); + counter += 1; + ty::BoundRegion { var, kind } + }; let ty = fcx.normalize_associated_types_in(cause.span, cause.ty); let ty = fcx.tcx.fold_regions(ty, |region, current_depth| { let br = match region.kind() { @@ -233,25 +241,24 @@ pub fn resolve_interior<'a, 'tcx>( let origin = fcx.region_var_origin(vid); match origin { RegionVariableOrigin::EarlyBoundRegion(span, _) => { - let kind = ty::BrAnon(counter, Some(span)); - let var = ty::BoundVar::from_u32(counter); - counter += 1; - ty::BoundRegion { var, kind } - } - _ => { - let kind = ty::BrAnon(counter, None); - let var = ty::BoundVar::from_u32(counter); - counter += 1; - ty::BoundRegion { var, kind } + mk_bound_region(Some(span)) } + _ => mk_bound_region(None), } } - _ => { - let kind = ty::BrAnon(counter, None); - let var = ty::BoundVar::from_u32(counter); - counter += 1; - ty::BoundRegion { var, kind } + // FIXME: these should use `BrNamed` + ty::ReEarlyBound(region) => { + mk_bound_region(Some(fcx.tcx.def_span(region.def_id))) } + ty::ReLateBound(_, ty::BoundRegion { kind, .. }) + | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind { + ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span), + ty::BoundRegionKind::BrNamed(def_id, _) => { + mk_bound_region(Some(fcx.tcx.def_span(def_id))) + } + ty::BoundRegionKind::BrEnv => mk_bound_region(None), + }, + _ => mk_bound_region(None), }; let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); r @@ -265,25 +272,34 @@ pub fn resolve_interior<'a, 'tcx>( }) .collect(); - let mut bound_vars: Vec = vec![]; + let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![]; let mut counter = 0; - let type_causes = fcx.tcx.fold_regions(type_causes, |region, current_depth| { - let br = match region.kind() { - ty::ReLateBound(_, br) => { - let kind = match br.kind { - ty::BrAnon(_, span) => ty::BrAnon(counter, span), - _ => br.kind, - }; - let var = ty::BoundVar::from_usize(bound_vars.len()); - bound_vars.push(ty::BoundVariableKind::Region(kind)); - counter += 1; - ty::BoundRegion { var, kind } - } - _ => bug!("All regions should have been replaced by ReLateBound"), - }; - let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); - r - }); + // Optimization: If there is only one captured type, then we don't actually + // need to fold and reindex (since the first type doesn't change). + let type_causes = if captured_tys.len() > 0 { + // Optimization: Use `replace_escaping_bound_vars_uncached` instead of + // `fold_regions`, since we only have late bound regions, and it skips + // types without bound regions. + fcx.tcx.replace_escaping_bound_vars_uncached( + type_causes, + FnMutDelegate { + regions: &mut |br| { + let kind = match br.kind { + ty::BrAnon(_, span) => ty::BrAnon(counter, span), + _ => br.kind, + }; + let var = ty::BoundVar::from_usize(bound_vars.len()); + bound_vars.push(ty::BoundVariableKind::Region(kind)); + counter += 1; + fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind })) + }, + types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"), + consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"), + }, + ) + } else { + type_causes + }; // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs index 7f39de1944fd..d0813ccd3b40 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs @@ -61,7 +61,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ); } (Some(sub_span), Some(sup_span), _, _) => { - err.span_note(sub_span, format!("the lifetime defined here, ...")); + err.span_note(sub_span, format!("the lifetime defined here...")); err.span_note( sup_span, format!("...must outlive the lifetime defined here"), diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.rs b/src/test/ui/generic-associated-types/bugs/issue-100013.rs index f995591d76ca..fc4e47a3ba18 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-100013.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-100013.rs @@ -11,7 +11,7 @@ pub trait FutureIterator { 's: 'cx; } -fn call_2() -> impl Send { +fn call() -> impl Send { async { // a generator checked for autotrait impl `Send` //~^ lifetime bound not satisfied let x = None::>; // a type referencing GAT @@ -19,4 +19,21 @@ fn call_2() -> impl Send { } } +fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + //~^ lifetime bound not satisfied + let x = None::>; // a type referencing GAT + //~^ lifetime may not live long enough + async {}.await; // a yield point + } +} + +fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + //~^ lifetime bound not satisfied + let x = None::>; // a type referencing GAT + async {}.await; // a yield point + } +} + fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.stderr b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr index 11d149faa8fb..d9fcf8c48e2f 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-100013.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr @@ -8,7 +8,7 @@ LL | | async {}.await; // a yield point LL | | } | |_____^ | -note: the lifetime defined here, ... +note: the lifetime defined here... --> $DIR/issue-100013.rs:17:38 | LL | let x = None::>; // a type referencing GAT @@ -19,5 +19,61 @@ note: ...must outlive the lifetime defined here LL | let x = None::>; // a type referencing GAT | ^^ -error: aborting due to previous error +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:23:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | +LL | | let x = None::>; // a type referencing GAT +LL | | +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:22:14 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:22:10 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ + +error: lifetime may not live long enough + --> $DIR/issue-100013.rs:25:17 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let x = None::>; // a type referencing GAT + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:32:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | +LL | | let x = None::>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:31:18 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:31:10 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ + +error: aborting due to 4 previous errors From 3c71fafd6d515004ebfd041d125338b6b82fddf9 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Mon, 7 Nov 2022 17:52:08 -0500 Subject: [PATCH 154/221] Add a known that this is a known limitation --- .../error_reporting/nice_region_error/placeholder_relation.rs | 1 + src/test/ui/generic-associated-types/bugs/issue-100013.stderr | 3 +++ 2 files changed, 4 insertions(+) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs index d0813ccd3b40..c42240f21724 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs @@ -69,6 +69,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } _ => {} } + err.note("this is a known limitation that will be removed in the future (see issue #100013 for more information)"); Some(err) } diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.stderr b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr index d9fcf8c48e2f..72ae288dcab6 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-100013.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr @@ -18,6 +18,7 @@ note: ...must outlive the lifetime defined here | LL | let x = None::>; // a type referencing GAT | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) error: lifetime bound not satisfied --> $DIR/issue-100013.rs:23:5 @@ -40,6 +41,7 @@ note: ...must outlive the lifetime defined here | LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) error: lifetime may not live long enough --> $DIR/issue-100013.rs:25:17 @@ -74,6 +76,7 @@ note: ...must outlive the lifetime defined here | LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) error: aborting due to 4 previous errors From 3925fc0c8e0b4ad9be48fbc1136281841d8985fa Mon Sep 17 00:00:00 2001 From: The 8472 Date: Tue, 8 Nov 2022 00:13:26 +0100 Subject: [PATCH 155/221] document and improve array Guard type The type is unsafe and now exposed to the whole crate. Document it properly and add an unsafe method so the caller can make it visible that something unsafe is happening. --- library/core/src/array/mod.rs | 39 ++++++++++++++++--- .../core/src/iter/adapters/array_chunks.rs | 8 ++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 24e5d0fba21b..2090756d7a3e 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -878,13 +878,11 @@ where ControlFlow::Continue(elem) => elem, }; - // SAFETY: `guard.initialized` starts at 0, is increased by one in the - // loop and the loop is aborted once it reaches N (which is - // `array.len()`). + // SAFETY: `guard.initialized` starts at 0, which means push can be called + // at most N times, which this loop does. unsafe { - guard.array_mut.get_unchecked_mut(guard.initialized).write(item); + guard.push_unchecked(item); } - guard.initialized += 1; } None => { let alive = 0..guard.initialized; @@ -902,11 +900,42 @@ where Ok(Try::from_output(output)) } +/// Panic guard for incremental initialization of arrays. +/// +/// Disarm the guard with `mem::forget` once the array has been initialized. +/// +/// # Safety +/// +/// All write accesses to this structure are unsafe and must maintain a correct +/// count of `initialized` elements. +/// +/// To minimize indirection fields are still pub but callers should at least use +/// `push_unchecked` to signal that something unsafe is going on. pub(crate) struct Guard<'a, T, const N: usize> { + /// The array to be initialized. pub array_mut: &'a mut [MaybeUninit; N], + /// The number of items that have been initialized so far. pub initialized: usize, } +impl Guard<'_, T, N> { + /// Adds an item to the array and updates the initialized item counter. + /// + /// # Safety + /// + /// No more than N elements must be initialized. + #[inline] + pub unsafe fn push_unchecked(&mut self, item: T) { + // SAFETY: If `initialized` was correct before and the caller does not + // invoke this method more than N times then writes will be in-bounds + // and slots will not be initialized more than once. + unsafe { + self.array_mut.get_unchecked_mut(self.initialized).write(item); + self.initialized = self.initialized.unchecked_add(1); + } + } +} + impl Drop for Guard<'_, T, N> { fn drop(&mut self) { debug_assert!(self.initialized <= N); diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 9bd135007b4a..5e4211058aa6 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -216,11 +216,13 @@ where while inner_len - i >= N { let mut chunk = MaybeUninit::uninit_array(); let mut guard = array::Guard { array_mut: &mut chunk, initialized: 0 }; - for j in 0..N { + while guard.initialized < N { // SAFETY: The method consumes the iterator and the loop condition ensures that // all accesses are in bounds and only happen once. - guard.array_mut[j].write(unsafe { self.iter.__iterator_get_unchecked(i + j) }); - guard.initialized = j + 1; + unsafe { + let idx = i + guard.initialized; + guard.push_unchecked(self.iter.__iterator_get_unchecked(idx)); + } } mem::forget(guard); // SAFETY: The loop above initialized all elements From 8e71a13022305e70916c8ee5d49c59829bfac68e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 7 Nov 2022 17:13:20 -0700 Subject: [PATCH 156/221] Update to latest version of flate2 --- Cargo.lock | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28684a310a3c..79a101d51cbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,12 +14,6 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "adler" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" - [[package]] name = "adler" version = "1.0.2" @@ -180,7 +174,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.5.3", + "miniz_oxide", "object", "rustc-demangle", ] @@ -1286,15 +1280,15 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" -version = "1.0.16" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "crc32fast", "libc", "libz-sys", - "miniz_oxide 0.4.0", + "miniz_oxide", ] [[package]] @@ -2209,22 +2203,13 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f" -dependencies = [ - "adler 0.2.3", -] - [[package]] name = "miniz_oxide" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ - "adler 1.0.2", + "adler", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", @@ -4682,7 +4667,7 @@ dependencies = [ "hashbrown", "hermit-abi 0.2.6", "libc", - "miniz_oxide 0.5.3", + "miniz_oxide", "object", "panic_abort", "panic_unwind", From ae5cc9c56e45e9561aa2bf69b423473c0c5fd7c6 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 7 Nov 2022 19:23:29 -0500 Subject: [PATCH 157/221] fix: lint against lint functions fix: lint against the functions `LintContext::{lookup_with_diagnostics,lookup,struct_span_lint,lint}`, `TyCtxt::struct_lint_node`, `LintLevelsBuilder::struct_lint`. --- compiler/rustc_lint/src/context.rs | 4 ++++ compiler/rustc_lint/src/levels.rs | 1 + compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_middle/src/ty/context.rs | 1 + 4 files changed, 7 insertions(+) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index cec0003ffea7..28f6ac61c5bd 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -579,6 +579,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn lookup_with_diagnostics( &self, lint: &'static Lint, @@ -882,6 +883,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn lookup>( &self, lint: &'static Lint, @@ -908,6 +910,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn struct_span_lint>( &self, lint: &'static Lint, @@ -933,6 +936,7 @@ pub trait LintContext: Sized { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] fn lint( &self, lint: &'static Lint, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index db0a3419e6a5..dfe52312ff00 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1073,6 +1073,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] pub(crate) fn struct_lint( &self, lint: &'static Lint, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 5288fc542d79..ebb7de70e057 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -36,6 +36,7 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(rustc_attrs)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index fc706b890d5f..10a8a5c78b50 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2856,6 +2856,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature + #[rustc_lint_diagnostics] pub fn struct_lint_node( self, lint: &'static Lint, From 1f21b96dce9c4165bcfae364b4e100953dd8167b Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 3 Nov 2022 14:15:17 +0800 Subject: [PATCH 158/221] add 'ty_error_with_guaranteed' and 'const_error_with_guaranteed' --- .../src/region_infer/opaque_types.rs | 4 +-- .../src/type_check/free_region_relations.rs | 5 ++-- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +-- .../rustc_errors/src/diagnostic_builder.rs | 4 +-- .../rustc_hir_analysis/src/astconv/mod.rs | 26 +++++++++++-------- .../src/check/compare_method.rs | 4 +-- compiler/rustc_hir_analysis/src/collect.rs | 3 +-- .../rustc_hir_analysis/src/collect/type_of.rs | 4 +-- compiler/rustc_hir_typeck/src/coercion.rs | 4 +-- compiler/rustc_hir_typeck/src/expr.rs | 19 +++++++------- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 5 ++-- compiler/rustc_hir_typeck/src/op.rs | 4 +-- compiler/rustc_hir_typeck/src/pat.rs | 6 ++--- compiler/rustc_hir_typeck/src/place_op.rs | 7 +++-- compiler/rustc_middle/src/ty/context.rs | 16 ++++++++++++ 15 files changed, 68 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 103c7ed8ef70..dd222485daf2 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -299,8 +299,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { if errors.is_empty() { definition_ty } else { - infcx.err_ctxt().report_fulfillment_errors(&errors, None); - self.tcx.ty_error() + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None); + self.tcx.ty_error_with_guaranteed(reported) } } } diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 02909592637d..14cfc3613bf0 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -247,12 +247,13 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { .and(type_op::normalize::Normalize::new(ty)) .fully_perform(self.infcx) .unwrap_or_else(|_| { - self.infcx + let reported = self + .infcx .tcx .sess .delay_span_bug(span, &format!("failed to normalize {:?}", ty)); TypeOpOutput { - output: self.infcx.tcx.ty_error(), + output: self.infcx.tcx.ty_error_with_guaranteed(reported), constraints: None, error_info: None, } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 50af229baaae..9c1d0bb8b235 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -233,11 +233,11 @@ pub(crate) fn type_check<'mir, 'tcx>( let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind()); if hidden_type.has_non_region_infer() { - infcx.tcx.sess.delay_span_bug( + let reported = infcx.tcx.sess.delay_span_bug( decl.hidden_type.span, &format!("could not resolve {:#?}", hidden_type.ty.kind()), ); - hidden_type.ty = infcx.tcx.ty_error(); + hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported); } (opaque_type_key, (hidden_type, decl.origin)) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index ecf8570e81f7..730061fca993 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -482,9 +482,9 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn delay_as_bug(&mut self) { + pub fn delay_as_bug(&mut self) -> G { self.downgrade_to_delayed_bug(); - self.emit(); + self.emit() } forward!( diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 8b1cc50a3a1f..2665813478c2 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1201,7 +1201,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (_, _) => { let got = if let Some(_) = term.ty() { "type" } else { "constant" }; let expected = def_kind.descr(assoc_item_def_id); - tcx.sess + let reported = tcx + .sess .struct_span_err( binding.span, &format!("expected {expected} bound, found {got}"), @@ -1212,11 +1213,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .emit(); term = match def_kind { - hir::def::DefKind::AssocTy => tcx.ty_error().into(), + hir::def::DefKind::AssocTy => { + tcx.ty_error_with_guaranteed(reported).into() + } hir::def::DefKind::AssocConst => tcx - .const_error( + .const_error_with_guaranteed( tcx.bound_type_of(assoc_item_def_id) .subst(tcx, projection_ty.skip_binder().substs), + reported, ) .into(), _ => unreachable!(), @@ -1334,8 +1338,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|&(trait_ref, _, _)| trait_ref.def_id()) .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) .map(|trait_ref| tcx.def_span(trait_ref)); - tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); - return tcx.ty_error(); + let reported = + tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); + return tcx.ty_error_with_guaranteed(reported); } // Check that there are no gross object safety violations; @@ -1345,14 +1350,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let object_safety_violations = astconv_object_safety_violations(tcx, item.trait_ref().def_id()); if !object_safety_violations.is_empty() { - report_object_safety_error( + let reported = report_object_safety_error( tcx, span, item.trait_ref().def_id(), &object_safety_violations, ) .emit(); - return tcx.ty_error(); + return tcx.ty_error_with_guaranteed(reported); } } @@ -2112,13 +2117,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "Type" }; - self.report_ambiguous_associated_type( + let reported = self.report_ambiguous_associated_type( span, type_name, &path_str, item_segment.ident.name, ); - return tcx.ty_error(); + return tcx.ty_error_with_guaranteed(reported) }; debug!("qpath_to_ty: self_type={:?}", self_ty); @@ -2560,8 +2565,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { err.span_note(impl_.self_ty.span, "not a concrete type"); } - err.emit(); - tcx.ty_error() + tcx.ty_error_with_guaranteed(err.emit()) } else { self.normalize_ty(span, ty) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 0e8ac17fb71b..660c56ee8b01 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -611,11 +611,11 @@ pub fn collect_trait_impl_trait_tys<'tcx>( collected_tys.insert(def_id, ty); } Err(err) => { - tcx.sess.delay_span_bug( + let reported = tcx.sess.delay_span_bug( return_span, format!("could not fully resolve: {ty} => {err:?}"), ); - collected_tys.insert(def_id, tcx.ty_error()); + collected_tys.insert(def_id, tcx.ty_error_with_guaranteed(reported)); } } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 25faacadf3d0..4bca16c3a1cc 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -512,8 +512,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } _ => {} } - err.emit(); - self.tcx().ty_error() + self.tcx().ty_error_with_guaranteed(err.emit()) } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index c29a645eb4a8..2402495c2e4a 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -698,7 +698,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T } let Some(hidden) = locator.found else { - tcx.sess.emit_err(UnconstrainedOpaqueType { + let reported = tcx.sess.emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), what: match tcx.hir().get(scope) { @@ -708,7 +708,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T _ => "item", }, }); - return tcx.ty_error(); + return tcx.ty_error_with_guaranteed(reported); }; // Only check against typeck if we didn't already error diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 25306ebf3567..4d8ab2c1c7ad 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1639,9 +1639,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if visitor.ret_exprs.len() > 0 && let Some(expr) = expression { self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs); } - err.emit_unless(unsized_return); + let reported = err.emit_unless(unsized_return); - self.final_ty = Some(fcx.tcx.ty_error()); + self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported)); } } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 89b5e5161a9c..e84734f46cb4 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -80,14 +80,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // coercions from ! to `expected`. if ty.is_never() { if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { - self.tcx().sess.delay_span_bug( + let reported = self.tcx().sess.delay_span_bug( expr.span, "expression with never type wound up being adjusted", ); return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] { target.to_owned() } else { - self.tcx().ty_error() + self.tcx().ty_error_with_guaranteed(reported) }; } @@ -396,8 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } - err.emit(); - oprnd_t = tcx.ty_error(); + oprnd_t = tcx.ty_error_with_guaranteed(err.emit()); } } hir::UnOp::Not => { @@ -1097,12 +1096,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the assignment expression itself is ill-formed, don't // bother emitting another error - if lhs_ty.references_error() || rhs_ty.references_error() { + let reported = if lhs_ty.references_error() || rhs_ty.references_error() { err.delay_as_bug() } else { - err.emit(); - } - return self.tcx.ty_error(); + err.emit() + }; + return self.tcx.ty_error_with_guaranteed(reported); } let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); @@ -2777,8 +2776,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - err.emit(); - self.tcx.ty_error() + let reported = err.emit(); + self.tcx.ty_error_with_guaranteed(reported) } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 35323137e2d5..6ed7a93d4633 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1212,9 +1212,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - err.emit(); - - return (tcx.ty_error(), res); + let reported = err.emit(); + return (tcx.ty_error_with_guaranteed(reported), res); } } } else { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index c3bcbcc993b7..38b3dd218a97 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -529,8 +529,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - err.emit(); - self.tcx.ty_error() + let reported = err.emit(); + self.tcx.ty_error_with_guaranteed(reported) } }; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ea90da4a6dc3..c248deb892b1 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1278,12 +1278,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) { - err.emit(); + let reported = err.emit(); // Walk subpatterns with an expected type of `err` in this case to silence // further errors being emitted when using the bindings. #50333 - let element_tys_iter = (0..max_len).map(|_| tcx.ty_error()); + let element_tys_iter = (0..max_len).map(|_| tcx.ty_error_with_guaranteed(reported)); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, tcx.ty_error(), def_bm, ti); + self.check_pat(elem, tcx.ty_error_with_guaranteed(reported), def_bm, ti); } tcx.mk_tup(element_tys_iter) } else { diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index ba8cf6926f30..952ea14887f7 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -90,8 +90,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - err.emit(); - Some((self.tcx.ty_error(), self.tcx.ty_error())) + let reported = err.emit(); + Some(( + self.tcx.ty_error_with_guaranteed(reported), + self.tcx.ty_error_with_guaranteed(reported), + )) } /// To type-check `base_expr[index_expr]`, we progressively autoderef diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index fc706b890d5f..4016a93caa86 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1283,6 +1283,12 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` + #[track_caller] + pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> { + self.mk_ty(Error(reported)) + } + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. #[track_caller] pub fn ty_error(self) -> Ty<'tcx> { @@ -1297,6 +1303,16 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(Error(reported)) } + /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed` + #[track_caller] + pub fn const_error_with_guaranteed( + self, + ty: Ty<'tcx>, + reported: ErrorGuaranteed, + ) -> Const<'tcx> { + self.mk_const(ty::ConstS { kind: ty::ConstKind::Error(reported), ty }) + } + /// Like [TyCtxt::ty_error] but for constants. #[track_caller] pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> { From 465ac26405d32cc1dd73460fa465c9303f40ea43 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 4 Nov 2022 10:02:54 +0800 Subject: [PATCH 159/221] deprecate unchecked_claim_error_was_emitted in error_reported --- compiler/rustc_middle/src/ty/visit.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index f0e9f990a811..5e366ef703f2 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -97,7 +97,11 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { } fn error_reported(&self) -> Result<(), ErrorGuaranteed> { if self.references_error() { - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) + if let Some(reported) = ty::tls::with(|tcx| tcx.sess.has_errors()) { + Err(reported) + } else { + bug!("expect tcx.sess.has_errors return true"); + } } else { Ok(()) } From 3320879f40034b32ef41f1c515baec5a1262f60d Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 4 Nov 2022 16:10:32 +0800 Subject: [PATCH 160/221] code cleanup with err.emit_unless --- compiler/rustc_hir_typeck/src/expr.rs | 6 +----- compiler/rustc_middle/src/ty/context.rs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index e84734f46cb4..43669489e69b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1096,11 +1096,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the assignment expression itself is ill-formed, don't // bother emitting another error - let reported = if lhs_ty.references_error() || rhs_ty.references_error() { - err.delay_as_bug() - } else { - err.emit() - }; + let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error()); return self.tcx.ty_error_with_guaranteed(reported); } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4016a93caa86..50eece301128 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1310,7 +1310,7 @@ impl<'tcx> TyCtxt<'tcx> { ty: Ty<'tcx>, reported: ErrorGuaranteed, ) -> Const<'tcx> { - self.mk_const(ty::ConstS { kind: ty::ConstKind::Error(reported), ty }) + self.mk_const(ty::ConstKind::Error(reported), ty) } /// Like [TyCtxt::ty_error] but for constants. From d6c97a32b4f5e38c0e85010df4438dc7205c44f4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Nov 2022 15:59:19 +1100 Subject: [PATCH 161/221] Simplify `unescape_{char,byte}`. The `usize` isn't needed in the error case. --- compiler/rustc_lexer/src/unescape.rs | 14 +++++--------- compiler/rustc_lexer/src/unescape/tests.rs | 12 ++++-------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 674bbff0878c..e405013dcabf 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -94,19 +94,15 @@ where } /// Takes a contents of a char literal (without quotes), and returns an -/// unescaped char or an error -pub fn unescape_char(src: &str) -> Result { - let mut chars = src.chars(); - unescape_char_or_byte(&mut chars, false).map_err(|err| (src.len() - chars.as_str().len(), err)) +/// unescaped char or an error. +pub fn unescape_char(src: &str) -> Result { + unescape_char_or_byte(&mut src.chars(), false) } /// Takes a contents of a byte literal (without quotes), and returns an /// unescaped byte or an error. -pub fn unescape_byte(src: &str) -> Result { - let mut chars = src.chars(); - unescape_char_or_byte(&mut chars, true) - .map(byte_from_char) - .map_err(|err| (src.len() - chars.as_str().len(), err)) +pub fn unescape_byte(src: &str) -> Result { + unescape_char_or_byte(&mut src.chars(), true).map(byte_from_char) } /// What kind of literal do we parse. diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs index 00c8401efdfe..c7ca8fd16ae4 100644 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ b/compiler/rustc_lexer/src/unescape/tests.rs @@ -3,8 +3,7 @@ use super::*; #[test] fn test_unescape_char_bad() { fn check(literal_text: &str, expected_error: EscapeError) { - let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err); - assert_eq!(actual_result, Err(expected_error)); + assert_eq!(unescape_char(literal_text), Err(expected_error)); } check("", EscapeError::ZeroChars); @@ -68,8 +67,7 @@ fn test_unescape_char_bad() { #[test] fn test_unescape_char_good() { fn check(literal_text: &str, expected_char: char) { - let actual_result = unescape_char(literal_text); - assert_eq!(actual_result, Ok(expected_char)); + assert_eq!(unescape_char(literal_text), Ok(expected_char)); } check("a", 'a'); @@ -149,8 +147,7 @@ fn test_unescape_str_good() { #[test] fn test_unescape_byte_bad() { fn check(literal_text: &str, expected_error: EscapeError) { - let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err); - assert_eq!(actual_result, Err(expected_error)); + assert_eq!(unescape_byte(literal_text), Err(expected_error)); } check("", EscapeError::ZeroChars); @@ -219,8 +216,7 @@ fn test_unescape_byte_bad() { #[test] fn test_unescape_byte_good() { fn check(literal_text: &str, expected_byte: u8) { - let actual_result = unescape_byte(literal_text); - assert_eq!(actual_result, Ok(expected_byte)); + assert_eq!(unescape_byte(literal_text), Ok(expected_byte)); } check("a", b'a'); From 667b15bb0ebb36683a2de31cff68ad2b5b0d3f57 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 27 Oct 2022 14:43:15 +0800 Subject: [PATCH 162/221] fix #103587, Recover from common if let syntax mistakes/typos --- .../locales/en-US/parser.ftl | 3 + .../src/infer/error_reporting/mod.rs | 74 +++++++++++++++++++ compiler/rustc_parse/src/errors.rs | 9 +++ compiler/rustc_parse/src/parser/expr.rs | 16 +++- src/test/ui/inference/issue-103587.rs | 12 +++ src/test/ui/inference/issue-103587.stderr | 40 ++++++++++ src/test/ui/suggestions/if-let-typo.stderr | 15 ++++ 7 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/inference/issue-103587.rs create mode 100644 src/test/ui/inference/issue-103587.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 455ff34f7247..6d42b23fb3a2 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -125,6 +125,9 @@ parser_if_expression_missing_condition = missing condition for `if` expression parser_expected_expression_found_let = expected expression, found `let` statement +parser_expect_eq_instead_of_eqeq = expected `=`, found `==` + .suggestion = consider using `=` here + parser_expected_else_block = expected `{"{"}`, found {$first_tok} .label = expected an `if` or a block after this `else` .suggestion = add an `if` if this is the condition of a chained `else if` statement diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 3dbc9b9f3f93..ee9e59968be8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength //! Error Reporting Code for the inference engine //! //! Because of the way inference, and in particular region inference, @@ -58,12 +59,14 @@ use crate::traits::{ StatementAsExpression, }; +use hir::intravisit::{walk_expr, walk_stmt}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::Node; use rustc_middle::dep_graph::DepContext; @@ -2333,6 +2336,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } } + // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`, + // we try to suggest to add the missing `let` for `if let Some(..) = expr` + (ty::Bool, ty::Tuple(list)) => if list.len() == 0 { + self.suggest_let_for_letchains(&mut err, &trace.cause, span); + } _ => {} } } @@ -2357,6 +2365,72 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { diag } + /// Try to find code with pattern `if Some(..) = expr` + /// use a `visitor` to mark the `if` which its span contains given error span, + /// and then try to find a assignment in the `cond` part, which span is equal with error span + fn suggest_let_for_letchains( + &self, + err: &mut Diagnostic, + cause: &ObligationCause<'_>, + span: Span, + ) { + let hir = self.tcx.hir(); + let fn_hir_id = hir.get_parent_node(cause.body_id); + if let Some(node) = self.tcx.hir().find(fn_hir_id) && + let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(_sig, _, body_id), .. + }) = node { + let body = hir.body(*body_id); + + /// Find the if expression with given span + struct IfVisitor { + pub result: bool, + pub found_if: bool, + pub err_span: Span, + } + + impl<'v> Visitor<'v> for IfVisitor { + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + if self.result { return; } + match ex.kind { + hir::ExprKind::If(cond, _, _) => { + self.found_if = true; + walk_expr(self, cond); + self.found_if = false; + } + _ => walk_expr(self, ex), + } + } + + fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { + if let hir::StmtKind::Local(hir::Local { + span, pat: hir::Pat{..}, ty: None, init: Some(_), .. + }) = &ex.kind + && self.found_if + && span.eq(&self.err_span) { + self.result = true; + } + walk_stmt(self, ex); + } + + fn visit_body(&mut self, body: &'v hir::Body<'v>) { + hir::intravisit::walk_body(self, body); + } + } + + let mut visitor = IfVisitor { err_span: span, found_if: false, result: false }; + visitor.visit_body(&body); + if visitor.result { + err.span_suggestion_verbose( + span.shrink_to_lo(), + "consider adding `let`", + "let ".to_string(), + Applicability::MachineApplicable, + ); + } + } + } + fn emit_tuple_wrap_err( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 0924c8537159..89d5fe3d9da1 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -420,6 +420,15 @@ pub(crate) struct ExpectedExpressionFoundLet { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parser_expect_eq_instead_of_eqeq)] +pub(crate) struct ExpectedEqForLetExpr { + #[primary_span] + pub span: Span, + #[suggestion_verbose(applicability = "maybe-incorrect", code = "=")] + pub sugg_span: Span, +} + #[derive(Diagnostic)] #[diag(parser_expected_else_block)] pub(crate) struct ExpectedElseBlock { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4a1162b95998..565371668a8c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -9,9 +9,9 @@ use crate::errors::{ ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect, BinaryFloatLiteralNotSupported, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg, - DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedExpressionFoundLet, - FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, - HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition, + DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedEqForLetExpr, + ExpectedExpressionFoundLet, FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, + FoundExprWouldBeStmt, HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, IntLiteralTooLarge, InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth, @@ -2334,7 +2334,15 @@ impl<'a> Parser<'a> { RecoverColon::Yes, CommaRecoveryMode::LikelyTuple, )?; - self.expect(&token::Eq)?; + if self.token == token::EqEq { + self.sess.emit_err(ExpectedEqForLetExpr { + span: self.token.span, + sugg_span: self.token.span, + }); + self.bump(); + } else { + self.expect(&token::Eq)?; + } let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) })?; diff --git a/src/test/ui/inference/issue-103587.rs b/src/test/ui/inference/issue-103587.rs new file mode 100644 index 000000000000..11536f9f4cc4 --- /dev/null +++ b/src/test/ui/inference/issue-103587.rs @@ -0,0 +1,12 @@ +fn main() { + let x = Some(123); + + if let Some(_) == x {} + //~^ ERROR expected `=`, found `==` + + if Some(_) = x {} + //~^ ERROR mismatched types + + if None = x { } + //~^ ERROR mismatched types +} diff --git a/src/test/ui/inference/issue-103587.stderr b/src/test/ui/inference/issue-103587.stderr new file mode 100644 index 000000000000..b373fbfbb948 --- /dev/null +++ b/src/test/ui/inference/issue-103587.stderr @@ -0,0 +1,40 @@ +error: expected `=`, found `==` + --> $DIR/issue-103587.rs:4:20 + | +LL | if let Some(_) == x {} + | ^^ + | +help: consider using `=` here + | +LL | if let Some(_) = x {} + | ~ + +error[E0308]: mismatched types + --> $DIR/issue-103587.rs:7:8 + | +LL | if Some(_) = x {} + | ^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(_) = x {} + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-103587.rs:10:8 + | +LL | if None = x { } + | ^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to use pattern matching + | +LL | if let None = x { } + | +++ +help: you might have meant to compare for equality + | +LL | if None == x { } + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr index 3d9ac40ec367..02148b7f7adf 100644 --- a/src/test/ui/suggestions/if-let-typo.stderr +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -25,12 +25,22 @@ error[E0308]: mismatched types | LL | if Some(x) = foo {} | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(x) = foo {} + | +++ error[E0308]: mismatched types --> $DIR/if-let-typo.rs:6:8 | LL | if Some(foo) = bar {} | ^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(foo) = bar {} + | +++ error[E0308]: mismatched types --> $DIR/if-let-typo.rs:7:8 @@ -51,6 +61,11 @@ error[E0308]: mismatched types | LL | if Some(3) = foo {} | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(3) = foo {} + | +++ error: aborting due to 7 previous errors From 9e7d2287cd87ad54cc3ed125ee4202fe870b380c Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 8 Nov 2022 16:04:14 +0800 Subject: [PATCH 163/221] use subdiagnostic for sugesting add let --- .../rustc_error_messages/locales/en-US/infer.ftl | 1 + compiler/rustc_infer/src/errors/mod.rs | 12 ++++++++++++ .../rustc_infer/src/infer/error_reporting/mod.rs | 8 ++------ compiler/rustc_parse/src/errors.rs | 2 +- src/test/ui/did_you_mean/issue-103909.stderr | 5 +++++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 18b3408b06ab..fa975ff2c20c 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -171,3 +171,4 @@ infer_msl_introduces_static = introduces a `'static` lifetime requirement infer_msl_unmet_req = because this has an unmet lifetime requirement infer_msl_trait_note = this has an implicit `'static` lifetime requirement infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement +infer_suggest_add_let_for_letchains = consider adding `let` diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index bb04e1c49bae..ec4eeb8caa27 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -180,6 +180,18 @@ pub enum SourceKindMultiSuggestion<'a> { }, } +#[derive(Subdiagnostic)] +#[suggestion( + infer_suggest_add_let_for_letchains, + style = "verbose", + applicability = "machine-applicable", + code = "let " +)] +pub(crate) struct SuggAddLetForLetChains { + #[primary_span] + pub span: Span, +} + impl<'a> SourceKindMultiSuggestion<'a> { pub fn new_fully_qualified( span: Span, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index ee9e59968be8..4d81de8b0b64 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -59,6 +59,7 @@ use crate::traits::{ StatementAsExpression, }; +use crate::errors::SuggAddLetForLetChains; use hir::intravisit::{walk_expr, walk_stmt}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; @@ -2421,12 +2422,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let mut visitor = IfVisitor { err_span: span, found_if: false, result: false }; visitor.visit_body(&body); if visitor.result { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "consider adding `let`", - "let ".to_string(), - Applicability::MachineApplicable, - ); + err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()}); } } } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 89d5fe3d9da1..e3acc11811f4 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -425,7 +425,7 @@ pub(crate) struct ExpectedExpressionFoundLet { pub(crate) struct ExpectedEqForLetExpr { #[primary_span] pub span: Span, - #[suggestion_verbose(applicability = "maybe-incorrect", code = "=")] + #[suggestion(applicability = "maybe-incorrect", code = "=", style = "verbose")] pub sugg_span: Span, } diff --git a/src/test/ui/did_you_mean/issue-103909.stderr b/src/test/ui/did_you_mean/issue-103909.stderr index a28914051b98..8641017470ba 100644 --- a/src/test/ui/did_you_mean/issue-103909.stderr +++ b/src/test/ui/did_you_mean/issue-103909.stderr @@ -14,6 +14,11 @@ error[E0308]: mismatched types | LL | if Err(err) = File::open("hello.txt") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Err(err) = File::open("hello.txt") { + | +++ error: aborting due to 2 previous errors From 807a7bfcee7d8eab9a66f039b031381ebce65cd1 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 8 Nov 2022 09:36:08 +0100 Subject: [PATCH 164/221] clarify licensing situation of mpsc and spsc queue --- library/std/src/sync/mpsc/mpsc_queue.rs | 11 +++++++++-- library/std/src/sync/mpsc/spsc_queue.rs | 8 ++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/library/std/src/sync/mpsc/mpsc_queue.rs b/library/std/src/sync/mpsc/mpsc_queue.rs index cdd64a5def50..7322512e3b45 100644 --- a/library/std/src/sync/mpsc/mpsc_queue.rs +++ b/library/std/src/sync/mpsc/mpsc_queue.rs @@ -8,8 +8,15 @@ //! method, and see the method for more information about it. Due to this //! caveat, this queue might not be appropriate for all use-cases. -// https://www.1024cores.net/home/lock-free-algorithms -// /queues/non-intrusive-mpsc-node-based-queue +// The original implementation is based off: +// https://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue +// +// Note that back when the code was imported, it was licensed under the BSD-2-Clause license: +// http://web.archive.org/web/20110411011612/https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue +// +// The original author of the code agreed to relicense it under `MIT OR Apache-2.0` in 2017, so as +// of today the license of this file is the same as the rest of the codebase: +// https://github.com/rust-lang/rust/pull/42149 #[cfg(all(test, not(target_os = "emscripten")))] mod tests; diff --git a/library/std/src/sync/mpsc/spsc_queue.rs b/library/std/src/sync/mpsc/spsc_queue.rs index 7e745eb31de6..61f91313ea96 100644 --- a/library/std/src/sync/mpsc/spsc_queue.rs +++ b/library/std/src/sync/mpsc/spsc_queue.rs @@ -4,7 +4,15 @@ //! concurrently between two threads. This data structure is safe to use and //! enforces the semantics that there is one pusher and one popper. +// The original implementation is based off: // https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue +// +// Note that back when the code was imported, it was licensed under the BSD-2-Clause license: +// http://web.archive.org/web/20110411011612/https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue +// +// The original author of the code agreed to relicense it under `MIT OR Apache-2.0` in 2017, so as +// of today the license of this file is the same as the rest of the codebase: +// https://github.com/rust-lang/rust/pull/42149 #[cfg(all(test, not(target_os = "emscripten")))] mod tests; From e5d01dcc78c32abf3abfadbc3b20c9080b5fca05 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 8 Nov 2022 11:51:10 +0000 Subject: [PATCH 165/221] Remove an address comparison from the parser --- compiler/rustc_parse/src/parser/expr.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4a1162b95998..728435b60299 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -833,16 +833,11 @@ impl<'a> Parser<'a> { ("cast", None) }; - // Save the memory location of expr before parsing any following postfix operators. - // This will be compared with the memory location of the output expression. - // If they different we can assume we parsed another expression because the existing expression is not reallocated. - let addr_before = &*cast_expr as *const _ as usize; let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; - let changed = addr_before != &*with_postfix as *const _ as usize; // Check if an illegal postfix operator has been added after the cast. // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. - if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || changed { + if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) { let msg = format!( "{cast_kind} cannot be followed by {}", match with_postfix.kind { From f1551bfc02845eb198a71cc5c0264bd71e336274 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 19 Oct 2022 17:17:19 +0200 Subject: [PATCH 166/221] selection failure: recompute applicable impls --- compiler/rustc_middle/src/traits/mod.rs | 3 -- compiler/rustc_middle/src/ty/mod.rs | 8 +-- .../src/traits/chalk_fulfill.rs | 15 +++++- .../src/traits/engine.rs | 17 +++--- .../src/traits/error_reporting/ambiguity.rs | 52 +++++++++++++++++++ .../src/traits/error_reporting/mod.rs | 38 +++++++------- .../src/traits/select/candidate_assembly.rs | 12 +---- .../src/traits/select/mod.rs | 4 -- src/test/ui/error-codes/E0282.rs | 3 +- src/test/ui/error-codes/E0401.rs | 4 +- src/test/ui/error-codes/E0401.stderr | 27 ++++++++-- .../impl-trait/cross-return-site-inference.rs | 9 ++-- .../cross-return-site-inference.stderr | 4 +- src/test/ui/inference/cannot-infer-async.rs | 3 +- src/test/ui/inference/cannot-infer-closure.rs | 3 +- src/test/ui/inference/issue-71732.rs | 3 +- src/test/ui/inference/issue-72616.rs | 3 +- src/test/ui/inference/issue-72616.stderr | 18 ++++++- .../ui/inference/question-mark-type-infer.rs | 3 +- src/test/ui/issues/issue-71584.rs | 3 +- src/test/ui/traits/issue-77982.stderr | 7 +-- 21 files changed, 166 insertions(+), 73 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a29f0722ff70..05382bd887cd 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -576,9 +576,6 @@ pub enum SelectionError<'tcx> { /// Signaling that an error has already been emitted, to avoid /// multiple errors being shown. ErrorReporting, - /// Multiple applicable `impl`s where found. The `DefId`s correspond to - /// all the `impl`s' Items. - Ambiguous(Vec), } /// When performing resolution, it is typically the case that there diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 27090c62d21e..b509ae6dd3b8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2550,11 +2550,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` /// with the name of the crate containing the impl. - pub fn span_of_impl(self, impl_did: DefId) -> Result { - if let Some(impl_did) = impl_did.as_local() { - Ok(self.def_span(impl_did)) + pub fn span_of_impl(self, impl_def_id: DefId) -> Result { + if let Some(impl_def_id) = impl_def_id.as_local() { + Ok(self.def_span(impl_def_id)) } else { - Err(self.crate_name(impl_did.krate)) + Err(self.crate_name(impl_def_id.krate)) } } diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index 81e1d64493e1..d32a990f182d 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -14,6 +14,8 @@ pub struct FulfillmentContext<'tcx> { obligations: FxIndexSet>, relationships: FxHashMap, + + usable_in_snapshot: bool, } impl FulfillmentContext<'_> { @@ -21,8 +23,13 @@ impl FulfillmentContext<'_> { FulfillmentContext { obligations: FxIndexSet::default(), relationships: FxHashMap::default(), + usable_in_snapshot: false, } } + + pub(crate) fn new_in_snapshot() -> Self { + FulfillmentContext { usable_in_snapshot: true, ..Self::new() } + } } impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { @@ -41,7 +48,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { infcx: &InferCtxt<'tcx>, obligation: PredicateObligation<'tcx>, ) { - assert!(!infcx.is_in_snapshot()); + if !self.usable_in_snapshot { + assert!(!infcx.is_in_snapshot()); + } let obligation = infcx.resolve_vars_if_possible(obligation); super::relationships::update(self, infcx, &obligation); @@ -72,7 +81,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { } fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { - assert!(!infcx.is_in_snapshot()); + if !self.usable_in_snapshot { + assert!(!infcx.is_in_snapshot()); + } let mut errors = Vec::new(); let mut next_round = FxIndexSet::default(); diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 21516c93efb5..0eafc49816d4 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -38,7 +38,7 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box { if tcx.sess.opts.unstable_opts.chalk { - Box::new(ChalkFulfillmentContext::new()) + Box::new(ChalkFulfillmentContext::new_in_snapshot()) } else { Box::new(FulfillmentContext::new_in_snapshot()) } @@ -119,13 +119,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { expected: T, actual: T, ) -> Result<(), TypeError<'tcx>> { - match self.infcx.at(cause, param_env).eq(expected, actual) { - Ok(InferOk { obligations, value: () }) => { - self.register_obligations(obligations); - Ok(()) - } - Err(e) => Err(e), - } + self.infcx + .at(cause, param_env) + .eq(expected, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } pub fn sup>( @@ -144,6 +141,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { } } + pub fn select_where_possible(&self) -> Vec> { + self.engine.borrow_mut().select_where_possible(self.infcx) + } + pub fn select_all_or_error(&self) -> Vec> { self.engine.borrow_mut().select_all_or_error(self.infcx) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs new file mode 100644 index 000000000000..58da54afb75b --- /dev/null +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -0,0 +1,52 @@ +use rustc_hir::def_id::DefId; +use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation}; +use rustc_span::DUMMY_SP; + +use crate::traits::ObligationCtxt; + +pub fn recompute_applicable_impls<'tcx>( + infcx: &InferCtxt<'tcx>, + obligation: &TraitObligation<'tcx>, +) -> Vec { + let tcx = infcx.tcx; + let param_env = obligation.param_env; + let dummy_cause = ObligationCause::dummy(); + let impl_may_apply = |impl_def_id| { + let ocx = ObligationCtxt::new_in_snapshot(infcx); + let placeholder_obligation = + infcx.replace_bound_vars_with_placeholders(obligation.predicate); + let obligation_trait_ref = + ocx.normalize(dummy_cause.clone(), param_env, placeholder_obligation.trait_ref); + + let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs); + let impl_trait_ref = ocx.normalize(ObligationCause::dummy(), param_env, impl_trait_ref); + + if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) { + return false; + } + + let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs); + ocx.register_obligations( + impl_predicates + .predicates + .iter() + .map(|&predicate| Obligation::new(dummy_cause.clone(), param_env, predicate)), + ); + + ocx.select_where_possible().is_empty() + }; + + let mut impls = Vec::new(); + tcx.for_each_relevant_impl( + obligation.predicate.def_id(), + obligation.predicate.skip_binder().trait_ref.self_ty(), + |impl_def_id| { + if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) { + impls.push(impl_def_id) + } + }, + ); + impls +} 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 c7dee4a18ac5..bcb00796cbab 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1,3 +1,4 @@ +mod ambiguity; pub mod on_unimplemented; pub mod suggestions; @@ -535,15 +536,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut span = obligation.cause.span; let mut err = match *error { - SelectionError::Ambiguous(ref impls) => { - let mut err = self.tcx.sess.struct_span_err( - obligation.cause.span, - &format!("multiple applicable `impl`s for `{}`", obligation.predicate), - ); - self.annotate_source_of_ambiguity(&mut err, impls, obligation.predicate); - err.emit(); - return; - } SelectionError::Unimplemented => { // If this obligation was generated as a result of well-formedness checking, see if we // can get a better error message by performing HIR-based well-formedness checking. @@ -2144,8 +2136,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { crate::traits::TraitQueryMode::Standard, ); match selcx.select_from_obligation(&obligation) { - Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => { - self.annotate_source_of_ambiguity(&mut err, &impls, predicate); + Ok(None) => { + let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation); + let has_non_region_infer = + trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer()); + // It doesn't make sense to talk about applicable impls if there are more + // than a handful of them. + if impls.len() > 1 && impls.len() < 5 && has_non_region_infer { + self.annotate_source_of_ambiguity(&mut err, &impls, predicate); + } else { + if self.is_tainted_by_errors() { + err.cancel(); + return; + } + err.note(&format!("cannot satisfy `{}`", predicate)); + } } _ => { if self.is_tainted_by_errors() { @@ -2441,7 +2446,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } } - let msg = format!("multiple `impl`s satisfying `{}` found", predicate); let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect(); crate_names.sort(); crate_names.dedup(); @@ -2462,13 +2466,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.downgrade_to_delayed_bug(); return; } - let post = if post.len() > 4 { - format!( - ":\n{}\nand {} more", - post.iter().map(|p| format!("- {}", p)).take(4).collect::>().join("\n"), - post.len() - 4, - ) - } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { + + let msg = format!("multiple `impl`s satisfying `{}` found", predicate); + let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::>().join("\n"),) } else if post.len() == 1 { format!(": `{}`", post[0]) 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 4c5bc333961d..3671a0d87df5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -20,7 +20,7 @@ use crate::traits; use crate::traits::coherence::Conflict; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{util, SelectionResult}; -use crate::traits::{Ambiguous, ErrorReporting, Overflow, Unimplemented}; +use crate::traits::{ErrorReporting, Overflow, Unimplemented}; use super::BuiltinImplConditions; use super::IntercrateAmbiguityCause; @@ -200,15 +200,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // and report ambiguity. if i > 1 { debug!("multiple matches, ambig"); - return Err(Ambiguous( - candidates - .into_iter() - .filter_map(|c| match c.candidate { - SelectionCandidate::ImplCandidate(def_id) => Some(def_id), - _ => None, - }) - .collect(), - )); + return Ok(None); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 84be1ced520f..2954a2c163f4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -294,9 +294,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { assert!(self.query_mode == TraitQueryMode::Canonical); return Err(SelectionError::Overflow(OverflowError::Canonical)); } - Err(SelectionError::Ambiguous(_)) => { - return Ok(None); - } Err(e) => { return Err(e); } @@ -931,7 +928,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), - Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical), Err(ErrorReporting) => Err(OverflowError::ErrorReporting), diff --git a/src/test/ui/error-codes/E0282.rs b/src/test/ui/error-codes/E0282.rs index 9bd16abb7bb8..f1f93b3aed61 100644 --- a/src/test/ui/error-codes/E0282.rs +++ b/src/test/ui/error-codes/E0282.rs @@ -1,3 +1,4 @@ fn main() { - let x = "hello".chars().rev().collect(); //~ ERROR E0282 + let x = "hello".chars().rev().collect(); + //~^ ERROR E0282 } diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs index c30e5f471887..8f8d6b87ef20 100644 --- a/src/test/ui/error-codes/E0401.rs +++ b/src/test/ui/error-codes/E0401.rs @@ -8,7 +8,9 @@ fn foo(x: T) { W: Fn()> (y: T) { //~ ERROR E0401 } - bfnr(x); //~ ERROR type annotations needed + bfnr(x); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index b0e2ef5b6f7e..9687eca61fab 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -21,7 +21,7 @@ LL | (y: T) { | ^ use of generic parameter from outer function error[E0401]: can't use generic parameters from outer function - --> $DIR/E0401.rs:22:25 + --> $DIR/E0401.rs:24:25 | LL | impl Iterator for A { | ---- `Self` type implicitly declared here, by this `impl` @@ -43,7 +43,28 @@ help: consider specifying the generic arguments LL | bfnr::(x); | +++++++++++ -error: aborting due to 4 previous errors +error[E0283]: type annotations needed + --> $DIR/E0401.rs:11:5 + | +LL | bfnr(x); + | ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr` + | + = note: multiple `impl`s satisfying `_: Fn<()>` found in the following crates: `alloc`, `core`: + - impl Fn for &F + where A: Tuple, F: Fn, F: ?Sized; + - impl Fn for Box + where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; +note: required by a bound in `bfnr` + --> $DIR/E0401.rs:4:30 + | +LL | fn bfnr, W: Fn()>(y: T) { + | ^^^^ required by this bound in `bfnr` +help: consider specifying the type arguments in the function call + | +LL | bfnr::(x); + | +++++++++++ -Some errors have detailed explanations: E0282, E0401. +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0282, E0283, E0401. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs index d881af9ed8fe..00aed2ad95a2 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.rs +++ b/src/test/ui/impl-trait/cross-return-site-inference.rs @@ -30,16 +30,19 @@ fn baa(b: bool) -> impl std::fmt::Debug { fn muh() -> Result<(), impl std::fmt::Debug> { Err("whoops")?; - Ok(()) //~ ERROR type annotations needed + Ok(()) + //~^ ERROR type annotations needed } fn muh2() -> Result<(), impl std::fmt::Debug> { - return Err(From::from("foo")); //~ ERROR type annotations needed + return Err(From::from("foo")); + //~^ ERROR type annotations needed Ok(()) } fn muh3() -> Result<(), impl std::fmt::Debug> { - Err(From::from("foo")) //~ ERROR type annotations needed + Err(From::from("foo")) + //~^ ERROR type annotations needed } fn main() {} diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr index 1ff777e65037..766614e9e50f 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.stderr +++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr @@ -10,7 +10,7 @@ LL | Ok::<(), E>(()) | +++++++++ error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:37:12 + --> $DIR/cross-return-site-inference.rs:38:12 | LL | return Err(From::from("foo")); | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` @@ -21,7 +21,7 @@ LL | return Err::<(), E>(From::from("foo")); | +++++++++ error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:42:5 + --> $DIR/cross-return-site-inference.rs:44:5 | LL | Err(From::from("foo")) | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs index e7fabd0ffbc8..b5152d04f695 100644 --- a/src/test/ui/inference/cannot-infer-async.rs +++ b/src/test/ui/inference/cannot-infer-async.rs @@ -10,6 +10,7 @@ fn main() { let fut = async { make_unit()?; - Ok(()) //~ ERROR type annotations needed + Ok(()) + //~^ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs index 1c350b18f5a6..bd5d10b41734 100644 --- a/src/test/ui/inference/cannot-infer-closure.rs +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -1,6 +1,7 @@ fn main() { let x = |a: (), b: ()| { Err(a)?; - Ok(b) //~ ERROR type annotations needed + Ok(b) + //~^ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/issue-71732.rs b/src/test/ui/inference/issue-71732.rs index 30063a0957c7..8a9d2b235f0e 100644 --- a/src/test/ui/inference/issue-71732.rs +++ b/src/test/ui/inference/issue-71732.rs @@ -15,7 +15,8 @@ use std::collections::hash_map::HashMap; fn foo(parameters: &HashMap) -> bool { parameters - .get(&"key".into()) //~ ERROR: type annotations needed + .get(&"key".into()) + //~^ ERROR type annotations needed .and_then(|found: &String| Some(false)) .unwrap_or(false) } diff --git a/src/test/ui/inference/issue-72616.rs b/src/test/ui/inference/issue-72616.rs index 5e5a3babfe02..7b0f5936d84e 100644 --- a/src/test/ui/inference/issue-72616.rs +++ b/src/test/ui/inference/issue-72616.rs @@ -18,7 +18,8 @@ pub fn main() { } { if String::from("a") == "a".try_into().unwrap() {} - //~^ ERROR: type annotations needed + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } { let _: String = match "_".try_into() { diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr index a71ce9a8ef27..da1a7ccdee15 100644 --- a/src/test/ui/inference/issue-72616.stderr +++ b/src/test/ui/inference/issue-72616.stderr @@ -16,6 +16,22 @@ help: try using a fully qualified path to specify the expected types LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} | +++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error[E0283]: type annotations needed + --> $DIR/issue-72616.rs:20:37 + | +LL | if String::from("a") == "a".try_into().unwrap() {} + | ^^^^^^^^ + | + = note: multiple `impl`s satisfying `_: TryFrom<&str>` found in the following crates: `core`, `std`: + - impl<> TryFrom<&str> for std::sys_common::net::LookupHost; + - impl TryFrom for T + where U: Into; + = note: required for `&str` to implement `TryInto<_>` +help: try using a fully qualified path to specify the expected types + | +LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} + | +++++++++++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/inference/question-mark-type-infer.rs b/src/test/ui/inference/question-mark-type-infer.rs index 64333a29313b..10560f85ed48 100644 --- a/src/test/ui/inference/question-mark-type-infer.rs +++ b/src/test/ui/inference/question-mark-type-infer.rs @@ -7,7 +7,8 @@ fn f(x: &i32) -> Result { fn g() -> Result, ()> { let l = [1, 2, 3, 4]; - l.iter().map(f).collect()? //~ ERROR type annotations needed + l.iter().map(f).collect()? + //~^ ERROR type annotations needed } fn main() { diff --git a/src/test/ui/issues/issue-71584.rs b/src/test/ui/issues/issue-71584.rs index c96cd598f0ce..7bf3ed60ec10 100644 --- a/src/test/ui/issues/issue-71584.rs +++ b/src/test/ui/issues/issue-71584.rs @@ -1,5 +1,6 @@ fn main() { let n: u32 = 1; let mut d: u64 = 2; - d = d % n.into(); //~ ERROR type annotations needed + d = d % n.into(); + //~^ ERROR type annotations needed } diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr index e210f11b3e0c..b6a04585583c 100644 --- a/src/test/ui/traits/issue-77982.stderr +++ b/src/test/ui/traits/issue-77982.stderr @@ -46,12 +46,7 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect( | | | required by a bound introduced by this call | - = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`: - - impl From for u32; - - impl From for u32; - - impl From for u32; - - impl From for u32; - and 3 more + = note: cannot satisfy `u32: From<_>` help: try using a fully qualified path to specify the expected types | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(>::into(0u32))).collect(); From 003ed76e41e9b8247d2b2fc040da76969e86d4a6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 31 Oct 2022 10:27:51 +0100 Subject: [PATCH 167/221] delay errors as bug --- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 bcb00796cbab..0f5d05afcf80 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2146,7 +2146,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.annotate_source_of_ambiguity(&mut err, &impls, predicate); } else { if self.is_tainted_by_errors() { - err.cancel(); + err.delay_as_bug(); return; } err.note(&format!("cannot satisfy `{}`", predicate)); @@ -2154,7 +2154,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } _ => { if self.is_tainted_by_errors() { - err.cancel(); + err.delay_as_bug(); return; } err.note(&format!("cannot satisfy `{}`", predicate)); From 91d5a32bc59c50af762928da5a02b024b36c1891 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 8 Nov 2022 14:16:49 +0100 Subject: [PATCH 168/221] ignore wasm in test --- src/test/ui/inference/issue-72616.rs | 2 ++ src/test/ui/inference/issue-72616.stderr | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/ui/inference/issue-72616.rs b/src/test/ui/inference/issue-72616.rs index 7b0f5936d84e..69ade1a7515c 100644 --- a/src/test/ui/inference/issue-72616.rs +++ b/src/test/ui/inference/issue-72616.rs @@ -1,3 +1,5 @@ +// ignore-wasm32 FIXME: ignoring wasm as it suggests slightly different impls + // Regression test for #72616, it used to emit incorrect diagnostics, like: // error[E0283]: type annotations needed for `String` // --> src/main.rs:8:30 diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr index da1a7ccdee15..6ee0626cab85 100644 --- a/src/test/ui/inference/issue-72616.stderr +++ b/src/test/ui/inference/issue-72616.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/issue-72616.rs:20:37 + --> $DIR/issue-72616.rs:22:37 | LL | if String::from("a") == "a".try_into().unwrap() {} | -- ^^^^^^^^ @@ -17,7 +17,7 @@ LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap( | +++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed - --> $DIR/issue-72616.rs:20:37 + --> $DIR/issue-72616.rs:22:37 | LL | if String::from("a") == "a".try_into().unwrap() {} | ^^^^^^^^ From a7a40ddc795a61091b6da4b22b935d82e3c94342 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 8 Nov 2022 14:45:24 +0000 Subject: [PATCH 169/221] Simplify some `Autoderef::new` calls --- compiler/rustc_hir_typeck/src/autoderef.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 59c366ad7d77..f30d53a4c870 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -12,7 +12,7 @@ use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { - Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span) + self.autoderef_overloaded_span(span, base_ty, span) } /// Like `autoderef`, but provides a custom `Span` to use for calls to diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ea90da4a6dc3..c4f1a3e4e1bb 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -19,7 +19,6 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, DUMMY_SP}; -use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::{ObligationCause, Pattern}; use ty::VariantDef; @@ -2132,7 +2131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let ty::Array(..) | ty::Slice(..) = ty.kind() { err.help("the semantics of slice patterns changed recently; see issue #62254"); - } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span) + } else if self.autoderef(span, expected_ty) .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) && let (Some(span), true) = (ti.span, ti.origin_expr) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) From 1d93b358553f1942214e6800bb3fc68a521abe90 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 8 Nov 2022 15:49:29 +0000 Subject: [PATCH 170/221] Remove overloaded_span argument from `new`, where it is usually redundant with the main span --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 3 +-- compiler/rustc_hir_typeck/src/autoderef.rs | 13 +------------ compiler/rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 7 +++---- compiler/rustc_trait_selection/src/autoderef.rs | 7 +++++-- .../src/traits/error_reporting/suggestions.rs | 1 - 6 files changed, 11 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index e2c967d0b083..6f901cf709a2 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1708,8 +1708,7 @@ fn receiver_is_valid<'tcx>( return true; } - let mut autoderef = - Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty, span); + let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty); // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`. if arbitrary_self_types_enabled { diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index f30d53a4c870..748237a7593a 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -12,18 +12,7 @@ use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { - self.autoderef_overloaded_span(span, base_ty, span) - } - - /// Like `autoderef`, but provides a custom `Span` to use for calls to - /// an overloaded `Deref` operator - pub fn autoderef_overloaded_span( - &'a self, - span: Span, - base_ty: Ty<'tcx>, - overloaded_span: Span, - ) -> Autoderef<'a, 'tcx> { - Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span) + Autoderef::new(self, self.param_env, self.body_id, span, base_ty) } pub fn try_overloaded_deref( diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index be4ea9986222..a0de38ef856e 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -152,7 +152,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various typeck results. let mut autoderef = - self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span); + self.autoderef(self.span, unadjusted_self_ty).with_overloaded_span(self.call_expr.span); let Some((ty, n)) = autoderef.nth(pick.autoderefs) else { return self.tcx.ty_error_with_message( rustc_span::DUMMY_SP, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index e88701685bc6..3fcd073f5979 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -475,10 +475,9 @@ fn method_autoderef_steps<'tcx>( let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal); let ParamEnvAnd { param_env, value: self_ty } = goal; - let mut autoderef = - Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP) - .include_raw_pointers() - .silence_errors(); + let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty) + .include_raw_pointers() + .silence_errors(); let mut reached_raw_pointer = false; let mut steps: Vec<_> = autoderef .by_ref() diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 61cfeec4bbb6..1a478f02df21 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -99,12 +99,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { body_id: hir::HirId, span: Span, base_ty: Ty<'tcx>, - overloaded_span: Span, ) -> Autoderef<'a, 'tcx> { Autoderef { infcx, span, - overloaded_span, + overloaded_span: span, body_id, param_env, state: AutoderefSnapshot { @@ -119,6 +118,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } } + pub fn with_overloaded_span(self, overloaded_span: Span) -> Self { + Self { overloaded_span, ..self } + } + fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { debug!("overloaded_deref_ty({:?})", ty); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 0f4aa87b43f5..aece4ab79228 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -714,7 +714,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligation.cause.body_id, span, base_ty, - span, ); if let Some(steps) = autoderef.find_map(|(ty, steps)| { // Re-add the `&` From b745a29fa51b59642f3883bc80ca1d502532757e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 8 Nov 2022 16:03:48 +0000 Subject: [PATCH 171/221] Remove an unused span --- compiler/rustc_hir_typeck/src/autoderef.rs | 6 +----- compiler/rustc_hir_typeck/src/method/confirm.rs | 3 +-- compiler/rustc_trait_selection/src/autoderef.rs | 10 ---------- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 748237a7593a..41b52a4c4a9f 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -44,11 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |InferOk { value: method, obligations: o }| { obligations.extend(o); if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() { - Some(OverloadedDeref { - region, - mutbl, - span: autoderef.overloaded_span(), - }) + Some(OverloadedDeref { region, mutbl, span: autoderef.span() }) } else { None } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index a0de38ef856e..d996d6ec610b 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -151,8 +151,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ) -> Ty<'tcx> { // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various typeck results. - let mut autoderef = - self.autoderef(self.span, unadjusted_self_ty).with_overloaded_span(self.call_expr.span); + let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty); let Some((ty, n)) = autoderef.nth(pick.autoderefs) else { return self.tcx.ty_error_with_message( rustc_span::DUMMY_SP, diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 1a478f02df21..46ee2f35976a 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -27,7 +27,6 @@ pub struct Autoderef<'a, 'tcx> { // Meta infos: infcx: &'a InferCtxt<'tcx>, span: Span, - overloaded_span: Span, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, @@ -103,7 +102,6 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { Autoderef { infcx, span, - overloaded_span: span, body_id, param_env, state: AutoderefSnapshot { @@ -118,10 +116,6 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } } - pub fn with_overloaded_span(self, overloaded_span: Span) -> Self { - Self { overloaded_span, ..self } - } - fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { debug!("overloaded_deref_ty({:?})", ty); @@ -196,10 +190,6 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { self.span } - pub fn overloaded_span(&self) -> Span { - self.overloaded_span - } - pub fn reached_recursion_limit(&self) -> bool { self.state.reached_recursion_limit } From 268ea3528d85c44126aa01a22b9c00f0951f21f0 Mon Sep 17 00:00:00 2001 From: Waffle Maybe Date: Tue, 8 Nov 2022 21:49:58 +0400 Subject: [PATCH 172/221] Fix outdated comment Co-authored-by: clubby789 --- compiler/rustc_parse/src/parser/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 728435b60299..d784fef2bed5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -836,7 +836,7 @@ impl<'a> Parser<'a> { let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; // Check if an illegal postfix operator has been added after the cast. - // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. + // If the resulting expression is not a cast, it is an illegal postfix operator. if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) { let msg = format!( "{cast_kind} cannot be followed by {}", From 755ca4b9aa064b77fa8a0f6cdaf050b768d844bc Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Fri, 28 Oct 2022 23:32:41 +0200 Subject: [PATCH 173/221] Reduce the scope of allow(rustc::potential_query_instability) in rustc_trait_selection Make InferCtxtExt use a FxIndexMap This should be faster, because the map is only being used to iterate, which is supposed to be faster with the IndexMap Make the user_computed_preds use an IndexMap It is being used mostly for iteration, so the change shouldn't result in a perf hit Make the RegionDeps fields use an IndexMap This change could be a perf hit. Both `larger` and `smaller` are used for iteration, but they are also used for insertions. Make types_without_default_bounds use an IndexMap It uses extend, but it also iterates and removes items. Not sure if this will be a perf hit. Make InferTtxt.reported_trait_errors use an IndexMap This change brought a lot of other changes. The map seems to have been mostly used for iteration, so the performance shouldn't suffer. Add FIXME to change ProvisionalEvaluationCache.map to use an IndexMap Right now this results in a perf hit. IndexMap doesn't have the `drain_filter` API, so in `on_completion` we now need to iterate two times over the map. --- .../src/check/compare_method.rs | 6 +++--- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 16 ++++++++-------- compiler/rustc_infer/src/infer/mod.rs | 3 ++- compiler/rustc_trait_selection/src/lib.rs | 1 - .../src/traits/auto_trait.rs | 12 ++++++------ .../rustc_trait_selection/src/traits/engine.rs | 6 +++--- .../src/traits/error_reporting/mod.rs | 4 ++-- .../src/traits/outlives_bounds.rs | 6 +++--- .../src/traits/select/mod.rs | 9 ++++++++- .../src/traits/specialize/mod.rs | 4 ++-- 10 files changed, 37 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 0e8ac17fb71b..818db4186d60 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -1,7 +1,7 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, LocalDefId}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -256,7 +256,7 @@ fn compare_predicate_entailment<'tcx>( // Compute placeholder form of impl and trait method tys. let tcx = infcx.tcx; - let mut wf_tys = FxHashSet::default(); + let mut wf_tys = FxIndexSet::default(); let impl_sig = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, @@ -479,7 +479,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let trait_sig = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_sig); let trait_return_ty = trait_sig.output(); - let wf_tys = FxHashSet::from_iter( + let wf_tys = FxIndexSet::from_iter( unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()), ); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index e2c967d0b083..6a12db9d36ad 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1,7 +1,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use hir::def::DefKind; use rustc_ast as ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -412,7 +412,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe .iter() .copied() .collect::>(), - &FxHashSet::default(), + &FxIndexSet::default(), gat_def_id.def_id, gat_generics, ) @@ -462,10 +462,10 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe .into_iter() .filter(|clause| match clause.kind().skip_binder() { ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { - !region_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b) + !region_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b) } ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => { - !ty_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b) + !ty_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b) } _ => bug!("Unexpected PredicateKind"), }) @@ -547,7 +547,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>( param_env: ty::ParamEnv<'tcx>, item_hir: hir::HirId, to_check: T, - wf_tys: &FxHashSet>, + wf_tys: &FxIndexSet>, gat_def_id: LocalDefId, gat_generics: &'tcx ty::Generics, ) -> Option>> { @@ -654,7 +654,7 @@ fn ty_known_to_outlive<'tcx>( tcx: TyCtxt<'tcx>, id: hir::HirId, param_env: ty::ParamEnv<'tcx>, - wf_tys: &FxHashSet>, + wf_tys: &FxIndexSet>, ty: Ty<'tcx>, region: ty::Region<'tcx>, ) -> bool { @@ -671,7 +671,7 @@ fn region_known_to_outlive<'tcx>( tcx: TyCtxt<'tcx>, id: hir::HirId, param_env: ty::ParamEnv<'tcx>, - wf_tys: &FxHashSet>, + wf_tys: &FxIndexSet>, region_a: ty::Region<'tcx>, region_b: ty::Region<'tcx>, ) -> bool { @@ -695,7 +695,7 @@ fn resolve_regions_with_wf_tys<'tcx>( tcx: TyCtxt<'tcx>, id: hir::HirId, param_env: ty::ParamEnv<'tcx>, - wf_tys: &FxHashSet>, + wf_tys: &FxIndexSet>, add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>), ) -> bool { // Unfortunately, we have to use a new `InferCtxt` each call, because diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index d5be9983ea7c..ccba197dc80b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -10,6 +10,7 @@ pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt}; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::Rollback; @@ -294,7 +295,7 @@ pub struct InferCtxt<'tcx> { /// the set of predicates on which errors have been reported, to /// avoid reporting the same error twice. - pub reported_trait_errors: RefCell>>>, + pub reported_trait_errors: RefCell>>>, pub reported_closure_mismatch: RefCell)>>, diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5d52aa075230..2dce18e2d3ca 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -10,7 +10,6 @@ //! //! This API is completely unstable and subject to change. -#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index ed34ab95ad6c..188f8bb7e2a5 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{PolyTraitRef, Region, RegionVid}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use std::collections::hash_map::Entry; use std::collections::VecDeque; @@ -27,8 +27,8 @@ pub enum RegionTarget<'tcx> { #[derive(Default, Debug, Clone)] pub struct RegionDeps<'tcx> { - larger: FxHashSet>, - smaller: FxHashSet>, + larger: FxIndexSet>, + smaller: FxIndexSet>, } pub enum AutoTraitResult { @@ -266,7 +266,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { })); let computed_preds = param_env.caller_bounds().iter(); - let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds().iter().collect(); + let mut user_computed_preds: FxIndexSet<_> = user_env.caller_bounds().iter().collect(); let mut new_env = param_env; let dummy_cause = ObligationCause::dummy(); @@ -389,7 +389,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { /// not just one specific lifetime (e.g., `'static`). fn add_user_pred( &self, - user_computed_preds: &mut FxHashSet>, + user_computed_preds: &mut FxIndexSet>, new_pred: ty::Predicate<'tcx>, ) { let mut should_add_new = true; @@ -585,7 +585,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { &self, ty: Ty<'_>, nested: impl Iterator>>, - computed_preds: &mut FxHashSet>, + computed_preds: &mut FxIndexSet>, fresh_preds: &mut FxHashSet>, predicates: &mut VecDeque>, select: &mut SelectionContext<'_, 'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 21516c93efb5..91bf5f0b39e7 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use super::TraitEngine; use super::{ChalkFulfillmentContext, FulfillmentContext}; use crate::infer::InferCtxtExt; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{ @@ -153,10 +153,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, span: Span, def_id: LocalDefId, - ) -> FxHashSet> { + ) -> FxIndexSet> { let tcx = self.infcx.tcx; let assumed_wf_types = tcx.assumed_wf_types(def_id); - let mut implied_bounds = FxHashSet::default(); + let mut implied_bounds = FxIndexSet::default(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let cause = ObligationCause::misc(span, hir_id); for ty in assumed_wf_types { 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 c7dee4a18ac5..2525b9fdd470 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -14,7 +14,7 @@ use crate::traits::query::normalize::AtExt as _; use crate::traits::specialize::to_pretty_impl_header; use on_unimplemented::OnUnimplementedNote; use on_unimplemented::TypeErrCtxtExt as _; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, Style, @@ -378,7 +378,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { index: Option, // None if this is an old error } - let mut error_map: FxHashMap<_, Vec<_>> = self + let mut error_map: FxIndexMap<_, Vec<_>> = self .reported_trait_errors .borrow() .iter() diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index b1a161c35363..e1092a788e32 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -2,7 +2,7 @@ use crate::infer::InferCtxt; use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use crate::traits::query::NoSolution; use crate::traits::ObligationCause; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::HirId; use rustc_middle::ty::{self, ParamEnv, Ty}; @@ -22,7 +22,7 @@ pub trait InferCtxtExt<'a, 'tcx> { &'a self, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, - tys: FxHashSet>, + tys: FxIndexSet>, ) -> Bounds<'a, 'tcx>; } @@ -103,7 +103,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { &'a self, param_env: ParamEnv<'tcx>, body_id: HirId, - tys: FxHashSet>, + tys: FxIndexSet>, ) -> Bounds<'a, 'tcx> { tys.into_iter() .map(move |ty| { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 84be1ced520f..f0d9a1c91397 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2,6 +2,12 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection +// FIXME: The `map` field in ProvisionalEvaluationCache should be changed to +// a `FxIndexMap` to avoid query instability, but right now it causes a perf regression. This would be +// fixed or at least lightened by the addition of the `drain_filter` method to `FxIndexMap` +// Relevant: https://github.com/rust-lang/rust/pull/103723 and https://github.com/bluss/indexmap/issues/242 +#![allow(rustc::potential_query_instability)] + use self::EvaluationResult::*; use self::SelectionCandidate::*; @@ -24,7 +30,8 @@ use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index c891658582a0..43819b3f490b 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -16,7 +16,7 @@ use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause}; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{struct_span_err, DiagnosticBuilder, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::{self, ImplSubject, TyCtxt}; @@ -435,7 +435,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti // FIXME: Currently only handles ?Sized. // Needs to support ?Move and ?DynSized when they are implemented. - let mut types_without_default_bounds = FxHashSet::default(); + let mut types_without_default_bounds = FxIndexSet::default(); let sized_trait = tcx.lang_items().sized_trait(); if !substs.is_empty() { From 9eb977bec440cf8610b9e687146c510f8a2fbf7c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 8 Nov 2022 11:29:58 -0800 Subject: [PATCH 174/221] Add llvm-main to triagebot.toml --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 202f9cad57a4..d3f9efcc41c3 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -12,6 +12,7 @@ allow-unauthenticated = [ "T-*", "WG-*", "const-hack", + "llvm-main", "needs-fcp", "relnotes", "requires-nightly", From ef40824fda03f6d8abd1f62b72d6daf649f452ba Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 8 Nov 2022 13:37:49 -0800 Subject: [PATCH 175/221] Update books --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/book b/src/doc/book index aa5ee485bd6b..3f64052c048c 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit aa5ee485bd6bd80d205da7c82fcdd776f92fdd51 +Subproject commit 3f64052c048c6def93b94a2b514ee88bba918744 diff --git a/src/doc/nomicon b/src/doc/nomicon index 9c7328377546..05532356e7a4 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 9c73283775466d22208a0b28afcab44db4c0cc10 +Subproject commit 05532356e7a4dbea2330aabb77611f5179493bb8 diff --git a/src/doc/reference b/src/doc/reference index 4ea7c5def38a..9f0cc13ffcd2 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 4ea7c5def38ac81df33a9e48e5637a82a5ac404d +Subproject commit 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d19 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 03491f33375c..2b15c0abf2ba 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 03491f33375c5a2a1661c7fa4be671fe95ce1249 +Subproject commit 2b15c0abf2bada6e00553814336bc3e2d8399097 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 51a37ad19a15..d0dc6c97a648 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 51a37ad19a15709d0601afbac6581f5aea6a45da +Subproject commit d0dc6c97a6486f68bac782fff135086eae6d77ec From 49be827dcae4b226a2cb6f56e49083d49908fa6f Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 8 Nov 2022 21:59:58 +0000 Subject: [PATCH 176/221] comment --- .../src/collect/lifetimes.rs | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index b9583bd2244b..c64177eea3f8 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -1834,6 +1834,27 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< debug!(?late_bound); return Some(tcx.arena.alloc(late_bound)); + /// Visits a `ty::Ty` collecting information about what generic parameters are constrained. + /// + /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;` + /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of` + /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally + /// handles cycle detection as we go through the query system. + /// + /// This is necessary in the first place for the following case: + /// ``` + /// type Alias<'a, T> = >::Assoc; + /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... } + /// ``` + /// + /// If we conservatively considered `'a` unconstrained then we could break users who had written code before + /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound + /// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` + /// but appears in the output type `<() as Trait<'a>>::Assoc`. + /// + /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not. + /// + /// See #100508 #85533 #47511 for additional context struct ConstrainedCollectorPostAstConv { arg_is_constrained: Box<[bool]>, } @@ -1886,17 +1907,8 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< None, hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, )) => { - // If this is a top level type alias attempt to "look through" it to see if the args - // are constrained, instead of assuming they are and inserting all the lifetimes. - // This is necessary for the following case: - // ``` - // type Alias<'a, T> = >::Assoc; - // fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... } - // ``` - // If we considered `'a` constrained then it would become late bound causing an error - // during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` - // but appears in the output type `<() as Trait<'a>>::Assoc`. - + // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider + // substs to be unconstrained. let generics = self.tcx.generics_of(alias_def); let mut walker = ConstrainedCollectorPostAstConv { arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(), From 983a90d7160b5e6054827f42c0ecf9aa52cebcd4 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 8 Nov 2022 22:15:40 +0000 Subject: [PATCH 177/221] tests --- .../auxiliary/upstream_alias.rs | 5 +++++ .../ui/late-bound-lifetimes/cross_crate_alias.rs | 10 ++++++++++ .../late_bound_through_alias.rs | 16 ++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs create mode 100644 src/test/ui/late-bound-lifetimes/cross_crate_alias.rs create mode 100644 src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs diff --git a/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs new file mode 100644 index 000000000000..5b9dc0e43087 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs @@ -0,0 +1,5 @@ +pub trait Trait<'a> { + type Assoc; +} + +pub type Alias<'a, T> = >::Assoc; diff --git a/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs new file mode 100644 index 000000000000..4154c2792432 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs @@ -0,0 +1,10 @@ +// aux-build:upstream_alias.rs +// check-pass + +extern crate upstream_alias; + +fn foo<'a, T: for<'b> upstream_alias::Trait<'b>>(_: upstream_alias::Alias<'a, T>) -> &'a () { + todo!() +} + +fn main() {} diff --git a/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs new file mode 100644 index 000000000000..91839673c1f7 --- /dev/null +++ b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs @@ -0,0 +1,16 @@ +// check-pass + +fn f(_: X) -> X { + unimplemented!() +} + +fn g<'a>(_: X<'a>) -> X<'a> { + unimplemented!() +} + +type X<'a> = &'a (); + +fn main() { + let _: for<'a> fn(X<'a>) -> X<'a> = g; + let _: for<'a> fn(X<'a>) -> X<'a> = f; +} From b3a328eecf539be2267b1373f8637f7d31cd6162 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 9 Nov 2022 02:08:22 +0000 Subject: [PATCH 178/221] Use `nominal_obligations_without_const` in wf for FnDef --- compiler/rustc_trait_selection/src/traits/wf.rs | 2 +- src/test/ui/consts/issue-104155.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/issue-104155.rs diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 8908fe230b0e..fc0a9f690033 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -547,7 +547,7 @@ impl<'tcx> WfPredicates<'tcx> { } ty::FnDef(did, substs) => { - let obligations = self.nominal_obligations(did, substs); + let obligations = self.nominal_obligations_without_const(did, substs); self.out.extend(obligations); } diff --git a/src/test/ui/consts/issue-104155.rs b/src/test/ui/consts/issue-104155.rs new file mode 100644 index 000000000000..1cc8f81b0d25 --- /dev/null +++ b/src/test/ui/consts/issue-104155.rs @@ -0,0 +1,5 @@ +// check-pass +const _: () = core::mem::forget(Box::::default); +const _: () = core::mem::forget(|| Box::::default()); + +fn main() {} From ba359d8a51d106907332a90c59e1a339b1fc3656 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Wed, 3 Aug 2022 04:30:13 -0700 Subject: [PATCH 179/221] Add support for custom MIR parsing --- compiler/rustc_borrowck/src/lib.rs | 14 + compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_feature/src/builtin_attrs.rs | 4 + compiler/rustc_middle/src/mir/mod.rs | 59 +++++ .../rustc_mir_build/src/build/custom/mod.rs | 155 +++++++++++ .../rustc_mir_build/src/build/custom/parse.rs | 245 ++++++++++++++++++ .../src/build/custom/parse/instruction.rs | 72 +++++ compiler/rustc_mir_build/src/build/mod.rs | 17 ++ compiler/rustc_mir_build/src/thir/cx/expr.rs | 16 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 11 +- .../rustc_mir_transform/src/check_unsafety.rs | 8 + .../rustc_mir_transform/src/pass_manager.rs | 71 ++--- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics.rs | 3 + library/core/src/intrinsics/mir.rs | 123 +++++++++ .../references.immut_ref.built.after.mir | 14 + .../custom/references.mut_ref.built.after.mir | 14 + .../mir-opt/building/custom/references.rs | 43 +++ .../mir-opt/building/custom/simple_assign.rs | 37 +++ .../simple_assign.simple.built.after.mir | 18 ++ .../simple_assign.simple_ref.built.after.mir | 10 + .../feature-gates/feature-gate-custom_mir.rs | 12 + .../feature-gate-custom_mir.stderr | 11 + 23 files changed, 920 insertions(+), 40 deletions(-) create mode 100644 compiler/rustc_mir_build/src/build/custom/mod.rs create mode 100644 compiler/rustc_mir_build/src/build/custom/parse.rs create mode 100644 compiler/rustc_mir_build/src/build/custom/parse/instruction.rs create mode 100644 library/core/src/intrinsics/mir.rs create mode 100644 src/test/mir-opt/building/custom/references.immut_ref.built.after.mir create mode 100644 src/test/mir-opt/building/custom/references.mut_ref.built.after.mir create mode 100644 src/test/mir-opt/building/custom/references.rs create mode 100644 src/test/mir-opt/building/custom/simple_assign.rs create mode 100644 src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir create mode 100644 src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir create mode 100644 src/test/ui/feature-gates/feature-gate-custom_mir.rs create mode 100644 src/test/ui/feature-gates/feature-gate-custom_mir.stderr diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index abfe253d43df..4a4887f19702 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -18,6 +18,7 @@ extern crate tracing; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::vec_map::VecMap; use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -129,6 +130,19 @@ fn mir_borrowck<'tcx>( ) -> &'tcx BorrowCheckResult<'tcx> { let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); + + if input_body.borrow().should_skip() { + debug!("Skipping borrowck because of injected body"); + // Let's make up a borrowck result! Fun times! + let result = BorrowCheckResult { + concrete_opaque_types: VecMap::new(), + closure_requirements: None, + used_mut_upvars: SmallVec::new(), + tainted_by_errors: None, + }; + return tcx.arena.alloc(result); + } + let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; let infcx = diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 09a747662e26..e94e038f9283 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -152,6 +152,8 @@ declare_features! ( (active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None), /// Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), + /// Allows writing custom MIR + (active, custom_mir, "1.65.0", None, None), /// Outputs useful `assert!` messages (active, generic_assert, "1.63.0", None, None), /// Allows using the `rust-intrinsic`'s "ABI". diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4ff3b3f2a38b..dc3a74956843 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -810,6 +810,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk), + gated!( + custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#), + ErrorFollowing, "the `#[custom_mir]` attribute is just used for the Rust test suite", + ), rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 0a96d23e3543..5290d5aae46c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -138,6 +138,48 @@ impl MirPhase { } } } + + /// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason. + pub fn parse(dialect: String, phase: Option) -> Self { + match &*dialect.to_ascii_lowercase() { + "built" => { + assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR"); + MirPhase::Built + } + "analysis" => Self::Analysis(AnalysisPhase::parse(phase)), + "runtime" => Self::Runtime(RuntimePhase::parse(phase)), + _ => panic!("Unknown MIR dialect {}", dialect), + } + } +} + +impl AnalysisPhase { + pub fn parse(phase: Option) -> Self { + let Some(phase) = phase else { + return Self::Initial; + }; + + match &*phase.to_ascii_lowercase() { + "initial" => Self::Initial, + "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup, + _ => panic!("Unknown analysis phase {}", phase), + } + } +} + +impl RuntimePhase { + pub fn parse(phase: Option) -> Self { + let Some(phase) = phase else { + return Self::Initial; + }; + + match &*phase.to_ascii_lowercase() { + "initial" => Self::Initial, + "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup, + "optimized" => Self::Optimized, + _ => panic!("Unknown runtime phase {}", phase), + } + } } impl Display for MirPhase { @@ -293,6 +335,13 @@ pub struct Body<'tcx> { /// potentially allow things like `[u8; std::mem::size_of::() * 0]` due to this. pub is_polymorphic: bool, + /// The phase at which this MIR should be "injected" into the compilation process. + /// + /// Everything that comes before this `MirPhase` should be skipped. + /// + /// This is only `Some` if the function that this body comes from was annotated with `rustc_custom_mir`. + pub injection_phase: Option, + pub tainted_by_errors: Option, } @@ -339,6 +388,7 @@ impl<'tcx> Body<'tcx> { span, required_consts: Vec::new(), is_polymorphic: false, + injection_phase: None, tainted_by_errors, }; body.is_polymorphic = body.has_non_region_param(); @@ -366,6 +416,7 @@ impl<'tcx> Body<'tcx> { required_consts: Vec::new(), var_debug_info: Vec::new(), is_polymorphic: false, + injection_phase: None, tainted_by_errors: None, }; body.is_polymorphic = body.has_non_region_param(); @@ -508,6 +559,14 @@ impl<'tcx> Body<'tcx> { pub fn generator_kind(&self) -> Option { self.generator.as_ref().map(|generator| generator.generator_kind) } + + #[inline] + pub fn should_skip(&self) -> bool { + let Some(injection_phase) = self.injection_phase else { + return false; + }; + injection_phase > self.phase + } } #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs new file mode 100644 index 000000000000..68d8766c9073 --- /dev/null +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -0,0 +1,155 @@ +//! Provides the implementation of the `custom_mir` attribute. +//! +//! Up until MIR building, this attribute has absolutely no effect. The `mir!` macro is a normal +//! decl macro that expands like any other, and the code goes through parsing, name resolution and +//! type checking like all other code. In MIR building we finally detect whether this attribute is +//! present, and if so we branch off into this module, which implements the attribute by +//! implementing a custom lowering from THIR to MIR. +//! +//! The result of this lowering is returned "normally" from the `mir_built` query, with the only +//! notable difference being that the `injected` field in the body is set. Various components of the +//! MIR pipeline, like borrowck and the pass manager will then consult this field (via +//! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user +//! specified. +//! +//! This file defines the general framework for the custom parsing. The parsing for all the +//! "top-level" constructs can be found in the `parse` submodule, while the parsing for statements, +//! terminators, and everything below can be found in the `parse::instruction` submodule. +//! + +use rustc_ast::Attribute; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::DefId; +use rustc_index::vec::IndexVec; +use rustc_middle::{ + mir::*, + thir::*, + ty::{Ty, TyCtxt}, +}; +use rustc_span::Span; + +mod parse; + +pub(super) fn build_custom_mir<'tcx>( + tcx: TyCtxt<'tcx>, + did: DefId, + thir: &Thir<'tcx>, + expr: ExprId, + params: &IndexVec>, + return_ty: Ty<'tcx>, + return_ty_span: Span, + span: Span, + attr: &Attribute, +) -> Body<'tcx> { + let mut body = Body { + basic_blocks: BasicBlocks::new(IndexVec::new()), + source: MirSource::item(did), + phase: MirPhase::Built, + source_scopes: IndexVec::new(), + generator: None, + local_decls: LocalDecls::new(), + user_type_annotations: IndexVec::new(), + arg_count: params.len(), + spread_arg: None, + var_debug_info: Vec::new(), + span, + required_consts: Vec::new(), + is_polymorphic: false, + tainted_by_errors: None, + injection_phase: None, + pass_count: 1, + }; + + body.local_decls.push(LocalDecl::new(return_ty, return_ty_span)); + body.basic_blocks_mut().push(BasicBlockData::new(None)); + body.source_scopes.push(SourceScopeData { + span, + parent_scope: None, + inlined: None, + inlined_parent_scope: None, + local_data: ClearCrossCrate::Clear, + }); + body.injection_phase = Some(parse_attribute(attr)); + + let mut pctxt = ParseCtxt { + tcx, + thir, + source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }, + body: &mut body, + local_map: FxHashMap::default(), + block_map: FxHashMap::default(), + }; + + let res = (|| { + pctxt.parse_args(¶ms)?; + pctxt.parse_body(expr) + })(); + if let Err(err) = res { + tcx.sess.diagnostic().span_fatal( + err.span, + format!("Could not parse {}, found: {:?}", err.expected, err.item_description), + ) + } + + body +} + +fn parse_attribute(attr: &Attribute) -> MirPhase { + let meta_items = attr.meta_item_list().unwrap(); + let mut dialect: Option = None; + let mut phase: Option = None; + + for nested in meta_items { + let name = nested.name_or_empty(); + let value = nested.value_str().unwrap().as_str().to_string(); + match name.as_str() { + "dialect" => { + assert!(dialect.is_none()); + dialect = Some(value); + } + "phase" => { + assert!(phase.is_none()); + phase = Some(value); + } + other => { + panic!("Unexpected key {}", other); + } + } + } + + let Some(dialect) = dialect else { + assert!(phase.is_none()); + return MirPhase::Built; + }; + + MirPhase::parse(dialect, phase) +} + +struct ParseCtxt<'tcx, 'body> { + tcx: TyCtxt<'tcx>, + thir: &'body Thir<'tcx>, + source_info: SourceInfo, + + body: &'body mut Body<'tcx>, + local_map: FxHashMap, + block_map: FxHashMap, +} + +struct ParseError { + span: Span, + item_description: String, + expected: String, +} + +impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { + fn expr_error(&self, expr: ExprId, expected: &'static str) -> ParseError { + let expr = &self.thir[expr]; + ParseError { + span: expr.span, + item_description: format!("{:?}", expr.kind), + expected: expected.to_string(), + } + } +} + +type PResult = Result; diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs new file mode 100644 index 000000000000..52cb0a4826d0 --- /dev/null +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -0,0 +1,245 @@ +use rustc_index::vec::IndexVec; +use rustc_middle::{mir::*, thir::*, ty::Ty}; +use rustc_span::Span; + +use super::{PResult, ParseCtxt, ParseError}; + +mod instruction; + +/// Helper macro for parsing custom MIR. +/// +/// Example usage looks something like: +/// ```rust,ignore (incomplete example) +/// parse_by_kind!( +/// self, // : &ParseCtxt +/// expr_id, // what you're matching against +/// "assignment", // the thing you're trying to parse +/// @call("mir_assign", args) => { args[0] }, // match invocations of the `mir_assign` special function +/// ExprKind::Assign { lhs, .. } => { lhs }, // match thir assignment expressions +/// // no need for fallthrough case - reasonable error is automatically generated +/// ) +/// ``` +macro_rules! parse_by_kind { + ( + $self:ident, + $expr_id:expr, + $expected:literal, + $( + @call($name:literal, $args:ident) => $call_expr:expr, + )* + $( + $pat:pat => $expr:expr, + )* + ) => {{ + let expr_id = $self.preparse($expr_id); + let expr = &$self.thir[expr_id]; + match &expr.kind { + $( + ExprKind::Call { ty, fun: _, args: $args, .. } if { + match ty.kind() { + ty::FnDef(did, _) => { + $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did) + } + _ => false, + } + } => $call_expr, + )* + $( + $pat => $expr, + )* + #[allow(unreachable_patterns)] + _ => return Err($self.expr_error(expr_id, $expected)) + } + }}; +} +pub(crate) use parse_by_kind; + +impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { + /// Expressions should only ever be matched on after preparsing them. This removes extra scopes + /// we don't care about. + fn preparse(&self, expr_id: ExprId) -> ExprId { + let expr = &self.thir[expr_id]; + match expr.kind { + ExprKind::Scope { value, .. } => self.preparse(value), + _ => expr_id, + } + } + + fn statement_as_expr(&self, stmt_id: StmtId) -> PResult { + match &self.thir[stmt_id].kind { + StmtKind::Expr { expr, .. } => Ok(*expr), + kind @ StmtKind::Let { pattern, .. } => { + return Err(ParseError { + span: pattern.span, + item_description: format!("{:?}", kind), + expected: "expression".to_string(), + }); + } + } + } + + pub fn parse_args(&mut self, params: &IndexVec>) -> PResult<()> { + for param in params.iter() { + let (var, span) = { + let pat = param.pat.as_ref().unwrap(); + match &pat.kind { + PatKind::Binding { var, .. } => (*var, pat.span), + _ => { + return Err(ParseError { + span: pat.span, + item_description: format!("{:?}", pat.kind), + expected: "local".to_string(), + }); + } + } + }; + let decl = LocalDecl::new(param.ty, span); + let local = self.body.local_decls.push(decl); + self.local_map.insert(var, local); + } + + Ok(()) + } + + /// Bodies are of the form: + /// + /// ```text + /// { + /// let bb1: BasicBlock; + /// let bb2: BasicBlock; + /// { + /// let RET: _; + /// let local1; + /// let local2; + /// + /// { + /// { // entry block + /// statement1; + /// terminator1 + /// }; + /// + /// bb1 = { + /// statement2; + /// terminator2 + /// }; + /// + /// bb2 = { + /// statement3; + /// terminator3 + /// } + /// + /// RET + /// } + /// } + /// } + /// ``` + /// + /// This allows us to easily parse the basic blocks declarations, local declarations, and + /// basic block definitions in order. + pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> { + let body = parse_by_kind!(self, expr_id, "whole body", + ExprKind::Block { block } => self.thir[*block].expr.unwrap(), + ); + let (block_decls, rest) = parse_by_kind!(self, body, "body with block decls", + ExprKind::Block { block } => { + let block = &self.thir[*block]; + (&block.stmts, block.expr.unwrap()) + }, + ); + self.parse_block_decls(block_decls.iter().copied())?; + + let (local_decls, rest) = parse_by_kind!(self, rest, "body with local decls", + ExprKind::Block { block } => { + let block = &self.thir[*block]; + (&block.stmts, block.expr.unwrap()) + }, + ); + self.parse_local_decls(local_decls.iter().copied())?; + + let block_defs = parse_by_kind!(self, rest, "body with block defs", + ExprKind::Block { block } => &self.thir[*block].stmts, + ); + for (i, block_def) in block_defs.iter().enumerate() { + let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?; + self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block; + } + + Ok(()) + } + + fn parse_block_decls(&mut self, stmts: impl Iterator) -> PResult<()> { + for stmt in stmts { + let (var, _, _) = self.parse_let_statement(stmt)?; + let data = BasicBlockData::new(None); + let block = self.body.basic_blocks_mut().push(data); + self.block_map.insert(var, block); + } + + Ok(()) + } + + fn parse_local_decls(&mut self, mut stmts: impl Iterator) -> PResult<()> { + let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?; + self.local_map.insert(ret_var, Local::from_u32(0)); + + for stmt in stmts { + let (var, ty, span) = self.parse_let_statement(stmt)?; + let decl = LocalDecl::new(ty, span); + let local = self.body.local_decls.push(decl); + self.local_map.insert(var, local); + } + + Ok(()) + } + + fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> { + let pattern = match &self.thir[stmt_id].kind { + StmtKind::Let { pattern, .. } => pattern, + StmtKind::Expr { expr, .. } => { + return Err(self.expr_error(*expr, "let statement")); + } + }; + + self.parse_var(pattern) + } + + fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> { + // Make sure we throw out any `AscribeUserType` we find + loop { + match &pat.kind { + PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)), + PatKind::AscribeUserType { subpattern, .. } => { + pat = subpattern; + } + _ => { + break Err(ParseError { + span: pat.span, + item_description: format!("{:?}", pat.kind), + expected: "local".to_string(), + }); + } + } + } + } + + fn parse_block_def(&self, expr_id: ExprId) -> PResult> { + let block = parse_by_kind!(self, expr_id, "basic block", + ExprKind::Block { block } => &self.thir[*block], + ); + + let mut data = BasicBlockData::new(None); + for stmt_id in &*block.stmts { + let stmt = self.statement_as_expr(*stmt_id)?; + let statement = self.parse_statement(stmt)?; + data.statements.push(Statement { source_info: self.source_info, kind: statement }); + } + + let Some(trailing) = block.expr else { + return Err(self.expr_error(expr_id, "terminator")) + }; + let terminator = self.parse_terminator(trailing)?; + data.terminator = Some(Terminator { source_info: self.source_info, kind: terminator }); + + Ok(data) + } +} diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs new file mode 100644 index 000000000000..6d6176584f5f --- /dev/null +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -0,0 +1,72 @@ +use rustc_middle::{mir::*, thir::*, ty}; + +use super::{parse_by_kind, PResult, ParseCtxt}; + +impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { + pub fn parse_statement(&self, expr_id: ExprId) -> PResult> { + parse_by_kind!(self, expr_id, "statement", + @call("mir_retag", args) => { + Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) + }, + @call("mir_retag_raw", args) => { + Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?))) + }, + ExprKind::Assign { lhs, rhs } => { + let lhs = self.parse_place(*lhs)?; + let rhs = self.parse_rvalue(*rhs)?; + Ok(StatementKind::Assign(Box::new((lhs, rhs)))) + }, + ) + } + + pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> { + parse_by_kind!(self, expr_id, "terminator", + @call("mir_return", _args) => { + Ok(TerminatorKind::Return) + }, + @call("mir_goto", args) => { + Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } ) + }, + ) + } + + fn parse_rvalue(&self, expr_id: ExprId) -> PResult> { + parse_by_kind!(self, expr_id, "rvalue", + ExprKind::Borrow { borrow_kind, arg } => Ok( + Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) + ), + ExprKind::AddressOf { mutability, arg } => Ok( + Rvalue::AddressOf(*mutability, self.parse_place(*arg)?) + ), + _ => self.parse_operand(expr_id).map(Rvalue::Use), + ) + } + + fn parse_operand(&self, expr_id: ExprId) -> PResult> { + parse_by_kind!(self, expr_id, "operand", + @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), + _ => self.parse_place(expr_id).map(Operand::Copy), + ) + } + + fn parse_place(&self, expr_id: ExprId) -> PResult> { + parse_by_kind!(self, expr_id, "place", + ExprKind::Deref { arg } => Ok( + self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx) + ), + _ => self.parse_local(expr_id).map(Place::from), + ) + } + + fn parse_local(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, "local", + ExprKind::VarRef { id } => Ok(self.local_map[id]), + ) + } + + fn parse_block(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, "basic block", + ExprKind::VarRef { id } => Ok(self.block_map[id]), + ) + } +} diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index cbcf9cd129f3..437ac8d82a1a 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -481,6 +481,22 @@ fn construct_fn<'tcx>( (None, fn_sig.output()) }; + if let Some(custom_mir_attr) = + tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir) + { + return custom::build_custom_mir( + tcx, + fn_def.did.to_def_id(), + thir, + expr, + arguments, + return_ty, + return_ty_span, + span, + custom_mir_attr, + ); + } + let infcx = tcx.infer_ctxt().build(); let mut builder = Builder::new( thir, @@ -1033,6 +1049,7 @@ pub(crate) fn parse_float_into_scalar( mod block; mod cfg; +mod custom; mod expr; mod matches; mod misc; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index c7a7c3e3fa8e..c4639d3a513d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -51,11 +51,17 @@ impl<'tcx> Cx<'tcx> { trace!(?expr.ty); // Now apply adjustments, if any. - for adjustment in self.typeck_results.expr_adjustments(hir_expr) { - trace!(?expr, ?adjustment); - let span = expr.span; - expr = - self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span)); + if self.apply_adjustments { + for adjustment in self.typeck_results.expr_adjustments(hir_expr) { + trace!(?expr, ?adjustment); + let span = expr.span; + expr = self.apply_adjustment( + hir_expr, + expr, + adjustment, + adjustment_span.unwrap_or(span), + ); + } } trace!(?expr.ty, "after adjustments"); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 1d95d6b53fbe..b5c4b7b137d4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -80,6 +80,9 @@ struct Cx<'tcx> { /// for the receiver. adjustment_span: Option<(HirId, Span)>, + /// False to indicate that adjustments should not be applied. Only used for `custom_mir` + apply_adjustments: bool, + /// The `DefId` of the owner of this body. body_owner: DefId, } @@ -87,6 +90,8 @@ struct Cx<'tcx> { impl<'tcx> Cx<'tcx> { fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam) -> Cx<'tcx> { let typeck_results = tcx.typeck_opt_const_arg(def); + let did = def.did; + let hir = tcx.hir(); Cx { tcx, thir: Thir::new(), @@ -94,8 +99,12 @@ impl<'tcx> Cx<'tcx> { region_scope_tree: tcx.region_scope_tree(def.did), typeck_results, rvalue_scopes: &typeck_results.rvalue_scopes, - body_owner: def.did.to_def_id(), + body_owner: did.to_def_id(), adjustment_span: None, + apply_adjustments: hir + .attrs(hir.local_def_id_to_hir_id(did)) + .iter() + .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir), } } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 269d9f3b102c..e783d1891377 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -471,6 +471,14 @@ fn unsafety_check_result<'tcx>( // `mir_built` force this. let body = &tcx.mir_built(def).borrow(); + if body.should_skip() { + return tcx.arena.alloc(UnsafetyCheckResult { + violations: Vec::new(), + used_unsafe_blocks: FxHashSet::default(), + unused_unsafes: Some(Vec::new()), + }); + } + let param_env = tcx.param_env(def.did); let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env); diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 230c6a7cb4b0..27dbc3e22c97 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -96,45 +96,48 @@ fn run_passes_inner<'tcx>( phase_change: Option, validate_each: bool, ) { - let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir; + let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip(); let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); - for pass in passes { - let name = pass.name(); + if !body.should_skip() { + for pass in passes { + let name = pass.name(); - let overridden = - overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { - trace!( - pass = %name, - "{} as requested by flag", - if *polarity { "Running" } else { "Not running" }, - ); - *polarity - }); - if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { - continue; + let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map( + |(_name, polarity)| { + trace!( + pass = %name, + "{} as requested by flag", + if *polarity { "Running" } else { "Not running" }, + ); + *polarity + }, + ); + if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { + continue; + } + + let dump_enabled = pass.is_mir_dump_enabled(); + + if dump_enabled { + dump_mir_for_pass(tcx, body, &name, false); + } + if validate { + validate_body(tcx, body, format!("before pass {}", name)); + } + + pass.run_pass(tcx, body); + + if dump_enabled { + dump_mir_for_pass(tcx, body, &name, true); + } + if validate { + validate_body(tcx, body, format!("after pass {}", name)); + } + + body.pass_count += 1; } - - let dump_enabled = pass.is_mir_dump_enabled(); - - if dump_enabled { - dump_mir_for_pass(tcx, body, &name, false); - } - if validate { - validate_body(tcx, body, format!("before pass {}", name)); - } - - pass.run_pass(tcx, body); - - if dump_enabled { - dump_mir_for_pass(tcx, body, &name, true); - } - if validate { - validate_body(tcx, body, format!("after pass {}", name)); - } - - body.pass_count += 1; } if let Some(new_phase) = phase_change { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cccc4897ecca..54a61483a11a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -584,6 +584,7 @@ symbols! { custom_attribute, custom_derive, custom_inner_attributes, + custom_mir, custom_test_frameworks, d, d32, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index bfbd4301230a..cec603dcb10e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -59,6 +59,9 @@ use crate::marker::DiscriminantKind; use crate::marker::Tuple; use crate::mem; +#[cfg(not(bootstrap))] +pub mod mir; + // These imports are used for simplifying intra-doc links #[allow(unused_imports)] #[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))] diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs new file mode 100644 index 000000000000..1bacdc39148a --- /dev/null +++ b/library/core/src/intrinsics/mir.rs @@ -0,0 +1,123 @@ +//! Rustc internal tooling for hand-writing MIR. +//! +//! If for some reasons you are not writing rustc tests and have found yourself considering using +//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make +//! anything work besides those things which the rustc test suite happened to need. If you make a +//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead +//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir). +//! +//! The documentation for this module describes how to use this feature. If you are interested in +//! hacking on the implementation, most of that documentation lives at +//! `rustc_mir_building/src/build/custom/mod.rs`. +//! +//! Typical usage will look like this: +//! +//! ```rust +//! #![feature(core_intrinsics, custom_mir)] +//! +//! extern crate core; +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! pub fn simple(x: i32) -> i32 { +//! mir!( +//! let temp1: i32; +//! let temp2: _; +//! +//! { +//! temp1 = x; +//! Goto(exit) +//! } +//! +//! exit = { +//! temp2 = Move(temp1); +//! RET = temp2; +//! Return() +//! } +//! ) +//! } +//! ``` +//! +//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details: +//! +//! - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This +//! attribute only works on functions - there is no way to insert custom MIR into the middle of +//! another function. +//! - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here. +//! This will normally be the phase that corresponds to the thing you are trying to test. The +//! phase can be omitted for dialects that have just one. +//! - You should define your function signature like you normally would. Externally, this function +//! can be called like any other function. +//! - Type inference works - you don't have to spell out the type of all of your locals. +//! +//! For now, all statements and terminators are parsed from nested invocations of the special +//! functions provided in this module. We additionally want to (but do not yet) support more +//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not +//! supported yet. +//! + +#![unstable( + feature = "custom_mir", + reason = "MIR is an implementation detail and extremely unstable", + issue = "none" +)] +#![allow(unused_variables, non_snake_case, missing_debug_implementations)] + +/// Type representing basic blocks. +/// +/// All terminators will have this type as a return type. It helps achieve some type safety. +pub struct BasicBlock; + +macro_rules! define { + ($name:literal, $($sig:tt)*) => { + #[rustc_diagnostic_item = $name] + pub $($sig)* { panic!() } + } +} + +define!("mir_return", fn Return() -> BasicBlock); +define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); +define!("mir_retag", fn Retag(place: T)); +define!("mir_retag_raw", fn RetagRaw(place: T)); +define!("mir_move", fn Move(place: T) -> T); + +/// Convenience macro for generating custom MIR. +/// +/// See the module documentation for syntax details. This macro is not magic - it only transforms +/// your MIR into something that is easier to parse in the compiler. +#[rustc_macro_transparency = "transparent"] +pub macro mir { + ( + $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* + + $entry_block:block + + $( + $block_name:ident = $block:block + )* + ) => {{ + // First, we declare all basic blocks. + $( + let $block_name: ::core::intrinsics::mir::BasicBlock; + )* + + { + // Now all locals + #[allow(non_snake_case)] + let RET; + $( + let $local_decl $(: $local_decl_ty)? ; + )* + + { + // Finally, the contents of the basic blocks + $entry_block; + $( + $block; + )* + + RET + } + } + }} +} diff --git a/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir new file mode 100644 index 000000000000..4a5ddde4081e --- /dev/null +++ b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir @@ -0,0 +1,14 @@ +// MIR for `immut_ref` after built + +fn immut_ref(_1: &i32) -> &i32 { + let mut _0: &i32; // return place in scope 0 at $DIR/references.rs:+0:30: +0:34 + let mut _2: *const i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _2 = &raw const (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:34 + Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:34 + _0 = &(*_2); // scope 0 at $DIR/references.rs:+0:1: +0:34 + Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:34 + return; // scope 0 at $DIR/references.rs:+0:1: +0:34 + } +} diff --git a/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir new file mode 100644 index 000000000000..ec8509f69d14 --- /dev/null +++ b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir @@ -0,0 +1,14 @@ +// MIR for `mut_ref` after built + +fn mut_ref(_1: &mut i32) -> &mut i32 { + let mut _0: &mut i32; // return place in scope 0 at $DIR/references.rs:+0:32: +0:40 + let mut _2: *mut i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _2 = &raw mut (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:40 + Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:40 + _0 = &mut (*_2); // scope 0 at $DIR/references.rs:+0:1: +0:40 + Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:40 + return; // scope 0 at $DIR/references.rs:+0:1: +0:40 + } +} diff --git a/src/test/mir-opt/building/custom/references.rs b/src/test/mir-opt/building/custom/references.rs new file mode 100644 index 000000000000..dee85722e865 --- /dev/null +++ b/src/test/mir-opt/building/custom/references.rs @@ -0,0 +1,43 @@ +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; +use core::ptr::{addr_of, addr_of_mut}; + +// EMIT_MIR references.mut_ref.built.after.mir +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn mut_ref(x: &mut i32) -> &mut i32 { + mir!( + let t: *mut i32; + + { + t = addr_of_mut!(*x); + RetagRaw(t); + RET = &mut *t; + Retag(RET); + Return() + } + ) +} + +// EMIT_MIR references.immut_ref.built.after.mir +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn immut_ref(x: &i32) -> &i32 { + mir!( + let t: *const i32; + + { + t = addr_of!(*x); + RetagRaw(t); + RET = & *t; + Retag(RET); + Return() + } + ) +} + +fn main() { + let mut x = 5; + assert_eq!(*mut_ref(&mut x), 5); + assert_eq!(*immut_ref(&x), 5); +} diff --git a/src/test/mir-opt/building/custom/simple_assign.rs b/src/test/mir-opt/building/custom/simple_assign.rs new file mode 100644 index 000000000000..ec6dbe1d0526 --- /dev/null +++ b/src/test/mir-opt/building/custom/simple_assign.rs @@ -0,0 +1,37 @@ +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; + +// EMIT_MIR simple_assign.simple.built.after.mir +#[custom_mir(dialect = "built")] +pub fn simple(x: i32) -> i32 { + mir!( + let temp1: i32; + let temp2: _; + + { + temp1 = x; + Goto(exit) + } + + exit = { + temp2 = Move(temp1); + RET = temp2; + Return() + } + ) +} + +// EMIT_MIR simple_assign.simple_ref.built.after.mir +#[custom_mir(dialect = "built")] +pub fn simple_ref(x: &mut i32) -> &mut i32 { + mir!({ + RET = Move(x); + Return() + }) +} + +fn main() { + assert_eq!(5, simple(5)); +} diff --git a/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir new file mode 100644 index 000000000000..a5a2834c2e1b --- /dev/null +++ b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir @@ -0,0 +1,18 @@ +// MIR for `simple` after built + +fn simple(_1: i32) -> i32 { + let mut _0: i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:26: +0:29 + let mut _2: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _3: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _2 = _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + goto -> bb1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + } + + bb1: { + _3 = move _2; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + _0 = _3; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + } +} diff --git a/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir new file mode 100644 index 000000000000..6c90f0130a2e --- /dev/null +++ b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `simple_ref` after built + +fn simple_ref(_1: &mut i32) -> &mut i32 { + let mut _0: &mut i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:35: +0:43 + + bb0: { + _0 = move _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43 + return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43 + } +} diff --git a/src/test/ui/feature-gates/feature-gate-custom_mir.rs b/src/test/ui/feature-gates/feature-gate-custom_mir.rs new file mode 100644 index 000000000000..0126dde2f7d4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-custom_mir.rs @@ -0,0 +1,12 @@ +#![feature(core_intrinsics)] + +extern crate core; + +#[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite +pub fn foo(_x: i32) -> i32 { + 0 +} + +fn main() { + assert_eq!(2, foo(2)); +} diff --git a/src/test/ui/feature-gates/feature-gate-custom_mir.stderr b/src/test/ui/feature-gates/feature-gate-custom_mir.stderr new file mode 100644 index 000000000000..3c149d30d82b --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-custom_mir.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite + --> $DIR/feature-gate-custom_mir.rs:5:1 + | +LL | #[custom_mir(dialect = "built")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From f6658479a83bae99c097031ea0e1e74e6e836c1e Mon Sep 17 00:00:00 2001 From: onestacked Date: Mon, 7 Nov 2022 21:47:46 +0100 Subject: [PATCH 180/221] const Compare Tuples --- library/core/src/tuple.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index fc91fe468cc2..28275798f751 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -22,7 +22,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialEq),+> PartialEq for ($($T,)+) + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl<$($T: ~const PartialEq),+> const PartialEq for ($($T,)+) where last_type!($($T,)+): ?Sized { @@ -40,7 +41,7 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Eq),+> Eq for ($($T,)+) + impl<$($T: Eq),+> Eq for ($($T,)+) where last_type!($($T,)+): ?Sized {} @@ -49,7 +50,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl<$($T: ~const PartialOrd + ~const PartialEq),+> const PartialOrd for ($($T,)+) where last_type!($($T,)+): ?Sized { @@ -79,7 +81,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Ord),+> Ord for ($($T,)+) + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl<$($T: ~const Ord),+> const Ord for ($($T,)+) where last_type!($($T,)+): ?Sized { From a68ec2205335e2c3de8ba56fb6a31b99f10c95a6 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 9 Nov 2022 02:52:59 -0600 Subject: [PATCH 181/221] Fix `rustdoc --version` when used with download-rustc Previously, rustdoc would unconditionally report the version that *rustc* was compiled with. That showed things like `nightly-2022-10-30`, which wasn't right, since this was a `dev` build compiled from source. Fix it by changing `rustc_driver::version` to a macro expanded at invocation time. --- .../src/debuginfo/mod.rs | 2 +- compiler/rustc_driver/src/lib.rs | 42 ++++++++++++++----- compiler/rustc_interface/src/lib.rs | 1 + compiler/rustc_interface/src/util.rs | 22 +++------- src/librustdoc/config.rs | 2 +- src/librustdoc/html/layout.rs | 2 +- 6 files changed, 42 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index c55db2017ee6..2ba012a77b0a 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -59,7 +59,7 @@ impl DebugContext { let producer = format!( "cg_clif (rustc {}, cranelift {})", - rustc_interface::util::version_str().unwrap_or("unknown version"), + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), cranelift_codegen::VERSION, ); let comp_dir = tcx diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index cf4bcc7c158f..030455177031 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(once_cell)] +#![feature(decl_macro)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -742,20 +743,41 @@ fn print_crate_info( } /// Prints version information -pub fn version(binary: &str, matches: &getopts::Matches) { +/// +/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate. +pub macro version($binary: literal, $matches: expr) { + fn unw(x: Option<&str>) -> &str { + x.unwrap_or("unknown") + } + $crate::version_at_macro_invocation( + $binary, + $matches, + unw(option_env!("CFG_VERSION")), + unw(option_env!("CFG_VER_HASH")), + unw(option_env!("CFG_VER_DATE")), + unw(option_env!("CFG_RELEASE")), + ) +} + +#[doc(hidden)] // use the macro instead +pub fn version_at_macro_invocation( + binary: &str, + matches: &getopts::Matches, + version: &str, + commit_hash: &str, + commit_date: &str, + release: &str, +) { let verbose = matches.opt_present("verbose"); - println!("{} {}", binary, util::version_str().unwrap_or("unknown version")); + println!("{} {}", binary, version); if verbose { - fn unw(x: Option<&str>) -> &str { - x.unwrap_or("unknown") - } println!("binary: {}", binary); - println!("commit-hash: {}", unw(util::commit_hash_str())); - println!("commit-date: {}", unw(util::commit_date_str())); + println!("commit-hash: {}", commit_hash); + println!("commit-date: {}", commit_date); println!("host: {}", config::host_triple()); - println!("release: {}", unw(util::release_str())); + println!("release: {}", release); let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); @@ -1071,7 +1093,7 @@ pub fn handle_options(args: &[String]) -> Option { } if matches.opt_present("version") { - version("rustc", &matches); + version!("rustc", &matches); return None; } @@ -1216,7 +1238,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { format!("we would appreciate a bug report: {}", bug_report_url).into(), format!( "rustc {} running on {}", - util::version_str().unwrap_or("unknown_version"), + util::version_str!().unwrap_or("unknown_version"), config::host_triple() ) .into(), diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index a41a749ee68e..542b638bbd7a 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,4 +1,5 @@ #![feature(box_patterns)] +#![feature(decl_macro)] #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(once_cell)] diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 62ee72f98830..2fe3fb2fa566 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -327,7 +327,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M let mut file: Option = None; let expected_names = &[ - format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")), + format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")), format!("rustc_codegen_{}", backend_name), ]; for entry in d.filter_map(|e| e.ok()) { @@ -554,22 +554,12 @@ pub fn build_output_filenames( } } -/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" -pub fn version_str() -> Option<&'static str> { +/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" when invoked by an in-tree tool. +pub macro version_str() { option_env!("CFG_VERSION") } -/// Returns a version string such as "0.12.0-dev". -pub fn release_str() -> Option<&'static str> { - option_env!("CFG_RELEASE") -} - -/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built. -pub fn commit_hash_str() -> Option<&'static str> { - option_env!("CFG_VER_HASH") -} - -/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string. -pub fn commit_date_str() -> Option<&'static str> { - option_env!("CFG_VER_DATE") +/// Returns the version string for `rustc` itself (which may be different from a tool version). +pub fn rustc_version_str() -> Option<&'static str> { + version_str!() } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9c08eac4edcb..789dd398be50 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -326,7 +326,7 @@ impl Options { crate::usage("rustdoc"); return Err(0); } else if matches.opt_present("version") { - rustc_driver::version("rustdoc", matches); + rustc_driver::version!("rustdoc", matches); return Err(0); } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 48c6abfca90c..a60e7cb10fa5 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -71,7 +71,7 @@ pub(crate) fn render( let mut themes: Vec = style_files.iter().map(|s| s.basename().unwrap()).collect(); themes.sort(); - let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version"); + let rustdoc_version = rustc_interface::util::version_str!().unwrap_or("unknown version"); let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar. let sidebar = Buffer::html().to_display(sidebar); PageLayout { From b6c05eb7d3f59b43b2e9ada520167f87bb4084aa Mon Sep 17 00:00:00 2001 From: onestacked Date: Wed, 9 Nov 2022 11:35:28 +0100 Subject: [PATCH 182/221] Cleanup fn trait ref test --- src/test/ui/consts/fn_trait_refs.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/test/ui/consts/fn_trait_refs.rs b/src/test/ui/consts/fn_trait_refs.rs index bc8766c74c60..b507492970ab 100644 --- a/src/test/ui/consts/fn_trait_refs.rs +++ b/src/test/ui/consts/fn_trait_refs.rs @@ -1,4 +1,4 @@ -// build-pass +// check-pass #![feature(const_fn_trait_ref_impls)] #![feature(fn_traits)] @@ -60,21 +60,18 @@ const fn test(i: i32) -> i32 { i + 1 } -const fn main() { +fn main() { const fn one() -> i32 { 1 }; const fn two() -> i32 { 2 }; + const _: () = { + let test_one = test_fn(one); + assert!(test_one == (1, 1, 1)); - // FIXME(const_cmp_tuple) - let test_one = test_fn(one); - assert!(test_one.0 == 1); - assert!(test_one.1 == 1); - assert!(test_one.2 == 1); - - let test_two = test_fn_mut(two); - assert!(test_two.0 == 1); - assert!(test_two.1 == 1); + let test_two = test_fn_mut(two); + assert!(test_two == (2, 2)); + }; } From 91b4e7c4fd9b5f9ea8878c4ac53c3bde80bedf25 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 9 Nov 2022 19:23:23 +0800 Subject: [PATCH 183/221] bless clippy --- src/tools/clippy/tests/ui/crashes/ice-6250.stderr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 878897c410cf..4506d1550bd4 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -23,6 +23,11 @@ error[E0308]: mismatched types | LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | let Some(reference) = cache.data.get(key) { + | +++ error: aborting due to 3 previous errors From 575f6098da83cef33676ef67e39b73b2b910a042 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 25 Aug 2022 15:34:30 +0200 Subject: [PATCH 184/221] Port unknown feature diagnostic to the new framework --- compiler/rustc_codegen_llvm/src/errors.rs | 33 +++++++++++++++++++ compiler/rustc_codegen_llvm/src/lib.rs | 1 + compiler/rustc_codegen_llvm/src/llvm_util.rs | 20 ++--------- .../locales/en-US/codegen_llvm.ftl | 14 ++++++++ compiler/rustc_error_messages/src/lib.rs | 1 + 5 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 compiler/rustc_codegen_llvm/src/errors.rs create mode 100644 compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs new file mode 100644 index 000000000000..b1f85e656b82 --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -0,0 +1,33 @@ +use rustc_errors::DiagnosticBuilder; +use rustc_session::SessionDiagnostic; +use rustc_errors::fluent; + +pub(crate) enum UnknownCTargetFeature { + UnknownFeaturePrefix { feature: String }, + UnknownFeature { feature: String, rust_feature: Option }, +} + +impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature { + fn into_diagnostic(self, sess: &'_ rustc_session::parse::ParseSess) -> DiagnosticBuilder<'_, ()> { + match self { + UnknownCTargetFeature::UnknownFeaturePrefix { feature } => { + let mut diag = sess.struct_warn(fluent::codegen_llvm::unknown_ctarget_feature); + diag.set_arg("feature", feature); + diag.note(fluent::codegen_llvm::unknown_feature_prefix); + diag + } + UnknownCTargetFeature::UnknownFeature { feature, rust_feature } => { + let mut diag = sess.struct_warn(fluent::codegen_llvm::unknown_ctarget_feature); + diag.set_arg("feature", feature); + diag.note(fluent::codegen_llvm::unknown_feature); + if let Some(rust_feature) = rust_feature { + diag.help(fluent::codegen_llvm::rust_feature); + diag.set_arg("rust_feature", rust_feature); + } else { + diag.note(fluent::codegen_llvm::unknown_feature_fill_request); + } + diag + } + } + } +} \ No newline at end of file diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index d51aced85df4..af632b2ff54b 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -62,6 +62,7 @@ mod context; mod coverageinfo; mod debuginfo; mod declare; +mod errors; mod intrinsic; // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912. diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 2fd58567c487..f8f174692c06 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,5 +1,6 @@ use crate::back::write::create_informational_target_machine; use crate::llvm; +use crate::errors::UnknownCTargetFeature; use libc::c_int; use rustc_codegen_ssa::target_features::{ supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES, @@ -434,12 +435,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec c, Some(_) => { if diagnostics { - let mut diag = sess.struct_warn(&format!( - "unknown feature specified for `-Ctarget-feature`: `{}`", - s - )); - diag.note("features must begin with a `+` to enable or `-` to disable it"); - diag.emit(); + sess.emit_warning(UnknownCTargetFeature::UnknownFeaturePrefix { feature: s.to_string() }); } return None; } @@ -456,17 +452,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", codegen_gcc => "../locales/en-US/codegen_gcc.ftl", + codegen_llvm => "../locales/en-US/codegen_llvm.ftl", codegen_ssa => "../locales/en-US/codegen_ssa.ftl", compiletest => "../locales/en-US/compiletest.ftl", const_eval => "../locales/en-US/const_eval.ftl", From a54c8003abd74310af973cbaca87d8ff7b9b4f0e Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 25 Aug 2022 15:42:20 +0200 Subject: [PATCH 185/221] Formatting --- compiler/rustc_codegen_llvm/src/errors.rs | 9 ++++++--- compiler/rustc_codegen_llvm/src/llvm_util.rs | 11 ++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index b1f85e656b82..c9af545a8182 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -1,6 +1,6 @@ +use rustc_errors::fluent; use rustc_errors::DiagnosticBuilder; use rustc_session::SessionDiagnostic; -use rustc_errors::fluent; pub(crate) enum UnknownCTargetFeature { UnknownFeaturePrefix { feature: String }, @@ -8,7 +8,10 @@ pub(crate) enum UnknownCTargetFeature { } impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature { - fn into_diagnostic(self, sess: &'_ rustc_session::parse::ParseSess) -> DiagnosticBuilder<'_, ()> { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> DiagnosticBuilder<'_, ()> { match self { UnknownCTargetFeature::UnknownFeaturePrefix { feature } => { let mut diag = sess.struct_warn(fluent::codegen_llvm::unknown_ctarget_feature); @@ -30,4 +33,4 @@ impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature { } } } -} \ No newline at end of file +} diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index f8f174692c06..81b325fee2d7 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,6 +1,6 @@ use crate::back::write::create_informational_target_machine; -use crate::llvm; use crate::errors::UnknownCTargetFeature; +use crate::llvm; use libc::c_int; use rustc_codegen_ssa::target_features::{ supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES, @@ -435,7 +435,9 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec c, Some(_) => { if diagnostics { - sess.emit_warning(UnknownCTargetFeature::UnknownFeaturePrefix { feature: s.to_string() }); + sess.emit_warning(UnknownCTargetFeature::UnknownFeaturePrefix { + feature: s.to_string(), + }); } return None; } @@ -452,7 +454,10 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Date: Thu, 25 Aug 2022 16:15:03 +0200 Subject: [PATCH 186/221] locales formatting --- compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 3c644d77bb7a..c946aacf3859 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -11,4 +11,4 @@ codegen_llvm_rust_feature = you might have meant: `{$rust_feature}` codegen_llvm_unknown_feature_fill_request = - consider filing a feature request \ No newline at end of file + consider filing a feature request From 21b04265c1bac993227a03ad2a0a50d45386a9b5 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 25 Aug 2022 16:18:06 +0200 Subject: [PATCH 187/221] Trailing whitespaces --- .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index c946aacf3859..33abf6ce5cfc 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -1,10 +1,10 @@ -codegen_llvm_unknown_ctarget_feature = +codegen_llvm_unknown_ctarget_feature = unknown feature specified for `-Ctarget-feature`: `{$feature}` -codegen_llvm_unknown_feature_prefix = +codegen_llvm_unknown_feature_prefix = features must begin with a `+` to enable or `-` to disable it -codegen_llvm_unknown_feature = +codegen_llvm_unknown_feature = it is still passed through to the codegen backend codegen_llvm_rust_feature = From b1647903f86970e4bdedc599ee1af8036a75ef26 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 25 Aug 2022 18:36:15 +0200 Subject: [PATCH 188/221] Change String in structs to &'a str --- compiler/rustc_codegen_llvm/src/errors.rs | 6 +++--- compiler/rustc_codegen_llvm/src/llvm_util.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index c9af545a8182..cf896f38c8c2 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -2,9 +2,9 @@ use rustc_errors::fluent; use rustc_errors::DiagnosticBuilder; use rustc_session::SessionDiagnostic; -pub(crate) enum UnknownCTargetFeature { - UnknownFeaturePrefix { feature: String }, - UnknownFeature { feature: String, rust_feature: Option }, +pub(crate) enum UnknownCTargetFeature<'a> { + UnknownFeaturePrefix { feature: &'a str }, + UnknownFeature { feature: &'a str, rust_feature: Option<&'a str> }, } impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 81b325fee2d7..f0122d5824f2 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -436,7 +436,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec { if diagnostics { sess.emit_warning(UnknownCTargetFeature::UnknownFeaturePrefix { - feature: s.to_string(), + feature: s, }); } return None; @@ -455,8 +455,8 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Date: Thu, 25 Aug 2022 19:23:55 +0200 Subject: [PATCH 189/221] Missing lifetime parameter and formatting --- compiler/rustc_codegen_llvm/src/errors.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index cf896f38c8c2..a2b88c4af11c 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -7,7 +7,7 @@ pub(crate) enum UnknownCTargetFeature<'a> { UnknownFeature { feature: &'a str, rust_feature: Option<&'a str> }, } -impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature { +impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature<'_> { fn into_diagnostic( self, sess: &'_ rustc_session::parse::ParseSess, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index f0122d5824f2..8f67913f91f0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -454,10 +454,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Date: Thu, 25 Aug 2022 21:01:36 +0200 Subject: [PATCH 190/221] Import `error creating import library` --- compiler/rustc_codegen_llvm/src/back/archive.rs | 8 ++++---- compiler/rustc_codegen_llvm/src/errors.rs | 8 ++++++++ .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 082665bba380..4fd8b0ef4bb7 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -12,6 +12,7 @@ use std::str; use object::read::macho::FatArch; use crate::common; +use crate::errors::ErrorCreatingImportLibrary; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; @@ -293,11 +294,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { }; if result == crate::llvm::LLVMRustResult::Failure { - sess.fatal(&format!( - "Error creating import library for {}: {}", + sess.emit_fatal(ErrorCreatingImportLibrary { lib_name, - llvm::last_error().unwrap_or("unknown LLVM error".to_string()) - )); + error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()), + }); } }; diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index a2b88c4af11c..03e55c72e222 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -1,5 +1,6 @@ use rustc_errors::fluent; use rustc_errors::DiagnosticBuilder; +use rustc_macros::SessionDiagnostic; use rustc_session::SessionDiagnostic; pub(crate) enum UnknownCTargetFeature<'a> { @@ -34,3 +35,10 @@ impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature<'_> { } } } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::error_creating_import_library)] +pub(crate) struct ErrorCreatingImportLibrary<'a> { + pub lib_name: &'a str, + pub error: String, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 33abf6ce5cfc..bfd3d5f033a8 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -12,3 +12,6 @@ codegen_llvm_rust_feature = codegen_llvm_unknown_feature_fill_request = consider filing a feature request + +codegen_llvm_error_creating_import_library = + Error creating import library for {$lib_name}: {$error} From 4c625dc6824e3f07232239d618408eb4161d44a6 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 25 Aug 2022 23:08:18 +0200 Subject: [PATCH 191/221] Port Instrument coverage requires llvm 12 to the new struct --- compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 3 ++- compiler/rustc_codegen_llvm/src/errors.rs | 4 ++++ compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 433f043209e5..8a8d889a2986 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,5 +1,6 @@ use crate::common::CodegenCx; use crate::coverageinfo; +use crate::errors::InstrumentCoverageRequiresLLVM12; use crate::llvm; use llvm::coverageinfo::CounterMappingRegion; @@ -37,7 +38,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { // LLVM 12. let version = coverageinfo::mapping_version(); if version < 4 { - tcx.sess.fatal("rustc option `-C instrument-coverage` requires LLVM 12 or higher."); + tcx.sess.emit_fatal(InstrumentCoverageRequiresLLVM12); } debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name()); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 03e55c72e222..b06ad78cf7b9 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -42,3 +42,7 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> { pub lib_name: &'a str, pub error: String, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::instrument_coverage_requires_llvm_12)] +pub(crate) struct InstrumentCoverageRequiresLLVM12; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index bfd3d5f033a8..9f75d5a0e475 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -15,3 +15,6 @@ codegen_llvm_unknown_feature_fill_request = codegen_llvm_error_creating_import_library = Error creating import library for {$lib_name}: {$error} + +codegen_llvm_instrument_coverage_requires_llvm_12 = + rustc option `-C instrument-coverage` requires LLVM 12 or higher. From 9f0c16576b9e094e84ec833a51a908ae5ff24d33 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 25 Aug 2022 23:30:17 +0200 Subject: [PATCH 192/221] Port `symbol_already_defined` error --- compiler/rustc_codegen_llvm/src/errors.rs | 9 +++++++++ compiler/rustc_codegen_llvm/src/mono_item.rs | 5 +---- .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index b06ad78cf7b9..34b2c844f503 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -2,6 +2,7 @@ use rustc_errors::fluent; use rustc_errors::DiagnosticBuilder; use rustc_macros::SessionDiagnostic; use rustc_session::SessionDiagnostic; +use rustc_span::Span; pub(crate) enum UnknownCTargetFeature<'a> { UnknownFeaturePrefix { feature: &'a str }, @@ -46,3 +47,11 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> { #[derive(SessionDiagnostic)] #[diag(codegen_llvm::instrument_coverage_requires_llvm_12)] pub(crate) struct InstrumentCoverageRequiresLLVM12; + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::SymbolAlreadyDefined)] +pub(crate) struct SymbolAlreadyDefined<'a> { + #[primary_span] + pub span: Span, + pub symbol_name: &'a str, +} diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 1eceb7f5c87b..d5096873c437 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -25,10 +25,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { - self.sess().span_fatal( - self.tcx.def_span(def_id), - &format!("symbol `{}` is already defined", symbol_name), - ) + self.sess().emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name }) }); unsafe { diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 9f75d5a0e475..c1222d3db5f7 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -18,3 +18,6 @@ codegen_llvm_error_creating_import_library = codegen_llvm_instrument_coverage_requires_llvm_12 = rustc option `-C instrument-coverage` requires LLVM 12 or higher. + +codegen_llvm_symbol_already_defined = + symbol `{$symbol_name}` is already defined From ec1e101e1b845579eaaed164b096ae3784f3479d Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 25 Aug 2022 23:47:11 +0200 Subject: [PATCH 193/221] Fix diag() and formatting --- compiler/rustc_codegen_llvm/src/errors.rs | 2 +- compiler/rustc_codegen_llvm/src/mono_item.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 34b2c844f503..ed435e555d7e 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -49,7 +49,7 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> { pub(crate) struct InstrumentCoverageRequiresLLVM12; #[derive(SessionDiagnostic)] -#[diag(codegen_llvm::SymbolAlreadyDefined)] +#[diag(codegen_llvm::symbol_already_defined)] pub(crate) struct SymbolAlreadyDefined<'a> { #[primary_span] pub span: Span, diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index d5096873c437..76f692b2016f 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -1,6 +1,7 @@ use crate::attributes; use crate::base; use crate::context::CodegenCx; +use crate::errors::SymbolAlreadyDefined; use crate::llvm; use crate::type_of::LayoutLlvmExt; use rustc_codegen_ssa::traits::*; @@ -25,7 +26,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { - self.sess().emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name }) + self.sess() + .emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name }) }); unsafe { From 59b8aedf0e7c48472e335d6e901e61e4641f5253 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 00:03:53 +0200 Subject: [PATCH 194/221] Port branch protection on aarch64 --- compiler/rustc_codegen_llvm/src/context.rs | 3 ++- compiler/rustc_codegen_llvm/src/errors.rs | 4 ++++ compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index c22ec128dacb..3ac0778e3bd4 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model; use crate::callee::get_fn; use crate::coverageinfo; use crate::debuginfo; +use crate::errors::BranchProtectionRequiresAArch64; use crate::llvm; use crate::llvm_util; use crate::type_::Type; @@ -275,7 +276,7 @@ pub unsafe fn create_module<'ll>( if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection { if sess.target.arch != "aarch64" { - sess.err("-Zbranch-protection is only supported on aarch64"); + sess.emit_err(BranchProtectionRequiresAArch64); } else { llvm::LLVMRustAddModuleFlag( llmod, diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index ed435e555d7e..e740e02dd1c2 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -55,3 +55,7 @@ pub(crate) struct SymbolAlreadyDefined<'a> { pub span: Span, pub symbol_name: &'a str, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::branch_protection_requires_aarch64)] +pub(crate) struct BranchProtectionRequiresAArch64; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index c1222d3db5f7..4fd3d364b479 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -21,3 +21,6 @@ codegen_llvm_instrument_coverage_requires_llvm_12 = codegen_llvm_symbol_already_defined = symbol `{$symbol_name}` is already defined + +codegen_llvm_branch_protection_requires_aarch64 = + -Zbranch-protection is only supported on aarch64 From f031823ecdef195c8e8295adb6d57433f83ca136 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 00:08:05 +0200 Subject: [PATCH 195/221] Formatting --- compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 4fd3d364b479..d713183f5729 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -19,7 +19,7 @@ codegen_llvm_error_creating_import_library = codegen_llvm_instrument_coverage_requires_llvm_12 = rustc option `-C instrument-coverage` requires LLVM 12 or higher. -codegen_llvm_symbol_already_defined = +codegen_llvm_symbol_already_defined = symbol `{$symbol_name}` is already defined codegen_llvm_branch_protection_requires_aarch64 = From 39d363fd58d7686265b14af41dc3029a30737282 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 10:14:15 +0200 Subject: [PATCH 196/221] Port layout size overflow --- compiler/rustc_codegen_llvm/src/context.rs | 5 +++-- compiler/rustc_codegen_llvm/src/errors.rs | 8 ++++++++ .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 3ac0778e3bd4..7ed4df16ea99 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -4,6 +4,7 @@ use crate::callee::get_fn; use crate::coverageinfo; use crate::debuginfo; use crate::errors::BranchProtectionRequiresAArch64; +use crate::errors::LayoutSizeOverflow; use crate::llvm; use crate::llvm_util; use crate::type_::Type; @@ -952,7 +953,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) = err { - self.sess().span_fatal(span, &err.to_string()) + self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) } else { span_bug!(span, "failed to get layout for `{}`: {}", ty, err) } @@ -970,7 +971,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.sess().span_fatal(span, &err.to_string()) + self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) } else { match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index e740e02dd1c2..95a12d98d5cf 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -59,3 +59,11 @@ pub(crate) struct SymbolAlreadyDefined<'a> { #[derive(SessionDiagnostic)] #[diag(codegen_llvm::branch_protection_requires_aarch64)] pub(crate) struct BranchProtectionRequiresAArch64; + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::layout_size_overflow)] +pub(crate) struct LayoutSizeOverflow { + #[primary_span] + pub span: Span, + pub error: String, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index d713183f5729..75c6547a4448 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -24,3 +24,6 @@ codegen_llvm_symbol_already_defined = codegen_llvm_branch_protection_requires_aarch64 = -Zbranch-protection is only supported on aarch64 + +codegen_llvm_layout_size_overflow = + {$error} From 5d79d3c4bb8768b4e8ee2b243a625bbfd740a696 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 10:30:43 +0200 Subject: [PATCH 197/221] Port InvalidMinimumAlignment --- compiler/rustc_codegen_llvm/src/consts.rs | 5 ++++- compiler/rustc_codegen_llvm/src/errors.rs | 6 ++++++ .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index bf5ac4e503e3..05fa87c80946 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -1,6 +1,7 @@ use crate::base; use crate::common::{self, CodegenCx}; use crate::debuginfo; +use crate::errors::InvalidMinimumAlignment; use crate::llvm::{self, True}; use crate::llvm_util; use crate::type_::Type; @@ -146,7 +147,9 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: match Align::from_bits(min) { Ok(min) => align = align.max(min), Err(err) => { - cx.sess().err(&format!("invalid minimum global alignment: {}", err)); + cx.sess().emit_err(InvalidMinimumAlignment { + err, + }); } } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 95a12d98d5cf..8c87d9eb1fbc 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -67,3 +67,9 @@ pub(crate) struct LayoutSizeOverflow { pub span: Span, pub error: String, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::invalid_minimum_alignment)] +pub(crate) struct InvalidMinimumAlignment { + pub err: String +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 75c6547a4448..1c38bbdce16c 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -27,3 +27,6 @@ codegen_llvm_branch_protection_requires_aarch64 = codegen_llvm_layout_size_overflow = {$error} + +codegen_llvm_invalid_minimum_alignment = + invalid minimum global alignment: {$err} From 60ee496c7439b7a4b8d45c89ac4cc780ca878eed Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 10:40:48 +0200 Subject: [PATCH 198/221] Port LinkageConstOrMutType error --- compiler/rustc_codegen_llvm/src/consts.rs | 11 +++-------- compiler/rustc_codegen_llvm/src/errors.rs | 9 ++++++++- .../locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 05fa87c80946..07c46e936321 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -1,7 +1,7 @@ use crate::base; use crate::common::{self, CodegenCx}; use crate::debuginfo; -use crate::errors::InvalidMinimumAlignment; +use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType}; use crate::llvm::{self, True}; use crate::llvm_util; use crate::type_::Type; @@ -147,9 +147,7 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: match Align::from_bits(min) { Ok(min) => align = align.max(min), Err(err) => { - cx.sess().emit_err(InvalidMinimumAlignment { - err, - }); + cx.sess().emit_err(InvalidMinimumAlignment { err }); } } } @@ -177,10 +175,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( let llty2 = if let ty::RawPtr(ref mt) = ty.kind() { cx.layout_of(mt.ty).llvm_type(cx) } else { - cx.sess().span_fatal( - cx.tcx.def_span(def_id), - "must have type `*const T` or `*mut T` due to `#[linkage]` attribute", - ) + cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) }) }; unsafe { // Declare a symbol `foo` with the desired linkage. diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 8c87d9eb1fbc..2661bd3cb997 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -71,5 +71,12 @@ pub(crate) struct LayoutSizeOverflow { #[derive(SessionDiagnostic)] #[diag(codegen_llvm::invalid_minimum_alignment)] pub(crate) struct InvalidMinimumAlignment { - pub err: String + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::linkage_const_or_mut_type)] +pub(crate) struct LinkageConstOrMutType { + #[primary_span] + pub span: Span, } diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 1c38bbdce16c..3804f0dbbfab 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -30,3 +30,6 @@ codegen_llvm_layout_size_overflow = codegen_llvm_invalid_minimum_alignment = invalid minimum global alignment: {$err} + +codegen_llvm_linkage_const_or_mut_type = + must have type `*const T` or `*mut T` due to `#[linkage]` attribute From 02403ee31d71a2e0ca00f5c0eff375206df74958 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 11:48:35 +0200 Subject: [PATCH 199/221] Reuse SymbolAlreadyDefined --- compiler/rustc_codegen_llvm/src/consts.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 07c46e936321..3b504d3a7df7 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -1,7 +1,7 @@ use crate::base; use crate::common::{self, CodegenCx}; use crate::debuginfo; -use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType}; +use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined}; use crate::llvm::{self, True}; use crate::llvm_util; use crate::type_::Type; @@ -191,10 +191,10 @@ fn check_and_apply_linkage<'ll, 'tcx>( let mut real_name = "_rust_extern_with_linkage_".to_string(); real_name.push_str(sym); let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| { - cx.sess().span_fatal( - cx.tcx.def_span(def_id), - &format!("symbol `{}` is already defined", &sym), - ) + cx.sess().emit_fatal(SymbolAlreadyDefined { + span: cx.tcx.def_span(def_id), + symbol_name: sym, + }) }); llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); llvm::LLVMSetInitializer(g2, g1); From 978b5f73e4be94fc99c757b5a66bf297404202f2 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 12:19:10 +0200 Subject: [PATCH 200/221] Port SanitizerMemtagRequiresMte --- compiler/rustc_codegen_llvm/src/attributes.rs | 3 ++- compiler/rustc_codegen_llvm/src/errors.rs | 4 ++++ compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index d96da5cc11d1..02eef1040773 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,6 +12,7 @@ use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtec use smallvec::SmallVec; use crate::attributes; +use crate::errors::SanitizerMemtagRequiresMte; use crate::llvm::AttributePlace::Function; use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects}; use crate::llvm_util; @@ -82,7 +83,7 @@ pub fn sanitize_attrs<'ll>( let mte_feature = features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..])); if let None | Some("-mte") = mte_feature { - cx.tcx.sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`"); + cx.tcx.sess.emit_err(SanitizerMemtagRequiresMte); } attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx)); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 2661bd3cb997..a652fb4c2a08 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -80,3 +80,7 @@ pub(crate) struct LinkageConstOrMutType { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::sanitizer_memtag_requires_mte)] +pub(crate) struct SanitizerMemtagRequiresMte; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 3804f0dbbfab..e4e1abfe2197 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -33,3 +33,6 @@ codegen_llvm_invalid_minimum_alignment = codegen_llvm_linkage_const_or_mut_type = must have type `*const T` or `*mut T` due to `#[linkage]` attribute + +codegen_llvm_sanitizer_memtag_requires_mte = + `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` From d32caf9cedd4f9777a1bcf3bde2913493f48bc6d Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 14:11:47 +0200 Subject: [PATCH 201/221] Port ArchiveBuildFailure --- compiler/rustc_codegen_llvm/src/back/archive.rs | 4 ++-- compiler/rustc_codegen_llvm/src/errors.rs | 6 ++++++ .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 4fd8b0ef4bb7..e6ab0e74b7d0 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -12,7 +12,7 @@ use std::str; use object::read::macho::FatArch; use crate::common; -use crate::errors::ErrorCreatingImportLibrary; +use crate::errors::{ErrorCreatingImportLibrary, ArchiveBuildFailure}; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; @@ -148,7 +148,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { fn build(mut self: Box, output: &Path) -> bool { match self.build_with_llvm(output) { Ok(any_members) => any_members, - Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)), + Err(e) => self.sess.emit_fatal(ArchiveBuildFailure { error: e }), } } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index a652fb4c2a08..12ea4166cf46 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -84,3 +84,9 @@ pub(crate) struct LinkageConstOrMutType { #[derive(SessionDiagnostic)] #[diag(codegen_llvm::sanitizer_memtag_requires_mte)] pub(crate) struct SanitizerMemtagRequiresMte; + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::archive_build_failure)] +pub(crate) struct ArchiveBuildFailure { + pub error: std::io::Error, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index e4e1abfe2197..7ce1bb18d62f 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -36,3 +36,6 @@ codegen_llvm_linkage_const_or_mut_type = codegen_llvm_sanitizer_memtag_requires_mte = `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` + +codegen_llvm_archive_build_failure = + failed to build archive: {$error} From ddbb6502893999b8f9a9780274318b63c3df25fb Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 14:17:15 +0200 Subject: [PATCH 202/221] Import ErrorWritingDEFFile --- compiler/rustc_codegen_llvm/src/back/archive.rs | 4 ++-- compiler/rustc_codegen_llvm/src/errors.rs | 6 ++++++ .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index e6ab0e74b7d0..01d4cda18d47 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -12,7 +12,7 @@ use std::str; use object::read::macho::FatArch; use crate::common; -use crate::errors::{ErrorCreatingImportLibrary, ArchiveBuildFailure}; +use crate::errors::{ArchiveBuildFailure, ErrorCreatingImportLibrary, ErrorWritingDEFFile}; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; @@ -218,7 +218,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { match std::fs::write(&def_file_path, def_file_content) { Ok(_) => {} Err(e) => { - sess.fatal(&format!("Error writing .DEF file: {}", e)); + sess.emit_fatal(ErrorWritingDEFFile { error: e }); } }; diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 12ea4166cf46..b7962fd0bae7 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -90,3 +90,9 @@ pub(crate) struct SanitizerMemtagRequiresMte; pub(crate) struct ArchiveBuildFailure { pub error: std::io::Error, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::error_writing_def_file)] +pub(crate) struct ErrorWritingDEFFile { + pub error: std::io::Error, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 7ce1bb18d62f..c26c11612cda 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -39,3 +39,6 @@ codegen_llvm_sanitizer_memtag_requires_mte = codegen_llvm_archive_build_failure = failed to build archive: {$error} + +codegen_llvm_error_writing_def_file = + Error writing .DEF file: {$error} From 81f7a8d7f1ddcbe9ed49757a925366d0041eda31 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 14:29:33 +0200 Subject: [PATCH 203/221] Port ErrorCallingDllTool --- compiler/rustc_codegen_llvm/src/back/archive.rs | 6 ++++-- compiler/rustc_codegen_llvm/src/errors.rs | 6 ++++++ .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 01d4cda18d47..e73e122ee68d 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -12,7 +12,9 @@ use std::str; use object::read::macho::FatArch; use crate::common; -use crate::errors::{ArchiveBuildFailure, ErrorCreatingImportLibrary, ErrorWritingDEFFile}; +use crate::errors::{ + ArchiveBuildFailure, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, +}; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; @@ -240,7 +242,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { match result { Err(e) => { - sess.fatal(&format!("Error calling dlltool: {}", e)); + sess.emit_fatal(ErrorCallingDllTool { error: e }); } Ok(output) if !output.status.success() => sess.fatal(&format!( "Dlltool could not create import library: {}\n{}", diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index b7962fd0bae7..4856cead1521 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -96,3 +96,9 @@ pub(crate) struct ArchiveBuildFailure { pub(crate) struct ErrorWritingDEFFile { pub error: std::io::Error, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::error_calling_dlltool)] +pub(crate) struct ErrorCallingDllTool { + pub error: std::io::Error, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index c26c11612cda..3c8a893b4a5a 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -42,3 +42,6 @@ codegen_llvm_archive_build_failure = codegen_llvm_error_writing_def_file = Error writing .DEF file: {$error} + +codegen_llvm_error_calling_dlltool = + Error calling dlltool: {$error} From c01546fcd64f703cd6a406752621d0e18ccb6a5a Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 19:01:22 +0200 Subject: [PATCH 204/221] Port `DlltoolFailImportLibrary` and implement `IntoDiagnosticArg` for `Cow<'a, str>` --- compiler/rustc_codegen_llvm/src/back/archive.rs | 14 ++++++++------ compiler/rustc_codegen_llvm/src/errors.rs | 9 +++++++++ .../locales/en-US/codegen_llvm.ftl | 3 +++ compiler/rustc_errors/src/diagnostic_impls.rs | 6 ++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index e73e122ee68d..9be104fde6c4 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -13,7 +13,8 @@ use object::read::macho::FatArch; use crate::common; use crate::errors::{ - ArchiveBuildFailure, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, + ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, + ErrorWritingDEFFile, }; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; @@ -244,11 +245,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { Err(e) => { sess.emit_fatal(ErrorCallingDllTool { error: e }); } - Ok(output) if !output.status.success() => sess.fatal(&format!( - "Dlltool could not create import library: {}\n{}", - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) - )), + Ok(output) if !output.status.success() => { + sess.emit_fatal(DlltoolFailImportLibrary { + stdout: String::from_utf8_lossy(&output.stdout), + stderr: String::from_utf8_lossy(&output.stderr), + }) + } _ => {} } } else { diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 4856cead1521..68c2e6928304 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use rustc_errors::fluent; use rustc_errors::DiagnosticBuilder; use rustc_macros::SessionDiagnostic; @@ -102,3 +104,10 @@ pub(crate) struct ErrorWritingDEFFile { pub(crate) struct ErrorCallingDllTool { pub error: std::io::Error, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::dlltool_fail_import_library)] +pub(crate) struct DlltoolFailImportLibrary<'a> { + pub stdout: Cow<'a, str>, + pub stderr: Cow<'a, str>, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 3c8a893b4a5a..f9266b54d137 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -45,3 +45,6 @@ codegen_llvm_error_writing_def_file = codegen_llvm_error_calling_dlltool = Error calling dlltool: {$error} + +codegen_llvm_dlltool_fail_import_library = + Dlltool could not create import library: {$stdout}\n{$stderr} diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 22f6fc700fad..c6035705e39f 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -107,6 +107,12 @@ impl IntoDiagnosticArg for String { } } +impl<'a> IntoDiagnosticArg for Cow<'a, str> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.into_owned())) + } +} + impl<'a> IntoDiagnosticArg for &'a Path { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) From 33ef16f291b6a43dc57dcb8915bdb4aa736a7936 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 19:42:29 +0200 Subject: [PATCH 205/221] Port `UnknownArchiveKind` --- compiler/rustc_codegen_llvm/src/back/archive.rs | 9 +++++---- compiler/rustc_codegen_llvm/src/errors.rs | 6 ++++++ .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 +++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 9be104fde6c4..99c9b51a9cda 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -14,7 +14,7 @@ use object::read::macho::FatArch; use crate::common; use crate::errors::{ ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, - ErrorWritingDEFFile, + ErrorWritingDEFFile, UnknownArchiveKind, }; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; @@ -312,9 +312,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { impl<'a> LlvmArchiveBuilder<'a> { fn build_with_llvm(&mut self, output: &Path) -> io::Result { let kind = &*self.sess.target.archive_format; - let kind = kind.parse::().map_err(|_| kind).unwrap_or_else(|kind| { - self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)) - }); + let kind = kind + .parse::() + .map_err(|_| kind) + .unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind: kind })); let mut additions = mem::take(&mut self.additions); let mut strings = Vec::new(); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 68c2e6928304..1fe88cc24824 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -111,3 +111,9 @@ pub(crate) struct DlltoolFailImportLibrary<'a> { pub stdout: Cow<'a, str>, pub stderr: Cow<'a, str>, } + +#[derive(SessionDiagnostic)] +#[diag(codegen_llvm::unknown_archive_kind)] +pub(crate) struct UnknownArchiveKind<'a> { + pub kind: &'a str, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index f9266b54d137..67160ca28820 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -48,3 +48,6 @@ codegen_llvm_error_calling_dlltool = codegen_llvm_dlltool_fail_import_library = Dlltool could not create import library: {$stdout}\n{$stderr} + +codegen_llvm_unknown_archive_kind = + Don't know how to build archive of type: {$kind} From 185ef7b6de0dcdd32af43fd75efa41fd128cbaad Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 26 Aug 2022 21:27:17 +0200 Subject: [PATCH 206/221] Port `MissingFeatures` and `TargetFeatureDisableOrEnable` --- compiler/rustc_codegen_llvm/src/attributes.rs | 14 ++++----- compiler/rustc_codegen_llvm/src/errors.rs | 29 ++++++++++++++++++- compiler/rustc_codegen_llvm/src/llvm_util.rs | 10 +++---- .../locales/en-US/codegen_llvm.ftl | 6 ++++ 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 02eef1040773..ce54c2813843 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,7 +12,7 @@ use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtec use smallvec::SmallVec; use crate::attributes; -use crate::errors::SanitizerMemtagRequiresMte; +use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable}; use crate::llvm::AttributePlace::Function; use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects}; use crate::llvm_util; @@ -394,13 +394,11 @@ pub fn from_fn_attrs<'ll, 'tcx>( .get_attrs(instance.def_id(), sym::target_feature) .next() .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); - let msg = format!( - "the target features {} must all be either enabled or disabled together", - f.join(", ") - ); - let mut err = cx.tcx.sess.struct_span_err(span, &msg); - err.help("add the missing features in a `target_feature` attribute"); - err.emit(); + cx.tcx + .sess + .create_err(TargetFeatureDisableOrEnable { features: f, span: Some(span) }) + .subdiagnostic(MissingFeatures) + .emit(); return; } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 1fe88cc24824..cd53ac4532ae 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -2,7 +2,8 @@ use std::borrow::Cow; use rustc_errors::fluent; use rustc_errors::DiagnosticBuilder; -use rustc_macros::SessionDiagnostic; +use rustc_errors::ErrorGuaranteed; +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; use rustc_session::SessionDiagnostic; use rustc_span::Span; @@ -117,3 +118,29 @@ pub(crate) struct DlltoolFailImportLibrary<'a> { pub(crate) struct UnknownArchiveKind<'a> { pub kind: &'a str, } + +pub(crate) struct TargetFeatureDisableOrEnable<'a> { + pub features: &'a [&'a str], + pub span: Option, +} + +#[derive(SessionSubdiagnostic)] +#[help(codegen_llvm::missing_features)] +pub(crate) struct MissingFeatures; + +impl SessionDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = if let Some(span) = self.span { + let mut diag = sess.struct_err(fluent::codegen_llvm::target_feature_disable_or_enable); + diag.set_span(span); + diag + } else { + sess.struct_err(fluent::codegen_llvm::target_feature_disable_or_enable) + }; + diag.set_arg("features", self.features.join(", ")); + diag + } +} diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 8f67913f91f0..8c2db38d84d8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,5 +1,5 @@ use crate::back::write::create_informational_target_machine; -use crate::errors::UnknownCTargetFeature; +use crate::errors::{TargetFeatureDisableOrEnable, UnknownCTargetFeature}; use crate::llvm; use libc::c_int; use rustc_codegen_ssa::target_features::{ @@ -480,10 +480,10 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Date: Sat, 27 Aug 2022 10:05:50 +0200 Subject: [PATCH 207/221] Fix CI Add missing 'the' to the error en-US translation --- compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 4113e6640d6e..940f727b21dd 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -53,7 +53,7 @@ codegen_llvm_unknown_archive_kind = Don't know how to build archive of type: {$kind} codegen_llvm_target_feature_disable_or_enable = - target features {$features} must all be enabled or disabled together + the target features {$features} must all be enabled or disabled together codegen_llvm_missing_features = add the missing features in a `target_feature` attribute From e9a5329a6f88935c92b506a19db628ec2c0cf6ed Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Tue, 30 Aug 2022 12:22:08 +0200 Subject: [PATCH 208/221] Correct tests to match errors --- compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl | 2 +- src/test/ui/target-feature/tied-features-cli.one.stderr | 2 +- src/test/ui/target-feature/tied-features-cli.three.stderr | 2 +- src/test/ui/target-feature/tied-features-cli.two.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 940f727b21dd..9d80b98f56c6 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -53,7 +53,7 @@ codegen_llvm_unknown_archive_kind = Don't know how to build archive of type: {$kind} codegen_llvm_target_feature_disable_or_enable = - the target features {$features} must all be enabled or disabled together + the target features {$features} must all be either enabled or disabled together codegen_llvm_missing_features = add the missing features in a `target_feature` attribute diff --git a/src/test/ui/target-feature/tied-features-cli.one.stderr b/src/test/ui/target-feature/tied-features-cli.one.stderr index 0cc901eecaa2..b4b50d98192b 100644 --- a/src/test/ui/target-feature/tied-features-cli.one.stderr +++ b/src/test/ui/target-feature/tied-features-cli.one.stderr @@ -1,4 +1,4 @@ -error: target features paca, pacg must all be enabled or disabled together +error: the target features paca, pacg must all be either enabled or disabled together error: aborting due to previous error diff --git a/src/test/ui/target-feature/tied-features-cli.three.stderr b/src/test/ui/target-feature/tied-features-cli.three.stderr index 0cc901eecaa2..b4b50d98192b 100644 --- a/src/test/ui/target-feature/tied-features-cli.three.stderr +++ b/src/test/ui/target-feature/tied-features-cli.three.stderr @@ -1,4 +1,4 @@ -error: target features paca, pacg must all be enabled or disabled together +error: the target features paca, pacg must all be either enabled or disabled together error: aborting due to previous error diff --git a/src/test/ui/target-feature/tied-features-cli.two.stderr b/src/test/ui/target-feature/tied-features-cli.two.stderr index 0cc901eecaa2..b4b50d98192b 100644 --- a/src/test/ui/target-feature/tied-features-cli.two.stderr +++ b/src/test/ui/target-feature/tied-features-cli.two.stderr @@ -1,4 +1,4 @@ -error: target features paca, pacg must all be enabled or disabled together +error: the target features paca, pacg must all be either enabled or disabled together error: aborting due to previous error From 67394e794519542490293487134f6d6293614ab1 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Sun, 30 Oct 2022 14:33:27 +0100 Subject: [PATCH 209/221] Flatten diagnostic structs --- compiler/rustc_codegen_llvm/src/errors.rs | 91 +++++++++++------------ 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index cd53ac4532ae..db3ca6a7783e 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -3,8 +3,9 @@ use std::borrow::Cow; use rustc_errors::fluent; use rustc_errors::DiagnosticBuilder; use rustc_errors::ErrorGuaranteed; -use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; -use rustc_session::SessionDiagnostic; +use rustc_errors::Handler; +use rustc_errors::IntoDiagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; pub(crate) enum UnknownCTargetFeature<'a> { @@ -12,27 +13,24 @@ pub(crate) enum UnknownCTargetFeature<'a> { UnknownFeature { feature: &'a str, rust_feature: Option<&'a str> }, } -impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature<'_> { - fn into_diagnostic( - self, - sess: &'_ rustc_session::parse::ParseSess, - ) -> DiagnosticBuilder<'_, ()> { +impl IntoDiagnostic<'_, ()> for UnknownCTargetFeature<'_> { + fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ()> { match self { UnknownCTargetFeature::UnknownFeaturePrefix { feature } => { - let mut diag = sess.struct_warn(fluent::codegen_llvm::unknown_ctarget_feature); + let mut diag = sess.struct_warn(fluent::codegen_llvm_unknown_ctarget_feature); diag.set_arg("feature", feature); - diag.note(fluent::codegen_llvm::unknown_feature_prefix); + diag.note(fluent::codegen_llvm_unknown_feature_prefix); diag } UnknownCTargetFeature::UnknownFeature { feature, rust_feature } => { - let mut diag = sess.struct_warn(fluent::codegen_llvm::unknown_ctarget_feature); + let mut diag = sess.struct_warn(fluent::codegen_llvm_unknown_ctarget_feature); diag.set_arg("feature", feature); - diag.note(fluent::codegen_llvm::unknown_feature); + diag.note(fluent::codegen_llvm_unknown_feature); if let Some(rust_feature) = rust_feature { - diag.help(fluent::codegen_llvm::rust_feature); + diag.help(fluent::codegen_llvm_rust_feature); diag.set_arg("rust_feature", rust_feature); } else { - diag.note(fluent::codegen_llvm::unknown_feature_fill_request); + diag.note(fluent::codegen_llvm_unknown_feature_fill_request); } diag } @@ -40,81 +38,81 @@ impl SessionDiagnostic<'_, ()> for UnknownCTargetFeature<'_> { } } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::error_creating_import_library)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_error_creating_import_library)] pub(crate) struct ErrorCreatingImportLibrary<'a> { pub lib_name: &'a str, pub error: String, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::instrument_coverage_requires_llvm_12)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_instrument_coverage_requires_llvm_12)] pub(crate) struct InstrumentCoverageRequiresLLVM12; -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::symbol_already_defined)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_symbol_already_defined)] pub(crate) struct SymbolAlreadyDefined<'a> { #[primary_span] pub span: Span, pub symbol_name: &'a str, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::branch_protection_requires_aarch64)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_branch_protection_requires_aarch64)] pub(crate) struct BranchProtectionRequiresAArch64; -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::layout_size_overflow)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_layout_size_overflow)] pub(crate) struct LayoutSizeOverflow { #[primary_span] pub span: Span, pub error: String, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::invalid_minimum_alignment)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_invalid_minimum_alignment)] pub(crate) struct InvalidMinimumAlignment { pub err: String, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::linkage_const_or_mut_type)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_linkage_const_or_mut_type)] pub(crate) struct LinkageConstOrMutType { #[primary_span] pub span: Span, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::sanitizer_memtag_requires_mte)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_sanitizer_memtag_requires_mte)] pub(crate) struct SanitizerMemtagRequiresMte; -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::archive_build_failure)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_archive_build_failure)] pub(crate) struct ArchiveBuildFailure { pub error: std::io::Error, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::error_writing_def_file)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_error_writing_def_file)] pub(crate) struct ErrorWritingDEFFile { pub error: std::io::Error, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::error_calling_dlltool)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_error_calling_dlltool)] pub(crate) struct ErrorCallingDllTool { pub error: std::io::Error, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::dlltool_fail_import_library)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_dlltool_fail_import_library)] pub(crate) struct DlltoolFailImportLibrary<'a> { pub stdout: Cow<'a, str>, pub stderr: Cow<'a, str>, } -#[derive(SessionDiagnostic)] -#[diag(codegen_llvm::unknown_archive_kind)] +#[derive(Diagnostic)] +#[diag(codegen_llvm_unknown_archive_kind)] pub(crate) struct UnknownArchiveKind<'a> { pub kind: &'a str, } @@ -124,21 +122,18 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub span: Option, } -#[derive(SessionSubdiagnostic)] -#[help(codegen_llvm::missing_features)] +#[derive(Subdiagnostic)] +#[help(codegen_llvm_missing_features)] pub(crate) struct MissingFeatures; -impl SessionDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic( - self, - sess: &'_ rustc_session::parse::ParseSess, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let mut diag = if let Some(span) = self.span { - let mut diag = sess.struct_err(fluent::codegen_llvm::target_feature_disable_or_enable); + let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); diag.set_span(span); diag } else { - sess.struct_err(fluent::codegen_llvm::target_feature_disable_or_enable) + sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable) }; diag.set_arg("features", self.features.join(", ")); diag From 3728e95596fa937eac9188af0ffe177e94635a5b Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Sun, 30 Oct 2022 16:07:04 +0100 Subject: [PATCH 210/221] Port diagnostics created by `Handler` --- compiler/rustc_codegen_llvm/src/back/lto.rs | 9 ++------- compiler/rustc_codegen_llvm/src/errors.rs | 11 +++++++++++ compiler/rustc_codegen_llvm/src/lib.rs | 5 ++++- .../locales/en-US/codegen_llvm.ftl | 7 +++++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index a49cc7f8d662..3fa21355b7f4 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -1,4 +1,5 @@ use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers}; +use crate::errors::DynamicLinkingWithLTO; use crate::llvm::{self, build_string}; use crate::{LlvmCodegenBackend, ModuleLlvm}; use object::read::archive::ArchiveFile; @@ -90,13 +91,7 @@ fn prepare_lto( } if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { - diag_handler - .struct_err("cannot prefer dynamic linking when performing LTO") - .note( - "only 'staticlib', 'bin', and 'cdylib' outputs are \ - supported with LTO", - ) - .emit(); + diag_handler.emit_err(DynamicLinkingWithLTO); return Err(FatalError); } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index db3ca6a7783e..c08827b95219 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -117,6 +117,17 @@ pub(crate) struct UnknownArchiveKind<'a> { pub kind: &'a str, } +#[derive(Diagnostic)] +#[diag(codegen_llvm_dynamic_linking_with_lto)] +#[note] +pub(crate) struct DynamicLinkingWithLTO; + +#[derive(Diagnostic)] +#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)] +pub(crate) struct FailParsingTargetMachineConfigToTargetMachine { + pub error: String, +} + pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub features: &'a [&'a str], pub span: Option, diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index af632b2ff54b..246e82545c87 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -12,6 +12,8 @@ #![feature(iter_intersperse)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; @@ -20,6 +22,7 @@ extern crate tracing; use back::write::{create_informational_target_machine, create_target_machine}; +use errors::FailParsingTargetMachineConfigToTargetMachine; pub use llvm_util::target_features; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; @@ -413,7 +416,7 @@ impl ModuleLlvm { let tm = match (cgcx.tm_factory)(tm_factory_config) { Ok(m) => m, Err(e) => { - handler.struct_err(&e).emit(); + handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e }); return Err(FatalError); } }; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index 9d80b98f56c6..ad4d6a676e66 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -57,3 +57,10 @@ codegen_llvm_target_feature_disable_or_enable = codegen_llvm_missing_features = add the missing features in a `target_feature` attribute + +codegen_llvm_dynamic_linking_with_lto = + cannot prefer dynamic linking when performing LTO + .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO + +codegen_llvm_fail_parsing_target_machine_config_to_target_machine = + failed to parse target machine config to target machine: {$error} From 9a1545861e7e2d0d63b730c39a115d89d2eeb21c Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Sun, 30 Oct 2022 19:26:12 +0100 Subject: [PATCH 211/221] Simplify existing Diagnostic implementations --- compiler/rustc_codegen_llvm/src/attributes.rs | 7 ++- compiler/rustc_codegen_llvm/src/errors.rs | 57 +++++++++---------- compiler/rustc_codegen_llvm/src/llvm_util.rs | 22 +++++-- .../locales/en-US/codegen_llvm.ftl | 17 ++---- 4 files changed, 53 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index ce54c2813843..a8b47633519a 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -396,8 +396,11 @@ pub fn from_fn_attrs<'ll, 'tcx>( .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); cx.tcx .sess - .create_err(TargetFeatureDisableOrEnable { features: f, span: Some(span) }) - .subdiagnostic(MissingFeatures) + .create_err(TargetFeatureDisableOrEnable { + features: f, + span: Some(span), + missing_features: Some(MissingFeatures), + }) .emit(); return; } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index c08827b95219..44896a8e8feb 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -8,34 +8,28 @@ use rustc_errors::IntoDiagnostic; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; -pub(crate) enum UnknownCTargetFeature<'a> { - UnknownFeaturePrefix { feature: &'a str }, - UnknownFeature { feature: &'a str, rust_feature: Option<&'a str> }, +#[derive(Diagnostic)] +#[diag(codegen_llvm_unknown_ctarget_feature_prefix)] +#[note] +pub(crate) struct UnknownCTargetFeaturePrefix<'a> { + pub feature: &'a str, } -impl IntoDiagnostic<'_, ()> for UnknownCTargetFeature<'_> { - fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ()> { - match self { - UnknownCTargetFeature::UnknownFeaturePrefix { feature } => { - let mut diag = sess.struct_warn(fluent::codegen_llvm_unknown_ctarget_feature); - diag.set_arg("feature", feature); - diag.note(fluent::codegen_llvm_unknown_feature_prefix); - diag - } - UnknownCTargetFeature::UnknownFeature { feature, rust_feature } => { - let mut diag = sess.struct_warn(fluent::codegen_llvm_unknown_ctarget_feature); - diag.set_arg("feature", feature); - diag.note(fluent::codegen_llvm_unknown_feature); - if let Some(rust_feature) = rust_feature { - diag.help(fluent::codegen_llvm_rust_feature); - diag.set_arg("rust_feature", rust_feature); - } else { - diag.note(fluent::codegen_llvm_unknown_feature_fill_request); - } - diag - } - } - } +#[derive(Diagnostic)] +#[diag(codegen_llvm_unknown_ctarget_feature)] +#[note] +pub(crate) struct UnknownCTargetFeature<'a> { + pub feature: &'a str, + #[subdiagnostic] + pub rust_feature: PossibleFeature<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum PossibleFeature<'a> { + #[help(possible_feature)] + Some { rust_feature: &'a str }, + #[help(consider_filing_feature_request)] + None, } #[derive(Diagnostic)] @@ -131,6 +125,7 @@ pub(crate) struct FailParsingTargetMachineConfigToTargetMachine { pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub features: &'a [&'a str], pub span: Option, + pub missing_features: Option, } #[derive(Subdiagnostic)] @@ -139,13 +134,13 @@ pub(crate) struct MissingFeatures; impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = if let Some(span) = self.span { - let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); + let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); + if let Some(span) = self.span { diag.set_span(span); - diag - } else { - sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable) }; + if let Some(missing_features) = self.missing_features { + diag.subdiagnostic(missing_features); + } diag.set_arg("features", self.features.join(", ")); diag } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 8c2db38d84d8..e1f54356228d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,5 +1,8 @@ use crate::back::write::create_informational_target_machine; -use crate::errors::{TargetFeatureDisableOrEnable, UnknownCTargetFeature}; +use crate::errors::{ + PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, + UnknownCTargetFeaturePrefix, +}; use crate::llvm; use libc::c_int; use rustc_codegen_ssa::target_features::{ @@ -435,9 +438,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec c, Some(_) => { if diagnostics { - sess.emit_warning(UnknownCTargetFeature::UnknownFeaturePrefix { - feature: s, - }); + sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s }); } return None; } @@ -454,7 +455,15 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Vec Date: Wed, 2 Nov 2022 19:23:05 +0100 Subject: [PATCH 212/221] Delay diagnostic translation in `rustc_codegen_ssa` --- compiler/rustc_codegen_ssa/src/back/write.rs | 27 +++++++++++++------- compiler/rustc_errors/src/diagnostic.rs | 9 +++++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index d0ac016b02e1..6e1a87ae9ebb 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,10 +15,8 @@ use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; -use rustc_errors::{ - translation::{to_fluent_args, Translate}, - DiagnosticId, FatalError, Handler, Level, -}; +use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level}; +use rustc_errors::{DiagnosticMessage, Style}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ @@ -38,6 +36,7 @@ use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; use rustc_target::spec::{MergeFunctions, SanitizerSet}; use std::any::Any; +use std::borrow::Cow; use std::fs; use std::io; use std::marker::PhantomData; @@ -969,8 +968,11 @@ pub enum Message { CodegenAborted, } +type DiagnosticArgName<'source> = Cow<'source, str>; + struct Diagnostic { - msg: String, + msg: Vec<(DiagnosticMessage, Style)>, + args: FxHashMap, rustc_errors::DiagnosticArgValue<'static>>, code: Option, lvl: Level, } @@ -1743,15 +1745,18 @@ impl Translate for SharedEmitter { impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { - let fluent_args = to_fluent_args(diag.args()); + let args: FxHashMap, rustc_errors::DiagnosticArgValue<'_>> = + diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect(); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: self.translate_messages(&diag.message, &fluent_args).to_string(), + msg: diag.message.clone(), + args: args.clone(), code: diag.code.clone(), lvl: diag.level(), }))); for child in &diag.children { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: self.translate_messages(&child.message, &fluent_args).to_string(), + msg: child.message.clone(), + args: args.clone(), code: None, lvl: child.level, }))); @@ -1782,10 +1787,14 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { let handler = sess.diagnostic(); - let mut d = rustc_errors::Diagnostic::new(diag.lvl, &diag.msg); + let mut d = rustc_errors::Diagnostic::new(diag.lvl, String::new()); + d.message = diag.msg; if let Some(code) = diag.code { d.code(code); } + for (name, arg) in diag.args { + d.set_arg(name, arg); + } handler.emit_diagnostic(&mut d); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 45c017df918e..b6370354b248 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -44,6 +44,15 @@ pub trait IntoDiagnosticArg { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>; } +impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + match self { + DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())), + DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n), + } + } +} + impl<'source> Into> for DiagnosticArgValue<'source> { fn into(self) -> FluentValue<'source> { match self { From 3b949eb7c1eff22e89c4889e191d916ad028ff28 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 3 Nov 2022 13:09:25 +0100 Subject: [PATCH 213/221] Add `replace_args` method for `rustc_errors::diagnostic::Diagnostic` --- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +--- compiler/rustc_errors/src/diagnostic.rs | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 6e1a87ae9ebb..f0e2e43509f9 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1792,9 +1792,7 @@ impl SharedEmitterMain { if let Some(code) = diag.code { d.code(code); } - for (name, arg) in diag.args { - d.set_arg(name, arg); - } + d.replace_args(diag.args); handler.emit_diagnostic(&mut d); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b6370354b248..8c76db84392e 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -940,6 +940,10 @@ impl Diagnostic { self } + pub fn replace_args(&mut self, args: FxHashMap, DiagnosticArgValue<'static>>) { + self.args = args; + } + pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] { &self.message } From 0381e51822129ca1791cb59df72056fe023e7566 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Thu, 3 Nov 2022 13:41:54 +0100 Subject: [PATCH 214/221] Formatting --- compiler/rustc_errors/src/diagnostic.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 8c76db84392e..b24814bfa387 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -940,7 +940,10 @@ impl Diagnostic { self } - pub fn replace_args(&mut self, args: FxHashMap, DiagnosticArgValue<'static>>) { + pub fn replace_args( + &mut self, + args: FxHashMap, DiagnosticArgValue<'static>>, + ) { self.args = args; } From a8a8055cc7f8481b0bed653f991648f120ea98a6 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Fri, 4 Nov 2022 20:08:01 +0100 Subject: [PATCH 215/221] Use `LayoutError`'s implementation of `IntoDiagnostic` --- compiler/rustc_codegen_llvm/src/context.rs | 6 +++--- compiler/rustc_codegen_llvm/src/errors.rs | 8 -------- .../rustc_error_messages/locales/en-US/codegen_llvm.ftl | 3 --- compiler/rustc_middle/src/ty/layout.rs | 8 ++++---- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 7ed4df16ea99..eaa2ccfc835c 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -4,7 +4,6 @@ use crate::callee::get_fn; use crate::coverageinfo; use crate::debuginfo; use crate::errors::BranchProtectionRequiresAArch64; -use crate::errors::LayoutSizeOverflow; use crate::llvm; use crate::llvm_util; use crate::type_::Type; @@ -28,6 +27,7 @@ use rustc_session::config::{BranchProtection, CFGuard, CFProtection}; use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet}; use rustc_session::Session; use rustc_span::source_map::Span; +use rustc_span::source_map::Spanned; use rustc_target::abi::{ call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx, }; @@ -953,7 +953,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) = err { - self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) + self.sess().emit_fatal(Spanned { span, node: err }) } else { span_bug!(span, "failed to get layout for `{}`: {}", ty, err) } @@ -971,7 +971,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) + self.sess().emit_fatal(Spanned { span, node: err }) } else { match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 44896a8e8feb..0fafc214f2f5 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -55,14 +55,6 @@ pub(crate) struct SymbolAlreadyDefined<'a> { #[diag(codegen_llvm_branch_protection_requires_aarch64)] pub(crate) struct BranchProtectionRequiresAArch64; -#[derive(Diagnostic)] -#[diag(codegen_llvm_layout_size_overflow)] -pub(crate) struct LayoutSizeOverflow { - #[primary_span] - pub span: Span, - pub error: String, -} - #[derive(Diagnostic)] #[diag(codegen_llvm_invalid_minimum_alignment)] pub(crate) struct InvalidMinimumAlignment { diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index a105b4a64e99..68a205df6c7a 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -20,9 +20,6 @@ codegen_llvm_symbol_already_defined = codegen_llvm_branch_protection_requires_aarch64 = -Zbranch-protection is only supported on aarch64 -codegen_llvm_layout_size_overflow = - {$error} - codegen_llvm_invalid_minimum_alignment = invalid minimum global alignment: {$err} diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 3312f44c67b2..c74d6bc3774a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -189,8 +189,8 @@ pub enum LayoutError<'tcx> { NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), } -impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> { - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> { +impl IntoDiagnostic<'_, !> for LayoutError<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { let mut diag = handler.struct_fatal(""); match self { @@ -1126,8 +1126,8 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> { } } -impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> { - fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> { +impl IntoDiagnostic<'_, !> for FnAbiError<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { handler.struct_fatal(self.to_string()) } } From 0baac880fcddf4b63a1a1f8a9cd2cec3b984a45e Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Tue, 8 Nov 2022 20:32:09 +0100 Subject: [PATCH 216/221] Update compiler/rustc_codegen_llvm/src/back/archive.rs Co-authored-by: David Wood --- compiler/rustc_codegen_llvm/src/back/archive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 99c9b51a9cda..5c68abeb08ba 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -315,7 +315,7 @@ impl<'a> LlvmArchiveBuilder<'a> { let kind = kind .parse::() .map_err(|_| kind) - .unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind: kind })); + .unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind })); let mut additions = mem::take(&mut self.additions); let mut strings = Vec::new(); From 39895b071645f2c377e4a9a3c16f92bc5c93c807 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Wed, 9 Nov 2022 13:47:46 +0100 Subject: [PATCH 217/221] Add constructor for `Diagnostic` that takes `Vec<(DiagnosticMessage, Style)>` --- compiler/rustc_codegen_ssa/src/back/write.rs | 3 +-- compiler/rustc_errors/src/diagnostic.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index f0e2e43509f9..e3d28a1aca20 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1787,8 +1787,7 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { let handler = sess.diagnostic(); - let mut d = rustc_errors::Diagnostic::new(diag.lvl, String::new()); - d.message = diag.msg; + let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg); if let Some(code) = diag.code { d.code(code); } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b24814bfa387..0ee4c6e722fc 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -213,6 +213,21 @@ impl Diagnostic { Diagnostic::new_with_code(level, None, message) } + #[track_caller] + pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self { + Diagnostic { + level, + message: messages, + code: None, + span: MultiSpan::new(), + children: vec![], + suggestions: Ok(vec![]), + args: Default::default(), + sort_span: DUMMY_SP, + is_lint: false, + } + } + #[track_caller] pub fn new_with_code>( level: Level, From caada745d1461a49f99f381bd5856451a5408ab4 Mon Sep 17 00:00:00 2001 From: SLASHLogin Date: Wed, 9 Nov 2022 15:14:58 +0100 Subject: [PATCH 218/221] Add missing `emitted_at` to the `Diagnostic` --- compiler/rustc_errors/src/diagnostic.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 0ee4c6e722fc..43101bbb9d31 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -225,6 +225,7 @@ impl Diagnostic { args: Default::default(), sort_span: DUMMY_SP, is_lint: false, + emitted_at: DiagnosticLocation::caller(), } } From 014f7f4092da54315c4f4a781f2e8879a2372120 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Nov 2022 17:06:41 +0000 Subject: [PATCH 219/221] Remove some redundant arguments --- .../src/annotate_snippet_emitter_writer.rs | 1 - compiler/rustc_errors/src/emitter.rs | 13 +++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f14b8ee3254f..c450c276366e 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -52,7 +52,6 @@ impl Emitter for AnnotateSnippetEmitterWriter { let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.source_map, &mut primary_span, &mut children, &diag.level, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index b7b8fe3f25a0..94df0c03b954 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -314,7 +314,6 @@ pub trait Emitter: Translate { fn fix_multispans_in_extern_macros_and_render_macro_backtrace( &self, - source_map: &Option>, span: &mut MultiSpan, children: &mut Vec, level: &Level, @@ -340,7 +339,7 @@ pub trait Emitter: Translate { .collect(); if !backtrace { - self.fix_multispans_in_extern_macros(source_map, span, children); + self.fix_multispans_in_extern_macros(span, children); } self.render_multispans_macro_backtrace(span, children, backtrace); @@ -480,15 +479,13 @@ pub trait Emitter: Translate { // this will change the span to point at the use site. fn fix_multispans_in_extern_macros( &self, - source_map: &Option>, span: &mut MultiSpan, children: &mut Vec, ) { - let Some(source_map) = source_map else { return }; debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); - self.fix_multispan_in_extern_macros(source_map, span); + self.fix_multispan_in_extern_macros(span); for child in children.iter_mut() { - self.fix_multispan_in_extern_macros(source_map, &mut child.span); + self.fix_multispan_in_extern_macros(&mut child.span); } debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children); } @@ -496,7 +493,8 @@ pub trait Emitter: Translate { // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. // Since these locations are often difficult to read, // we move these spans from the external macros to their corresponding use site. - fn fix_multispan_in_extern_macros(&self, source_map: &Lrc, span: &mut MultiSpan) { + fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) { + let Some(source_map) = self.source_map() else { return }; // First, find all the spans in external macros and point instead at their use site. let replacements: Vec<(Span, Span)> = span .primary_spans() @@ -544,7 +542,6 @@ impl Emitter for EmitterWriter { debug!("emit_diagnostic: suggestions={:?}", suggestions); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.sm, &mut primary_span, &mut children, &diag.level, From 21ce58732bc70a1696e31219ca5f2c0c25860798 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 11 Nov 2022 14:45:18 +0000 Subject: [PATCH 220/221] Don't add message that will never be shown to users It will still be used in json, as seen by the ui test changes --- .../src/traits/error_reporting/suggestions.rs | 4 ++-- src/test/ui/iterators/collect-into-array.rs | 1 - src/test/ui/iterators/collect-into-array.stderr | 2 +- src/test/ui/iterators/collect-into-slice.rs | 2 -- src/test/ui/iterators/collect-into-slice.stderr | 6 +++--- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index aece4ab79228..02e880a8e6e9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2445,12 +2445,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { (Ok(l), Ok(r)) => l.line == r.line, _ => true, }; - if !ident.span.overlaps(span) && !same_line { + if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line { multispan.push_span_label(ident.span, "required by a bound in this"); } } let descr = format!("required by a bound in `{}`", item_name); - if span != DUMMY_SP { + if !span.is_dummy() { let msg = format!("required by this bound in `{}`", item_name); multispan.push_span_label(span, msg); err.span_note(multispan, &descr); diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs index 7d35da825328..4c424999b754 100644 --- a/src/test/ui/iterators/collect-into-array.rs +++ b/src/test/ui/iterators/collect-into-array.rs @@ -1,5 +1,4 @@ fn main() { - //~^ NOTE required by a bound in this let whatever: [u32; 10] = (0..10).collect(); //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()` diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr index 7fe9707e6d23..a23a36a88abb 100644 --- a/src/test/ui/iterators/collect-into-array.stderr +++ b/src/test/ui/iterators/collect-into-array.stderr @@ -1,5 +1,5 @@ error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator - --> $DIR/collect-into-array.rs:3:31 + --> $DIR/collect-into-array.rs:2:31 | LL | let whatever: [u32; 10] = (0..10).collect(); | ^^^^^^^ ------- required by a bound introduced by this call diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs index 5eade075613f..09832c260d04 100644 --- a/src/test/ui/iterators/collect-into-slice.rs +++ b/src/test/ui/iterators/collect-into-slice.rs @@ -1,6 +1,4 @@ fn process_slice(data: &[i32]) { - //~^ NOTE required by a bound in this - //~| NOTE required by a bound in this todo!() } diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr index bce40118bdfa..bc152467ce3a 100644 --- a/src/test/ui/iterators/collect-into-slice.stderr +++ b/src/test/ui/iterators/collect-into-slice.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/collect-into-slice.rs:8:9 + --> $DIR/collect-into-slice.rs:6:9 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -9,7 +9,7 @@ LL | let some_generated_vec = (0..10).collect(); = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/collect-into-slice.rs:8:38 + --> $DIR/collect-into-slice.rs:6:38 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ doesn't have a size known at compile-time @@ -22,7 +22,7 @@ LL | fn collect>(self) -> B | ^ required by this bound in `collect` error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size - --> $DIR/collect-into-slice.rs:8:30 + --> $DIR/collect-into-slice.rs:6:30 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ ------- required by a bound introduced by this call From df2adc4760a1c03096ab4b39512ba90b983c2332 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 4 Nov 2022 16:04:47 +0000 Subject: [PATCH 221/221] Print all labels, even if they have no span. Fall back to main item's span. --- .../locales/en-US/passes.ftl | 5 +- compiler/rustc_errors/src/emitter.rs | 47 ++++++++++++---- compiler/rustc_passes/src/check_attr.rs | 55 ++++++++++++++----- compiler/rustc_passes/src/errors.rs | 3 + compiler/rustc_resolve/src/diagnostics.rs | 10 ++-- .../rustc_resolve/src/late/diagnostics.rs | 18 +++--- src/test/ui/asm/naked-invalid-attr.stderr | 2 +- ...43106-gating-of-builtin-attrs-error.stderr | 6 +- .../issue-43106-gating-of-builtin-attrs.rs | 2 +- ...issue-43106-gating-of-builtin-attrs.stderr | 8 +-- .../issue-69396-const-no-type-in-macro.stderr | 5 +- 11 files changed, 110 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index 5239ff9dc057..001e53d1d0e4 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -47,7 +47,10 @@ passes_no_coverage_not_coverable = passes_should_be_applied_to_fn = attribute should be applied to a function definition - .label = not a function definition + .label = {$on_crate -> + [true] cannot be applied to crates + *[false] not a function definition + } passes_naked_tracked_caller = cannot use `#[track_caller]` with `#[naked]` diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 94df0c03b954..55c7997a5136 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2210,22 +2210,45 @@ impl FileWithAnnotatedLines { if let Some(ref sm) = emitter.source_map() { for span_label in msp.span_labels() { + let fixup_lo_hi = |span: Span| { + let lo = sm.lookup_char_pos(span.lo()); + let mut hi = sm.lookup_char_pos(span.hi()); + + // Watch out for "empty spans". If we get a span like 6..6, we + // want to just display a `^` at 6, so convert that to + // 6..7. This is degenerate input, but it's best to degrade + // gracefully -- and the parser likes to supply a span like + // that for EOF, in particular. + + if lo.col_display == hi.col_display && lo.line == hi.line { + hi.col_display += 1; + } + (lo, hi) + }; + if span_label.span.is_dummy() { + if let Some(span) = msp.primary_span() { + // if we don't know where to render the annotation, emit it as a note + // on the primary span. + + let (lo, hi) = fixup_lo_hi(span); + + let ann = Annotation { + start_col: lo.col_display, + end_col: hi.col_display, + is_primary: span_label.is_primary, + label: span_label + .label + .as_ref() + .map(|m| emitter.translate_message(m, args).to_string()), + annotation_type: AnnotationType::Singleline, + }; + add_annotation_to_file(&mut output, lo.file, lo.line, ann); + } continue; } - let lo = sm.lookup_char_pos(span_label.span.lo()); - let mut hi = sm.lookup_char_pos(span_label.span.hi()); - - // Watch out for "empty spans". If we get a span like 6..6, we - // want to just display a `^` at 6, so convert that to - // 6..7. This is degenerate input, but it's best to degrade - // gracefully -- and the parser likes to supply a span like - // that for EOF, in particular. - - if lo.col_display == hi.col_display && lo.line == hi.line { - hi.col_display += 1; - } + let (lo, hi) = fixup_lo_hi(span_label.span); if lo.line != hi.line { let ml = MultilineAnnotation { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 27a57adf964a..0c34b0e1bf3f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -119,13 +119,13 @@ impl CheckAttrVisitor<'_> { } sym::naked => self.check_naked(hir_id, attr, span, target), sym::rustc_legacy_const_generics => { - self.check_rustc_legacy_const_generics(&attr, span, target, item) + self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item) } sym::rustc_lint_query_instability => { - self.check_rustc_lint_query_instability(&attr, span, target) + self.check_rustc_lint_query_instability(hir_id, &attr, span, target) } sym::rustc_lint_diagnostics => { - self.check_rustc_lint_diagnostics(&attr, span, target) + self.check_rustc_lint_diagnostics(hir_id, &attr, span, target) } sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target), sym::rustc_lint_opt_deny_field_access => { @@ -135,7 +135,9 @@ impl CheckAttrVisitor<'_> { | sym::rustc_dirty | sym::rustc_if_this_changed | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), - sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target), + sym::cmse_nonsecure_entry => { + self.check_cmse_nonsecure_entry(hir_id, attr, span, target) + } sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target), sym::const_trait => self.check_const_trait(attr, span, target), sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), @@ -386,6 +388,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -393,7 +396,13 @@ impl CheckAttrVisitor<'_> { } /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition. - fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_cmse_nonsecure_entry( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, @@ -401,6 +410,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -465,9 +475,11 @@ impl CheckAttrVisitor<'_> { true } _ => { - self.tcx - .sess - .emit_err(errors::TrackedCallerWrongLocation { attr_span, defn_span: span }); + self.tcx.sess.emit_err(errors::TrackedCallerWrongLocation { + attr_span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); false } } @@ -576,6 +588,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -1240,7 +1253,7 @@ impl CheckAttrVisitor<'_> { UNUSED_ATTRIBUTES, hir_id, attr.span, - errors::Cold { span }, + errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID }, ); } } @@ -1376,6 +1389,7 @@ impl CheckAttrVisitor<'_> { /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, @@ -1386,6 +1400,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); return false; } @@ -1450,12 +1465,19 @@ impl CheckAttrVisitor<'_> { /// Helper function for checking that the provided attribute is only applied to a function or /// method. - fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_applied_to_fn_or_method( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { let is_function = matches!(target, Target::Fn | Target::Method(..)); if !is_function { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } else { @@ -1467,17 +1489,24 @@ impl CheckAttrVisitor<'_> { /// or method. fn check_rustc_lint_query_instability( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, ) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or /// method. - fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + fn check_rustc_lint_diagnostics( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1dbf0d642e2a..c6cd69add28a 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -81,6 +81,7 @@ pub struct AttrShouldBeAppliedToFn { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -97,6 +98,7 @@ pub struct TrackedCallerWrongLocation { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -367,6 +369,7 @@ pub struct MustNotSuspend { pub struct Cold { #[label] pub span: Span, + pub on_crate: bool, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7961e3f1194e..a12918b29799 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -241,10 +241,12 @@ impl<'a> Resolver<'a> { )); err.span_label(span, format!("`{}` re{} here", name, new_participle)); - err.span_label( - self.session.source_map().guess_head_span(old_binding.span), - format!("previous {} of the {} `{}` here", old_noun, old_kind, name), - ); + if !old_binding.span.is_dummy() && old_binding.span != span { + err.span_label( + self.session.source_map().guess_head_span(old_binding.span), + format!("previous {} of the {} `{}` here", old_noun, old_kind, name), + ); + } // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a1338dcd4771..346024bb5984 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -806,14 +806,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.code(rustc_errors::error_code!(E0411)); err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); if let Some(item_kind) = self.diagnostic_metadata.current_item { - err.span_label( - item_kind.ident.span, - format!( - "`Self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), - ); + if !item_kind.ident.span.is_dummy() { + err.span_label( + item_kind.ident.span, + format!( + "`Self` not allowed in {} {}", + item_kind.kind.article(), + item_kind.kind.descr() + ), + ); + } } true } diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr index 58344be93346..e8ddccc854ab 100644 --- a/src/test/ui/asm/naked-invalid-attr.stderr +++ b/src/test/ui/asm/naked-invalid-attr.stderr @@ -36,7 +36,7 @@ error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:5:1 | LL | #![naked] - | ^^^^^^^^^ + | ^^^^^^^^^ cannot be applied to crates error: aborting due to 5 previous errors diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 5a645cf4ef98..787670404218 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -110,19 +110,19 @@ error: attribute should be applied to an `extern crate` item --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 | LL | #![no_link] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ not an `extern crate` item error: attribute should be applied to a free function, impl method or static --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1 | LL | #![export_name = "2200"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1 | LL | #![inline] - | ^^^^^^^^^^ + | ^^^^^^^^^^ not a function or closure error: `macro_export` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 8db12e55d25c..1fa315f3d215 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -1,6 +1,6 @@ //~ NOTE not a function //~| NOTE not a foreign function or static -//~| NOTE not a function or static +//~| NOTE cannot be applied to crates //~| NOTE not an `extern` block // This test enumerates as many compiler-builtin ungated attributes as // possible (that is, all the mutually compatible ones), and checks diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 310d1f720eb7..30039267979f 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -403,7 +403,7 @@ warning: attribute should be applied to a function definition --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 | LL | #![cold] - | ^^^^^^^^ + | ^^^^^^^^ cannot be applied to crates | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -411,7 +411,7 @@ warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 | LL | #![link()] - | ^^^^^^^^^^ + | ^^^^^^^^^^ not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -419,7 +419,7 @@ warning: attribute should be applied to a foreign function or static --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 | LL | #![link_name = "1900"] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -427,7 +427,7 @@ warning: attribute should be applied to a function or static --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 | LL | #![link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr index f581429a2815..89aeafebac49 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -2,10 +2,7 @@ error[E0428]: the name `A` is defined multiple times --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13 | LL | const A = "A".$fn(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | `A` redefined here - | previous definition of the value `A` here + | ^^^^^^^^^^^^^^^^^^^^ `A` redefined here ... LL | / suite! { LL | | len;