diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 651f4c6fabd0e..f17c43ceaff73 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -568,10 +568,13 @@ impl Drop for DropType { } /// An arena which can be used to allocate any type. +/// +/// # Safety +/// /// Allocating in this arena is unsafe since the type system /// doesn't know which types it contains. In order to -/// allocate safely, you must store a PhantomData -/// alongside this arena for each type T you allocate. +/// allocate safely, you must store a `PhantomData` +/// alongside this arena for each type `T` you allocate. #[derive(Default)] pub struct DropArena { /// A list of destructors to run when the arena drops. @@ -589,7 +592,7 @@ impl DropArena { ptr::write(mem, object); let result = &mut *mem; // Record the destructor after doing the allocation as that may panic - // and would cause `object`'s destructor to run twice if it was recorded before + // and would cause `object`'s destructor to run twice if it was recorded before. self.destructors .borrow_mut() .push(DropType { drop_fn: drop_for_type::, obj: result as *mut T as *mut u8 }); @@ -607,16 +610,16 @@ impl DropArena { let start_ptr = self.arena.alloc_raw(Layout::array::(len).unwrap()) as *mut T; let mut destructors = self.destructors.borrow_mut(); - // Reserve space for the destructors so we can't panic while adding them + // Reserve space for the destructors so we can't panic while adding them. destructors.reserve(len); // Move the content to the arena by copying it and then forgetting - // the content of the SmallVec + // the content of the SmallVec. vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); mem::forget(vec.drain(..)); // Record the destructors after doing the allocation as that may panic - // and would cause `object`'s destructor to run twice if it was recorded before + // and would cause `object`'s destructor to run twice if it was recorded before. for i in 0..len { destructors .push(DropType { drop_fn: drop_for_type::, obj: start_ptr.add(i) as *mut u8 }); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 8801211d51bc3..4aa25aae74760 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -487,6 +487,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) } else if reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) { // LLVM doesn't recognize x30 "{lr}".to_string() + } else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) { + // LLVM doesn't recognize r14 + "{lr}".to_string() } else { format!("{{{}}}", reg.name()) } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 870b5c92d8983..c5d0927760b6a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1067,8 +1067,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn visit_expr(&mut self, expr: &mut P) { self.cfg.configure_expr(expr); visit_clobber(expr.deref_mut(), |mut expr| { - self.cfg.configure_expr_kind(&mut expr.kind); - if let Some(attr) = self.take_first_attr(&mut expr) { // Collect the invoc regardless of whether or not attributes are permitted here // expansion will eat the attribute so it won't error later. @@ -1166,8 +1164,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn filter_map_expr(&mut self, expr: P) -> Option> { let expr = configure!(self, expr); expr.filter_map(|mut expr| { - self.cfg.configure_expr_kind(&mut expr.kind); - if let Some(attr) = self.take_first_attr(&mut expr) { self.cfg.maybe_emit_expr_attr_err(&attr.0); @@ -1192,7 +1188,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } fn visit_pat(&mut self, pat: &mut P) { - self.cfg.configure_pat(pat); match pat.kind { PatKind::MacCall(_) => {} _ => return noop_visit_pat(pat, self), @@ -1406,15 +1401,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }); } - fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - self.cfg.configure_foreign_mod(foreign_mod); - noop_visit_foreign_mod(foreign_mod, self); - } - fn flat_map_foreign_item( &mut self, - mut foreign_item: P, + foreign_item: P, ) -> SmallVec<[P; 1]> { + let mut foreign_item = configure!(self, foreign_item); + if let Some(attr) = self.take_first_attr(&mut foreign_item) { return self .collect_attr( @@ -1439,11 +1431,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - fn visit_item_kind(&mut self, item: &mut ast::ItemKind) { - self.cfg.configure_item_kind(item); - noop_visit_item_kind(item, self); - } - fn flat_map_generic_param( &mut self, param: ast::GenericParam, @@ -1602,11 +1589,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { *id = self.cx.resolver.next_node_id() } } - - fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { - self.cfg.configure_fn_decl(&mut fn_decl); - noop_visit_fn_decl(fn_decl, self); - } } pub struct ExpansionConfig<'feat> { @@ -1614,9 +1596,8 @@ pub struct ExpansionConfig<'feat> { pub features: Option<&'feat Features>, pub recursion_limit: Limit, pub trace_mac: bool, - pub should_test: bool, // If false, strip `#[test]` nodes - pub keep_macs: bool, - pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span` + pub should_test: bool, // If false, strip `#[test]` nodes + pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span` pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics } @@ -1628,7 +1609,6 @@ impl<'feat> ExpansionConfig<'feat> { recursion_limit: Limit::new(1024), trace_mac: false, should_test: false, - keep_macs: false, span_debug: false, proc_macro_backtrace: false, } diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 3b722c04cb154..c5d8ff25ea94b 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(or_patterns)] diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index d040539cd7ea1..98682ba42959a 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -371,12 +371,4 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { } } } - - fn visit_mod(&mut self, module: &mut ast::Mod) { - noop_visit_mod(module, self); - // remove macro definitions - module.items.retain( - |item| !matches!(item.kind, ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs), - ); - } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 1546c1e559f57..074c9252481aa 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -639,6 +639,10 @@ struct QueryTypeRelatingDelegate<'a, 'tcx> { } impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.param_env + } + fn create_next_universe(&mut self) -> ty::UniverseIndex { self.infcx.create_next_universe() } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index e034ac5e8fd70..5e11932eafc4e 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -221,6 +221,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { /// As `3 + 4` contains `N` in its substs, this must not succeed. /// /// See `src/test/ui/const-generics/occurs-check/` for more examples where this is relevant. + #[instrument(level = "debug", skip(self))] fn unify_const_variable( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 97ef685cf6f82..e720a6f13086d 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -72,6 +72,8 @@ where } pub trait TypeRelatingDelegate<'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx>; + /// Push a constraint `sup: sub` -- this constraint must be /// satisfied for the two types to be related. `sub` and `sup` may /// be regions from the type or new variables created through the @@ -473,9 +475,8 @@ where self.infcx.tcx } - // FIXME(oli-obk): not sure how to get the correct ParamEnv fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::empty() + self.delegate.param_env() } fn tag(&self) -> &'static str { @@ -819,9 +820,8 @@ where self.infcx.tcx } - // FIXME(oli-obk): not sure how to get the correct ParamEnv fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::empty() + self.delegate.param_env() } fn tag(&self) -> &'static str { diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 0517ec5bb1a8c..3e7b93b32a6a5 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -31,6 +31,7 @@ impl<'tcx> TyCtxt<'tcx> { /// constant `bar::()` requires a substitution for `T`, if the substitution for `T` is still /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is /// returned. + #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 163b400973b7c..f34ee22860259 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -228,7 +228,10 @@ pub enum ObligationCauseCode<'tcx> { /// Inline asm operand type must be `Sized`. InlineAsmSized, /// `[T, ..n]` implies that `T` must be `Copy`. - RepeatVec, + /// If the function in the array repeat expression is a `const fn`, + /// display a help message suggesting to move the function call to a + /// new `const` item while saying that `T` doesn't implement `Copy`. + RepeatVec(bool), /// Types of fields (other than the last, except for packed structs) in a struct must be sized. FieldSized { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 1669c59d7f1b9..4f359caf31d7c 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -228,12 +228,17 @@ impl<'tcx> ty::TyS<'tcx> { ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(), ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(), ty::Array(t, n) => { + if t.is_simple_ty() { + return format!("array `{}`", self).into(); + } + let n = tcx.lift(n).unwrap(); - match n.try_eval_usize(tcx, ty::ParamEnv::empty()) { - _ if t.is_simple_ty() => format!("array `{}`", self).into(), - Some(n) => format!("array of {} element{}", n, pluralize!(n)).into(), - None => "array".into(), + if let ty::ConstKind::Value(v) = n.val { + if let Some(n) = v.try_to_machine_usize(tcx) { + return format!("array of {} element{}", n, pluralize!(n)).into(); + } } + "array".into() } ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(), ty::Slice(_) => "slice".into(), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 6ca5dcc532d22..de012a6957419 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -347,6 +347,7 @@ impl<'tcx> Instance<'tcx> { } // This should be kept up to date with `resolve`. + #[instrument(level = "debug", skip(tcx))] pub fn resolve_opt_const_arg( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 52b1ff3877da7..f64848e694cca 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -43,6 +43,9 @@ use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations} use crate::dataflow::impls::MaybeInitializedPlaces; use crate::dataflow::move_paths::MoveData; use crate::dataflow::ResultsCursor; +use crate::transform::{ + check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression, +}; use crate::borrow_check::{ borrow_set::BorrowSet, @@ -1098,6 +1101,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) -> Fallible<()> { relate_tys::relate_types( self.infcx, + self.param_env, a, v, b, @@ -1988,18 +1992,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Operand::Copy(..) | Operand::Constant(..) => { // These are always okay: direct use of a const, or a value that can evidently be copied. } - Operand::Move(_) => { + Operand::Move(place) => { // Make sure that repeated elements implement `Copy`. let span = body.source_info(location).span; let ty = operand.ty(body, tcx); if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) { + let ccx = ConstCx::new_with_param_env(tcx, body, self.param_env); + let is_const_fn = + is_const_fn_in_array_repeat_expression(&ccx, &place, &body); + + debug!("check_rvalue: is_const_fn={:?}", is_const_fn); + let def_id = body.source.def_id().expect_local(); self.infcx.report_selection_error( &traits::Obligation::new( ObligationCause::new( span, self.tcx().hir().local_def_id_to_hir_id(def_id), - traits::ObligationCauseCode::RepeatVec, + traits::ObligationCauseCode::RepeatVec(is_const_fn), ), self.param_env, ty::Binder::bind(ty::TraitRef::new( diff --git a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs b/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs index 6665eb5ad5fff..249945f04b7b0 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs @@ -18,6 +18,7 @@ use crate::borrow_check::type_check::{BorrowCheckContext, Locations}; /// variables, but not the type `b`. pub(super) fn relate_types<'tcx>( infcx: &InferCtxt<'_, 'tcx>, + param_env: ty::ParamEnv<'tcx>, a: Ty<'tcx>, v: ty::Variance, b: Ty<'tcx>, @@ -28,7 +29,7 @@ pub(super) fn relate_types<'tcx>( debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations); TypeRelating::new( infcx, - NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), + NllTypeRelatingDelegate::new(infcx, borrowck_context, param_env, locations, category), v, ) .relate(a, b)?; @@ -39,6 +40,8 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { infcx: &'me InferCtxt<'me, 'tcx>, borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>, + param_env: ty::ParamEnv<'tcx>, + /// Where (and why) is this relation taking place? locations: Locations, @@ -50,14 +53,19 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( infcx: &'me InferCtxt<'me, 'tcx>, borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>, + param_env: ty::ParamEnv<'tcx>, locations: Locations, category: ConstraintCategory, ) -> Self { - Self { infcx, borrowck_context, locations, category } + Self { infcx, borrowck_context, param_env, locations, category } } } impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.param_env + } + fn create_next_universe(&mut self) -> ty::UniverseIndex { self.infcx.create_next_universe() } diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index 252f5e7ef2ff2..ed450c0c2a056 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -208,7 +208,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { - // see comment in const_eval_raw_provider for what we're doing here + // see comment in eval_to_allocation_raw_provider for what we're doing here if key.param_env.reveal() == Reveal::All { let mut key = key; key.param_env = key.param_env.with_user_facing(); diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs index 0b7492631c41d..dac8ddccad67e 100644 --- a/compiler/rustc_mir/src/interpret/validity.rs +++ b/compiler/rustc_mir/src/interpret/validity.rs @@ -21,7 +21,7 @@ use std::hash::Hash; use super::{ CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, - ValueVisitor, + ScalarMaybeUninit, ValueVisitor, }; macro_rules! throw_validation_failure { @@ -378,7 +378,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' value: OpTy<'tcx, M::PointerTag>, kind: &str, ) -> InterpResult<'tcx> { - let value = self.ecx.read_immediate(value)?; + let value = try_validation!( + self.ecx.read_immediate(value), + self.path, + err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" }, + ); // Handle wide pointers. // Check metadata early, for better diagnostics let place = try_validation!( @@ -485,6 +489,17 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(()) } + fn read_scalar( + &self, + op: OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, ScalarMaybeUninit> { + Ok(try_validation!( + self.ecx.read_scalar(op), + self.path, + err_unsup!(ReadPointerAsBytes) => { "(potentially part of) a pointer" } expected { "plain (non-pointer) bytes" }, + )) + } + /// Check if this is a value of primitive type, and if yes check the validity of the value /// at that type. Return `true` if the type is indeed primitive. fn try_visit_primitive( @@ -495,7 +510,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let ty = value.layout.ty; match ty.kind() { ty::Bool => { - let value = self.ecx.read_scalar(value)?; + let value = self.read_scalar(value)?; try_validation!( value.to_bool(), self.path, @@ -505,7 +520,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::Char => { - let value = self.ecx.read_scalar(value)?; + let value = self.read_scalar(value)?; try_validation!( value.to_char(), self.path, @@ -515,11 +530,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { - let value = try_validation!( - self.ecx.read_scalar(value), - self.path, - err_unsup!(ReadPointerAsBytes) => { "read of part of a pointer" }, - ); + let value = self.read_scalar(value)?; // NOTE: Keep this in sync with the array optimization for int/float // types below! if self.ctfe_mode.is_some() { @@ -541,9 +552,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // actually enforce the strict rules for raw pointers (mostly because // that lets us re-use `ref_to_mplace`). let place = try_validation!( - self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), + self.ecx.read_immediate(value).and_then(|i| self.ecx.ref_to_mplace(i)), self.path, err_ub!(InvalidUninitBytes(None)) => { "uninitialized raw pointer" }, + err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" }, ); if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta, place.layout)?; @@ -569,9 +581,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::FnPtr(_sig) => { - let value = self.ecx.read_scalar(value)?; + let value = try_validation!( + self.ecx.read_immediate(value), + self.path, + err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" }, + ); let _fn = try_validation!( - value.check_init().and_then(|ptr| self.ecx.memory.get_fn(ptr)), + value.to_scalar().and_then(|ptr| self.ecx.memory.get_fn(ptr)), self.path, err_ub!(DanglingIntPointer(..)) | err_ub!(InvalidFunctionPointer(..)) | @@ -615,7 +631,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' op: OpTy<'tcx, M::PointerTag>, scalar_layout: &Scalar, ) -> InterpResult<'tcx> { - let value = self.ecx.read_scalar(op)?; + let value = self.read_scalar(op)?; let valid_range = &scalar_layout.valid_range; let (lo, hi) = valid_range.clone().into_inner(); // Determine the allowed range diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index b4504a0e223f6..1d4438d80c95a 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -1231,3 +1231,38 @@ pub fn promote_candidates<'tcx>( promotions } + +/// This function returns `true` if the function being called in the array +/// repeat expression is a `const` function. +crate fn is_const_fn_in_array_repeat_expression<'tcx>( + ccx: &ConstCx<'_, 'tcx>, + place: &Place<'tcx>, + body: &Body<'tcx>, +) -> bool { + match place.as_local() { + // rule out cases such as: `let my_var = some_fn(); [my_var; N]` + Some(local) if body.local_decls[local].is_user_variable() => return false, + None => return false, + _ => {} + } + + for block in body.basic_blocks() { + if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) = + &block.terminator + { + if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func { + if let ty::FnDef(def_id, _) = *ty.kind() { + if let Some((destination_place, _)) = destination { + if destination_place == place { + if is_const_fn(ccx.tcx, def_id) { + return true; + } + } + } + } + } + } + } + + false +} diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 79c5c7f110c4f..4b03d38ccba5b 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -510,11 +510,10 @@ impl Span { /// items can be used (that is, a macro marked with /// `#[allow_internal_unstable]`). pub fn allows_unstable(&self, feature: Symbol) -> bool { - self.ctxt().outer_expn_data().allow_internal_unstable.map_or(false, |features| { - features - .iter() - .any(|&f| f == feature || f == sym::allow_internal_unstable_backcompat_hack) - }) + self.ctxt() + .outer_expn_data() + .allow_internal_unstable + .map_or(false, |features| features.iter().any(|&f| f == feature)) } /// Checks if this span arises from a compiler desugaring of kind `kind`. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ef062da3f6e89..8c90eeb7f3f4a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -252,7 +252,6 @@ symbols! { allow_fail, allow_internal_unsafe, allow_internal_unstable, - allow_internal_unstable_backcompat_hack, allowed, always, and, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 34bd332951c06..9fd2f12100740 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1881,10 +1881,26 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::Coercion { source: _, target } => { err.note(&format!("required by cast to type `{}`", self.ty_to_string(target))); } - ObligationCauseCode::RepeatVec => { + ObligationCauseCode::RepeatVec(is_const_fn) => { err.note( "the `Copy` trait is required because the repeated element will be copied", ); + + if is_const_fn { + err.help( + "consider creating a new `const` item and initializing with the result \ + of the function call to be used in the repeat position, like \ + `const VAL: Type = const_fn();` and `let x = [VAL; 42];`", + ); + } + + if self.tcx.sess.is_nightly_build() && is_const_fn { + err.help( + "create an inline `const` block, see PR \ + #2920 \ + for more information", + ); + } } ObligationCauseCode::VariableType(hir_id) => { let parent_node = self.tcx.hir().get_parent_node(hir_id); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index cf2c6efb4711f..1cc580a198386 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -10,6 +10,7 @@ use traits::{translate_substs, Reveal}; use tracing::debug; +#[instrument(level = "debug", skip(tcx))] fn resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>, @@ -38,13 +39,13 @@ fn resolve_instance_of_const_arg<'tcx>( ) } +#[instrument(level = "debug", skip(tcx))] fn inner_resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam, SubstsRef<'tcx>)>, ) -> Result>, ErrorReported> { let (param_env, (def, substs)) = key.into_parts(); - debug!("resolve(def={:?}, substs={:?})", def.did, substs); let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) { debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); let item = tcx.associated_item(def.did); @@ -93,7 +94,7 @@ fn inner_resolve_instance<'tcx>( }; Ok(Some(Instance { def, substs })) }; - debug!("resolve(def.did={:?}, substs={:?}) = {:?}", def.did, substs, result); + debug!("inner_resolve_instance: result={:?}", result); result } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index c619b5bf8edd1..f2ec277448440 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -649,12 +649,12 @@ impl BTreeSet { /// #![feature(map_first_last)] /// use std::collections::BTreeSet; /// - /// let mut map = BTreeSet::new(); - /// assert_eq!(map.first(), None); - /// map.insert(1); - /// assert_eq!(map.first(), Some(&1)); - /// map.insert(2); - /// assert_eq!(map.first(), Some(&1)); + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.first(), None); + /// set.insert(1); + /// assert_eq!(set.first(), Some(&1)); + /// set.insert(2); + /// assert_eq!(set.first(), Some(&1)); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn first(&self) -> Option<&T> @@ -675,12 +675,12 @@ impl BTreeSet { /// #![feature(map_first_last)] /// use std::collections::BTreeSet; /// - /// let mut map = BTreeSet::new(); - /// assert_eq!(map.last(), None); - /// map.insert(1); - /// assert_eq!(map.last(), Some(&1)); - /// map.insert(2); - /// assert_eq!(map.last(), Some(&2)); + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.last(), None); + /// set.insert(1); + /// assert_eq!(set.last(), Some(&1)); + /// set.insert(2); + /// assert_eq!(set.last(), Some(&2)); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn last(&self) -> Option<&T> diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 73cf5d138bf75..2df5e562745d0 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -401,8 +401,6 @@ impl<'a> Arguments<'a> { /// # Examples /// /// ```rust - /// #![feature(fmt_as_str)] - /// /// use std::fmt::Arguments; /// /// fn write_str(_: &str) { /* ... */ } @@ -417,13 +415,11 @@ impl<'a> Arguments<'a> { /// ``` /// /// ```rust - /// #![feature(fmt_as_str)] - /// /// assert_eq!(format_args!("hello").as_str(), Some("hello")); /// assert_eq!(format_args!("").as_str(), Some("")); /// assert_eq!(format_args!("{}", 1).as_str(), None); /// ``` - #[unstable(feature = "fmt_as_str", issue = "74442")] + #[stable(feature = "fmt_as_str", since = "1.52.0")] #[inline] pub fn as_str(&self) -> Option<&'static str> { match (self.pieces, self.args) { diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7aaf5a5fd4614..b3802c1abde9f 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -816,6 +816,7 @@ pub(crate) mod builtin { #[macro_export] macro_rules! env { ($name:expr $(,)?) => {{ /* compiler built-in */ }}; + ($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }}; } /// Optionally inspects an environment variable at compile time. diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index c9c8f68cd9cce..5bb3f6bdcfd7b 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -76,6 +76,10 @@ pub struct OsString { inner: Buf, } +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl crate::sealed::Sealed for OsString {} + /// Borrowed reference to an OS string (see [`OsString`]). /// /// This type represents a borrowed reference to a string in the operating system's preferred @@ -100,6 +104,10 @@ pub struct OsStr { inner: Slice, } +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl crate::sealed::Sealed for OsStr {} + impl OsString { /// Constructs a new empty `OsString`. /// diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 961cff661e3ba..bc9b47029417d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -264,7 +264,6 @@ #![feature(exhaustive_patterns)] #![feature(extend_one)] #![feature(external_doc)] -#![feature(fmt_as_str)] #![feature(fn_traits)] #![feature(format_args_nl)] #![feature(gen_future)] @@ -582,3 +581,11 @@ include!("keyword_docs.rs"); // is unconditional, so the unstable feature needs to be defined somewhere. #[unstable(feature = "restricted_std", issue = "none")] mod __restricted_std_workaround {} + +mod sealed { + /// This trait being unreachable from outside the crate + /// prevents outside implementations of our extension traits. + /// This allows adding more trait methods in the future. + #[unstable(feature = "sealed", issue = "none")] + pub trait Sealed {} +} diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 89a822a7229f1..3e634239ad301 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -408,7 +408,7 @@ impl Stream for AssertUnwindSafe { /// aborting the process as well. This function *only* catches unwinding panics, /// not those that abort the process. /// -/// Also note that unwinding into Rust code with a foreign exception (e.g. a +/// Also note that unwinding into Rust code with a foreign exception (e.g. /// an exception thrown from C++ code) is undefined behavior. /// /// # Examples diff --git a/library/std/src/process.rs b/library/std/src/process.rs index fb78e62834a07..6480e654c55f0 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -498,6 +498,10 @@ pub struct Command { inner: imp::Command, } +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl crate::sealed::Sealed for Command {} + impl Command { /// Constructs a new `Command` for launching the program at /// path `program`, with the following default configuration: @@ -1375,6 +1379,10 @@ impl From for Stdio { #[stable(feature = "process", since = "1.0.0")] pub struct ExitStatus(imp::ExitStatus); +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl crate::sealed::Sealed for ExitStatus {} + impl ExitStatus { /// Was termination successful? Signal termination is not considered a /// success, and success is defined as a zero exit status. diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index 724b5dcca6a36..7559c1f1d9e29 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -6,20 +6,16 @@ use crate::ffi::OsStr; use crate::io; use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::process; +use crate::sealed::Sealed; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -mod private { - /// This trait being unreachable from outside the crate - /// prevents other implementations of the `ExitStatusExt` trait, - /// which allows potentially adding more trait methods in the future. - #[stable(feature = "none", since = "1.51.0")] - pub trait Sealed {} -} - /// Unix-specific extensions to the [`process::Command`] builder. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. #[stable(feature = "rust1", since = "1.0.0")] -pub trait CommandExt { +pub trait CommandExt: Sealed { /// Sets the child process's user ID. This translates to a /// `setuid` call in the child process. Failure in the `setuid` /// call will cause the spawn to fail. @@ -193,7 +189,7 @@ impl CommandExt for process::Command { /// This trait is sealed: it cannot be implemented outside the standard library. /// This is so that future additional methods are not breaking changes. #[stable(feature = "rust1", since = "1.0.0")] -pub trait ExitStatusExt: private::Sealed { +pub trait ExitStatusExt: Sealed { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of /// a process. #[stable(feature = "exit_status_from", since = "1.12.0")] @@ -228,9 +224,6 @@ pub trait ExitStatusExt: private::Sealed { fn into_raw(self) -> i32; } -#[stable(feature = "none", since = "1.51.0")] -impl private::Sealed for process::ExitStatus {} - #[stable(feature = "rust1", since = "1.0.0")] impl ExitStatusExt for process::ExitStatus { fn from_raw(raw: i32) -> Self { diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index dec886208103d..9789ed085e29d 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -1023,7 +1023,7 @@ extern "system" { pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; // >= Vista / Server 2008 - // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinka + // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw pub fn CreateSymbolicLinkW( lpSymlinkFileName: LPCWSTR, lpTargetFileName: LPCWSTR, diff --git a/library/std/src/sys/windows/ext/ffi.rs b/library/std/src/sys/windows/ext/ffi.rs index 1df2a0df143b3..c89b9ff1efa6b 100644 --- a/library/std/src/sys/windows/ext/ffi.rs +++ b/library/std/src/sys/windows/ext/ffi.rs @@ -53,6 +53,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::ffi::{OsStr, OsString}; +use crate::sealed::Sealed; use crate::sys::os_str::Buf; use crate::sys_common::wtf8::Wtf8Buf; use crate::sys_common::{AsInner, FromInner}; @@ -61,8 +62,11 @@ use crate::sys_common::{AsInner, FromInner}; pub use crate::sys_common::wtf8::EncodeWide; /// Windows-specific extensions to [`OsString`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. #[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStringExt { +pub trait OsStringExt: Sealed { /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of /// 16-bit code units. /// @@ -92,8 +96,11 @@ impl OsStringExt for OsString { } /// Windows-specific extensions to [`OsStr`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. #[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStrExt { +pub trait OsStrExt: Sealed { /// Re-encodes an `OsStr` as a wide character sequence, i.e., potentially /// ill-formed UTF-16. /// diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs index 7a92381d6609b..3d680a7f2d94f 100644 --- a/library/std/src/sys/windows/ext/process.rs +++ b/library/std/src/sys/windows/ext/process.rs @@ -4,17 +4,10 @@ use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; use crate::process; +use crate::sealed::Sealed; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -mod private { - /// This trait being unreachable from outside the crate - /// prevents other implementations of the `ExitStatusExt` trait, - /// which allows potentially adding more trait methods in the future. - #[stable(feature = "none", since = "1.51.0")] - pub trait Sealed {} -} - #[stable(feature = "process_extensions", since = "1.2.0")] impl FromRawHandle for process::Stdio { unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio { @@ -85,7 +78,7 @@ impl IntoRawHandle for process::ChildStderr { /// This trait is sealed: it cannot be implemented outside the standard library. /// This is so that future additional methods are not breaking changes. #[stable(feature = "exit_status_from", since = "1.12.0")] -pub trait ExitStatusExt: private::Sealed { +pub trait ExitStatusExt: Sealed { /// Creates a new `ExitStatus` from the raw underlying `u32` return value of /// a process. #[stable(feature = "exit_status_from", since = "1.12.0")] @@ -99,12 +92,12 @@ impl ExitStatusExt for process::ExitStatus { } } -#[stable(feature = "none", since = "1.51.0")] -impl private::Sealed for process::ExitStatus {} - /// Windows-specific extensions to the [`process::Command`] builder. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. #[stable(feature = "windows_process_extensions", since = "1.16.0")] -pub trait CommandExt { +pub trait CommandExt: Sealed { /// Sets the [process creation flags][1] to be passed to `CreateProcess`. /// /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`. diff --git a/library/std/src/sys_common/os_str_bytes.rs b/library/std/src/sys_common/os_str_bytes.rs index 497e5fc7bdd16..302c519740717 100644 --- a/library/std/src/sys_common/os_str_bytes.rs +++ b/library/std/src/sys_common/os_str_bytes.rs @@ -6,6 +6,7 @@ use crate::ffi::{OsStr, OsString}; use crate::fmt; use crate::mem; use crate::rc::Rc; +use crate::sealed::Sealed; use crate::str; use crate::sync::Arc; use crate::sys_common::bytestring::debug_fmt_bytestring; @@ -232,8 +233,11 @@ impl Slice { } /// Platform-specific extensions to [`OsString`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. #[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStringExt { +pub trait OsStringExt: Sealed { /// Creates an [`OsString`] from a byte vector. /// /// See the module documentation for an example. @@ -258,8 +262,11 @@ impl OsStringExt for OsString { } /// Platform-specific extensions to [`OsStr`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. #[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStrExt { +pub trait OsStrExt: Sealed { #[stable(feature = "rust1", since = "1.0.0")] /// Creates an [`OsStr`] from a byte slice. /// diff --git a/src/README.md b/src/README.md index ef0dec1c45be2..9752bc3f66d44 100644 --- a/src/README.md +++ b/src/README.md @@ -1,4 +1,5 @@ This directory contains the source code of the rust project, including: + - The test suite - The bootstrapping build system - Various submodules for tools, like rustdoc, rls, etc. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 8fddd8cba08de..a9099981e644a 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -579,8 +579,7 @@ impl<'a> Builder<'a> { self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths); } - pub fn default_doc(&self, paths: Option<&[PathBuf]>) { - let paths = paths.unwrap_or(&[]); + pub fn default_doc(&self, paths: &[PathBuf]) { self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths); } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 3ebfdb24879fa..802b5c99500cc 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -68,7 +68,7 @@ impl Step for Docs { if !builder.config.docs { return None; } - builder.default_doc(None); + builder.default_doc(&[]); let dest = "share/doc/rust/html"; @@ -103,7 +103,7 @@ impl Step for RustcDocs { if !builder.config.compiler_docs { return None; } - builder.default_doc(None); + builder.default_doc(&[]); let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple); tarball.set_product_name("Rustc Documentation"); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index d9132f20d85b3..7830dc8239464 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -111,7 +111,7 @@ impl Step for Linkcheck { builder.info(&format!("Linkcheck ({})", host)); - builder.default_doc(None); + builder.default_doc(&[]); let _time = util::timeit(&builder); try_run( diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 30b18eb56a125..3d6579250a014 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -300,7 +300,7 @@ flag][prefer-dynamic] may be used to influence which is used. If the same crate name is specified with and without a path, the one with the path is used and the pathless flag has no effect. -[extern prelude]: ../reference/items/extern-crates.html#extern-prelude +[extern prelude]: ../reference/names/preludes.html#extern-prelude [prefer-dynamic]: codegen-options/index.md#prefer-dynamic diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7e7e417bb6544..3decdd02b0012 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1269,7 +1269,7 @@ impl Clean for ty::AssocItem { AssocTypeItem(bounds, ty.clean(cx)) } else { - // FIXME: when could this happen? ASsociated items in inherent impls? + // FIXME: when could this happen? Associated items in inherent impls? let type_ = cx.tcx.type_of(self.def_id).clean(cx); TypedefItem( Typedef { diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs index 64b7c93cbc3e6..09901a7a39c08 100644 --- a/src/test/assembly/asm/arm-types.rs +++ b/src/test/assembly/asm/arm-types.rs @@ -91,6 +91,15 @@ pub unsafe fn sym_static() { asm!("adr r0, {}", sym extern_static); } +// Regression test for #82052. +// CHECK-LABEL: issue_82052 +// CHECK: push {{.*}}lr +// CHECK: @APP +// CHECK: @NO_APP +pub unsafe fn issue_82052() { + asm!("", out("r14") _); +} + macro_rules! check { ($func:ident $ty:ident $class:ident $mov:literal) => { #[no_mangle] diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs new file mode 100644 index 0000000000000..8f02bfb937a5a --- /dev/null +++ b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs @@ -0,0 +1,21 @@ +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +// This test is a minimized reproduction for #79518 where +// during error handling for the type mismatch we would try +// to evaluate std::mem::size_of:: causing an ICE + +trait Foo { + type Assoc: PartialEq; + const AssocInstance: Self::Assoc; + + fn foo() + where + [(); std::mem::size_of::()]: , + { + Self::AssocInstance == [(); std::mem::size_of::()]; + //~^ Error: mismatched types + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr new file mode 100644 index 0000000000000..c90774e944f1f --- /dev/null +++ b/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32 + | +LL | Self::AssocInstance == [(); std::mem::size_of::()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]` + | + = note: expected associated type `::Assoc` + found array `[(); _]` + = help: consider constraining the associated type `::Assoc` to `[(); _]` or calling a method that returns `::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs new file mode 100644 index 0000000000000..a34d74b29e9f0 --- /dev/null +++ b/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +// This tests that the correct `param_env` is used so that +// attempting to normalize `Self::N` does not cause an ICE. + +pub struct Foo; + +impl Foo { + pub fn foo() {} +} + +pub trait Bar { + const N: usize; + fn bar() + where + [(); Self::N]: , + { + Foo::<{ Self::N }>::foo(); + } +} + +fn main() {} diff --git a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr index b75452cd21702..303de078013ac 100644 --- a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -7,6 +7,8 @@ LL | let _: [Option; 2] = [no_copy(); 2]; = help: the following implementations were found: as Copy> = note: the `Copy` trait is required because the repeated element will be copied + = help: consider creating a new `const` item and initializing with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` + = help: create an inline `const` block, see PR #2920 for more information error: aborting due to previous error diff --git a/src/test/ui/consts/const-fn-in-vec.rs b/src/test/ui/consts/const-fn-in-vec.rs new file mode 100644 index 0000000000000..a40290eca0972 --- /dev/null +++ b/src/test/ui/consts/const-fn-in-vec.rs @@ -0,0 +1,7 @@ +fn main() { + // should hint to create an inline `const` block + // or to create a new `const` item + let strings: [String; 5] = [String::new(); 5]; + //~^ ERROR the trait bound `String: Copy` is not satisfied + println!("{:?}", strings); +} diff --git a/src/test/ui/consts/const-fn-in-vec.stderr b/src/test/ui/consts/const-fn-in-vec.stderr new file mode 100644 index 0000000000000..f9f184dfc06b6 --- /dev/null +++ b/src/test/ui/consts/const-fn-in-vec.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:4:32 + | +LL | let strings: [String; 5] = [String::new(); 5]; + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | + = note: the `Copy` trait is required because the repeated element will be copied + = help: consider creating a new `const` item and initializing with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` + = help: create an inline `const` block, see PR #2920 for more information + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/issue-79690.stderr b/src/test/ui/consts/issue-79690.stderr index 918dd4c20f96c..ca56ff220564a 100644 --- a/src/test/ui/consts/issue-79690.stderr +++ b/src/test/ui/consts/issue-79690.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-79690.rs:29:1 | LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered read of part of a pointer at .1..size.foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered (potentially part of) a pointer at .1..size.foo, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/pattern/usefulness/issue-72377.rs b/src/test/ui/pattern/usefulness/issue-72377.rs new file mode 100644 index 0000000000000..b0d8a53ed93b0 --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-72377.rs @@ -0,0 +1,17 @@ +#[derive(PartialEq, Eq)] +enum X { A, B, C, } + +fn main() { + let x = X::A; + let y = Some(X::A); + + match (x, y) { + //~^ ERROR non-exhaustive patterns: `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 + //~| more not covered + (_, None) => false, + (v, Some(w)) if v == w => true, + (X::B, Some(X::C)) => false, + (X::B, Some(X::A)) => false, + (X::A, Some(X::C)) | (X::C, Some(X::A)) => false, + }; +} diff --git a/src/test/ui/pattern/usefulness/issue-72377.stderr b/src/test/ui/pattern/usefulness/issue-72377.stderr new file mode 100644 index 0000000000000..b4a68333967b3 --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-72377.stderr @@ -0,0 +1,12 @@ +error[E0004]: non-exhaustive patterns: `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 more not covered + --> $DIR/issue-72377.rs:8:11 + | +LL | match (x, y) { + | ^^^^^^ patterns `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 more not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `(X, Option)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 336909b63a14b..7435b9e98c928 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 336909b63a14b801520c6627d90d750babcfe280 +Subproject commit 7435b9e98c9280043605748c11a1f450669e04d6