about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-01 21:45:19 +0000
committerbors <bors@rust-lang.org>2021-07-01 21:45:19 +0000
commit56dee7c49ecdec4c2c9eccc6ff966cf58847bda6 (patch)
tree8b0ca08467f70bd8ecacca624c75303d5d3f7ad5
parent7100b311df0367c4d9067687573d1396b22411df (diff)
parent76bf7c006959ccdf2d161f9113a86491b98e7eae (diff)
downloadrust-56dee7c49ecdec4c2c9eccc6ff966cf58847bda6.tar.gz
rust-56dee7c49ecdec4c2c9eccc6ff966cf58847bda6.zip
Auto merge of #86791 - JohnTitor:rollup-96ltzpz, r=JohnTitor
Rollup of 7 pull requests

Successful merges:

 - #86148 (Check the number of generic lifetime and const parameters of intrinsics)
 - #86659 (fix(rustdoc): generics search)
 - #86768 (Add myself to mailmap)
 - #86775 (Test for const trait impls behind feature gates)
 - #86779 (Allow anyone to add or remove any label starting with perf-)
 - #86783 (Move Mutex::unlock to T: ?Sized)
 - #86785 (proc_macro/bridge: Remove dead code Slice type)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--.mailmap1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0094.md2
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs61
-rw-r--r--compiler/rustc_typeck/src/errors.rs8
-rw-r--r--library/proc_macro/src/bridge/buffer.rs29
-rw-r--r--library/std/src/sync/mutex.rs40
-rw-r--r--src/librustdoc/html/render/cache.rs18
-rw-r--r--src/librustdoc/html/render/mod.rs9
-rw-r--r--src/librustdoc/html/static/search.js80
-rw-r--r--src/test/rustdoc-js-std/alias-4.js7
-rw-r--r--src/test/rustdoc-js/generics-trait.js23
-rw-r--r--src/test/rustdoc-js/generics-trait.rs8
-rw-r--r--src/test/rustdoc-js/generics.js44
-rw-r--r--src/test/rustdoc-js/generics.rs21
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs22
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.rs18
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr (renamed from src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.stderr)2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs (renamed from src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-enabled.rs)4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr (renamed from src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.stderr)4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.rs39
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr18
-rw-r--r--src/test/ui/simd-intrinsic/issue-85855.rs19
-rw-r--r--src/test/ui/simd-intrinsic/issue-85855.stderr21
-rw-r--r--triagebot.toml2
25 files changed, 389 insertions, 121 deletions
diff --git a/.mailmap b/.mailmap
index 113feb3a8f5..5d9bc173364 100644
--- a/.mailmap
+++ b/.mailmap
@@ -72,6 +72,7 @@ Daniel Ramos <dan@daramos.com>
 David Klein <david.klein@baesystemsdetica.com>
 David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au>
 David Ross <daboross@daboross.net>
+Deadbeef <ent3rm4n@gmail.com> <fee1-dead-beef@protonmail.com>
 Derek Chiang <derekchiang93@gmail.com> Derek Chiang (Enchi Jiang) <derekchiang93@gmail.com>
 Diggory Hardy <diggory.hardy@gmail.com> Diggory Hardy <github@dhardy.name>
 Donough Liu <ldm2993593805@163.com> <donoughliu@gmail.com>
diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md
index 42baa65bf9f..ec86ec44ece 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0094.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0094.md
@@ -1,4 +1,4 @@
-An invalid number of type 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 a259fc6a488..a56aefcef9c 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,
+    WrongNumberOfGenericArgumentsToIntrinsic,
 };
 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,45 @@ 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 (own_counts, span) = match &it.kind {
+        hir::ForeignItemKind::Fn(.., generics) => {
+            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")
                 .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!(),
-        };
+    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
+        }
+    };
 
-        tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic {
-            span,
-            found: i_n_tps,
-            expected: n_tps,
-        });
-        return;
+    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);
     }
-
-    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 the unsafety of the given intrinsic.
@@ -121,7 +130,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 +152,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 +381,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 return;
             }
         };
-        (n_tps, 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);
-    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 +481,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 1a21c085d53..1e6a240b2f8 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 WrongNumberOfGenericArgumentsToIntrinsic<'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/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs
index 717201aef10..d82669d3e23 100644
--- a/library/proc_macro/src/bridge/buffer.rs
+++ b/library/proc_macro/src/bridge/buffer.rs
@@ -6,35 +6,6 @@ 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<T> Copy for Slice<'a, T> {}
-impl<T> Clone for Slice<'a, T> {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-
-impl<T> 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<T> 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<T: Copy> {
     data: *mut T,
     len: usize,
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index e7c5479ab9b..e1d6324c17e 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -217,26 +217,6 @@ impl<T> Mutex<T> {
             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<T: ?Sized> Mutex<T> {
@@ -333,6 +313,26 @@ impl<T: ?Sized> Mutex<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);
+    }
+
     /// Determines whether the mutex is poisoned.
     ///
     /// If another thread is active, the mutex can still become poisoned at any
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 4372ece5c01..0734d2670cc 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<usize, usize>`
+/// are supposed to match only results where both parameters are `usize`.
+fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
+    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::<Vec<_>>();
+        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<T>` will return
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 6e73b2a5bef..0583efa92ff 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<String>,
+    generics: Option<Vec<String>>,
 }
 
 /// 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 f6343e4c3d2..a7fc0b831f4 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<B, C>, D") == ["A<B, C>", "D"]
+        // tokenizeQuery("A<B, C, D") == ["A<B", "C", "D"]
+        function tokenizeQuery(raw) {
+            var i, matched;
+            var l = raw.length;
+            var depth = 0;
+            var nextAngle = /(<|>)/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 00000000000..bf2bb4d2981
--- /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 00000000000..7876622435b
--- /dev/null
+++ b/src/test/rustdoc-js/generics-trait.js
@@ -0,0 +1,23 @@
+const QUERY = [
+    'Result<SomeTrait>',
+    '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 00000000000..20db117ccd5
--- /dev/null
+++ b/src/test/rustdoc-js/generics-trait.rs
@@ -0,0 +1,8 @@
+pub trait SomeTrait {}
+pub trait OtherThingxxxxxxxx {}
+
+pub fn alef<T: OtherThingxxxxxxxx>() -> Result<T, ()> { loop {} }
+pub fn bet<T: SomeTrait>() -> Result<T, ()> { loop {} }
+
+pub fn alpha<T: OtherThingxxxxxxxx>(_param: Result<T, ()>) { loop {} }
+pub fn beta<T: SomeTrait>(_param: Result<T, ()>) { loop {} }
diff --git a/src/test/rustdoc-js/generics.js b/src/test/rustdoc-js/generics.js
new file mode 100644
index 00000000000..49a80ae2360
--- /dev/null
+++ b/src/test/rustdoc-js/generics.js
@@ -0,0 +1,44 @@
+// exact-check
+
+const QUERY = [
+  '"R<P>"',
+  '"P"',
+  'P',
+  '"ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>"',
+];
+
+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 00000000000..a0dc086e9f9
--- /dev/null
+++ b/src/test/rustdoc-js/generics.rs
@@ -0,0 +1,21 @@
+pub struct P;
+pub struct Q;
+pub struct R<T>(T);
+
+// returns test
+pub fn alef() -> R<P> { loop {} }
+pub fn bet() -> R<Q> { loop {} }
+
+// in_args test
+pub fn alpha(_x: R<P>) { loop {} }
+pub fn beta(_x: R<Q>) { loop {} }
+
+// test case with multiple appearances of the same type
+pub struct ExtraCreditStructMulti<T, U> { t: T, u: U }
+pub struct ExtraCreditInnerMulti {}
+pub fn extracreditlabhomework(
+    _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>
+) { loop {} }
+pub fn redherringmatchforextracredit(
+    _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ()>
+) { loop {} }
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 00000000000..734ce17001e
--- /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/cross-crate-feature-disabled.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate-feature-disabled.rs
deleted file mode 100644
index abd11d8b0e9..00000000000
--- 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
index a544c0dd285..30baa385475 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
index b79ccc7712f..c28ff638958 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
index b86583b9e07..e6a86f251ca 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();
    |     ^^^^^^^^^^^^
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 00000000000..39a1b6066de
--- /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 `<staged_api::Unstable as staged_api::MyTrait>::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 00000000000..d2ff4ce2001
--- /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 00000000000..91c5469bd90
--- /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: `<staged_api::Unstable as staged_api::MyTrait>::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
+
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 00000000000..f276fbd6694
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/issue-85855.rs
@@ -0,0 +1,19 @@
+// 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) -> T;
+
+    fn simd_sub<T, U>(x: T, y: U);
+    //~^ ERROR: intrinsic has wrong number of type parameters
+
+    fn simd_mul<T, const N: usize>(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 00000000000..fb2f1fbc5b1
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/issue-85855.stderr
@@ -0,0 +1,21 @@
+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 type parameters: found 2, expected 1
+  --> $DIR/issue-85855.rs:14:16
+   |
+LL |     fn simd_sub<T, U>(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:17:16
+   |
+LL |     fn simd_mul<T, const N: usize>(x: T, y: T);
+   |                ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0094`.
diff --git a/triagebot.toml b/triagebot.toml
index 4621adb2ba8..968b80414bc 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",