diff options
| author | bors <bors@rust-lang.org> | 2021-02-16 02:14:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-02-16 02:14:13 +0000 |
| commit | 42a4673fbd40b09a99d057eaa9b3e5579b54c184 (patch) | |
| tree | 5ab393dcc74c0ab38a4cdf58f513e8eb94bb9420 /compiler | |
| parent | d1206f950ffb76c76e1b74a19ae33c2b7d949454 (diff) | |
| parent | a105280a067891b557498cf9131843a75c20829a (diff) | |
| download | rust-42a4673fbd40b09a99d057eaa9b3e5579b54c184.tar.gz rust-42a4673fbd40b09a99d057eaa9b3e5579b54c184.zip | |
Auto merge of #82153 - jonas-schievink:rollup-ls5r943, r=jonas-schievink
Rollup of 19 pull requests
Successful merges:
- #81503 (Suggest to create a new `const` item if the `fn` in the array is a `const fn`)
- #81897 (Add match pattern diagnostics regression test)
- #81975 (Seal the CommandExt, OsStrExt and OsStringExt traits)
- #82009 (const_generics: Dont evaluate array length const when handling errors)
- #82060 (Fix typos in BTreeSet::{first, last} docs)
- #82061 (CTFE validation: catch ReadPointerAsBytes and better error)
- #82063 (Fixed minor typo in catch_unwind docs)
- #82067 (const_generics: Fix incorrect ty::ParamEnv::empty() usage)
- #82077 (Edit `rustc_arena::DropArena` docs)
- #82096 (Fix a typo)
- #82106 (Remove unnecessary `Option` in `default_doc`)
- #82107 (expand: Some cleanup)
- #82118 (Add missing env!-decl variant)
- #82119 (Fix typo in link to CreateSymbolicLinkW documentation.)
- #82120 (Stabilize Arguments::as_str)
- #82129 (Remove redundant bool_to_option feature gate)
- #82133 (Update link for extern prelude.)
- #82141 (32-bit ARM: Emit `lr` instead of `r14` when specified as an `asm!` output register.)
- #82147 (:arrow_up: rust-analyzer)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
21 files changed, 152 insertions, 76 deletions
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<T> -/// alongside this arena for each type T you allocate. +/// allocate safely, you must store a `PhantomData<T>` +/// 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::<T>, obj: result as *mut T as *mut u8 }); @@ -607,16 +610,16 @@ impl DropArena { let start_ptr = self.arena.alloc_raw(Layout::array::<T>(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::<T>, 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<ast::Expr>) { 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<ast::Expr>) -> Option<P<ast::Expr>> { 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<ast::Pat>) { - 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<ast::ForeignItem>, + foreign_item: P<ast::ForeignItem>, ) -> SmallVec<[P<ast::ForeignItem>; 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<ast::FnDecl>) { - 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::<T>()` 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) => { + 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 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<M::PointerTag>> { + 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 <https://github.com/rust-lang/rfcs/pull/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<DefId>, SubstsRef<'tcx>)>, ) -> Result<Option<Instance<'tcx>>, 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 } |
