diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1060f911a9ed4..b309a124e8089 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -918,12 +918,29 @@ fn generic_simd_intrinsic( } if let Some(stripped) = name_str.strip_prefix("simd_shuffle") { - let n: u64 = stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }); + // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. + // If there is no suffix, use the index array length. + let n: u64 = if stripped.is_empty() { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { + span_bug!(span, "could not evaluate shuffle index array length") + }) + } + _ => return_error!( + "simd_shuffle index must be an array of `u32`, got `{}`", + args[2].layout.ty + ), + } + } else { + stripped.parse().unwrap_or_else(|_| { + span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") + }) + }; require_simd!(ret_ty, "return"); - let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, diff --git a/compiler/rustc_error_codes/src/error_codes/E0439.md b/compiler/rustc_error_codes/src/error_codes/E0439.md index 3e663df866caa..24268aef2222a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0439.md +++ b/compiler/rustc_error_codes/src/error_codes/E0439.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + The length of the platform-intrinsic function `simd_shuffle` wasn't specified. Erroneous code example: -```compile_fail,E0439 +```ignore (no longer emitted) #![feature(platform_intrinsics)] extern "platform-intrinsic" { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c816d06045681..3eec1ae4c4da0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1211,6 +1211,7 @@ symbols! { simd_select_bitmask, simd_shl, simd_shr, + simd_shuffle, simd_sub, simd_trunc, simd_xor, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f5be8bf0949e6..8adf9015933c3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1487,10 +1487,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => false, (ParamCandidate(other), ParamCandidate(victim)) => { - let value_same_except_bound_vars = other.value.skip_binder() + let same_except_bound_vars = other.value.skip_binder() == victim.value.skip_binder() + && other.constness == victim.constness && !other.value.skip_binder().has_escaping_bound_vars(); - if value_same_except_bound_vars { + if same_except_bound_vars { // See issue #84398. In short, we can generate multiple ParamCandidates which are // the same except for unused bound vars. Just pick the one with the fewest bound vars // or the current one if tied (they should both evaluate to the same answer). This is diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index d578fac4cdb22..f4e3c8e0d9f7f 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1842,7 +1842,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_t ); err.span_label(field.span, "method, not a field"); - if !self.expr_in_place(expr.hir_id) { + let expr_is_call = + if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) = + self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id)) + { + expr.hir_id == callee.hir_id + } else { + false + }; + let expr_snippet = + self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new()); + if expr_is_call && expr_snippet.starts_with("(") && expr_snippet.ends_with(")") { + let after_open = expr.span.lo() + rustc_span::BytePos(1); + let before_close = expr.span.hi() - rustc_span::BytePos(1); + err.multipart_suggestion( + "remove wrapping parentheses to call the method", + vec![ + (expr.span.with_hi(after_open), String::new()), + (expr.span.with_lo(before_close), String::new()), + ], + Applicability::MachineApplicable, + ); + } else if !self.expr_in_place(expr.hir_id) { self.suggest_method_call( &mut err, "use parentheses to call the method", diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 664954b0eb7a2..ff7a26853b188 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -2,7 +2,7 @@ //! intrinsics that the compiler exposes. use crate::errors::{ - SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, + UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, WrongNumberOfGenericArgumentsToIntrinsic, }; use crate::require_same_types; @@ -468,6 +468,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_reduce_max | sym::simd_reduce_min_nanless | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), + sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)), name if name.as_str().starts_with("simd_shuffle") => { match name.as_str()["simd_shuffle".len()..].parse() { Ok(n) => { @@ -475,7 +476,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) (2, params, param(1)) } Err(_) => { - tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name }); + let msg = + format!("unrecognized platform-specific intrinsic function: `{}`", name); + tcx.sess.struct_span_err(it.span, &msg).emit(); return; } } diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 1e6a240b2f86d..47077779616c0 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -121,14 +121,6 @@ pub struct AssocTypeBindingNotAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[error = "E0439"] -pub struct SimdShuffleMissingLength { - #[message = "invalid `simd_shuffle`, needs length: `{name}`"] - pub span: Span, - pub name: Symbol, -} - #[derive(SessionDiagnostic)] #[error = "E0436"] pub struct FunctionalRecordUpdateOnNonStruct { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2adf6a549e641..e56b631dbaf8d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1916,7 +1916,8 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] - pub fn get_mut(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")] + pub const fn get_mut(&mut self) -> &mut T { &mut self.value } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index d12e86b7c1deb..386ffb384a81e 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -925,6 +925,11 @@ impl Step for RustdocGUI { .env("RUSTDOC", builder.rustdoc(self.compiler)) .env("RUSTC", builder.rustc(self.compiler)) .current_dir(path); + // FIXME: implement a `// compile-flags` command or similar + // instead of hard-coding this test + if entry.file_name() == "link_to_definition" { + cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition"); + } builder.run(&mut cargo); } } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index f9ddef4120bbe..eada8f4a04dae 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -217,7 +217,7 @@ a { color: #c5c5c5; } body.source .example-wrap pre.rust a { - background: #c5c5c5; + background: #333; } .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml index 00326e9bbc4cc..6fb92e196602e 100644 --- a/src/test/rustdoc-gui/code-sidebar-toggle.goml +++ b/src/test/rustdoc-gui/code-sidebar-toggle.goml @@ -1,5 +1,6 @@ goto: file://|DOC_PATH|/test_docs/index.html click: ".srclink" +wait-for: "#sidebar-toggle" click: "#sidebar-toggle" wait-for: 500 fail: true diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml new file mode 100644 index 0000000000000..3df899e0f2618 --- /dev/null +++ b/src/test/rustdoc-gui/jump-to-def-background.goml @@ -0,0 +1,23 @@ +// We check the background color on the jump to definition links in the source code page. +goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html + +// Set the theme to dark. +local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL) + +// Set the theme to ayu. +local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL) + +// Set the theme to light. +local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(238, 238, 238)"}, ALL) diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock new file mode 100644 index 0000000000000..e4b4e52d028e5 --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "link_to_definition" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml new file mode 100644 index 0000000000000..cdd294d74d3ae --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "link_to_definition" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/link_to_definition/lib.rs b/src/test/rustdoc-gui/src/link_to_definition/lib.rs new file mode 100644 index 0000000000000..de9ee66a2bad0 --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/lib.rs @@ -0,0 +1,6 @@ +pub struct Bar { + pub a: String, + pub b: u32, +} + +pub fn foo(_b: &Bar) {} diff --git a/src/test/ui/error-codes/E0439.rs b/src/test/ui/error-codes/E0439.rs deleted file mode 100644 index 86e9cb55a9c86..0000000000000 --- a/src/test/ui/error-codes/E0439.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439 -} - -fn main () { -} diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr deleted file mode 100644 index 8021f7d3951a8..0000000000000 --- a/src/test/ui/error-codes/E0439.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle` - --> $DIR/E0439.rs:4:5 - | -LL | fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0439`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index 7185376b440c8..cc24dbd96d253 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -16,12 +16,17 @@ impl const PartialEq for S { // This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const // bound. -// const fn equals_self(t: &T) -> bool { -// FIXME(fee1-dead)^ why should the order matter here? -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { *t == *t } -pub const EQ: bool = equals_self(&S); +trait A: PartialEq {} +impl A for T {} + +const fn equals_self2(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S) && equals_self2(&S); fn main() {} diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs new file mode 100644 index 0000000000000..9611780ac079e --- /dev/null +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs @@ -0,0 +1,33 @@ +// build-fail + +// Test that the simd_shuffle intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct Simd([T; N]); + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +fn main() { + const I: [u32; 2] = [0; 2]; + const I2: [f32; 2] = [0.; 2]; + let v = Simd::([0; 4]); + + unsafe { + let _: Simd = simd_shuffle(v, v, I); + + let _: Simd = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd = simd_shuffle(v, v, I2); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } +} diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr new file mode 100644 index 0000000000000..9eeb000fd261f --- /dev/null +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr @@ -0,0 +1,21 @@ +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4 + --> $DIR/simd-intrinsic-generic-shuffle.rs:24:31 + | +LL | let _: Simd = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd`), found `Simd` with element type `f32` + --> $DIR/simd-intrinsic-generic-shuffle.rs:27:31 + | +LL | let _: Simd = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]` + --> $DIR/simd-intrinsic-generic-shuffle.rs:30:31 + | +LL | let _: Simd = simd_shuffle(v, v, I2); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.rs b/src/test/ui/simd/shuffle-not-out-of-bounds.rs index 8a533453e75fd..aae6ce4663fba 100644 --- a/src/test/ui/simd/shuffle-not-out-of-bounds.rs +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.rs @@ -188,4 +188,14 @@ fn main() { 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); + + extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; + } + let v = u8x2(0, 0); + const I: [u32; 2] = [4, 4]; + unsafe { + let _: u8x2 = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } } diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr index 07253a4ae46bc..737fb5e6e51e2 100644 --- a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr @@ -71,6 +71,12 @@ LL | | 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) + --> $DIR/shuffle-not-out-of-bounds.rs:198:23 + | +LL | let _: u8x2 = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd/shuffle.rs b/src/test/ui/simd/shuffle.rs new file mode 100644 index 0000000000000..3592adfdc6ad1 --- /dev/null +++ b/src/test/ui/simd/shuffle.rs @@ -0,0 +1,24 @@ +//run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + const I1: [u32; 4] = [0, 2, 4, 6]; + const I2: [u32; 2] = [1, 5]; + let a = Simd::([0, 1, 2, 3]); + let b = Simd::([4, 5, 6, 7]); + unsafe { + let x: Simd = simd_shuffle(a, b, I1); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd = simd_shuffle(a, b, I2); + assert_eq!(y.0, [1, 5]); + } +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.fixed b/src/test/ui/typeck/issue-88803-call-expr-method.fixed new file mode 100644 index 0000000000000..19b96ecf3fc3a --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + a.unwrap() //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.rs b/src/test/ui/typeck/issue-88803-call-expr-method.rs new file mode 100644 index 0000000000000..a061994663749 --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap)() //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.stderr b/src/test/ui/typeck/issue-88803-call-expr-method.stderr new file mode 100644 index 0000000000000..dd717ed9416d3 --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.stderr @@ -0,0 +1,15 @@ +error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` + --> $DIR/issue-88803-call-expr-method.rs:7:12 + | +LL | (a.unwrap)() + | ^^^^^^ method, not a field + | +help: remove wrapping parentheses to call the method + | +LL - (a.unwrap)() +LL + a.unwrap() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`.