diff --git a/Cargo.lock b/Cargo.lock index de5158ab073f7..9d726b240da93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3568,7 +3568,6 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "version_check", ] [[package]] diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml index 5f941a0a650f8..dc0711a5b0f30 100644 --- a/compiler/rustc_attr/Cargo.toml +++ b/compiler/rustc_attr/Cargo.toml @@ -18,4 +18,3 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_ast = { path = "../rustc_ast" } -version_check = "0.9" diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index ead90f23ce7a1..26baaf07880f1 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -10,7 +10,6 @@ use rustc_session::Session; use rustc_span::hygiene::Transparency; use rustc_span::{symbol::sym, symbol::Symbol, Span}; use std::num::NonZeroU32; -use version_check::Version; pub fn is_builtin_attr(attr: &Attribute) -> bool { attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some() @@ -526,6 +525,26 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F } } +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +struct Version { + major: u16, + minor: u16, + patch: u16, +} + +fn parse_version(s: &str, allow_appendix: bool) -> Option { + let mut components = s.split('-'); + let d = components.next()?; + if !allow_appendix && components.next().is_some() { + return None; + } + let mut digits = d.splitn(3, '.'); + let major = digits.next()?.parse().ok()?; + let minor = digits.next()?.parse().ok()?; + let patch = digits.next().unwrap_or("0").parse().ok()?; + Some(Version { major, minor, patch }) +} + /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to /// evaluate individual items. pub fn eval_condition( @@ -555,16 +574,21 @@ pub fn eval_condition( return false; } }; - let min_version = match Version::parse(&min_version.as_str()) { + let min_version = match parse_version(&min_version.as_str(), false) { Some(ver) => ver, None => { - sess.span_diagnostic.struct_span_err(*span, "invalid version literal").emit(); + sess.span_diagnostic + .struct_span_warn( + *span, + "unknown version literal format, assuming it refers to a future version", + ) + .emit(); return false; } }; let channel = env!("CFG_RELEASE_CHANNEL"); let nightly = channel == "nightly" || channel == "dev"; - let rustc_version = Version::parse(env!("CFG_RELEASE")).unwrap(); + let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap(); // See https://github.com/rust-lang/rust/issues/64796#issuecomment-625474439 for details if nightly { rustc_version > min_version } else { rustc_version >= min_version } diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index bb6d3f6a0076c..f82269c4eee4f 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -12,27 +12,43 @@ use rustc_span::{Span, DUMMY_SP}; pub fn expand_assert<'cx>( cx: &'cx mut ExtCtxt<'_>, - sp: Span, + span: Span, tts: TokenStream, ) -> Box { - let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) { + let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) { Ok(assert) => assert, Err(mut err) => { err.emit(); - return DummyResult::any(sp); + return DummyResult::any(span); } }; // `core::panic` and `std::panic` are different macros, so we use call-site // context to pick up whichever is currently in scope. - let sp = cx.with_call_site_ctxt(sp); + let sp = cx.with_call_site_ctxt(span); let panic_call = if let Some(tokens) = custom_message { + let path = if span.rust_2021() { + // On edition 2021, we always call `$crate::panic!()`. + Path { + span: sp, + segments: cx + .std_path(&[sym::panic]) + .into_iter() + .map(|ident| PathSegment::from_ident(ident)) + .collect(), + tokens: None, + } + } else { + // Before edition 2021, we call `panic!()` unqualified, + // such that it calls either `std::panic!()` or `core::panic!()`. + Path::from_ident(Ident::new(sym::panic, sp)) + }; // Pass the custom message to panic!(). cx.expr( sp, ExprKind::MacCall(MacCall { - path: Path::from_ident(Ident::new(sym::panic, sp)), + path, args: P(MacArgs::Delimited( DelimSpan::from_single(sp), MacDelimiter::Parenthesis, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e51904f308dd4..72e049b6d7469 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -885,9 +885,22 @@ fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linke } fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { - let default_sysroot = filesearch::get_or_default_sysroot(); - let default_tlib = - filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple()); + fn find_sanitizer_runtime(sess: &Session, filename: &String) -> PathBuf { + let session_tlib = + filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple()); + let path = session_tlib.join(&filename); + if path.exists() { + return session_tlib; + } else { + let default_sysroot = filesearch::get_or_default_sysroot(); + let default_tlib = filesearch::make_target_lib_path( + &default_sysroot, + sess.opts.target_triple.triple(), + ); + return default_tlib; + } + } + let channel = option_env!("CFG_RELEASE_CHANNEL") .map(|channel| format!("-{}", channel)) .unwrap_or_default(); @@ -898,10 +911,11 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { // LLVM will link to `@rpath/*.dylib`, so we need to specify an // rpath to the library as well (the rpath should be absolute, see // PR #41352 for details). - let libname = format!("rustc{}_rt.{}", channel, name); - let rpath = default_tlib.to_str().expect("non-utf8 component in path"); + let filename = format!("rustc{}_rt.{}", channel, name); + let path = find_sanitizer_runtime(&sess, &filename); + let rpath = path.to_str().expect("non-utf8 component in path"); linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); - linker.link_dylib(Symbol::intern(&libname)); + linker.link_dylib(Symbol::intern(&filename)); } "aarch64-fuchsia" | "aarch64-unknown-linux-gnu" @@ -909,7 +923,7 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { | "x86_64-unknown-freebsd" | "x86_64-unknown-linux-gnu" => { let filename = format!("librustc{}_rt.{}.a", channel, name); - let path = default_tlib.join(&filename); + let path = find_sanitizer_runtime(&sess, &filename).join(&filename); linker.link_whole_rlib(&path); } _ => {} diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 2ce5fe5ad504b..b205ea9cf6c9d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -783,7 +783,7 @@ impl CrateInfo { } } -pub fn provide_both(providers: &mut Providers) { +pub fn provide(providers: &mut Providers) { providers.backend_optimization_level = |tcx, cratenum| { let for_speed = match tcx.sess.opts.optimize { // If globally no optimisation is done, #[optimize] has no effect. diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index e27eac3f69b00..0307117e1c8b2 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -160,13 +160,12 @@ pub struct CodegenResults { pub fn provide(providers: &mut Providers) { crate::back::symbol_export::provide(providers); - crate::base::provide_both(providers); + crate::base::provide(providers); crate::target_features::provide(providers); } pub fn provide_extern(providers: &mut Providers) { crate::back::symbol_export::provide_extern(providers); - crate::base::provide_both(providers); } /// Checks if the given filename ends with the `.rcgu.o` extension that `rustc` diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 1cfbce2355e3a..ad62e3c9fc8f4 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -8,7 +8,6 @@ use super::iterate::reverse_post_order; use super::ControlFlowGraph; use rustc_index::vec::{Idx, IndexVec}; -use std::borrow::BorrowMut; use std::cmp::Ordering; #[cfg(test)] @@ -20,22 +19,17 @@ pub fn dominators(graph: G) -> Dominators { dominators_given_rpo(graph, &rpo) } -fn dominators_given_rpo>( - mut graph: G, - rpo: &[G::Node], -) -> Dominators { - let start_node = graph.borrow().start_node(); +fn dominators_given_rpo(graph: G, rpo: &[G::Node]) -> Dominators { + let start_node = graph.start_node(); assert_eq!(rpo[0], start_node); // compute the post order index (rank) for each node - let mut post_order_rank: IndexVec = - (0..graph.borrow().num_nodes()).map(|_| 0).collect(); + let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes()); for (index, node) in rpo.iter().rev().cloned().enumerate() { post_order_rank[node] = index; } - let mut immediate_dominators: IndexVec> = - (0..graph.borrow().num_nodes()).map(|_| None).collect(); + let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes()); immediate_dominators[start_node] = Some(start_node); let mut changed = true; @@ -44,7 +38,7 @@ fn dominators_given_rpo>( for &node in &rpo[1..] { let mut new_idom = None; - for pred in graph.borrow_mut().predecessors(node) { + for pred in graph.predecessors(node) { if immediate_dominators[pred].is_some() { // (*) dominators for `pred` have been calculated new_idom = Some(if let Some(new_idom) = new_idom { diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 99ffb0edce9e1..6f98760a7b0ad 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -268,16 +268,20 @@ impl NonConstOp for CellBorrow { } #[derive(Debug)] +/// This op is for `&mut` borrows in the trailing expression of a constant +/// which uses the "enclosing scopes rule" to leak its locals into anonymous +/// static or const items. pub struct MutBorrow(pub hir::BorrowKind); impl NonConstOp for MutBorrow { - fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - // Forbid everywhere except in const fn with a feature gate - if ccx.const_kind() == hir::ConstContext::ConstFn { - Status::Unstable(sym::const_mut_refs) - } else { - Status::Forbidden - } + fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status { + Status::Forbidden + } + + fn importance(&self) -> DiagnosticImportance { + // If there were primary errors (like non-const function calls), do not emit further + // errors about mutable references. + DiagnosticImportance::Secondary } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { @@ -286,25 +290,15 @@ impl NonConstOp for MutBorrow { hir::BorrowKind::Ref => "", }; - let mut err = if ccx.const_kind() == hir::ConstContext::ConstFn { - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_mut_refs, - span, - &format!("{}mutable references are not allowed in {}s", raw, ccx.const_kind()), - ) - } else { - let mut err = struct_span_err!( - ccx.tcx.sess, - span, - E0764, - "{}mutable references are not allowed in {}s", - raw, - ccx.const_kind(), - ); - err.span_label(span, format!("`&{}mut` is only allowed in `const fn`", raw)); - err - }; + let mut err = struct_span_err!( + ccx.tcx.sess, + span, + E0764, + "{}mutable references are not allowed in the final value of {}s", + raw, + ccx.const_kind(), + ); + if ccx.tcx.sess.teach(&err.get_code().unwrap()) { err.note( "References in statics and constants may only refer \ @@ -321,6 +315,29 @@ impl NonConstOp for MutBorrow { } } +#[derive(Debug)] +pub struct TransientMutBorrow(pub hir::BorrowKind); + +impl NonConstOp for TransientMutBorrow { + fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { + Status::Unstable(sym::const_mut_refs) + } + + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let raw = match self.0 { + hir::BorrowKind::Raw => "raw ", + hir::BorrowKind::Ref => "", + }; + + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_mut_refs, + span, + &format!("{}mutable references are not allowed in {}s", raw, ccx.const_kind()), + ) + } +} + #[derive(Debug)] pub struct MutDeref; impl NonConstOp for MutDeref { @@ -329,7 +346,7 @@ impl NonConstOp for MutDeref { } fn importance(&self) -> DiagnosticImportance { - // Usually a side-effect of a `MutBorrow` somewhere. + // Usually a side-effect of a `TransientMutBorrow` somewhere. DiagnosticImportance::Secondary } diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 08d969b27bea5..a92997dddac6a 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -466,6 +466,29 @@ impl Validator<'mir, 'tcx> { } } } + + fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) { + match self.const_kind() { + // In a const fn all borrows are transient or point to the places given via + // references in the arguments (so we already checked them with + // TransientMutBorrow/MutBorrow as appropriate). + // The borrow checker guarantees that no new non-transient borrows are created. + // NOTE: Once we have heap allocations during CTFE we need to figure out + // how to prevent `const fn` to create long-lived allocations that point + // to mutable memory. + hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)), + _ => { + // Locals with StorageDead do not live beyond the evaluation and can + // thus safely be borrowed without being able to be leaked to the final + // value of the constant. + if self.local_has_storage_dead(local) { + self.check_op(ops::TransientMutBorrow(kind)); + } else { + self.check_op(ops::MutBorrow(kind)); + } + } + } + } } impl Visitor<'tcx> for Validator<'mir, 'tcx> { @@ -562,15 +585,15 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { if !is_allowed { if let BorrowKind::Mut { .. } = kind { - self.check_op(ops::MutBorrow(hir::BorrowKind::Ref)); + self.check_mut_borrow(place.local, hir::BorrowKind::Ref) } else { self.check_op(ops::CellBorrow); } } } - Rvalue::AddressOf(Mutability::Mut, _) => { - self.check_op(ops::MutBorrow(hir::BorrowKind::Raw)) + Rvalue::AddressOf(Mutability::Mut, ref place) => { + self.check_mut_borrow(place.local, hir::BorrowKind::Raw) } Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, ref place) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 80a24c90421e7..3b1b53553d5e4 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -290,6 +290,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { } fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { + self.in_pat = true; match pat.kind { PatKind::Struct(ref path, ref fields, _) => { let res = self.typeck_results().qpath_res(path, pat.hir_id); @@ -302,7 +303,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { _ => (), } - self.in_pat = true; intravisit::walk_pat(self, pat); self.in_pat = false; } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index ab3c26fac8338..47361092a5c50 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -846,21 +846,13 @@ pub(super) fn check_specialization_validity<'tcx>( Ok(ancestors) => ancestors, Err(_) => return, }; - let mut ancestor_impls = ancestors - .skip(1) - .filter_map(|parent| { - if parent.is_from_trait() { - None - } else { - Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id))) - } - }) - .peekable(); - - if ancestor_impls.peek().is_none() { - // No parent, nothing to specialize. - return; - } + let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| { + if parent.is_from_trait() { + None + } else { + Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id))) + } + }); let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| { match parent_item { @@ -902,8 +894,6 @@ pub(super) fn check_impl_items_against_trait<'tcx>( impl_trait_ref: ty::TraitRef<'tcx>, impl_item_refs: &[hir::ImplItemRef<'_>], ) { - let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); - // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` // isn't populated for such impls. @@ -931,111 +921,75 @@ pub(super) fn check_impl_items_against_trait<'tcx>( // Locate trait definition and items let trait_def = tcx.trait_def(impl_trait_ref.def_id); - - let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id)); + let impl_items = impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id)); + let associated_items = tcx.associated_items(impl_trait_ref.def_id); // Check existing impl methods to see if they are both present in trait // and compatible with trait signature - for impl_item in impl_items() { - let namespace = impl_item.kind.namespace(); + for impl_item in impl_items { let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id)); - let ty_trait_item = tcx - .associated_items(impl_trait_ref.def_id) - .find_by_name_and_namespace(tcx, ty_impl_item.ident, namespace, impl_trait_ref.def_id) - .or_else(|| { - // Not compatible, but needed for the error message - tcx.associated_items(impl_trait_ref.def_id) - .filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id) - .next() - }); - - // Check that impl definition matches trait definition - if let Some(ty_trait_item) = ty_trait_item { + + let mut items = + associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id); + + let (compatible_kind, ty_trait_item) = if let Some(ty_trait_item) = items.next() { + let is_compatible = |ty: &&ty::AssocItem| match (ty.kind, &impl_item.kind) { + (ty::AssocKind::Const, hir::ImplItemKind::Const(..)) => true, + (ty::AssocKind::Fn, hir::ImplItemKind::Fn(..)) => true, + (ty::AssocKind::Type, hir::ImplItemKind::TyAlias(..)) => true, + _ => false, + }; + + // If we don't have a compatible item, we'll use the first one whose name matches + // to report an error. + let mut compatible_kind = is_compatible(&ty_trait_item); + let mut trait_item = ty_trait_item; + + if !compatible_kind { + if let Some(ty_trait_item) = items.find(is_compatible) { + compatible_kind = true; + trait_item = ty_trait_item; + } + } + + (compatible_kind, trait_item) + } else { + continue; + }; + + if compatible_kind { match impl_item.kind { hir::ImplItemKind::Const(..) => { // Find associated const definition. - if ty_trait_item.kind == ty::AssocKind::Const { - compare_const_impl( - tcx, - &ty_impl_item, - impl_item.span, - &ty_trait_item, - impl_trait_ref, - ); - } else { - let mut err = struct_span_err!( - tcx.sess, - impl_item.span, - E0323, - "item `{}` is an associated const, \ - which doesn't match its trait `{}`", - ty_impl_item.ident, - impl_trait_ref.print_only_trait_path() - ); - err.span_label(impl_item.span, "does not match trait"); - // We can only get the spans from local trait definition - // Same for E0324 and E0325 - if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) { - err.span_label(trait_span, "item in trait"); - } - err.emit() - } + compare_const_impl( + tcx, + &ty_impl_item, + impl_item.span, + &ty_trait_item, + impl_trait_ref, + ); } hir::ImplItemKind::Fn(..) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); - if ty_trait_item.kind == ty::AssocKind::Fn { - compare_impl_method( - tcx, - &ty_impl_item, - impl_item.span, - &ty_trait_item, - impl_trait_ref, - opt_trait_span, - ); - } else { - let mut err = struct_span_err!( - tcx.sess, - impl_item.span, - E0324, - "item `{}` is an associated method, \ - which doesn't match its trait `{}`", - ty_impl_item.ident, - impl_trait_ref.print_only_trait_path() - ); - err.span_label(impl_item.span, "does not match trait"); - if let Some(trait_span) = opt_trait_span { - err.span_label(trait_span, "item in trait"); - } - err.emit() - } + compare_impl_method( + tcx, + &ty_impl_item, + impl_item.span, + &ty_trait_item, + impl_trait_ref, + opt_trait_span, + ); } hir::ImplItemKind::TyAlias(_) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); - if ty_trait_item.kind == ty::AssocKind::Type { - compare_ty_impl( - tcx, - &ty_impl_item, - impl_item.span, - &ty_trait_item, - impl_trait_ref, - opt_trait_span, - ); - } else { - let mut err = struct_span_err!( - tcx.sess, - impl_item.span, - E0325, - "item `{}` is an associated type, \ - which doesn't match its trait `{}`", - ty_impl_item.ident, - impl_trait_ref.print_only_trait_path() - ); - err.span_label(impl_item.span, "does not match trait"); - if let Some(trait_span) = opt_trait_span { - err.span_label(trait_span, "item in trait"); - } - err.emit() - } + compare_ty_impl( + tcx, + &ty_impl_item, + impl_item.span, + &ty_trait_item, + impl_trait_ref, + opt_trait_span, + ); } } @@ -1046,12 +1000,22 @@ pub(super) fn check_impl_items_against_trait<'tcx>( impl_id.to_def_id(), impl_item, ); + } else { + report_mismatch_error( + tcx, + ty_trait_item.def_id, + impl_trait_ref, + impl_item, + &ty_impl_item, + ); } } - // Check for missing items from trait - let mut missing_items = Vec::new(); if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) { + let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); + + // Check for missing items from trait + let mut missing_items = Vec::new(); for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { let is_implemented = ancestors .leaf_def(tcx, trait_item.ident, trait_item.kind) @@ -1064,11 +1028,63 @@ pub(super) fn check_impl_items_against_trait<'tcx>( } } } + + if !missing_items.is_empty() { + missing_items_err(tcx, impl_span, &missing_items, full_impl_span); + } } +} + +#[inline(never)] +#[cold] +fn report_mismatch_error<'tcx>( + tcx: TyCtxt<'tcx>, + trait_item_def_id: DefId, + impl_trait_ref: ty::TraitRef<'tcx>, + impl_item: &hir::ImplItem<'_>, + ty_impl_item: &ty::AssocItem, +) { + let mut err = match impl_item.kind { + hir::ImplItemKind::Const(..) => { + // Find associated const definition. + struct_span_err!( + tcx.sess, + impl_item.span, + E0323, + "item `{}` is an associated const, which doesn't match its trait `{}`", + ty_impl_item.ident, + impl_trait_ref.print_only_trait_path() + ) + } + + hir::ImplItemKind::Fn(..) => { + struct_span_err!( + tcx.sess, + impl_item.span, + E0324, + "item `{}` is an associated method, which doesn't match its trait `{}`", + ty_impl_item.ident, + impl_trait_ref.print_only_trait_path() + ) + } - if !missing_items.is_empty() { - missing_items_err(tcx, impl_span, &missing_items, full_impl_span); + hir::ImplItemKind::TyAlias(_) => { + struct_span_err!( + tcx.sess, + impl_item.span, + E0325, + "item `{}` is an associated type, which doesn't match its trait `{}`", + ty_impl_item.ident, + impl_trait_ref.print_only_trait_path() + ) + } + }; + + err.span_label(impl_item.span, "does not match trait"); + if let Some(trait_span) = tcx.hir().span_if_local(trait_item_def_id) { + err.span_label(trait_span, "item in trait"); } + err.emit(); } /// Checks whether a type can be represented in memory. In particular, it diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 88b4e2a2436e7..b1443bc33d2ff 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -1067,13 +1067,23 @@ impl fmt::Debug for Duration { } if self.secs > 0 { - fmt_decimal(f, self.secs, self.nanos, 100_000_000)?; + fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10)?; f.write_str("s") - } else if self.nanos >= 1_000_000 { - fmt_decimal(f, self.nanos as u64 / 1_000_000, self.nanos % 1_000_000, 100_000)?; + } else if self.nanos >= NANOS_PER_MILLI { + fmt_decimal( + f, + (self.nanos / NANOS_PER_MILLI) as u64, + self.nanos % NANOS_PER_MILLI, + NANOS_PER_MILLI / 10, + )?; f.write_str("ms") - } else if self.nanos >= 1_000 { - fmt_decimal(f, self.nanos as u64 / 1_000, self.nanos % 1_000, 100)?; + } else if self.nanos >= NANOS_PER_MICRO { + fmt_decimal( + f, + (self.nanos / NANOS_PER_MICRO) as u64, + self.nanos % NANOS_PER_MICRO, + NANOS_PER_MICRO / 10, + )?; f.write_str("µs") } else { fmt_decimal(f, self.nanos as u64, 0, 1)?; diff --git a/library/std/src/error.rs b/library/std/src/error.rs index ca83c409822fc..605d953f5da71 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -486,6 +486,27 @@ impl Error for Box { } } +#[stable(feature = "error_by_ref", since = "1.51.0")] +impl<'a, T: Error + ?Sized> Error for &'a T { + #[allow(deprecated, deprecated_in_future)] + fn description(&self) -> &str { + Error::description(&**self) + } + + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn Error> { + Error::cause(&**self) + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) + } + + fn backtrace(&self) -> Option<&Backtrace> { + Error::backtrace(&**self) + } +} + #[stable(feature = "fmt_error", since = "1.11.0")] impl Error for fmt::Error { #[allow(deprecated)] diff --git a/library/std/src/future.rs b/library/std/src/future.rs deleted file mode 100644 index 9d9c36e9afb0f..0000000000000 --- a/library/std/src/future.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Asynchronous values. - -#[doc(inline)] -#[stable(feature = "futures_api", since = "1.36.0")] -pub use core::future::Future; - -#[doc(inline)] -#[unstable(feature = "gen_future", issue = "50547")] -pub use core::future::{from_generator, get_context, ResumeTy}; - -#[doc(inline)] -#[stable(feature = "future_readiness_fns", since = "1.48.0")] -pub use core::future::{pending, ready, Pending, Ready}; - -#[doc(inline)] -#[unstable(feature = "into_future", issue = "67644")] -pub use core::future::IntoFuture; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5ba13c2f91334..92c8b7c177477 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -406,6 +406,8 @@ pub use core::cmp; pub use core::convert; #[stable(feature = "rust1", since = "1.0.0")] pub use core::default; +#[stable(feature = "futures_api", since = "1.36.0")] +pub use core::future; #[stable(feature = "rust1", since = "1.0.0")] pub use core::hash; #[stable(feature = "core_hint", since = "1.27.0")] @@ -505,9 +507,6 @@ pub mod task { pub use alloc::task::*; } -#[stable(feature = "futures_api", since = "1.36.0")] -pub mod future; - // Platform-abstraction modules #[macro_use] mod sys_common; diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 8006c3d277164..fee1bf4c3a6a7 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -103,6 +103,8 @@ crate struct Options { crate should_test: bool, /// List of arguments to pass to the test harness, if running tests. crate test_args: Vec, + /// The working directory in which to run tests. + crate test_run_directory: Option, /// Optional path to persist the doctest executables to, defaults to a /// temporary directory if not set. crate persist_doctests: Option, @@ -175,6 +177,7 @@ impl fmt::Debug for Options { .field("lint_cap", &self.lint_cap) .field("should_test", &self.should_test) .field("test_args", &self.test_args) + .field("test_run_directory", &self.test_run_directory) .field("persist_doctests", &self.persist_doctests) .field("default_passes", &self.default_passes) .field("manual_passes", &self.manual_passes) @@ -572,6 +575,7 @@ impl Options { let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some(); let static_root_path = matches.opt_str("static-root-path"); let generate_search_filter = !matches.opt_present("disable-per-crate-search"); + let test_run_directory = matches.opt_str("test-run-directory").map(PathBuf::from); let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from); let test_builder = matches.opt_str("test-builder").map(PathBuf::from); let codegen_options_strs = matches.opt_strs("C"); @@ -613,6 +617,7 @@ impl Options { display_warnings, show_coverage, crate_version, + test_run_directory, persist_doctests, runtool, runtool_args, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index bbf4de5cdc9a8..30ff124dac60f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -365,6 +365,9 @@ fn run_test( } else { cmd = Command::new(output_file); } + if let Some(run_directory) = options.test_run_directory { + cmd.current_dir(run_directory); + } match cmd.output() { Err(e) => return Err(TestFailure::ExecutionError(e)), diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8e010839ad81e..ef45c98e40629 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2474,7 +2474,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean:: fn render_implementor( cx: &Context<'_>, implementor: &Impl, - parent: &clean::Item, + trait_: &clean::Item, w: &mut Buffer, implementor_dups: &FxHashMap, aliases: &[String], @@ -2494,11 +2494,11 @@ fn render_implementor( w, cx, implementor, - parent, + trait_, AssocItemLink::Anchor(None), RenderMode::Normal, - implementor.impl_item.stable_since(cx.tcx()).as_deref(), - implementor.impl_item.const_stable_since(cx.tcx()).as_deref(), + trait_.stable_since(cx.tcx()).as_deref(), + trait_.const_stable_since(cx.tcx()).as_deref(), false, Some(use_absolute), false, @@ -2937,34 +2937,25 @@ fn render_stability_since_raw( containing_ver: Option<&str>, containing_const_ver: Option<&str>, ) { - let ver = ver.and_then(|inner| if !inner.is_empty() { Some(inner) } else { None }); - - let const_ver = const_ver.and_then(|inner| if !inner.is_empty() { Some(inner) } else { None }); + let ver = ver.filter(|inner| !inner.is_empty()); + let const_ver = const_ver.filter(|inner| !inner.is_empty()); - if let Some(v) = ver { - if let Some(cv) = const_ver { - if const_ver != containing_const_ver { - write!( - w, - "{0} (const: {1})", - v, cv - ); - } else if ver != containing_ver { - write!( - w, - "{0}", - v - ); - } - } else { - if ver != containing_ver { - write!( - w, - "{0}", - v - ); - } + match (ver, const_ver) { + (Some(v), Some(cv)) if const_ver != containing_const_ver => { + write!( + w, + "{0} (const: {1})", + v, cv + ); + } + (Some(v), _) if ver != containing_ver => { + write!( + w, + "{0}", + v + ); } + _ => {} } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 83736295beb19..c61cbf78f771a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -168,6 +168,14 @@ fn opts() -> Vec { stable("test-args", |o| { o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS") }), + unstable("test-run-directory", |o| { + o.optopt( + "", + "test-run-directory", + "The working directory in which to run tests", + "PATH", + ) + }), stable("target", |o| o.optopt("", "target", "target triple to document", "TRIPLE")), stable("markdown-css", |o| { o.optmulti( diff --git a/src/test/rustdoc-ui/run-directory.correct.stdout b/src/test/rustdoc-ui/run-directory.correct.stdout new file mode 100644 index 0000000000000..e9b2754794a78 --- /dev/null +++ b/src/test/rustdoc-ui/run-directory.correct.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/run-directory.rs - foo (line 10) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/test/rustdoc-ui/run-directory.incorrect.stdout b/src/test/rustdoc-ui/run-directory.incorrect.stdout new file mode 100644 index 0000000000000..97a5dbc5c0cd1 --- /dev/null +++ b/src/test/rustdoc-ui/run-directory.incorrect.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/run-directory.rs - foo (line 19) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/test/rustdoc-ui/run-directory.rs b/src/test/rustdoc-ui/run-directory.rs new file mode 100644 index 0000000000000..78431c0e80b59 --- /dev/null +++ b/src/test/rustdoc-ui/run-directory.rs @@ -0,0 +1,23 @@ +// this test asserts that the cwd of doctest invocations is set correctly. + +// revisions: correct incorrect +// check-pass +// [correct]compile-flags:--test --test-run-directory={{src-base}} +// [incorrect]compile-flags:--test --test-run-directory={{src-base}}/coverage +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +/// ``` +/// assert_eq!( +/// std::fs::read_to_string("run-directory.rs").unwrap(), +/// include_str!("run-directory.rs"), +/// ); +/// ``` +#[cfg(correct)] +pub fn foo() {} + +/// ``` +/// assert!(std::fs::read_to_string("run-directory.rs").is_err()); +/// ``` +#[cfg(incorrect)] +pub fn foo() {} diff --git a/src/test/rustdoc/implementor-stable-version.rs b/src/test/rustdoc/implementor-stable-version.rs new file mode 100644 index 0000000000000..0a065d8095bf2 --- /dev/null +++ b/src/test/rustdoc/implementor-stable-version.rs @@ -0,0 +1,19 @@ +#![crate_name = "foo"] + +#![feature(staged_api)] + +#[stable(feature = "bar", since = "OLD 1.0")] +pub trait Bar {} + +#[stable(feature = "baz", since = "OLD 1.0")] +pub trait Baz {} + +pub struct Foo; + +// @has foo/trait.Bar.html '//div[@id="implementors-list"]//span[@class="since"]' 'NEW 2.0' +#[stable(feature = "foobar", since = "NEW 2.0")] +impl Bar for Foo {} + +// @!has foo/trait.Baz.html '//div[@id="implementors-list"]//span[@class="since"]' 'OLD 1.0' +#[stable(feature = "foobaz", since = "OLD 1.0")] +impl Baz for Foo {} diff --git a/src/test/ui/check-static-immutable-mut-slices.rs b/src/test/ui/check-static-immutable-mut-slices.rs index 3be02f6a0f674..8f9680778aa03 100644 --- a/src/test/ui/check-static-immutable-mut-slices.rs +++ b/src/test/ui/check-static-immutable-mut-slices.rs @@ -1,6 +1,6 @@ // Checks that immutable static items can't have mutable slices static TEST: &'static mut [isize] = &mut []; -//~^ ERROR mutable references are not allowed in statics +//~^ ERROR mutable references are not allowed pub fn main() { } diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr index 9ffbb483d139d..a32a94c1315ab 100644 --- a/src/test/ui/check-static-immutable-mut-slices.stderr +++ b/src/test/ui/check-static-immutable-mut-slices.stderr @@ -1,8 +1,8 @@ -error[E0764]: mutable references are not allowed in statics +error[E0764]: mutable references are not allowed in the final value of statics --> $DIR/check-static-immutable-mut-slices.rs:3:37 | LL | static TEST: &'static mut [isize] = &mut []; - | ^^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/const-address-of-mut.stderr b/src/test/ui/consts/const-address-of-mut.stderr index ec2dac5a7d16f..60cdcc7df7449 100644 --- a/src/test/ui/consts/const-address-of-mut.stderr +++ b/src/test/ui/consts/const-address-of-mut.stderr @@ -1,20 +1,29 @@ -error[E0764]: raw mutable references are not allowed in constants +error[E0658]: raw mutable references are not allowed in constants --> $DIR/const-address-of-mut.rs:3:32 | LL | const A: () = { let mut x = 2; &raw mut x; }; - | ^^^^^^^^^^ `&raw mut` is only allowed in `const fn` + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0764]: raw mutable references are not allowed in statics +error[E0658]: raw mutable references are not allowed in statics --> $DIR/const-address-of-mut.rs:5:33 | LL | static B: () = { let mut x = 2; &raw mut x; }; - | ^^^^^^^^^^ `&raw mut` is only allowed in `const fn` + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0764]: raw mutable references are not allowed in statics +error[E0658]: raw mutable references are not allowed in statics --> $DIR/const-address-of-mut.rs:7:37 | LL | static mut C: () = { let mut x = 2; &raw mut x; }; - | ^^^^^^^^^^ `&raw mut` is only allowed in `const fn` + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: raw mutable references are not allowed in constant functions --> $DIR/const-address-of-mut.rs:11:13 @@ -27,5 +36,4 @@ LL | let y = &raw mut x; error: aborting due to 4 previous errors -Some errors have detailed explanations: E0658, E0764. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr index 771d368d78391..ec229d7f53a0f 100644 --- a/src/test/ui/consts/const-eval/issue-65394.stderr +++ b/src/test/ui/consts/const-eval/issue-65394.stderr @@ -1,8 +1,11 @@ -error[E0764]: mutable references are not allowed in constants +error[E0658]: mutable references are not allowed in constants --> $DIR/issue-65394.rs:8:13 | LL | let r = &mut x; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/issue-65394.rs:7:9 @@ -15,5 +18,5 @@ LL | }; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0493, E0764. +Some errors have detailed explanations: E0493, E0658. For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr index c0a320d46cbf9..dd5cadfe2951e 100644 --- a/src/test/ui/consts/const-multi-ref.stderr +++ b/src/test/ui/consts/const-multi-ref.stderr @@ -1,8 +1,11 @@ -error[E0764]: mutable references are not allowed in constants +error[E0658]: mutable references are not allowed in constants --> $DIR/const-multi-ref.rs:6:13 | LL | let p = &mut a; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability --> $DIR/const-multi-ref.rs:16:13 @@ -15,5 +18,4 @@ LL | let p = &a; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0764. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs index 5819daa817af0..24df647f05b7e 100644 --- a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(const_mut_refs)] #![feature(const_fn)] #![feature(raw_ref_op)] @@ -22,9 +23,7 @@ const fn baz(foo: &mut Foo)-> *mut usize { const _: () = { foo().bar(); - //~^ ERROR mutable references are not allowed in constants baz(&mut foo()); - //~^ ERROR mutable references are not allowed in constants }; fn main() {} diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr b/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr deleted file mode 100644 index 2214ce6ee1c87..0000000000000 --- a/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0764]: mutable references are not allowed in constants - --> $DIR/const_mut_address_of.rs:24:5 - | -LL | foo().bar(); - | ^^^^^ `&mut` is only allowed in `const fn` - -error[E0764]: mutable references are not allowed in constants - --> $DIR/const_mut_address_of.rs:26:9 - | -LL | baz(&mut foo()); - | ^^^^^^^^^^ `&mut` is only allowed in `const fn` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs index 9099d5a1b8ea6..544458dfcd8bb 100644 --- a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs +++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(const_mut_refs)] struct Foo { @@ -29,9 +30,6 @@ const fn bazz(foo: &mut Foo) -> usize { fn main() { let _: [(); foo().bar()] = [(); 1]; - //~^ ERROR mutable references are not allowed in constants let _: [(); baz(&mut foo())] = [(); 2]; - //~^ ERROR mutable references are not allowed in constants let _: [(); bazz(&mut foo())] = [(); 3]; - //~^ ERROR mutable references are not allowed in constants } diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr deleted file mode 100644 index 4ca7b128b7c4b..0000000000000 --- a/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0764]: mutable references are not allowed in constants - --> $DIR/const_mut_refs.rs:31:17 - | -LL | let _: [(); foo().bar()] = [(); 1]; - | ^^^^^ `&mut` is only allowed in `const fn` - -error[E0764]: mutable references are not allowed in constants - --> $DIR/const_mut_refs.rs:33:21 - | -LL | let _: [(); baz(&mut foo())] = [(); 2]; - | ^^^^^^^^^^ `&mut` is only allowed in `const fn` - -error[E0764]: mutable references are not allowed in constants - --> $DIR/const_mut_refs.rs:35:22 - | -LL | let _: [(); bazz(&mut foo())] = [(); 3]; - | ^^^^^^^^^^ `&mut` is only allowed in `const fn` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs new file mode 100644 index 0000000000000..166ba20f124e6 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -0,0 +1,57 @@ +#![feature(const_mut_refs)] +#![feature(const_fn)] +#![feature(raw_ref_op)] +#![feature(const_raw_ptr_deref)] + +const NULL: *mut i32 = std::ptr::null_mut(); +const A: *const i32 = &4; + +// It could be made sound to allow it to compile, +// but we do not want to allow this to compile, +// as that would be an enormous footgun in oli-obk's opinion. +const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed + +// Ok, no actual mutable allocation exists +const B2: Option<&mut i32> = None; + +// Not ok, can't prove that no mutable allocation ends up in final value +const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped while borrowed + +const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) } +const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed + +// Ok, because no references to mutable data exist here, since the `{}` moves +// its value and then takes a reference to that. +const C: *const i32 = &{ + let mut x = 42; + x += 3; + x +}; + +use std::cell::UnsafeCell; +struct NotAMutex(UnsafeCell); + +unsafe impl Sync for NotAMutex {} + +const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +// `BAR` works, because `&42` promotes immediately instead of relying on +// the enclosing scope rule. +const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); + +fn main() { + println!("{}", unsafe { *A }); + unsafe { *B = 4 } // Bad news + + unsafe { + **FOO.0.get() = 99; + assert_eq!(**FOO.0.get(), 99); + } +} diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr new file mode 100644 index 0000000000000..cbae74cce6f6b --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -0,0 +1,60 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/mut_ref_in_final.rs:12:21 + | +LL | const B: *mut i32 = &mut 4; + | ^^^^^^ + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:18:40 + | +LL | const B3: Option<&mut i32> = Some(&mut 42); + | ----------^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:21:42 + | +LL | const B4: Option<&mut i32> = helper(&mut 42); + | ------------^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:36:65 + | +LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:39:67 + | +LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:42:71 + | +LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0716, E0764. +For more information about an error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs new file mode 100644 index 0000000000000..1e856ec0a0acc --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -0,0 +1,28 @@ +#![feature(const_mut_refs)] +#![feature(const_fn)] +#![feature(raw_ref_op)] +#![feature(const_raw_ptr_deref)] + +// This file checks that our dynamic checks catch things that the static checks miss. +// We do not have static checks for these, because we do not look into function bodies. +// We treat all functions as not returning a mutable reference, because there is no way to +// do that without causing the borrow checker to complain (see the B4/helper test in +// mut_ref_in_final.rs). + +const fn helper() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour (integer as pointer), who doesn't love tests like this. + // This code never gets executed, because the static checks fail before that. + Some(&mut *(42 as *mut i32)) //~ ERROR any use of this value will cause an error +} } +// The error is an evaluation error and not a validation error, so the error is reported +// directly at the site where it occurs. +const A: Option<&mut i32> = helper(); + +const fn helper2() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour (dangling pointer), who doesn't love tests like this. + // This code never gets executed, because the static checks fail before that. + Some(&mut *(&mut 42 as *mut i32)) +} } +const B: Option<&mut i32> = helper2(); //~ ERROR encountered dangling pointer in final constant + +fn main() {} diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr new file mode 100644 index 0000000000000..0bbf84b71bb68 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -0,0 +1,23 @@ +error: any use of this value will cause an error + --> $DIR/mut_ref_in_final_dynamic_check.rs:15:10 + | +LL | Some(&mut *(42 as *mut i32)) + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | unable to turn bytes into a pointer + | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:15:10 + | inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:19:29 +... +LL | const A: Option<&mut i32> = helper(); + | ------------------------------------- + | + = note: `#[deny(const_err)]` on by default + +error: encountered dangling pointer in final constant + --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1 + | +LL | const B: Option<&mut i32> = helper2(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr index dc86e178a42c3..3eac61c0ce670 100644 --- a/src/test/ui/consts/const_let_assign3.stderr +++ b/src/test/ui/consts/const_let_assign3.stderr @@ -7,19 +7,24 @@ LL | const fn foo(&mut self, x: u32) { = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0764]: mutable references are not allowed in constants +error[E0658]: mutable references are not allowed in constants --> $DIR/const_let_assign3.rs:16:5 | LL | s.foo(3); - | ^ `&mut` is only allowed in `const fn` + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0764]: mutable references are not allowed in constants +error[E0658]: mutable references are not allowed in constants --> $DIR/const_let_assign3.rs:22:13 | LL | let y = &mut x; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error: aborting due to 3 previous errors -Some errors have detailed explanations: E0658, E0764. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/issue-17718-const-bad-values.rs b/src/test/ui/consts/issue-17718-const-bad-values.rs index 49023f18ddbfb..62bbb3b569c37 100644 --- a/src/test/ui/consts/issue-17718-const-bad-values.rs +++ b/src/test/ui/consts/issue-17718-const-bad-values.rs @@ -1,10 +1,9 @@ const C1: &'static mut [usize] = &mut []; -//~^ ERROR: mutable references are not allowed in constants +//~^ ERROR: mutable references are not allowed static mut S: usize = 3; const C2: &'static mut usize = unsafe { &mut S }; //~^ ERROR: constants cannot refer to statics //~| ERROR: constants cannot refer to statics -//~| ERROR: mutable references are not allowed in constants fn main() {} diff --git a/src/test/ui/consts/issue-17718-const-bad-values.stderr b/src/test/ui/consts/issue-17718-const-bad-values.stderr index 7c50978d4ebb8..ce60aaa0797f8 100644 --- a/src/test/ui/consts/issue-17718-const-bad-values.stderr +++ b/src/test/ui/consts/issue-17718-const-bad-values.stderr @@ -1,8 +1,8 @@ -error[E0764]: mutable references are not allowed in constants +error[E0764]: mutable references are not allowed in the final value of constants --> $DIR/issue-17718-const-bad-values.rs:1:34 | LL | const C1: &'static mut [usize] = &mut []; - | ^^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^^ error[E0013]: constants cannot refer to statics --> $DIR/issue-17718-const-bad-values.rs:5:46 @@ -20,13 +20,7 @@ LL | const C2: &'static mut usize = unsafe { &mut S }; | = help: consider extracting the value of the `static` to a `const`, and referring to that -error[E0764]: mutable references are not allowed in constants - --> $DIR/issue-17718-const-bad-values.rs:5:41 - | -LL | const C2: &'static mut usize = unsafe { &mut S }; - | ^^^^^^ `&mut` is only allowed in `const fn` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0013, E0764. For more information about an error, try `rustc --explain E0013`. diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/projection_qualif.mut_refs.stderr deleted file mode 100644 index fad8f011f75f5..0000000000000 --- a/src/test/ui/consts/projection_qualif.mut_refs.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0764]: mutable references are not allowed in constants - --> $DIR/projection_qualif.rs:10:27 - | -LL | let b: *mut u32 = &mut a; - | ^^^^^^ `&mut` is only allowed in `const fn` - -error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/projection_qualif.rs:11:18 - | -LL | unsafe { *b = 5; } - | ^^^^^^ - | - = note: see issue #51911 for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0658, E0764. -For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr deleted file mode 100644 index fad8f011f75f5..0000000000000 --- a/src/test/ui/consts/projection_qualif.stock.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0764]: mutable references are not allowed in constants - --> $DIR/projection_qualif.rs:10:27 - | -LL | let b: *mut u32 = &mut a; - | ^^^^^^ `&mut` is only allowed in `const fn` - -error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/projection_qualif.rs:11:18 - | -LL | unsafe { *b = 5; } - | ^^^^^^ - | - = note: see issue #51911 for more information - = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0658, E0764. -For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/read_from_static_mut_ref.rs b/src/test/ui/consts/read_from_static_mut_ref.rs deleted file mode 100644 index 5faa983ab09f7..0000000000000 --- a/src/test/ui/consts/read_from_static_mut_ref.rs +++ /dev/null @@ -1,9 +0,0 @@ -// We are keeping this test in case we decide to allow mutable references in statics again -#![feature(const_mut_refs)] -#![allow(const_err)] - -static OH_NO: &mut i32 = &mut 42; -//~^ ERROR mutable references are not allowed in statics -fn main() { - assert_eq!(*OH_NO, 42); -} diff --git a/src/test/ui/consts/read_from_static_mut_ref.stderr b/src/test/ui/consts/read_from_static_mut_ref.stderr deleted file mode 100644 index c936ac0b7d585..0000000000000 --- a/src/test/ui/consts/read_from_static_mut_ref.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0764]: mutable references are not allowed in statics - --> $DIR/read_from_static_mut_ref.rs:5:26 - | -LL | static OH_NO: &mut i32 = &mut 42; - | ^^^^^^^ `&mut` is only allowed in `const fn` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr index 36c280ca5c607..8db75dd63cf2a 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr @@ -1,9 +1,9 @@ -error[E0764]: mutable references are not allowed in statics - --> $DIR/static_mut_containing_mut_ref2.rs:7:46 +error[E0080]: could not evaluate static initializer + --> $DIR/static_mut_containing_mut_ref2.rs:7:45 | LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer error: aborting due to previous error -For more information about this error, try `rustc --explain E0764`. +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index 2821d1a015435..61368546083db 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -5,6 +5,7 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; -//~^ ERROR mutable references are not allowed in statics +//[mut_refs]~^ ERROR could not evaluate static initializer +//[stock]~^^ ERROR mutable references are not allowed in statics fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr index 36c280ca5c607..5cdcea2323109 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr @@ -1,9 +1,12 @@ -error[E0764]: mutable references are not allowed in statics +error[E0658]: mutable references are not allowed in statics --> $DIR/static_mut_containing_mut_ref2.rs:7:46 | LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0764`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr b/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr new file mode 100644 index 0000000000000..3ee50907461ca --- /dev/null +++ b/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr @@ -0,0 +1,12 @@ +error[E0658]: dereferencing raw pointers in constants is unstable + --> $DIR/write_to_mut_ref_dest.rs:11:18 + | +LL | unsafe { *b = 5; } + | ^^^^^^ + | + = note: see issue #51911 for more information + = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/write_to_mut_ref_dest.rs similarity index 72% rename from src/test/ui/consts/projection_qualif.rs rename to src/test/ui/consts/write_to_mut_ref_dest.rs index 5e2584a6e951a..d35df330bb8c3 100644 --- a/src/test/ui/consts/projection_qualif.rs +++ b/src/test/ui/consts/write_to_mut_ref_dest.rs @@ -7,7 +7,7 @@ use std::cell::Cell; const FOO: &u32 = { let mut a = 42; { - let b: *mut u32 = &mut a; //~ ERROR mutable references are not allowed in constants + let b: *mut u32 = &mut a; //[stock]~ ERROR mutable references are not allowed in constants unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants } &{a} diff --git a/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr new file mode 100644 index 0000000000000..2b6d1d3267b61 --- /dev/null +++ b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr @@ -0,0 +1,21 @@ +error[E0658]: mutable references are not allowed in constants + --> $DIR/write_to_mut_ref_dest.rs:10:27 + | +LL | let b: *mut u32 = &mut a; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: dereferencing raw pointers in constants is unstable + --> $DIR/write_to_mut_ref_dest.rs:11:18 + | +LL | unsafe { *b = 5; } + | ^^^^^^ + | + = note: see issue #51911 for more information + = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/write_to_static_via_mut_ref.rs b/src/test/ui/consts/write_to_static_via_mut_ref.rs new file mode 100644 index 0000000000000..665c305e9617f --- /dev/null +++ b/src/test/ui/consts/write_to_static_via_mut_ref.rs @@ -0,0 +1,8 @@ +#![feature(const_mut_refs)] +#![allow(const_err)] + +static OH_NO: &mut i32 = &mut 42; //~ ERROR mutable references are not allowed +fn main() { + assert_eq!(*OH_NO, 42); + *OH_NO = 43; //~ ERROR cannot assign to `*OH_NO`, as `OH_NO` is an immutable static +} diff --git a/src/test/ui/consts/write_to_static_via_mut_ref.stderr b/src/test/ui/consts/write_to_static_via_mut_ref.stderr new file mode 100644 index 0000000000000..d19e998d61736 --- /dev/null +++ b/src/test/ui/consts/write_to_static_via_mut_ref.stderr @@ -0,0 +1,16 @@ +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/write_to_static_via_mut_ref.rs:4:26 + | +LL | static OH_NO: &mut i32 = &mut 42; + | ^^^^^^^ + +error[E0594]: cannot assign to `*OH_NO`, as `OH_NO` is an immutable static item + --> $DIR/write_to_static_via_mut_ref.rs:7:5 + | +LL | *OH_NO = 43; + | ^^^^^^^^^^^ cannot assign + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0594, E0764. +For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs index 262f7bc72c739..c211ad1a2f8f6 100644 --- a/src/test/ui/error-codes/E0017.rs +++ b/src/test/ui/error-codes/E0017.rs @@ -2,12 +2,13 @@ static X: i32 = 1; const C: i32 = 2; static mut M: i32 = 3; -const CR: &'static mut i32 = &mut C; //~ ERROR E0764 +const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0764 +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 //~| ERROR cannot borrow + //~| ERROR mutable references are not allowed -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764 +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable -static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0764 +static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not fn main() {} diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr index ea591587e6daa..7d959b6d148ed 100644 --- a/src/test/ui/error-codes/E0017.stderr +++ b/src/test/ui/error-codes/E0017.stderr @@ -13,17 +13,26 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in constants +error[E0764]: mutable references are not allowed in the final value of constants --> $DIR/E0017.rs:5:30 | LL | const CR: &'static mut i32 = &mut C; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ -error[E0764]: mutable references are not allowed in statics +error[E0658]: mutation through a reference is not allowed in statics --> $DIR/E0017.rs:7:39 | LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0017.rs:7:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ error[E0596]: cannot borrow immutable static item `X` as mutable --> $DIR/E0017.rs:7:39 @@ -32,7 +41,7 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; | ^^^^^^ cannot borrow as mutable warning: taking a mutable reference to a `const` item - --> $DIR/E0017.rs:10:38 + --> $DIR/E0017.rs:11:38 | LL | static CONST_REF: &'static mut i32 = &mut C; | ^^^^^^ @@ -45,19 +54,19 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in statics - --> $DIR/E0017.rs:10:38 +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0017.rs:11:38 | LL | static CONST_REF: &'static mut i32 = &mut C; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ -error[E0764]: mutable references are not allowed in statics - --> $DIR/E0017.rs:12:52 +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0017.rs:13:52 | LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ -error: aborting due to 5 previous errors; 2 warnings emitted +error: aborting due to 6 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0596, E0764. +Some errors have detailed explanations: E0596, E0658, E0764. For more information about an error, try `rustc --explain E0596`. diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs index bb0c4979b9ac9..6049d95f0d277 100644 --- a/src/test/ui/error-codes/E0388.rs +++ b/src/test/ui/error-codes/E0388.rs @@ -1,12 +1,13 @@ static X: i32 = 1; const C: i32 = 2; -const CR: &'static mut i32 = &mut C; //~ ERROR E0764 +const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow - //~| ERROR E0764 + //~| ERROR E0658 + //~| ERROR mutable references are not allowed -static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764 +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable fn main() {} diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr index 73e0b139cd056..4886a156d2ea5 100644 --- a/src/test/ui/error-codes/E0388.stderr +++ b/src/test/ui/error-codes/E0388.stderr @@ -13,17 +13,26 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in constants +error[E0764]: mutable references are not allowed in the final value of constants --> $DIR/E0388.rs:4:30 | LL | const CR: &'static mut i32 = &mut C; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ -error[E0764]: mutable references are not allowed in statics +error[E0658]: mutation through a reference is not allowed in statics --> $DIR/E0388.rs:6:39 | LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0388.rs:6:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ error[E0596]: cannot borrow immutable static item `X` as mutable --> $DIR/E0388.rs:6:39 @@ -32,7 +41,7 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; | ^^^^^^ cannot borrow as mutable warning: taking a mutable reference to a `const` item - --> $DIR/E0388.rs:9:38 + --> $DIR/E0388.rs:10:38 | LL | static CONST_REF: &'static mut i32 = &mut C; | ^^^^^^ @@ -45,13 +54,13 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in statics - --> $DIR/E0388.rs:9:38 +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0388.rs:10:38 | LL | static CONST_REF: &'static mut i32 = &mut C; - | ^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^ -error: aborting due to 4 previous errors; 2 warnings emitted +error: aborting due to 5 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0596, E0764. +Some errors have detailed explanations: E0596, E0658, E0764. For more information about an error, try `rustc --explain E0596`. diff --git a/src/test/ui/feature-gates/feature-gate-cfg-version.rs b/src/test/ui/feature-gates/feature-gate-cfg-version.rs index c29ef99945e71..e35784a68d101 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-version.rs +++ b/src/test/ui/feature-gates/feature-gate-cfg-version.rs @@ -1,3 +1,9 @@ +#[cfg(version(42))] //~ ERROR: expected a version literal +//~^ ERROR `cfg(version)` is experimental and subject to change +fn foo() {} +#[cfg(version(1.20))] //~ ERROR: expected a version literal +//~^ ERROR `cfg(version)` is experimental and subject to change +fn foo() -> bool { true } #[cfg(version("1.44"))] //~^ ERROR `cfg(version)` is experimental and subject to change fn foo() -> bool { true } @@ -11,30 +17,32 @@ fn bar() -> bool { false } #[cfg(version(false))] //~ ERROR: expected a version literal //~^ ERROR `cfg(version)` is experimental and subject to change fn bar() -> bool { false } -#[cfg(version("foo"))] //~ ERROR: invalid version literal +#[cfg(version("foo"))] //~ WARNING: unknown version literal format //~^ ERROR `cfg(version)` is experimental and subject to change fn bar() -> bool { false } -#[cfg(version("999"))] +#[cfg(version("999"))] //~ WARNING: unknown version literal format //~^ ERROR `cfg(version)` is experimental and subject to change fn bar() -> bool { false } -#[cfg(version("-1"))] //~ ERROR: invalid version literal +#[cfg(version("-1"))] //~ WARNING: unknown version literal format //~^ ERROR `cfg(version)` is experimental and subject to change fn bar() -> bool { false } -#[cfg(version("65536"))] //~ ERROR: invalid version literal +#[cfg(version("65536"))] //~ WARNING: unknown version literal format //~^ ERROR `cfg(version)` is experimental and subject to change fn bar() -> bool { false } -#[cfg(version("0"))] +#[cfg(version("0"))] //~ WARNING: unknown version literal format //~^ ERROR `cfg(version)` is experimental and subject to change fn bar() -> bool { true } - -#[cfg(version("1.65536.2"))] +#[cfg(version("1.0"))] +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { true } +#[cfg(version("1.65536.2"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version("1.20.0-stable"))] //~ WARNING: unknown version literal format //~^ ERROR `cfg(version)` is experimental and subject to change -fn version_check_bug() {} +fn bar() {} fn main() { - // This should fail but due to a bug in version_check `1.65536.2` is interpreted as `1.2`. - // See https://github.com/SergioBenitez/version_check/issues/11 - version_check_bug(); assert!(foo()); assert!(bar()); assert!(cfg!(version("1.42"))); //~ ERROR `cfg(version)` is experimental and subject to change diff --git a/src/test/ui/feature-gates/feature-gate-cfg-version.stderr b/src/test/ui/feature-gates/feature-gate-cfg-version.stderr index bdf160b5a0270..ae899d409ecf9 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-version.stderr +++ b/src/test/ui/feature-gates/feature-gate-cfg-version.stderr @@ -1,6 +1,36 @@ error[E0658]: `cfg(version)` is experimental and subject to change --> $DIR/feature-gate-cfg-version.rs:1:7 | +LL | #[cfg(version(42))] + | ^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error: expected a version literal + --> $DIR/feature-gate-cfg-version.rs:1:15 + | +LL | #[cfg(version(42))] + | ^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:4:7 + | +LL | #[cfg(version(1.20))] + | ^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error: expected a version literal + --> $DIR/feature-gate-cfg-version.rs:4:15 + | +LL | #[cfg(version(1.20))] + | ^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:7:7 + | LL | #[cfg(version("1.44"))] | ^^^^^^^^^^^^^^^ | @@ -8,7 +38,7 @@ LL | #[cfg(version("1.44"))] = help: add `#![feature(cfg_version)]` to the crate attributes to enable error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:4:11 + --> $DIR/feature-gate-cfg-version.rs:10:11 | LL | #[cfg(not(version("1.44")))] | ^^^^^^^^^^^^^^^ @@ -17,7 +47,7 @@ LL | #[cfg(not(version("1.44")))] = help: add `#![feature(cfg_version)]` to the crate attributes to enable error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:8:7 + --> $DIR/feature-gate-cfg-version.rs:14:7 | LL | #[cfg(version("1.43", "1.44", "1.45"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,13 +56,13 @@ LL | #[cfg(version("1.43", "1.44", "1.45"))] = help: add `#![feature(cfg_version)]` to the crate attributes to enable error: expected single version literal - --> $DIR/feature-gate-cfg-version.rs:8:7 + --> $DIR/feature-gate-cfg-version.rs:14:7 | LL | #[cfg(version("1.43", "1.44", "1.45"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:11:7 + --> $DIR/feature-gate-cfg-version.rs:17:7 | LL | #[cfg(version(false))] | ^^^^^^^^^^^^^^ @@ -41,13 +71,13 @@ LL | #[cfg(version(false))] = help: add `#![feature(cfg_version)]` to the crate attributes to enable error: expected a version literal - --> $DIR/feature-gate-cfg-version.rs:11:15 + --> $DIR/feature-gate-cfg-version.rs:17:15 | LL | #[cfg(version(false))] | ^^^^^ error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:14:7 + --> $DIR/feature-gate-cfg-version.rs:20:7 | LL | #[cfg(version("foo"))] | ^^^^^^^^^^^^^^ @@ -55,14 +85,14 @@ LL | #[cfg(version("foo"))] = note: see issue #64796 for more information = help: add `#![feature(cfg_version)]` to the crate attributes to enable -error: invalid version literal - --> $DIR/feature-gate-cfg-version.rs:14:15 +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:20:15 | LL | #[cfg(version("foo"))] | ^^^^^ error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:17:7 + --> $DIR/feature-gate-cfg-version.rs:23:7 | LL | #[cfg(version("999"))] | ^^^^^^^^^^^^^^ @@ -70,8 +100,14 @@ LL | #[cfg(version("999"))] = note: see issue #64796 for more information = help: add `#![feature(cfg_version)]` to the crate attributes to enable +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:23:15 + | +LL | #[cfg(version("999"))] + | ^^^^^ + error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:20:7 + --> $DIR/feature-gate-cfg-version.rs:26:7 | LL | #[cfg(version("-1"))] | ^^^^^^^^^^^^^ @@ -79,14 +115,14 @@ LL | #[cfg(version("-1"))] = note: see issue #64796 for more information = help: add `#![feature(cfg_version)]` to the crate attributes to enable -error: invalid version literal - --> $DIR/feature-gate-cfg-version.rs:20:15 +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:26:15 | LL | #[cfg(version("-1"))] | ^^^^ error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:23:7 + --> $DIR/feature-gate-cfg-version.rs:29:7 | LL | #[cfg(version("65536"))] | ^^^^^^^^^^^^^^^^ @@ -94,14 +130,14 @@ LL | #[cfg(version("65536"))] = note: see issue #64796 for more information = help: add `#![feature(cfg_version)]` to the crate attributes to enable -error: invalid version literal - --> $DIR/feature-gate-cfg-version.rs:23:15 +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:29:15 | LL | #[cfg(version("65536"))] | ^^^^^^^ error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:26:7 + --> $DIR/feature-gate-cfg-version.rs:32:7 | LL | #[cfg(version("0"))] | ^^^^^^^^^^^^ @@ -109,8 +145,23 @@ LL | #[cfg(version("0"))] = note: see issue #64796 for more information = help: add `#![feature(cfg_version)]` to the crate attributes to enable +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:32:15 + | +LL | #[cfg(version("0"))] + | ^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:35:7 + | +LL | #[cfg(version("1.0"))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:30:7 + --> $DIR/feature-gate-cfg-version.rs:38:7 | LL | #[cfg(version("1.65536.2"))] | ^^^^^^^^^^^^^^^^^^^^ @@ -118,8 +169,29 @@ LL | #[cfg(version("1.65536.2"))] = note: see issue #64796 for more information = help: add `#![feature(cfg_version)]` to the crate attributes to enable +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:38:15 + | +LL | #[cfg(version("1.65536.2"))] + | ^^^^^^^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:41:7 + | +LL | #[cfg(version("1.20.0-stable"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:41:15 + | +LL | #[cfg(version("1.20.0-stable"))] + | ^^^^^^^^^^^^^^^ + error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:40:18 + --> $DIR/feature-gate-cfg-version.rs:48:18 | LL | assert!(cfg!(version("1.42"))); | ^^^^^^^^^^^^^^^ @@ -127,6 +199,6 @@ LL | assert!(cfg!(version("1.42"))); = note: see issue #64796 for more information = help: add `#![feature(cfg_version)]` to the crate attributes to enable -error: aborting due to 16 previous errors +error: aborting due to 19 previous errors; 7 warnings emitted For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/hygiene/no_implicit_prelude-2021.rs b/src/test/ui/hygiene/no_implicit_prelude-2021.rs new file mode 100644 index 0000000000000..0fe9ae56c6564 --- /dev/null +++ b/src/test/ui/hygiene/no_implicit_prelude-2021.rs @@ -0,0 +1,9 @@ +// check-pass +// edition:2021 + +#![no_implicit_prelude] + +fn main() { + assert!(true, "hoi"); + assert!(false, "hoi {}", 123); +} diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs index 273187a5a13be..6ec6e7bdcb81e 100644 --- a/src/test/ui/issues/issue-46604.rs +++ b/src/test/ui/issues/issue-46604.rs @@ -1,4 +1,4 @@ -static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0764 +static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR mutable references are not allowed fn write>(buffer: T) { } fn main() { diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr index 5421721dec2e3..7faa2d79ba483 100644 --- a/src/test/ui/issues/issue-46604.stderr +++ b/src/test/ui/issues/issue-46604.stderr @@ -1,8 +1,8 @@ -error[E0764]: mutable references are not allowed in statics +error[E0764]: mutable references are not allowed in the final value of statics --> $DIR/issue-46604.rs:1:25 | LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; - | ^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^^^^^^^^^^^^^^^ error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:6:5 diff --git a/src/test/ui/lint/dead-code/const-and-self.rs b/src/test/ui/lint/dead-code/const-and-self.rs index 1a7b3f43cda14..0bcdd6edf0d66 100644 --- a/src/test/ui/lint/dead-code/const-and-self.rs +++ b/src/test/ui/lint/dead-code/const-and-self.rs @@ -1,6 +1,6 @@ // check-pass -#![deny(dead_code)] +#![warn(dead_code)] const TLC: usize = 4; @@ -28,8 +28,27 @@ impl Foo for X { } } +enum E { + A, + B, //~ WARN variant is never constructed: `B` + C, //~ WARN variant is never constructed: `C` +} + +type F = E; + +impl E { + fn check(&self) -> bool { + match self { + Self::A => true, + Self::B => false, + F::C => false, + } + } +} + fn main() { let s = [0,1,2,3]; s.doit(); X::foo(); + E::A.check(); } diff --git a/src/test/ui/lint/dead-code/const-and-self.stderr b/src/test/ui/lint/dead-code/const-and-self.stderr new file mode 100644 index 0000000000000..c0e406189e8ab --- /dev/null +++ b/src/test/ui/lint/dead-code/const-and-self.stderr @@ -0,0 +1,20 @@ +warning: variant is never constructed: `B` + --> $DIR/const-and-self.rs:33:5 + | +LL | B, + | ^ + | +note: the lint level is defined here + --> $DIR/const-and-self.rs:3:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: variant is never constructed: `C` + --> $DIR/const-and-self.rs:34:5 + | +LL | C, + | ^ + +warning: 2 warnings emitted + diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr index 051896cb89c8f..1683841e9d781 100644 --- a/src/test/ui/never_type/issue-52443.stderr +++ b/src/test/ui/never_type/issue-52443.stderr @@ -39,11 +39,14 @@ error[E0015]: calls in constants are limited to constant functions, tuple struct LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ -error[E0764]: mutable references are not allowed in constants +error[E0658]: mutable references are not allowed in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants --> $DIR/issue-52443.rs:9:21 @@ -53,5 +56,5 @@ LL | [(); { for _ in 0usize.. {}; 0}]; error: aborting due to 6 previous errors; 1 warning emitted -Some errors have detailed explanations: E0015, E0308, E0744, E0764. +Some errors have detailed explanations: E0015, E0308, E0658, E0744. For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/unsafe/ranged_ints2_const.rs b/src/test/ui/unsafe/ranged_ints2_const.rs index 65e0d79308ca3..b7178c2b52bfb 100644 --- a/src/test/ui/unsafe/ranged_ints2_const.rs +++ b/src/test/ui/unsafe/ranged_ints2_const.rs @@ -18,3 +18,9 @@ const fn bar() -> NonZero { let y = unsafe { &mut x.0 }; //~ ERROR mutable references unsafe { NonZero(1) } } + +const fn boo() -> NonZero { + let mut x = unsafe { NonZero(1) }; + unsafe { let y = &mut x.0; } //~ ERROR mutable references + unsafe { NonZero(1) } +} diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.stderr index 5ce4296458e6d..a0dc950e76dd1 100644 --- a/src/test/ui/unsafe/ranged_ints2_const.stderr +++ b/src/test/ui/unsafe/ranged_ints2_const.stderr @@ -16,6 +16,15 @@ LL | let y = unsafe { &mut x.0 }; = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:24:22 + | +LL | unsafe { let y = &mut x.0; } + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block --> $DIR/ranged_ints2_const.rs:11:13 | @@ -24,7 +33,7 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0133, E0658. For more information about an error, try `rustc --explain E0133`. diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index 29131f686a9dc..6ec292aba6495 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -149,7 +149,22 @@ fn get_commands(template: &str) -> Result, ()> { } } - let args = cap.name("args").map_or(vec![], |m| shlex::split(m.as_str()).unwrap()); + let args = cap.name("args").map_or(Some(vec![]), |m| shlex::split(m.as_str())); + + let args = match args { + Some(args) => args, + None => { + print_err( + &format!( + "Invalid arguments to shlex::split: `{}`", + cap.name("args").unwrap().as_str() + ), + lineno, + ); + errors = true; + continue; + } + }; if !cmd.validate(&args, commands.len(), lineno) { errors = true;