diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 651f4c6fabd..f17c43ceaff 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 8801211d51b..4aa25aae747 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 870b5c92d89..c5d0927760b 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 3b722c04cb1..c5d8ff25ea9 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 d040539cd7e..98682ba4295 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 1546c1e559f..074c9252481 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 e034ac5e8fd..5e11932eafc 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 97ef685cf6f..e720a6f1308 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 0517ec5bb1a..3e7b93b32a6 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 163b400973b..f34ee228602 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 1669c59d7f1..4f359caf31d 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) => { - 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 t.is_simple_ty() { + return format!("array `{}`", self).into(); } + + let n = tcx.lift(n).unwrap(); + 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 6ca5dcc532d..de012a69574 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 52b1ff3877d..f64848e694c 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 6665eb5ad5f..249945f04b7 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 252f5e7ef2f..ed450c0c2a0 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 0b7492631c4..dac8ddccad6 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 b4504a0e223..1d4438d80c9 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 79c5c7f110c..4b03d38ccba 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 ef062da3f6e..8c90eeb7f3f 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 34bd332951c..9fd2f121007 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 cf2c6efb471..1cc580a1983 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 c619b5bf8ed..f2ec2774484 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 73cf5d138bf..2df5e562745 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 7aaf5a5fd46..b3802c1abde 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 c9c8f68cd9c..5bb3f6bdcfd 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 961cff661e3..bc9b4702941 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 89a822a7229..3e634239ad3 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 fb78e62834a..6480e654c55 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 724b5dcca6a..7559c1f1d9e 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 dec88620810..9789ed085e2 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 1df2a0df143..c89b9ff1efa 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 7a92381d660..3d680a7f2d9 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 497e5fc7bdd..302c5197407 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 ef0dec1c45b..9752bc3f66d 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 8fddd8cba08..a9099981e64 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 3ebfdb24879..802b5c99500 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 d9132f20d85..7830dc82394 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 30b18eb56a1..3d6579250a0 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 7e7e417bb65..3decdd02b00 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 64b7c93cbc3..09901a7a39c 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 00000000000..8f02bfb937a --- /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 00000000000..c90774e944f --- /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 00000000000..a34d74b29e9 --- /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 b75452cd217..303de078013 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 00000000000..a40290eca09 --- /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 00000000000..f9f184dfc06 --- /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 918dd4c20f9..ca56ff22056 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 00000000000..b0d8a53ed93 --- /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 00000000000..b4a68333967 --- /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 336909b63a1..7435b9e98c9 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 336909b63a14b801520c6627d90d750babcfe280 +Subproject commit 7435b9e98c9280043605748c11a1f450669e04d6