Auto merge of #91539 - matthiaskrgr:rollup-rnl10yb, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #89642 (environ on macos uses directly libc which has the correct signature.) - #90022 (Explain why `Self` is invalid in generic parameters) - #90023 (Postpone the evaluation of constant expressions that depend on inference variables) - #91215 (Implement VecDeque::retain_mut) - #91355 (std: Stabilize the `thread_local_const_init` feature) - #91528 (LLVM support .insn directive) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5e93f6e318
@ -1,5 +1,6 @@
|
||||
use crate::infer::type_variable::TypeVariableOriginKind;
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::rustc_middle::ty::TypeFoldable;
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Namespace};
|
||||
@ -400,36 +401,75 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
GenericArgKind::Const(ct) => {
|
||||
if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
|
||||
let origin =
|
||||
self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
|
||||
if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
|
||||
origin.kind
|
||||
{
|
||||
return InferenceDiagnosticsData {
|
||||
name: name.to_string(),
|
||||
span: Some(origin.span),
|
||||
kind: UnderspecifiedArgKind::Const { is_parameter: true },
|
||||
parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
|
||||
};
|
||||
}
|
||||
match ct.val {
|
||||
ty::ConstKind::Infer(InferConst::Var(vid)) => {
|
||||
let origin = self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table()
|
||||
.probe_value(vid)
|
||||
.origin;
|
||||
if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
|
||||
origin.kind
|
||||
{
|
||||
return InferenceDiagnosticsData {
|
||||
name: name.to_string(),
|
||||
span: Some(origin.span),
|
||||
kind: UnderspecifiedArgKind::Const { is_parameter: true },
|
||||
parent: InferenceDiagnosticsParentData::for_def_id(
|
||||
self.tcx, def_id,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
debug_assert!(!origin.span.is_dummy());
|
||||
let mut s = String::new();
|
||||
let mut printer =
|
||||
ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
|
||||
if let Some(highlight) = highlight {
|
||||
printer.region_highlight_mode = highlight;
|
||||
debug_assert!(!origin.span.is_dummy());
|
||||
let mut s = String::new();
|
||||
let mut printer =
|
||||
ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
|
||||
if let Some(highlight) = highlight {
|
||||
printer.region_highlight_mode = highlight;
|
||||
}
|
||||
let _ = ct.print(printer);
|
||||
InferenceDiagnosticsData {
|
||||
name: s,
|
||||
span: Some(origin.span),
|
||||
kind: UnderspecifiedArgKind::Const { is_parameter: false },
|
||||
parent: None,
|
||||
}
|
||||
}
|
||||
let _ = ct.print(printer);
|
||||
InferenceDiagnosticsData {
|
||||
name: s,
|
||||
span: Some(origin.span),
|
||||
kind: UnderspecifiedArgKind::Const { is_parameter: false },
|
||||
parent: None,
|
||||
ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
substs_: Some(substs), ..
|
||||
}) => {
|
||||
assert!(substs.has_infer_types_or_consts());
|
||||
|
||||
// FIXME: We only use the first inference variable we encounter in
|
||||
// `substs` here, this gives insufficiently informative diagnostics
|
||||
// in case there are multiple inference variables
|
||||
for s in substs.iter() {
|
||||
match s.unpack() {
|
||||
GenericArgKind::Type(t) => match t.kind() {
|
||||
ty::Infer(_) => {
|
||||
return self.extract_inference_diagnostics_data(s, None);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
GenericArgKind::Const(c) => match c.val {
|
||||
ty::ConstKind::Infer(InferConst::Var(_)) => {
|
||||
return self.extract_inference_diagnostics_data(s, None);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
bug!(
|
||||
"expected an inference variable in substs of unevaluated const {:?}",
|
||||
ct
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
bug!("unexpect const: {:?}", ct);
|
||||
}
|
||||
} else {
|
||||
bug!("unexpect const: {:?}", ct);
|
||||
}
|
||||
}
|
||||
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
|
||||
|
@ -21,6 +21,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
|
||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::mir::interpret::EvalToConstValueResult;
|
||||
use rustc_middle::traits::select;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
@ -1584,13 +1585,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
unevaluated: ty::Unevaluated<'tcx>,
|
||||
span: Option<Span>,
|
||||
) -> EvalToConstValueResult<'tcx> {
|
||||
let mut original_values = OriginalQueryValues::default();
|
||||
let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values);
|
||||
let mut substs = unevaluated.substs(self.tcx);
|
||||
substs = self.resolve_vars_if_possible(substs);
|
||||
|
||||
// Postpone the evaluation of constants whose substs depend on inference
|
||||
// variables
|
||||
if substs.has_infer_types_or_consts() {
|
||||
return Err(ErrorHandled::TooGeneric);
|
||||
}
|
||||
|
||||
let param_env_erased = self.tcx.erase_regions(param_env);
|
||||
let substs_erased = self.tcx.erase_regions(substs);
|
||||
|
||||
let unevaluated = ty::Unevaluated {
|
||||
def: unevaluated.def,
|
||||
substs_: Some(substs_erased),
|
||||
promoted: unevaluated.promoted,
|
||||
};
|
||||
|
||||
let (param_env, unevaluated) = canonical.value;
|
||||
// The return value is the evaluated value which doesn't contain any reference to inference
|
||||
// variables, thus we don't need to substitute back the original values.
|
||||
self.tcx.const_eval_resolve(param_env, unevaluated, span)
|
||||
self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
|
||||
}
|
||||
|
||||
/// If `typ` is a type variable of some kind, resolve it one level
|
||||
|
@ -51,7 +51,6 @@
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(thread_local_const_init)]
|
||||
#![feature(trusted_step)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_reserve_kind)]
|
||||
|
@ -92,6 +92,19 @@ impl<'a> Parser<'a> {
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let param =
|
||||
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
|
||||
if this.eat_keyword_noexpect(kw::SelfUpper) {
|
||||
// `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing
|
||||
// as if `Self` never existed.
|
||||
this.struct_span_err(
|
||||
this.prev_token.span,
|
||||
"unexpected keyword `Self` in generic parameters",
|
||||
)
|
||||
.note("you cannot use `Self` as a generic parameter because it is reserved for associated items")
|
||||
.emit();
|
||||
|
||||
this.eat(&token::Comma);
|
||||
}
|
||||
|
||||
let param = if this.check_lifetime() {
|
||||
let lifetime = this.expect_lifetime();
|
||||
// Parse lifetime parameter.
|
||||
|
@ -5,7 +5,6 @@
|
||||
#![feature(iter_zip)]
|
||||
#![feature(let_else)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(thread_local_const_init)]
|
||||
#![feature(extern_types)]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -20,7 +20,6 @@
|
||||
#![feature(negative_impls)]
|
||||
#![feature(nll)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(thread_local_const_init)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -2148,6 +2148,37 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
pub fn retain<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
self.retain_mut(|elem| f(elem));
|
||||
}
|
||||
|
||||
/// Retains only the elements specified by the predicate.
|
||||
///
|
||||
/// In other words, remove all elements `e` such that `f(&e)` returns false.
|
||||
/// This method operates in place, visiting each element exactly once in the
|
||||
/// original order, and preserves the order of the retained elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(vec_retain_mut)]
|
||||
///
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut buf = VecDeque::new();
|
||||
/// buf.extend(1..5);
|
||||
/// buf.retain_mut(|x| if *x % 2 == 0 {
|
||||
/// *x += 1;
|
||||
/// true
|
||||
/// } else {
|
||||
/// false
|
||||
/// });
|
||||
/// assert_eq!(buf, [3, 5]);
|
||||
/// ```
|
||||
#[unstable(feature = "vec_retain_mut", issue = "90829")]
|
||||
pub fn retain_mut<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
let len = self.len();
|
||||
let mut idx = 0;
|
||||
@ -2155,7 +2186,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
|
||||
// Stage 1: All values are retained.
|
||||
while cur < len {
|
||||
if !f(&self[cur]) {
|
||||
if !f(&mut self[cur]) {
|
||||
cur += 1;
|
||||
break;
|
||||
}
|
||||
@ -2164,7 +2195,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
}
|
||||
// Stage 2: Swap retained value into current idx.
|
||||
while cur < len {
|
||||
if !f(&self[cur]) {
|
||||
if !f(&mut self[cur]) {
|
||||
cur += 1;
|
||||
continue;
|
||||
}
|
||||
@ -2173,7 +2204,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
cur += 1;
|
||||
idx += 1;
|
||||
}
|
||||
// Stage 3: Trancate all values after idx.
|
||||
// Stage 3: Truncate all values after idx.
|
||||
if cur != idx {
|
||||
self.truncate(idx);
|
||||
}
|
||||
|
@ -216,10 +216,7 @@
|
||||
// std may use features in a platform-specific way
|
||||
#![allow(unused_features)]
|
||||
#![feature(rustc_allow_const_fn_unstable)]
|
||||
#![cfg_attr(
|
||||
test,
|
||||
feature(internal_output_capture, print_internals, update_panic_count, thread_local_const_init)
|
||||
)]
|
||||
#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))]
|
||||
#![cfg_attr(
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
feature(slice_index_methods, coerce_unsized, sgx_platform)
|
||||
|
@ -473,10 +473,7 @@ impl Iterator for Env {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
extern "C" {
|
||||
fn _NSGetEnviron() -> *mut *const *const c_char;
|
||||
}
|
||||
_NSGetEnviron()
|
||||
libc::_NSGetEnviron() as *mut *const *const c_char
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
|
@ -178,7 +178,6 @@ macro_rules! __thread_local_inner {
|
||||
(@key $t:ty, const $init:expr) => {{
|
||||
#[cfg_attr(not(windows), inline)] // see comments below
|
||||
unsafe fn __getit() -> $crate::option::Option<&'static $t> {
|
||||
const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local();
|
||||
const INIT_EXPR: $t = $init;
|
||||
|
||||
// wasm without atomics maps directly to `static mut`, and dtors
|
||||
|
@ -204,13 +204,6 @@ pub use self::local::os::Key as __OsLocalKeyInner;
|
||||
#[doc(hidden)]
|
||||
pub use self::local::statik::Key as __StaticLocalKeyInner;
|
||||
|
||||
// This is only used to make thread locals with `const { .. }` initialization
|
||||
// expressions unstable. If and/or when that syntax is stabilized with thread
|
||||
// locals this will simply be removed.
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "thread_local_const_init", issue = "84223")]
|
||||
pub const fn require_unstable_const_init_thread_local() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builder
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 01c8b654f9a01371414d1fd69cba38b289510a9e
|
||||
Subproject commit 2b9078f4afae82f60c5ac0fdb4af42d269e2f2f3
|
@ -1,5 +1,4 @@
|
||||
#![crate_type = "lib"]
|
||||
#![feature(thread_local_const_init)]
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
// ignore-android does not use #[thread_local]
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(thread_local_const_init)]
|
||||
|
||||
extern crate thread_local_aux as aux;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// run-pass
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
@ -22,8 +21,11 @@ where
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Test that we can correctly infer `T` which requires evaluating
|
||||
// `{ N + 1 }` which has substs containing an inference var
|
||||
// FIXME(generic_const_exprs): We can't correctly infer `T` which requires
|
||||
// evaluating `{ N + 1 }` which has substs containing an inference var
|
||||
let mut _q = Default::default();
|
||||
//~^ ERROR type annotations needed
|
||||
|
||||
_q = foo::<_, 2>(_q);
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/const_eval_resolve_canonical.rs:26:9
|
||||
|
|
||||
LL | let mut _q = Default::default();
|
||||
| ^^^^^^ consider giving `_q` a type
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/const_eval_resolve_canonical.rs:29:10
|
||||
|
|
||||
LL | _q = foo::<_, 2>(_q);
|
||||
| ^^^^^^^^^^^ cannot infer type
|
||||
|
|
||||
note: multiple `impl`s satisfying `(): Foo<{ N + 1 }>` found
|
||||
--> $DIR/const_eval_resolve_canonical.rs:8:1
|
||||
|
|
||||
LL | impl Foo<0> for () {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | impl Foo<3> for () {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/const_eval_resolve_canonical.rs:18:9
|
||||
|
|
||||
LL | fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc
|
||||
| --- required by a bound in this
|
||||
LL | where
|
||||
LL | (): Foo<{ N + 1 }>,
|
||||
| ^^^^^^^^^^^^^^ required by this bound in `foo`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0283.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
23
src/test/ui/const-generics/issues/issue-83249.rs
Normal file
23
src/test/ui/const-generics/issues/issue-83249.rs
Normal file
@ -0,0 +1,23 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
trait Foo {
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
impl Foo for u8 {
|
||||
const N: usize = 1;
|
||||
}
|
||||
|
||||
fn foo<T: Foo>(_: [u8; T::N]) -> T {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn bar() {
|
||||
let _: u8 = foo([0; 1]);
|
||||
|
||||
let _ = foo([0; 1]);
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
11
src/test/ui/const-generics/issues/issue-83249.stderr
Normal file
11
src/test/ui/const-generics/issues/issue-83249.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-83249.rs:19:13
|
||||
|
|
||||
LL | let _ = foo([0; 1]);
|
||||
| - ^^^ cannot infer type for type parameter `T` declared on the function `foo`
|
||||
| |
|
||||
| consider giving this pattern a type
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
69
src/test/ui/const-generics/issues/issue-83288.rs
Normal file
69
src/test/ui/const-generics/issues/issue-83288.rs
Normal file
@ -0,0 +1,69 @@
|
||||
// build-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
use std::{marker::PhantomData, ops::Mul};
|
||||
|
||||
pub enum Nil {}
|
||||
pub struct Cons<T, L> {
|
||||
_phantom: PhantomData<(T, L)>,
|
||||
}
|
||||
|
||||
pub trait Indices<const N: usize> {
|
||||
const RANK: usize;
|
||||
const NUM_ELEMS: usize;
|
||||
}
|
||||
|
||||
impl<const N: usize> Indices<N> for Nil {
|
||||
const RANK: usize = 0;
|
||||
const NUM_ELEMS: usize = 1;
|
||||
}
|
||||
|
||||
impl<T, I: Indices<N>, const N: usize> Indices<N> for Cons<T, I> {
|
||||
const RANK: usize = I::RANK + 1;
|
||||
const NUM_ELEMS: usize = I::NUM_ELEMS * N;
|
||||
}
|
||||
|
||||
pub trait Concat<J> {
|
||||
type Output;
|
||||
}
|
||||
|
||||
impl<J> Concat<J> for Nil {
|
||||
type Output = J;
|
||||
}
|
||||
|
||||
impl<T, I, J> Concat<J> for Cons<T, I>
|
||||
where
|
||||
I: Concat<J>,
|
||||
{
|
||||
type Output = Cons<T, <I as Concat<J>>::Output>;
|
||||
}
|
||||
|
||||
pub struct Tensor<I: Indices<N>, const N: usize>
|
||||
where
|
||||
[u8; I::NUM_ELEMS]: Sized,
|
||||
{
|
||||
pub data: [u8; I::NUM_ELEMS],
|
||||
_phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<I: Indices<N>, J: Indices<N>, const N: usize> Mul<Tensor<J, N>> for Tensor<I, N>
|
||||
where
|
||||
I: Concat<J>,
|
||||
<I as Concat<J>>::Output: Indices<N>,
|
||||
[u8; I::NUM_ELEMS]: Sized,
|
||||
[u8; J::NUM_ELEMS]: Sized,
|
||||
[u8; <I as Concat<J>>::Output::NUM_ELEMS]: Sized,
|
||||
{
|
||||
type Output = Tensor<<I as Concat<J>>::Output, N>;
|
||||
|
||||
fn mul(self, _rhs: Tensor<J, N>) -> Self::Output {
|
||||
Tensor {
|
||||
data: [0u8; <I as Concat<J>>::Output::NUM_ELEMS],
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
24
src/test/ui/const-generics/issues/issue-87470.rs
Normal file
24
src/test/ui/const-generics/issues/issue-87470.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// build-pass
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub trait TraitWithConst {
|
||||
const SOME_CONST: usize;
|
||||
}
|
||||
|
||||
pub trait OtherTrait: TraitWithConst {
|
||||
fn some_fn(self) -> [u8 ; <Self as TraitWithConst>::SOME_CONST];
|
||||
}
|
||||
|
||||
impl TraitWithConst for f32 {
|
||||
const SOME_CONST: usize = 32;
|
||||
}
|
||||
|
||||
impl OtherTrait for f32 {
|
||||
fn some_fn(self) -> [u8 ; <Self as TraitWithConst>::SOME_CONST] {
|
||||
[0; 32]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
29
src/test/ui/const-generics/issues/issue-87964.rs
Normal file
29
src/test/ui/const-generics/issues/issue-87964.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// build-pass
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub trait Target {
|
||||
const LENGTH: usize;
|
||||
}
|
||||
|
||||
|
||||
pub struct Container<T: Target>
|
||||
where
|
||||
[(); T::LENGTH]: Sized,
|
||||
{
|
||||
_target: T,
|
||||
}
|
||||
|
||||
impl<T: Target> Container<T>
|
||||
where
|
||||
[(); T::LENGTH]: Sized,
|
||||
{
|
||||
pub fn start(
|
||||
_target: T,
|
||||
) -> Container<T> {
|
||||
Container { _target }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
26
src/test/ui/const-generics/issues/issue-89146.rs
Normal file
26
src/test/ui/const-generics/issues/issue-89146.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// build-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
pub trait Foo {
|
||||
const SIZE: usize;
|
||||
|
||||
fn to_bytes(&self) -> [u8; Self::SIZE];
|
||||
}
|
||||
|
||||
pub fn bar<G: Foo>(a: &G) -> u8
|
||||
where
|
||||
[(); G::SIZE]: Sized,
|
||||
{
|
||||
deeper_bar(a)
|
||||
}
|
||||
|
||||
fn deeper_bar<G: Foo>(a: &G) -> u8
|
||||
where
|
||||
[(); G::SIZE]: Sized,
|
||||
{
|
||||
a.to_bytes()[0]
|
||||
}
|
||||
|
||||
fn main() {}
|
19
src/test/ui/const-generics/issues/issue-89320.rs
Normal file
19
src/test/ui/const-generics/issues/issue-89320.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// build-pass
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub trait Enumerable {
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SymmetricGroup<S>
|
||||
where
|
||||
S: Enumerable,
|
||||
[(); S::N]: Sized,
|
||||
{
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,4 +0,0 @@
|
||||
thread_local!(static X: u32 = const { 0 });
|
||||
//~^ ERROR: use of unstable library feature 'thread_local_const_init'
|
||||
|
||||
fn main() {}
|
@ -1,13 +0,0 @@
|
||||
error[E0658]: use of unstable library feature 'thread_local_const_init'
|
||||
--> $DIR/thread-local-const-init.rs:1:1
|
||||
|
|
||||
LL | thread_local!(static X: u32 = const { 0 });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #84223 <https://github.com/rust-lang/rust/issues/84223> for more information
|
||||
= help: add `#![feature(thread_local_const_init)]` to the crate attributes to enable
|
||||
= note: this error originates in the macro `$crate::__thread_local_inner` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,10 +1,10 @@
|
||||
// Regression test of #36638.
|
||||
|
||||
struct Foo<Self>(Self);
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
//~^^ ERROR E0392
|
||||
//~^ ERROR unexpected keyword `Self` in generic parameters
|
||||
//~| ERROR recursive type `Foo` has infinite size
|
||||
|
||||
trait Bar<Self> {}
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
//~^ ERROR unexpected keyword `Self` in generic parameters
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,24 +1,33 @@
|
||||
error: expected identifier, found keyword `Self`
|
||||
error: unexpected keyword `Self` in generic parameters
|
||||
--> $DIR/keyword-self-as-type-param.rs:3:12
|
||||
|
|
||||
LL | struct Foo<Self>(Self);
|
||||
| ^^^^ expected identifier, found keyword
|
||||
| ^^^^
|
||||
|
|
||||
= note: you cannot use `Self` as a generic parameter because it is reserved for associated items
|
||||
|
||||
error: expected identifier, found keyword `Self`
|
||||
error: unexpected keyword `Self` in generic parameters
|
||||
--> $DIR/keyword-self-as-type-param.rs:7:11
|
||||
|
|
||||
LL | trait Bar<Self> {}
|
||||
| ^^^^ expected identifier, found keyword
|
||||
| ^^^^
|
||||
|
|
||||
= note: you cannot use `Self` as a generic parameter because it is reserved for associated items
|
||||
|
||||
error[E0392]: parameter `Self` is never used
|
||||
--> $DIR/keyword-self-as-type-param.rs:3:12
|
||||
error[E0072]: recursive type `Foo` has infinite size
|
||||
--> $DIR/keyword-self-as-type-param.rs:3:1
|
||||
|
|
||||
LL | struct Foo<Self>(Self);
|
||||
| ^^^^ unused parameter
|
||||
| ^^^^^^^^^^^^^^^^^----^^
|
||||
| | |
|
||||
| | recursive without indirection
|
||||
| recursive type has infinite size
|
||||
|
|
||||
= help: consider removing `Self`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `Self` to be a const parameter, use `const Self: usize` instead
|
||||
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
||||
|
|
||||
LL | struct Foo<Self>(Box<Self>);
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0392`.
|
||||
For more information about this error, try `rustc --explain E0072`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user