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
This commit is contained in:
commit
56dee7c49e
25 changed files with 391 additions and 123 deletions
1
.mailmap
1
.mailmap
|
@ -72,6 +72,7 @@ Daniel Ramos <dan@daramos.com>
|
||||||
David Klein <david.klein@baesystemsdetica.com>
|
David Klein <david.klein@baesystemsdetica.com>
|
||||||
David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au>
|
David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au>
|
||||||
David Ross <daboross@daboross.net>
|
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>
|
Derek Chiang <derekchiang93@gmail.com> Derek Chiang (Enchi Jiang) <derekchiang93@gmail.com>
|
||||||
Diggory Hardy <diggory.hardy@gmail.com> Diggory Hardy <github@dhardy.name>
|
Diggory Hardy <diggory.hardy@gmail.com> Diggory Hardy <github@dhardy.name>
|
||||||
Donough Liu <ldm2993593805@163.com> <donoughliu@gmail.com>
|
Donough Liu <ldm2993593805@163.com> <donoughliu@gmail.com>
|
||||||
|
|
|
@ -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:
|
Erroneous code example:
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
|
SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
|
||||||
WrongNumberOfTypeArgumentsToInstrinsic,
|
WrongNumberOfGenericArgumentsToIntrinsic,
|
||||||
};
|
};
|
||||||
use crate::require_same_types;
|
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_hir as hir;
|
||||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
|
@ -21,36 +21,45 @@ fn equate_intrinsic_type<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
it: &hir::ForeignItem<'_>,
|
it: &hir::ForeignItem<'_>,
|
||||||
n_tps: usize,
|
n_tps: usize,
|
||||||
|
n_lts: usize,
|
||||||
sig: ty::PolyFnSig<'tcx>,
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
) {
|
) {
|
||||||
match it.kind {
|
let (own_counts, span) = match &it.kind {
|
||||||
hir::ForeignItemKind::Fn(..) => {}
|
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")
|
struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function")
|
||||||
.span_label(it.span, "expected a function")
|
.span_label(it.span, "expected a function")
|
||||||
.emit();
|
.emit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|
||||||
span,
|
|
||||||
found: i_n_tps,
|
|
||||||
expected: n_tps,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
/// 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();
|
let split: Vec<&str> = name_str.split('_').collect();
|
||||||
assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(n_tps, inputs, output, hir::Unsafety::Unsafe)
|
(n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
|
||||||
} else {
|
} else {
|
||||||
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
|
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
|
||||||
let (n_tps, inputs, output) = match 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;
|
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 = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
|
||||||
let sig = ty::Binder::bind_with_vars(sig, bound_vars);
|
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.
|
/// Type-check `extern "platform-intrinsic" { ... }` functions.
|
||||||
|
@ -472,5 +481,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
|
||||||
Abi::PlatformIntrinsic,
|
Abi::PlatformIntrinsic,
|
||||||
);
|
);
|
||||||
let sig = ty::Binder::dummy(sig);
|
let sig = ty::Binder::dummy(sig);
|
||||||
equate_intrinsic_type(tcx, it, n_tps, sig)
|
equate_intrinsic_type(tcx, it, n_tps, 0, sig)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,15 @@ pub struct UnrecognizedAtomicOperation<'a> {
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0094"]
|
#[error = "E0094"]
|
||||||
pub struct WrongNumberOfTypeArgumentsToInstrinsic {
|
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||||
#[message = "intrinsic has wrong number of type \
|
#[message = "intrinsic has wrong number of {descr} \
|
||||||
parameters: found {found}, expected {expected}"]
|
parameters: found {found}, expected {expected}"]
|
||||||
#[label = "expected {expected} type parameter"]
|
#[label = "expected {expected} {descr} parameter{expected_pluralize}"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub found: usize,
|
pub found: usize,
|
||||||
pub expected: usize,
|
pub expected: usize,
|
||||||
|
pub expected_pluralize: &'a str,
|
||||||
|
pub descr: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
|
|
|
@ -5,35 +5,6 @@ use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::slice;
|
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)]
|
#[repr(C)]
|
||||||
pub struct Buffer<T: Copy> {
|
pub struct Buffer<T: Copy> {
|
||||||
data: *mut T,
|
data: *mut T,
|
||||||
|
|
|
@ -217,26 +217,6 @@ impl<T> Mutex<T> {
|
||||||
data: UnsafeCell::new(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> {
|
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.
|
/// Determines whether the mutex is poisoned.
|
||||||
///
|
///
|
||||||
/// If another thread is active, the mutex can still become poisoned at any
|
/// If another thread is active, the mutex can still become poisoned at any
|
||||||
|
|
|
@ -219,6 +219,7 @@ crate fn get_index_search_type<'tcx>(
|
||||||
fn get_index_type(clean_type: &clean::Type) -> RenderType {
|
fn get_index_type(clean_type: &clean::Type) -> RenderType {
|
||||||
RenderType {
|
RenderType {
|
||||||
name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()),
|
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.
|
/// 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
|
/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
|
||||||
|
|
|
@ -96,6 +96,7 @@ crate struct IndexItem {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
crate struct RenderType {
|
crate struct RenderType {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
generics: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Full type of functions/methods in the search index.
|
/// Full type of functions/methods in the search index.
|
||||||
|
@ -149,7 +150,13 @@ impl Serialize for TypeWithKind {
|
||||||
where
|
where
|
||||||
S: Serializer,
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ function levenshtein(s1, s2) {
|
||||||
window.initSearch = function(rawSearchIndex) {
|
window.initSearch = function(rawSearchIndex) {
|
||||||
var MAX_LEV_DISTANCE = 3;
|
var MAX_LEV_DISTANCE = 3;
|
||||||
var MAX_RESULTS = 200;
|
var MAX_RESULTS = 200;
|
||||||
var GENERICS_DATA = 1;
|
var GENERICS_DATA = 2;
|
||||||
var NAME = 0;
|
var NAME = 0;
|
||||||
var INPUTS_DATA = 0;
|
var INPUTS_DATA = 0;
|
||||||
var OUTPUT_DATA = 1;
|
var OUTPUT_DATA = 1;
|
||||||
|
@ -306,6 +306,9 @@ window.initSearch = function(rawSearchIndex) {
|
||||||
var elems = Object.create(null);
|
var elems = Object.create(null);
|
||||||
var elength = obj[GENERICS_DATA].length;
|
var elength = obj[GENERICS_DATA].length;
|
||||||
for (var x = 0; x < elength; ++x) {
|
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;
|
elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
|
||||||
}
|
}
|
||||||
var total = 0;
|
var total = 0;
|
||||||
|
@ -354,10 +357,13 @@ window.initSearch = function(rawSearchIndex) {
|
||||||
if (literalSearch) {
|
if (literalSearch) {
|
||||||
if (val.generics && val.generics.length !== 0) {
|
if (val.generics && val.generics.length !== 0) {
|
||||||
if (obj.length > GENERICS_DATA &&
|
if (obj.length > GENERICS_DATA &&
|
||||||
obj[GENERICS_DATA].length >= val.generics.length) {
|
obj[GENERICS_DATA].length > 0) {
|
||||||
var elems = Object.create(null);
|
var elems = Object.create(null);
|
||||||
len = obj[GENERICS_DATA].length;
|
len = obj[GENERICS_DATA].length;
|
||||||
for (x = 0; x < len; ++x) {
|
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;
|
elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,26 +381,23 @@ window.initSearch = function(rawSearchIndex) {
|
||||||
if (allFound) {
|
if (allFound) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
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 {
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (literalSearch) {
|
||||||
// Names didn't match so let's check if one of the generic types could.
|
if ((!val.generics || val.generics.length === 0) &&
|
||||||
if (literalSearch) {
|
obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
|
||||||
if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
|
|
||||||
return obj[GENERICS_DATA].some(
|
return obj[GENERICS_DATA].some(
|
||||||
function(name) {
|
function(name) {
|
||||||
return name === val.name;
|
return name === val.name;
|
||||||
|
@ -1167,7 +1170,48 @@ window.initSearch = function(rawSearchIndex) {
|
||||||
return ret;
|
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 = {
|
var results = {
|
||||||
"in_args": [],
|
"in_args": [],
|
||||||
"returned": [],
|
"returned": [],
|
||||||
|
|
7
src/test/rustdoc-js-std/alias-4.js
Normal file
7
src/test/rustdoc-js-std/alias-4.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
const QUERY = '<';
|
||||||
|
|
||||||
|
const EXPECTED = {
|
||||||
|
'others': [
|
||||||
|
{ 'name': 'Ord' },
|
||||||
|
],
|
||||||
|
};
|
23
src/test/rustdoc-js/generics-trait.js
Normal file
23
src/test/rustdoc-js/generics-trait.js
Normal file
|
@ -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' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
8
src/test/rustdoc-js/generics-trait.rs
Normal file
8
src/test/rustdoc-js/generics-trait.rs
Normal file
|
@ -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 {} }
|
44
src/test/rustdoc-js/generics.js
Normal file
44
src/test/rustdoc-js/generics.js
Normal file
|
@ -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': [],
|
||||||
|
},
|
||||||
|
];
|
21
src/test/rustdoc-js/generics.rs
Normal file
21
src/test/rustdoc-js/generics.rs
Normal file
|
@ -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 {} }
|
|
@ -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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() {}
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
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();
|
LL | NonConst.func();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
|
@ -1,4 +1,5 @@
|
||||||
#![feature(const_trait_impl)]
|
// revisions: stock gated
|
||||||
|
#![cfg_attr(gated, feature(const_trait_impl))]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
// aux-build: cross-crate.rs
|
// aux-build: cross-crate.rs
|
||||||
|
@ -15,6 +16,7 @@ const fn const_context() {
|
||||||
NonConst.func();
|
NonConst.func();
|
||||||
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
Const.func();
|
Const.func();
|
||||||
|
//[stock]~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
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();
|
LL | NonConst.func();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
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();
|
LL | Const.func();
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
39
src/test/ui/rfc-2632-const-trait-impl/staged-api.rs
Normal file
39
src/test/ui/rfc-2632-const-trait-impl/staged-api.rs
Normal file
|
@ -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() {}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
19
src/test/ui/simd-intrinsic/issue-85855.rs
Normal file
19
src/test/ui/simd-intrinsic/issue-85855.rs
Normal file
|
@ -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
|
||||||
|
}
|
21
src/test/ui/simd-intrinsic/issue-85855.stderr
Normal file
21
src/test/ui/simd-intrinsic/issue-85855.stderr
Normal file
|
@ -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`.
|
|
@ -4,7 +4,7 @@ allow-unauthenticated = [
|
||||||
"D-*",
|
"D-*",
|
||||||
"requires-nightly",
|
"requires-nightly",
|
||||||
"regression-*",
|
"regression-*",
|
||||||
"perf-regression",
|
"perf-*",
|
||||||
# I-* without I-nominated
|
# I-* without I-nominated
|
||||||
"I-*", "!I-nominated",
|
"I-*", "!I-nominated",
|
||||||
"AsyncAwait-OnDeck",
|
"AsyncAwait-OnDeck",
|
||||||
|
|
Loading…
Add table
Reference in a new issue