From 7b2befc27b2e65e0ffdd9e8280951e7349317e39 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Tue, 8 Jun 2021 20:38:43 +0200 Subject: [PATCH 1/9] Check the number of generic lifetime and const parameters of intrinsics --- .../src/error_codes/E0094.md | 3 +- compiler/rustc_typeck/src/check/intrinsic.rs | 86 +++++++++++++------ compiler/rustc_typeck/src/errors.rs | 8 +- src/test/ui/simd-intrinsic/issue-85855.rs | 20 +++++ src/test/ui/simd-intrinsic/issue-85855.stderr | 27 ++++++ 5 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/simd-intrinsic/issue-85855.rs create mode 100644 src/test/ui/simd-intrinsic/issue-85855.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 42baa65bf9faf..42cd2aa185315 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -1,4 +1,5 @@ -An invalid number of type parameters was given to an intrinsic function. +An invalid number of generic type, lifetime, or const parameters was +given to an intrinsic function. Erroneous code example: diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 5741b6824b5d7..7a7ecb06132b9 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -3,11 +3,11 @@ use crate::errors::{ SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, - WrongNumberOfTypeArgumentsToInstrinsic, + WrongNumberOfGenericArgumentsToInstrinsic, }; use crate::require_same_types; -use rustc_errors::struct_span_err; +use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::Subst; @@ -21,36 +21,68 @@ fn equate_intrinsic_type<'tcx>( tcx: TyCtxt<'tcx>, it: &hir::ForeignItem<'_>, n_tps: usize, + n_lts: usize, sig: ty::PolyFnSig<'tcx>, ) { - match it.kind { - hir::ForeignItemKind::Fn(..) => {} + let (gen_lts, gen_tys, gen_cns, span) = match &it.kind { + hir::ForeignItemKind::Fn(.., generics) => { + let mut gen_lts = 0; + let mut gen_tys = 0; + let mut gen_cns = 0; + + for param in generics.params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => { + gen_lts += 1; + } + hir::GenericParamKind::Type { .. } => { + gen_tys += 1; + } + hir::GenericParamKind::Const { .. } => { + gen_cns += 1; + } + } + } + + (gen_lts, gen_tys, gen_cns, generics.span) + } _ => { struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") .span_label(it.span, "expected a function") .emit(); return; } - } - - let i_n_tps = tcx.generics_of(it.def_id).own_counts().types; - if i_n_tps != n_tps { - let span = match it.kind { - hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span, - _ => bug!(), - }; + }; - tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic { + if gen_lts != n_lts { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { + span, + found: gen_lts, + expected: n_lts, + expected_pluralize: pluralize!(n_lts), + descr: "lifetime", + }); + } else if gen_tys != n_tps { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { span, - found: i_n_tps, + found: gen_tys, expected: n_tps, + expected_pluralize: pluralize!(n_tps), + descr: "type", }); - return; + } else if gen_cns != 0 { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { + span, + found: gen_cns, + expected: 0, + expected_pluralize: pluralize!(0), + descr: "const", + }); + } else { + let fty = tcx.mk_fn_ptr(sig); + let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); } - - let fty = tcx.mk_fn_ptr(sig); - let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); - require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); } /// Returns `true` if the given intrinsic is unsafe to call or not. @@ -121,7 +153,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }) }; - let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") { + let (n_tps, n_lts, inputs, output, unsafety) = if name_str.starts_with("atomic_") { let split: Vec<&str> = name_str.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); @@ -143,7 +175,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - (n_tps, inputs, output, hir::Unsafety::Unsafe) + (n_tps, 0, inputs, output, hir::Unsafety::Unsafe) } else { let unsafety = intrinsic_operation_unsafety(intrinsic_name); let (n_tps, inputs, output) = match intrinsic_name { @@ -372,11 +404,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - (n_tps, inputs, output, unsafety) + ( + n_tps, + if matches!(intrinsic_name, sym::va_copy) { 1 } else { 0 }, + inputs, + output, + unsafety, + ) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, n_lts, sig) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -472,5 +510,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) Abi::PlatformIntrinsic, ); let sig = ty::Binder::dummy(sig); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, 0, sig) } diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 5068242692ae8..bc686a025a650 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -24,13 +24,15 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(SessionDiagnostic)] #[error = "E0094"] -pub struct WrongNumberOfTypeArgumentsToInstrinsic { - #[message = "intrinsic has wrong number of type \ +pub struct WrongNumberOfGenericArgumentsToInstrinsic<'a> { + #[message = "intrinsic has wrong number of {descr} \ parameters: found {found}, expected {expected}"] - #[label = "expected {expected} type parameter"] + #[label = "expected {expected} {descr} parameter{expected_pluralize}"] pub span: Span, pub found: usize, pub expected: usize, + pub expected_pluralize: &'a str, + pub descr: &'a str, } #[derive(SessionDiagnostic)] diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd-intrinsic/issue-85855.rs new file mode 100644 index 0000000000000..61aa15be47f63 --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.rs @@ -0,0 +1,20 @@ +// Check that appropriate errors are reported if an intrinsic is defined +// with the wrong number of generic lifetime/type/const parameters, and +// that no ICE occurs in these cases. + +#![feature(platform_intrinsics)] +#![crate_type="lib"] + +extern "platform-intrinsic" { + fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of lifetime parameters + + fn simd_add<'a, T>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of lifetime parameters + + fn simd_sub(x: T, y: U); + //~^ ERROR: intrinsic has wrong number of type parameters + + fn simd_mul(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of const parameters +} diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd-intrinsic/issue-85855.stderr new file mode 100644 index 0000000000000..7dfdecb9520a7 --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.stderr @@ -0,0 +1,27 @@ +error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:9:27 + | +LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + | ^^^^^^^^^^^ expected 0 lifetime parameters + +error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:12:16 + | +LL | fn simd_add<'a, T>(x: T, y: T); + | ^^^^^^^ expected 0 lifetime parameters + +error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 + --> $DIR/issue-85855.rs:15:16 + | +LL | fn simd_sub(x: T, y: U); + | ^^^^^^ expected 1 type parameter + +error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:18:16 + | +LL | fn simd_mul(x: T, y: T); + | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0094`. From b24feb9d3b69206960e8cfb8e8c7fda3a2cd21a8 Mon Sep 17 00:00:00 2001 From: fee1-dead Date: Thu, 1 Jul 2021 10:05:37 +0800 Subject: [PATCH 2/9] Update mailmap for me --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 8cb74824d939a..831443fffe4b1 100644 --- a/.mailmap +++ b/.mailmap @@ -72,6 +72,7 @@ Daniel Ramos David Klein David Manescu David Ross +Deadbeef Derek Chiang Derek Chiang (Enchi Jiang) Diggory Hardy Diggory Hardy Donough Liu From b3a79832c0898969c322e262f2fddf4bf60be894 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 1 Jul 2021 17:24:45 +0800 Subject: [PATCH 3/9] Use revisions for cross-crate test --- .../cross-crate-feature-disabled.rs | 18 ------------------ ...enabled.stderr => cross-crate.gated.stderr} | 2 +- ...crate-feature-enabled.rs => cross-crate.rs} | 4 +++- ...isabled.stderr => cross-crate.stock.stderr} | 4 ++-- 4 files changed, 6 insertions(+), 22 deletions(-) delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.rs rename src/test/ui/rfc-2632-const-trait-impl/{cross-crate-feature-enabled.stderr => cross-crate.gated.stderr} (85%) rename src/test/ui/rfc-2632-const-trait-impl/{cross-crate-feature-enabled.rs => cross-crate.rs} (65%) rename src/test/ui/rfc-2632-const-trait-impl/{cross-crate-feature-disabled.stderr => cross-crate.stock.stderr} (82%) diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.rs deleted file mode 100644 index abd11d8b0e923..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.rs +++ /dev/null @@ -1,18 +0,0 @@ -// aux-build: cross-crate.rs -extern crate cross_crate; - -use cross_crate::*; - -fn non_const_context() { - NonConst.func(); - Const.func(); -} - -const fn const_context() { - NonConst.func(); - //~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants - Const.func(); - //~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants -} - -fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr similarity index 85% rename from src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.stderr rename to src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr index a544c0dd285fc..30baa38547580 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr @@ -1,5 +1,5 @@ error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/cross-crate-feature-enabled.rs:15:5 + --> $DIR/cross-crate.rs:16:5 | LL | NonConst.func(); | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs similarity index 65% rename from src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.rs rename to src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs index b79ccc7712ff2..c28ff63895841 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs @@ -1,4 +1,5 @@ -#![feature(const_trait_impl)] +// revisions: stock gated +#![cfg_attr(gated, feature(const_trait_impl))] #![allow(incomplete_features)] // aux-build: cross-crate.rs @@ -15,6 +16,7 @@ const fn const_context() { NonConst.func(); //~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants Const.func(); + //[stock]~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr similarity index 82% rename from src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.stderr rename to src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr index b86583b9e079f..e6a86f251ca3c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -1,11 +1,11 @@ error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/cross-crate-feature-disabled.rs:12:5 + --> $DIR/cross-crate.rs:16:5 | LL | NonConst.func(); | ^^^^^^^^^^^^^^^ error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/cross-crate-feature-disabled.rs:14:5 + --> $DIR/cross-crate.rs:18:5 | LL | Const.func(); | ^^^^^^^^^^^^ From ee9c614ecee7f6388cc2c694b2228bf0226585a9 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 1 Jul 2021 18:43:08 +0800 Subject: [PATCH 4/9] Test for const trait impls behind feature gates --- .../auxiliary/staged-api.rs | 22 +++++++++++ .../rfc-2632-const-trait-impl/staged-api.rs | 39 +++++++++++++++++++ .../staged-api.staged.stderr | 10 +++++ .../staged-api.stock.stderr | 18 +++++++++ 4 files changed, 89 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs new file mode 100644 index 0000000000000..734ce17001edd --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -0,0 +1,22 @@ +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait MyTrait { + #[stable(feature = "rust1", since = "1.0.0")] + fn func(); +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Unstable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "staged", issue = "none")] +impl const MyTrait for Unstable { + fn func() { + + } +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs new file mode 100644 index 0000000000000..39a1b6066dea3 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -0,0 +1,39 @@ +// revisions: stock staged +#![cfg_attr(staged, feature(staged))] + +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +// aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(staged, rustc_const_stable(feature = "rust1", since = "1.0.0"))] +// ^ should trigger error with or without the attribute +impl const MyTrait for Stable { + fn func() { //~ ERROR trait methods cannot be stable const fn + + } +} + +fn non_const_context() { + Unstable::func(); + Stable::func(); +} + +#[unstable(feature = "none", issue = "none")] +const fn const_context() { + Unstable::func(); + //[stock]~^ ERROR `::func` is not yet stable as a const fn + Stable::func(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr new file mode 100644 index 0000000000000..d2ff4ce200130 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr @@ -0,0 +1,10 @@ +error: trait methods cannot be stable const fn + --> $DIR/staged-api.rs:22:5 + | +LL | / fn func() { +LL | | +LL | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr new file mode 100644 index 0000000000000..91c5469bd90a5 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr @@ -0,0 +1,18 @@ +error: trait methods cannot be stable const fn + --> $DIR/staged-api.rs:22:5 + | +LL | / fn func() { +LL | | +LL | | } + | |_____^ + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:34:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(staged)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + From 07aa46e9e44a85bafd1acfc63887152968024b76 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Thu, 1 Jul 2021 14:56:24 +0200 Subject: [PATCH 5/9] Allow anyone to add or remove any label starting with perf- --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 4621adb2ba837..968b80414bcfe 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -4,7 +4,7 @@ allow-unauthenticated = [ "D-*", "requires-nightly", "regression-*", - "perf-regression", + "perf-*", # I-* without I-nominated "I-*", "!I-nominated", "AsyncAwait-OnDeck", From cedd2425b6ede6669f47794d85c67af1c43bd877 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 26 Jun 2021 12:00:26 -0700 Subject: [PATCH 6/9] fix(rustdoc): generics search This commit adds a test case for generics, re-adds generics data to the search index, and tweaks function indexing to use less space in JSON. This reverts commit 14ca89446c076bcf484d3d05bd991a4b7985a409. --- src/librustdoc/html/render/cache.rs | 18 ++++++ src/librustdoc/html/render/mod.rs | 9 ++- src/librustdoc/html/static/search.js | 80 +++++++++++++++++++++------ src/test/rustdoc-js-std/alias-4.js | 7 +++ src/test/rustdoc-js/generics-trait.js | 23 ++++++++ src/test/rustdoc-js/generics-trait.rs | 8 +++ src/test/rustdoc-js/generics.js | 44 +++++++++++++++ src/test/rustdoc-js/generics.rs | 21 +++++++ 8 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 src/test/rustdoc-js-std/alias-4.js create mode 100644 src/test/rustdoc-js/generics-trait.js create mode 100644 src/test/rustdoc-js/generics-trait.rs create mode 100644 src/test/rustdoc-js/generics.js create mode 100644 src/test/rustdoc-js/generics.rs diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 4372ece5c0105..0734d2670ccfa 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -219,6 +219,7 @@ crate fn get_index_search_type<'tcx>( fn get_index_type(clean_type: &clean::Type) -> RenderType { RenderType { name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()), + generics: get_generics(clean_type), } } @@ -251,6 +252,23 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option } } +/// Return a list of generic parameters for use in the search index. +/// +/// This function replaces bounds with types, so that `T where T: Debug` just becomes `Debug`. +/// It does return duplicates, and that's intentional, since search queries like `Result` +/// are supposed to match only results where both parameters are `usize`. +fn get_generics(clean_type: &clean::Type) -> Option> { + clean_type.generics().and_then(|types| { + let r = types + .iter() + .filter_map(|t| { + get_index_type_name(t, false).map(|name| name.as_str().to_ascii_lowercase()) + }) + .collect::>(); + if r.is_empty() { None } else { Some(r) } + }) +} + /// The point of this function is to replace bounds with types. /// /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option` will return diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6e73b2a5bef46..0583efa92ffad 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -96,6 +96,7 @@ crate struct IndexItem { #[derive(Debug)] crate struct RenderType { name: Option, + generics: Option>, } /// Full type of functions/methods in the search index. @@ -149,7 +150,13 @@ impl Serialize for TypeWithKind { where S: Serializer, { - (&self.ty.name, self.kind).serialize(serializer) + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.ty.name)?; + seq.serialize_element(&self.kind)?; + if let Some(generics) = &self.ty.generics { + seq.serialize_element(generics)?; + } + seq.end() } } diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/search.js index f6343e4c3d246..a7fc0b831f410 100644 --- a/src/librustdoc/html/static/search.js +++ b/src/librustdoc/html/static/search.js @@ -106,7 +106,7 @@ function levenshtein(s1, s2) { window.initSearch = function(rawSearchIndex) { var MAX_LEV_DISTANCE = 3; var MAX_RESULTS = 200; - var GENERICS_DATA = 1; + var GENERICS_DATA = 2; var NAME = 0; var INPUTS_DATA = 0; var OUTPUT_DATA = 1; @@ -306,6 +306,9 @@ window.initSearch = function(rawSearchIndex) { var elems = Object.create(null); var elength = obj[GENERICS_DATA].length; for (var x = 0; x < elength; ++x) { + if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) { + elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0; + } elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1; } var total = 0; @@ -354,10 +357,13 @@ window.initSearch = function(rawSearchIndex) { if (literalSearch) { if (val.generics && val.generics.length !== 0) { if (obj.length > GENERICS_DATA && - obj[GENERICS_DATA].length >= val.generics.length) { + obj[GENERICS_DATA].length > 0) { var elems = Object.create(null); len = obj[GENERICS_DATA].length; for (x = 0; x < len; ++x) { + if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) { + elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0; + } elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1; } @@ -375,26 +381,23 @@ window.initSearch = function(rawSearchIndex) { if (allFound) { return true; } - } else { - return false; } + return false; } return true; - } - // If the type has generics but don't match, then it won't return at this point. - // Otherwise, `checkGenerics` will return 0 and it'll return. - if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { - var tmp_lev = checkGenerics(obj, val); - if (tmp_lev <= MAX_LEV_DISTANCE) { - return tmp_lev; - } } else { - return 0; + // If the type has generics but don't match, then it won't return at this point. + // Otherwise, `checkGenerics` will return 0 and it'll return. + if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { + var tmp_lev = checkGenerics(obj, val); + if (tmp_lev <= MAX_LEV_DISTANCE) { + return tmp_lev; + } + } } - } - // Names didn't match so let's check if one of the generic types could. - if (literalSearch) { - if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { + } else if (literalSearch) { + if ((!val.generics || val.generics.length === 0) && + obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { return obj[GENERICS_DATA].some( function(name) { return name === val.name; @@ -1167,7 +1170,48 @@ window.initSearch = function(rawSearchIndex) { return ret; } - var queries = query.raw.split(","); + // Split search query by ",", while respecting angle bracket nesting. + // Since "<" is an alias for the Ord family of traits, it also uses + // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket. + // + // tokenizeQuery("A, D") == ["A", "D"] + // tokenizeQuery("A)/g; + var ret = []; + var start = 0; + for (i = 0; i < l; ++i) { + switch (raw[i]) { + case "<": + nextAngle.lastIndex = i + 1; + matched = nextAngle.exec(raw); + if (matched && matched[1] === '>') { + depth += 1; + } + break; + case ">": + if (depth > 0) { + depth -= 1; + } + break; + case ",": + if (depth === 0) { + ret.push(raw.substring(start, i)); + start = i + 1; + } + break; + } + } + if (start !== i) { + ret.push(raw.substring(start, i)); + } + return ret; + } + + var queries = tokenizeQuery(query.raw); var results = { "in_args": [], "returned": [], diff --git a/src/test/rustdoc-js-std/alias-4.js b/src/test/rustdoc-js-std/alias-4.js new file mode 100644 index 0000000000000..bf2bb4d2981fc --- /dev/null +++ b/src/test/rustdoc-js-std/alias-4.js @@ -0,0 +1,7 @@ +const QUERY = '<'; + +const EXPECTED = { + 'others': [ + { 'name': 'Ord' }, + ], +}; diff --git a/src/test/rustdoc-js/generics-trait.js b/src/test/rustdoc-js/generics-trait.js new file mode 100644 index 0000000000000..7876622435b60 --- /dev/null +++ b/src/test/rustdoc-js/generics-trait.js @@ -0,0 +1,23 @@ +const QUERY = [ + 'Result', + 'OtherThingxxxxxxxx', +]; + +const EXPECTED = [ + { + 'in_args': [ + { 'path': 'generics_trait', 'name': 'beta' }, + ], + 'returned': [ + { 'path': 'generics_trait', 'name': 'bet' }, + ], + }, + { + 'in_args': [ + { 'path': 'generics_trait', 'name': 'alpha' }, + ], + 'returned': [ + { 'path': 'generics_trait', 'name': 'alef' }, + ], + }, +]; diff --git a/src/test/rustdoc-js/generics-trait.rs b/src/test/rustdoc-js/generics-trait.rs new file mode 100644 index 0000000000000..20db117ccd5ce --- /dev/null +++ b/src/test/rustdoc-js/generics-trait.rs @@ -0,0 +1,8 @@ +pub trait SomeTrait {} +pub trait OtherThingxxxxxxxx {} + +pub fn alef() -> Result { loop {} } +pub fn bet() -> Result { loop {} } + +pub fn alpha(_param: Result) { loop {} } +pub fn beta(_param: Result) { loop {} } diff --git a/src/test/rustdoc-js/generics.js b/src/test/rustdoc-js/generics.js new file mode 100644 index 0000000000000..49a80ae2360f5 --- /dev/null +++ b/src/test/rustdoc-js/generics.js @@ -0,0 +1,44 @@ +// exact-check + +const QUERY = [ + '"R

"', + '"P"', + 'P', + '"ExtraCreditStructMulti"', +]; + +const EXPECTED = [ + { + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'others': [ + { 'path': 'generics', 'name': 'P' }, + ], + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'in_args': [ + { 'path': 'generics', 'name': 'extracreditlabhomework' }, + ], + 'returned': [], + }, +]; diff --git a/src/test/rustdoc-js/generics.rs b/src/test/rustdoc-js/generics.rs new file mode 100644 index 0000000000000..a0dc086e9f9cf --- /dev/null +++ b/src/test/rustdoc-js/generics.rs @@ -0,0 +1,21 @@ +pub struct P; +pub struct Q; +pub struct R(T); + +// returns test +pub fn alef() -> R

{ loop {} } +pub fn bet() -> R { loop {} } + +// in_args test +pub fn alpha(_x: R

) { loop {} } +pub fn beta(_x: R) { loop {} } + +// test case with multiple appearances of the same type +pub struct ExtraCreditStructMulti { t: T, u: U } +pub struct ExtraCreditInnerMulti {} +pub fn extracreditlabhomework( + _param: ExtraCreditStructMulti +) { loop {} } +pub fn redherringmatchforextracredit( + _param: ExtraCreditStructMulti +) { loop {} } From fe9334910998308f797207f05ed98beb37242973 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Thu, 1 Jul 2021 13:52:44 +0200 Subject: [PATCH 7/9] Minor adjustments and refactoring --- .../src/error_codes/E0094.md | 3 +- compiler/rustc_typeck/src/check/intrinsic.rs | 77 ++++++------------- compiler/rustc_typeck/src/errors.rs | 2 +- src/test/ui/simd-intrinsic/issue-85855.rs | 3 +- src/test/ui/simd-intrinsic/issue-85855.stderr | 12 +-- 5 files changed, 30 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 42cd2aa185315..ec86ec44ece8e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -1,5 +1,4 @@ -An invalid number of generic type, lifetime, or const parameters was -given to an intrinsic function. +An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 7a7ecb06132b9..38ace42618bfc 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -3,7 +3,7 @@ use crate::errors::{ SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, - WrongNumberOfGenericArgumentsToInstrinsic, + WrongNumberOfGenericArgumentsToIntrinsic, }; use crate::require_same_types; @@ -24,27 +24,10 @@ fn equate_intrinsic_type<'tcx>( n_lts: usize, sig: ty::PolyFnSig<'tcx>, ) { - let (gen_lts, gen_tys, gen_cns, span) = match &it.kind { + let (own_counts, span) = match &it.kind { hir::ForeignItemKind::Fn(.., generics) => { - let mut gen_lts = 0; - let mut gen_tys = 0; - let mut gen_cns = 0; - - for param in generics.params { - match param.kind { - hir::GenericParamKind::Lifetime { .. } => { - gen_lts += 1; - } - hir::GenericParamKind::Type { .. } => { - gen_tys += 1; - } - hir::GenericParamKind::Const { .. } => { - gen_cns += 1; - } - } - } - - (gen_lts, gen_tys, gen_cns, generics.span) + let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts(); + (own_counts, generics.span) } _ => { struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") @@ -54,31 +37,25 @@ fn equate_intrinsic_type<'tcx>( } }; - if gen_lts != n_lts { - tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { - span, - found: gen_lts, - expected: n_lts, - expected_pluralize: pluralize!(n_lts), - descr: "lifetime", - }); - } else if gen_tys != n_tps { - tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { - span, - found: gen_tys, - expected: n_tps, - expected_pluralize: pluralize!(n_tps), - descr: "type", - }); - } else if gen_cns != 0 { - tcx.sess.emit_err(WrongNumberOfGenericArgumentsToInstrinsic { - span, - found: gen_cns, - expected: 0, - expected_pluralize: pluralize!(0), - descr: "const", - }); - } else { + let gen_count_ok = |found: usize, expected: usize, descr: &str| -> bool { + if found != expected { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToIntrinsic { + span, + found, + expected, + expected_pluralize: pluralize!(expected), + descr, + }); + false + } else { + true + } + }; + + if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime") + && gen_count_ok(own_counts.types, n_tps, "type") + && gen_count_ok(own_counts.consts, 0, "const") + { let fty = tcx.mk_fn_ptr(sig); let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); @@ -404,13 +381,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - ( - n_tps, - if matches!(intrinsic_name, sym::va_copy) { 1 } else { 0 }, - inputs, - output, - unsafety, - ) + (n_tps, 0, inputs, output, unsafety) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index bc686a025a650..184a827a4f902 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -24,7 +24,7 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(SessionDiagnostic)] #[error = "E0094"] -pub struct WrongNumberOfGenericArgumentsToInstrinsic<'a> { +pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[message = "intrinsic has wrong number of {descr} \ parameters: found {found}, expected {expected}"] #[label = "expected {expected} {descr} parameter{expected_pluralize}"] diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd-intrinsic/issue-85855.rs index 61aa15be47f63..f276fbd669470 100644 --- a/src/test/ui/simd-intrinsic/issue-85855.rs +++ b/src/test/ui/simd-intrinsic/issue-85855.rs @@ -9,8 +9,7 @@ extern "platform-intrinsic" { fn simd_saturating_add<'a, T: 'a>(x: T, y: T); //~^ ERROR: intrinsic has wrong number of lifetime parameters - fn simd_add<'a, T>(x: T, y: T); - //~^ ERROR: intrinsic has wrong number of lifetime parameters + fn simd_add<'a, T>(x: T, y: T) -> T; fn simd_sub(x: T, y: U); //~^ ERROR: intrinsic has wrong number of type parameters diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd-intrinsic/issue-85855.stderr index 7dfdecb9520a7..fb2f1fbc5b1cc 100644 --- a/src/test/ui/simd-intrinsic/issue-85855.stderr +++ b/src/test/ui/simd-intrinsic/issue-85855.stderr @@ -4,24 +4,18 @@ error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expect LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); | ^^^^^^^^^^^ expected 0 lifetime parameters -error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 - --> $DIR/issue-85855.rs:12:16 - | -LL | fn simd_add<'a, T>(x: T, y: T); - | ^^^^^^^ expected 0 lifetime parameters - error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 - --> $DIR/issue-85855.rs:15:16 + --> $DIR/issue-85855.rs:14:16 | LL | fn simd_sub(x: T, y: U); | ^^^^^^ expected 1 type parameter error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 - --> $DIR/issue-85855.rs:18:16 + --> $DIR/issue-85855.rs:17:16 | LL | fn simd_mul(x: T, y: T); | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0094`. From 057bc913998fb9b057eb9723392b54f657c9ec4b Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 1 Jul 2021 12:04:41 -0500 Subject: [PATCH 8/9] Move Mutex::unlock to T: ?Sized --- library/std/src/sync/mutex.rs | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index e7c5479ab9bb6..e1d6324c17e33 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -217,26 +217,6 @@ impl Mutex { data: UnsafeCell::new(t), } } - - /// Immediately drops the guard, and consequently unlocks the mutex. - /// - /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. - /// Alternately, the guard will be automatically dropped when it goes out of scope. - /// - /// ``` - /// #![feature(mutex_unlock)] - /// - /// use std::sync::Mutex; - /// let mutex = Mutex::new(0); - /// - /// let mut guard = mutex.lock().unwrap(); - /// *guard += 20; - /// Mutex::unlock(guard); - /// ``` - #[unstable(feature = "mutex_unlock", issue = "81872")] - pub fn unlock(guard: MutexGuard<'_, T>) { - drop(guard); - } } impl Mutex { @@ -333,6 +313,26 @@ impl Mutex { } } + /// Immediately drops the guard, and consequently unlocks the mutex. + /// + /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. + /// Alternately, the guard will be automatically dropped when it goes out of scope. + /// + /// ``` + /// #![feature(mutex_unlock)] + /// + /// use std::sync::Mutex; + /// let mutex = Mutex::new(0); + /// + /// let mut guard = mutex.lock().unwrap(); + /// *guard += 20; + /// Mutex::unlock(guard); + /// ``` + #[unstable(feature = "mutex_unlock", issue = "81872")] + pub fn unlock(guard: MutexGuard<'_, T>) { + drop(guard); + } + /// Determines whether the mutex is poisoned. /// /// If another thread is active, the mutex can still become poisoned at any From 0b3fedc8df1c102a9a7ea7b345e8105e91676f93 Mon Sep 17 00:00:00 2001 From: Jade Date: Thu, 1 Jul 2021 10:20:57 -0700 Subject: [PATCH 9/9] proc_macro/bridge: Remove dead code Slice type See https://github.com/rust-lang/rust/pull/85390#discussion_r662464868 --- library/proc_macro/src/bridge/buffer.rs | 29 ------------------------- 1 file changed, 29 deletions(-) diff --git a/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs index 717201aef102b..d82669d3e2336 100644 --- a/library/proc_macro/src/bridge/buffer.rs +++ b/library/proc_macro/src/bridge/buffer.rs @@ -5,35 +5,6 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::slice; -#[repr(C)] -struct Slice<'a, T> { - data: &'a [T; 0], - len: usize, -} - -unsafe impl<'a, T: Sync> Sync for Slice<'a, T> {} -unsafe impl<'a, T: Sync> Send for Slice<'a, T> {} - -impl Copy for Slice<'a, T> {} -impl Clone for Slice<'a, T> { - fn clone(&self) -> Self { - *self - } -} - -impl From<&'a [T]> for Slice<'a, T> { - fn from(xs: &'a [T]) -> Self { - Slice { data: unsafe { &*(xs.as_ptr() as *const [T; 0]) }, len: xs.len() } - } -} - -impl Deref for Slice<'a, T> { - type Target = [T]; - fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } - } -} - #[repr(C)] pub struct Buffer { data: *mut T,