From 6f09370028341778c07d822c2c59947bed30fa90 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 7 Oct 2021 20:47:17 +0100 Subject: [PATCH 1/9] environ on macos uses directly libc which has the correct signature. --- library/std/src/sys/unix/os.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 87893d26912..a596fc67671 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -472,10 +472,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"))] From a72dd4a5b973a3d94876ebea66e428fabaff00b0 Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Tue, 19 Oct 2021 01:31:23 +0900 Subject: [PATCH 2/9] Explain why `Self` is invalid in generic parameters --- compiler/rustc_parse/src/parser/generics.rs | 13 +++++++++ .../ui/keyword/keyword-self-as-type-param.rs | 6 ++-- .../keyword/keyword-self-as-type-param.stderr | 29 ++++++++++++------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index f175c5b50b3..ec7e3766566 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -89,6 +89,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. diff --git a/src/test/ui/keyword/keyword-self-as-type-param.rs b/src/test/ui/keyword/keyword-self-as-type-param.rs index 785d64ec8ea..55c7ac128ff 100644 --- a/src/test/ui/keyword/keyword-self-as-type-param.rs +++ b/src/test/ui/keyword/keyword-self-as-type-param.rs @@ -1,10 +1,10 @@ // Regression test of #36638. struct Foo(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 {} -//~^ ERROR expected identifier, found keyword `Self` +//~^ ERROR unexpected keyword `Self` in generic parameters fn main() {} diff --git a/src/test/ui/keyword/keyword-self-as-type-param.stderr b/src/test/ui/keyword/keyword-self-as-type-param.stderr index cc3df2e36f7..fd101b32b4c 100644 --- a/src/test/ui/keyword/keyword-self-as-type-param.stderr +++ b/src/test/ui/keyword/keyword-self-as-type-param.stderr @@ -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); - | ^^^^ 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 {} - | ^^^^ 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); - | ^^^^ 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(Box); + | ++++ + 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`. From 7530c43b79b8054924430e4cb643003aa273d79f Mon Sep 17 00:00:00 2001 From: b-naber Date: Mon, 18 Oct 2021 17:36:45 +0200 Subject: [PATCH 3/9] postpone evaluation of constants whose substs depend on inference vars or regions --- compiler/rustc_infer/src/infer/mod.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6b905f67e68..4873d3a6421 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -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,10 +1585,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { unevaluated: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - let mut original_values = OriginalQueryValues::default(); - let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values); + let param_env = self.tcx.erase_regions(param_env); + let mut substs = unevaluated.substs(self.tcx); + substs = self.tcx.erase_regions(substs); + 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 unevaluated = ty::Unevaluated { + def: unevaluated.def, + substs_: Some(substs), + 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) From 6000b4844a954879df51dafe95dc88239cb485a5 Mon Sep 17 00:00:00 2001 From: b-naber Date: Mon, 18 Oct 2021 18:25:45 +0200 Subject: [PATCH 4/9] add tests --- .../const_eval_resolve_canonical.rs | 7 +- .../const_eval_resolve_canonical.stderr | 9 +++ .../ui/const-generics/issues/issue-83249.rs | 23 +++++++ .../const-generics/issues/issue-83249.stderr | 22 ++++++ .../ui/const-generics/issues/issue-83288.rs | 69 +++++++++++++++++++ .../ui/const-generics/issues/issue-87470.rs | 24 +++++++ .../ui/const-generics/issues/issue-87964.rs | 29 ++++++++ .../ui/const-generics/issues/issue-89146.rs | 26 +++++++ .../ui/const-generics/issues/issue-89320.rs | 19 +++++ 9 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr create mode 100644 src/test/ui/const-generics/issues/issue-83249.rs create mode 100644 src/test/ui/const-generics/issues/issue-83249.stderr create mode 100644 src/test/ui/const-generics/issues/issue-83288.rs create mode 100644 src/test/ui/const-generics/issues/issue-87470.rs create mode 100644 src/test/ui/const-generics/issues/issue-87964.rs create mode 100644 src/test/ui/const-generics/issues/issue-89146.rs create mode 100644 src/test/ui/const-generics/issues/issue-89320.rs diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs index b79bc262d2b..bcb3e83b73a 100644 --- a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs +++ b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs @@ -1,4 +1,3 @@ -// run-pass #![feature(generic_const_exprs)] #![allow(incomplete_features)] @@ -22,8 +21,10 @@ 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); } diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr new file mode 100644 index 00000000000..75bca058e7c --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr @@ -0,0 +1,9 @@ +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: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/issues/issue-83249.rs b/src/test/ui/const-generics/issues/issue-83249.rs new file mode 100644 index 00000000000..65148c55ee5 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83249.rs @@ -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(_: [u8; T::N]) -> T { + todo!() +} + +pub fn bar() { + let _: u8 = foo([0; 1]); + + let _ = foo([0; 1]); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-83249.stderr b/src/test/ui/const-generics/issues/issue-83249.stderr new file mode 100644 index 00000000000..13914134eb2 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83249.stderr @@ -0,0 +1,22 @@ +error[E0283]: 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 + | + = note: cannot satisfy `_: Foo` +note: required by a bound in `foo` + --> $DIR/issue-83249.rs:12:11 + | +LL | fn foo(_: [u8; T::N]) -> T { + | ^^^ required by this bound in `foo` +help: consider specifying the type argument in the function call + | +LL | let _ = foo::([0; 1]); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/const-generics/issues/issue-83288.rs b/src/test/ui/const-generics/issues/issue-83288.rs new file mode 100644 index 00000000000..a24596d242e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83288.rs @@ -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 { + _phantom: PhantomData<(T, L)>, +} + +pub trait Indices { + const RANK: usize; + const NUM_ELEMS: usize; +} + +impl Indices for Nil { + const RANK: usize = 0; + const NUM_ELEMS: usize = 1; +} + +impl, const N: usize> Indices for Cons { + const RANK: usize = I::RANK + 1; + const NUM_ELEMS: usize = I::NUM_ELEMS * N; +} + +pub trait Concat { + type Output; +} + +impl Concat for Nil { + type Output = J; +} + +impl Concat for Cons +where + I: Concat, +{ + type Output = Cons>::Output>; +} + +pub struct Tensor, const N: usize> +where + [u8; I::NUM_ELEMS]: Sized, +{ + pub data: [u8; I::NUM_ELEMS], + _phantom: PhantomData, +} + +impl, J: Indices, const N: usize> Mul> for Tensor +where + I: Concat, + >::Output: Indices, + [u8; I::NUM_ELEMS]: Sized, + [u8; J::NUM_ELEMS]: Sized, + [u8; >::Output::NUM_ELEMS]: Sized, +{ + type Output = Tensor<>::Output, N>; + + fn mul(self, _rhs: Tensor) -> Self::Output { + Tensor { + data: [0u8; >::Output::NUM_ELEMS], + _phantom: PhantomData, + } + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-87470.rs b/src/test/ui/const-generics/issues/issue-87470.rs new file mode 100644 index 00000000000..d60181a418a --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87470.rs @@ -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 ; ::SOME_CONST]; +} + +impl TraitWithConst for f32 { + const SOME_CONST: usize = 32; +} + +impl OtherTrait for f32 { + fn some_fn(self) -> [u8 ; ::SOME_CONST] { + [0; 32] + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-87964.rs b/src/test/ui/const-generics/issues/issue-87964.rs new file mode 100644 index 00000000000..116686abb9e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87964.rs @@ -0,0 +1,29 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Target { + const LENGTH: usize; +} + + +pub struct Container +where + [(); T::LENGTH]: Sized, +{ + _target: T, +} + +impl Container +where + [(); T::LENGTH]: Sized, +{ + pub fn start( + _target: T, + ) -> Container { + Container { _target } + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-89146.rs b/src/test/ui/const-generics/issues/issue-89146.rs new file mode 100644 index 00000000000..e3540f46f1e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-89146.rs @@ -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(a: &G) -> u8 +where + [(); G::SIZE]: Sized, +{ + deeper_bar(a) +} + +fn deeper_bar(a: &G) -> u8 +where + [(); G::SIZE]: Sized, +{ + a.to_bytes()[0] +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-89320.rs b/src/test/ui/const-generics/issues/issue-89320.rs new file mode 100644 index 00000000000..afa5c8fab74 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-89320.rs @@ -0,0 +1,19 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Enumerable { + const N: usize; +} + +#[derive(Clone)] +pub struct SymmetricGroup +where + S: Enumerable, + [(); S::N]: Sized, +{ + _phantom: std::marker::PhantomData, +} + +fn main() {} From dae24073687fca6682c351379d41d61397e7c329 Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 5 Nov 2021 18:11:08 +0100 Subject: [PATCH 5/9] resolve variables before erasing lifetimes --- compiler/rustc_infer/src/infer/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4873d3a6421..5e687a7063c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1585,9 +1585,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { unevaluated: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - let param_env = self.tcx.erase_regions(param_env); let mut substs = unevaluated.substs(self.tcx); - substs = self.tcx.erase_regions(substs); substs = self.resolve_vars_if_possible(substs); // Postpone the evaluation of constants whose substs depend on inference @@ -1596,15 +1594,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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), + substs_: Some(substs_erased), promoted: unevaluated.promoted, }; // 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 From 37ed2db1e04e5b9dcdf833374d364b1f5e374fc3 Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 7 Nov 2021 22:38:33 +0100 Subject: [PATCH 6/9] consider unevaluated consts in extract_inference_diagnostics_data --- .../infer/error_reporting/need_type_info.rs | 94 +++++++++++++------ .../const_eval_resolve_canonical.rs | 1 + .../const_eval_resolve_canonical.stderr | 28 +++++- .../const-generics/issues/issue-83249.stderr | 15 +-- 4 files changed, 96 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index e00003face9..5b39897bc1d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -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}; @@ -390,36 +391,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"), diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs index bcb3e83b73a..18f33acaabb 100644 --- a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs +++ b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs @@ -27,4 +27,5 @@ fn main() { //~^ ERROR type annotations needed _q = foo::<_, 2>(_q); + //~^ ERROR type annotations needed } diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr index 75bca058e7c..e59f1ac8027 100644 --- a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr @@ -4,6 +4,30 @@ error[E0282]: type annotations needed LL | let mut _q = Default::default(); | ^^^^^^ consider giving `_q` a type -error: aborting due to previous error +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) -> <() as Foo<{ N + 1 }>>::Assoc + | --- required by a bound in this +LL | where +LL | (): Foo<{ N + 1 }>, + | ^^^^^^^^^^^^^^ required by this bound in `foo` -For more information about this error, try `rustc --explain E0282`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/issues/issue-83249.stderr b/src/test/ui/const-generics/issues/issue-83249.stderr index 13914134eb2..402b3aa2d61 100644 --- a/src/test/ui/const-generics/issues/issue-83249.stderr +++ b/src/test/ui/const-generics/issues/issue-83249.stderr @@ -1,22 +1,11 @@ -error[E0283]: type annotations needed +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 - | - = note: cannot satisfy `_: Foo` -note: required by a bound in `foo` - --> $DIR/issue-83249.rs:12:11 - | -LL | fn foo(_: [u8; T::N]) -> T { - | ^^^ required by this bound in `foo` -help: consider specifying the type argument in the function call - | -LL | let _ = foo::([0; 1]); - | +++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0282`. From 0466a1256f46fac36cbdfcabe08153c8d0763cbd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 25 Nov 2021 11:48:31 +0100 Subject: [PATCH 7/9] Implement VecDeque::retain_mut --- .../alloc/src/collections/vec_deque/mod.rs | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index de607c8fdab..18c945e1c06 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2148,6 +2148,37 @@ impl VecDeque { pub fn retain(&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(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, { let len = self.len(); let mut idx = 0; @@ -2155,7 +2186,7 @@ impl VecDeque { // 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 VecDeque { } // 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 VecDeque { cur += 1; idx += 1; } - // Stage 3: Trancate all values after idx. + // Stage 3: Truncate all values after idx. if cur != idx { self.truncate(idx); } From a0c959750abec28bb875be492c5f0532920a8907 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 29 Nov 2021 07:21:35 -0800 Subject: [PATCH 8/9] std: Stabilize the `thread_local_const_init` feature This commit is intended to follow the stabilization disposition of the FCP that has now finished in #84223. This stabilizes the ability to flag thread local initializers as `const` expressions which enables the macro to generate more efficient code for accessing it, notably removing runtime checks for initialization. More information can also be found in #84223 as well as the tests where the feature usage was removed in this PR. Closes #84223 --- compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_query_system/src/lib.rs | 1 - compiler/rustc_span/src/lib.rs | 1 - library/std/src/lib.rs | 5 +---- library/std/src/thread/local.rs | 1 - library/std/src/thread/mod.rs | 7 ------- src/test/codegen/auxiliary/thread_local_aux.rs | 1 - src/test/codegen/thread-local.rs | 1 - .../ui/feature-gates/thread-local-const-init.rs | 4 ---- .../ui/feature-gates/thread-local-const-init.stderr | 13 ------------- 10 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 src/test/ui/feature-gates/thread-local-const-init.rs delete mode 100644 src/test/ui/feature-gates/thread-local-const-init.stderr diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index b67ad8b770e..66d1ae1420a 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -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)] diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index b1295ba48cc..0da141f6836 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -5,7 +5,6 @@ #![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] -#![feature(thread_local_const_init)] #![feature(extern_types)] #[macro_use] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 66c01140abc..e06379caddd 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -20,7 +20,6 @@ #![feature(negative_impls)] #![feature(nll)] #![feature(min_specialization)] -#![feature(thread_local_const_init)] #[macro_use] extern crate rustc_macros; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 504c3b7e9f9..380de97407d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -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) diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 4da59577d78..ed0c47bc18f 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -164,7 +164,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 diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 343d3ef8dc5..64f6c7fa022 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -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 //////////////////////////////////////////////////////////////////////////////// diff --git a/src/test/codegen/auxiliary/thread_local_aux.rs b/src/test/codegen/auxiliary/thread_local_aux.rs index 29b5e3ca244..bebaa7754dd 100644 --- a/src/test/codegen/auxiliary/thread_local_aux.rs +++ b/src/test/codegen/auxiliary/thread_local_aux.rs @@ -1,5 +1,4 @@ #![crate_type = "lib"] -#![feature(thread_local_const_init)] use std::cell::Cell; diff --git a/src/test/codegen/thread-local.rs b/src/test/codegen/thread-local.rs index f14368e3990..5ac30d949fa 100644 --- a/src/test/codegen/thread-local.rs +++ b/src/test/codegen/thread-local.rs @@ -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; diff --git a/src/test/ui/feature-gates/thread-local-const-init.rs b/src/test/ui/feature-gates/thread-local-const-init.rs deleted file mode 100644 index 6584ffa7cf9..00000000000 --- a/src/test/ui/feature-gates/thread-local-const-init.rs +++ /dev/null @@ -1,4 +0,0 @@ -thread_local!(static X: u32 = const { 0 }); -//~^ ERROR: use of unstable library feature 'thread_local_const_init' - -fn main() {} diff --git a/src/test/ui/feature-gates/thread-local-const-init.stderr b/src/test/ui/feature-gates/thread-local-const-init.stderr deleted file mode 100644 index f80506831b4..00000000000 --- a/src/test/ui/feature-gates/thread-local-const-init.stderr +++ /dev/null @@ -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 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`. From ced26764889e027476ce09093026af51e0259b04 Mon Sep 17 00:00:00 2001 From: piegames Date: Thu, 18 Nov 2021 00:57:25 +0100 Subject: [PATCH 9/9] LLVM support .insn directive --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 01c8b654f9a..2b9078f4afa 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 01c8b654f9a01371414d1fd69cba38b289510a9e +Subproject commit 2b9078f4afae82f60c5ac0fdb4af42d269e2f2f3