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:
bors 2021-12-05 00:38:01 +00:00
commit 5e93f6e318
27 changed files with 397 additions and 89 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(thread_local_const_init)]
#![feature(extern_types)]
#[macro_use]

View File

@ -20,7 +20,6 @@
#![feature(negative_impls)]
#![feature(nll)]
#![feature(min_specialization)]
#![feature(thread_local_const_init)]
#[macro_use]
extern crate rustc_macros;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,4 @@
#![crate_type = "lib"]
#![feature(thread_local_const_init)]
use std::cell::Cell;

View File

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

View File

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

View File

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

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

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

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

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

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

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

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

View File

@ -1,4 +0,0 @@
thread_local!(static X: u32 = const { 0 });
//~^ ERROR: use of unstable library feature 'thread_local_const_init'
fn main() {}

View File

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

View File

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

View File

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