Auto merge of - JohnTitor:rollup-96ltzpz, r=JohnTitor

Rollup of 7 pull requests

Successful merges:

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

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-07-01 21:45:19 +00:00
commit 56dee7c49e
25 changed files with 391 additions and 123 deletions

View file

@ -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>

View file

@ -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:

View file

@ -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)
} }

View file

@ -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)]

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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()
} }
} }

View file

@ -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": [],

View file

@ -0,0 +1,7 @@
const QUERY = '<';
const EXPECTED = {
'others': [
{ 'name': 'Ord' },
],
};

View 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' },
],
},
];

View 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 {} }

View 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': [],
},
];

View 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 {} }

View file

@ -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() {
}
}

View file

@ -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() {}

View file

@ -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();
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^

View file

@ -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() {}

View file

@ -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();
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^

View 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() {}

View file

@ -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

View file

@ -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

View 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
}

View 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`.

View file

@ -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",