Skip to content

Commit

Permalink
Auto merge of rust-lang#91539 - matthiaskrgr:rollup-rnl10yb, r=matthi…
Browse files Browse the repository at this point in the history
…askrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#89642 (environ on macos uses directly libc which has the correct signature.)
 - rust-lang#90022 (Explain why `Self` is invalid in generic parameters)
 - rust-lang#90023 (Postpone the evaluation of constant expressions that depend on inference variables)
 - rust-lang#91215 (Implement VecDeque::retain_mut)
 - rust-lang#91355 (std: Stabilize the `thread_local_const_init` feature)
 - rust-lang#91528 (LLVM support .insn directive)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Dec 5, 2021
2 parents efec545 + 2ba5917 commit 5e93f6e
Show file tree
Hide file tree
Showing 27 changed files with 396 additions and 88 deletions.
92 changes: 66 additions & 26 deletions compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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(),
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;
}
let _ = ct.print(printer);
InferenceDiagnosticsData {
name: s,
span: Some(origin.span),
kind: UnderspecifiedArgKind::Const { is_parameter: true },
parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
};
kind: UnderspecifiedArgKind::Const { is_parameter: false },
parent: None,
}
}

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;
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
);
}
let _ = ct.print(printer);
InferenceDiagnosticsData {
name: s,
span: Some(origin.span),
kind: UnderspecifiedArgKind::Const { is_parameter: false },
parent: None,
_ => {
bug!("unexpect const: {:?}", ct);
}
} else {
bug!("unexpect const: {:?}", ct);
}
}
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
Expand Down
23 changes: 19 additions & 4 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_parse/src/parser/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_query_system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(thread_local_const_init)]
#![feature(extern_types)]

#[macro_use]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#![feature(negative_impls)]
#![feature(nll)]
#![feature(min_specialization)]
#![feature(thread_local_const_init)]

#[macro_use]
extern crate rustc_macros;
Expand Down
37 changes: 34 additions & 3 deletions library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2148,14 +2148,45 @@ 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;
let mut cur = 0;

// Stage 1: All values are retained.
while cur < len {
if !f(&self[cur]) {
if !f(&mut self[cur]) {
cur += 1;
break;
}
Expand All @@ -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;
}
Expand All @@ -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);
}
Expand Down
5 changes: 1 addition & 4 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 1 addition & 4 deletions library/std/src/sys/unix/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down
1 change: 0 additions & 1 deletion library/std/src/thread/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 0 additions & 7 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
////////////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 0 additions & 1 deletion src/test/codegen/auxiliary/thread_local_aux.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![crate_type = "lib"]
#![feature(thread_local_const_init)]

use std::cell::Cell;

Expand Down
1 change: 0 additions & 1 deletion src/test/codegen/thread-local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// run-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

Expand All @@ -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
}
Original file line number Diff line number Diff line change
@@ -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 changes: 23 additions & 0 deletions src/test/ui/const-generics/issues/issue-83249.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Loading

0 comments on commit 5e93f6e

Please sign in to comment.