From 39466bc58b15cca644afcdf79a152625fc75987e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 5 Aug 2020 16:49:48 +1000 Subject: [PATCH 01/26] implement Error for &(impl Error) --- library/std/src/error.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 3b4cb859dd425..cb70b38850cbe 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -506,6 +506,27 @@ impl Error for Box { } } +#[stable(feature = "error_by_ref", since = "1.47.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)] From 573ec314b635178533f68160f2dab3dd345d5df2 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sat, 31 Oct 2020 20:16:15 +1000 Subject: [PATCH 02/26] update stabilization to 1.49.0 --- library/std/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index cb70b38850cbe..8fd9f09b9de75 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -506,7 +506,7 @@ impl Error for Box { } } -#[stable(feature = "error_by_ref", since = "1.47.0")] +#[stable(feature = "error_by_ref", since = "1.49.0")] impl<'a, T: Error + ?Sized> Error for &'a T { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { From bbf5001b9428bbf5b4ac93f42dc7017b27c9002f Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 21 Dec 2020 18:40:34 +1000 Subject: [PATCH 03/26] bump stabilization to 1.51.0 --- library/std/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 8fd9f09b9de75..4ff60709b2079 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -506,7 +506,7 @@ impl Error for Box { } } -#[stable(feature = "error_by_ref", since = "1.49.0")] +#[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 { From 737867618b3c92330c42b7bb488eb0ee387f2e04 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Tue, 19 Jan 2021 20:08:30 -0800 Subject: [PATCH 04/26] Fix sysroot option not being honored across rustc Change link_sanitizer_runtime() to check if the sanitizer library exists in the specified/session sysroot, and if it doesn't exist, use the default sysroot. --- compiler/rustc_codegen_ssa/src/back/link.rs | 28 +++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 55fddb38e10be..175094b129c8f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -887,9 +887,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(); @@ -900,10 +913,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" @@ -911,7 +925,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); } _ => {} From 3e9f27dadfea2921649837c1a282ad159ceb8684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 08:06:01 +0100 Subject: [PATCH 05/26] Remove unnecessary closure --- compiler/rustc_typeck/src/check/check.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 8e339eb26b26c..279c4422fe129 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -932,11 +932,11 @@ 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)); // Check existing impl methods to see if they are both present in trait // and compatible with trait signature - for impl_item in impl_items() { + for impl_item in impl_items { let namespace = impl_item.kind.namespace(); let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id)); let ty_trait_item = tcx From 58a90de9adfac7cc26fe178b3f736153b756a515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 08:14:25 +0100 Subject: [PATCH 06/26] No peeking --- compiler/rustc_typeck/src/check/check.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 279c4422fe129..e89a063598ab7 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -854,13 +854,7 @@ pub(super) fn check_specialization_validity<'tcx>( } 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 opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| { match parent_item { From 9988821a04073360c27bd95b9535a8dceca67d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 08:22:15 +0100 Subject: [PATCH 07/26] Move missing_item check inside condition --- compiler/rustc_typeck/src/check/check.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index e89a063598ab7..ace2ccb2fceac 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1043,9 +1043,9 @@ pub(super) fn check_impl_items_against_trait<'tcx>( } } - // 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()) { + // 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) @@ -1058,10 +1058,10 @@ 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); + if !missing_items.is_empty() { + missing_items_err(tcx, impl_span, &missing_items, full_impl_span); + } } } From d63b278c2ff01b73653397a5e2c469689ef0adf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 18:15:55 +0100 Subject: [PATCH 08/26] Only scan through assoc items once in check_impl_items_against_trait --- compiler/rustc_typeck/src/check/check.rs | 215 ++++++++++++----------- 1 file changed, 117 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index ace2ccb2fceac..eda5a27e97e3a 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -846,15 +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))) - } - }); + 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 { @@ -931,105 +929,72 @@ pub(super) fn check_impl_items_against_trait<'tcx>( // 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(); 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 associated_items = tcx.associated_items(impl_trait_ref.def_id); + + 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, + ); } } @@ -1040,6 +1005,8 @@ 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); } } @@ -1065,6 +1032,58 @@ pub(super) fn check_impl_items_against_trait<'tcx>( } } +#[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() + ) + } + + 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 /// identifies types that contain themselves without indirection through a /// pointer, which would mean their size is unbounded. From ee639de007e952c006cee53278f9bc1fd773e7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 18:17:53 +0100 Subject: [PATCH 09/26] Only guess span if absolutely necessary --- compiler/rustc_typeck/src/check/check.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index eda5a27e97e3a..f937970aa552f 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -894,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. @@ -1011,6 +1009,8 @@ pub(super) fn check_impl_items_against_trait<'tcx>( } 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() { From aa4f5833e1e3dc468923be7be988eb9e25a9e4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 18:19:27 +0100 Subject: [PATCH 10/26] Only query associated_items once --- compiler/rustc_typeck/src/check/check.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index f937970aa552f..fa630bb2b52e3 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -921,14 +921,13 @@ 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 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 ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id)); - let associated_items = tcx.associated_items(impl_trait_ref.def_id); let mut items = associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id); @@ -1010,7 +1009,7 @@ pub(super) fn check_impl_items_against_trait<'tcx>( 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() { From f29b32983d1e885b0e141b6aac2cae281ff39a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 22 Jan 2021 18:55:37 +0100 Subject: [PATCH 11/26] Fix formatting --- compiler/rustc_typeck/src/check/check.rs | 26 ++++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index fa630bb2b52e3..518090a710d3b 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -929,17 +929,15 @@ pub(super) fn check_impl_items_against_trait<'tcx>( for impl_item in impl_items { let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id)); - let mut items = associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id); + 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 - } + 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 @@ -947,7 +945,7 @@ pub(super) fn check_impl_items_against_trait<'tcx>( let mut compatible_kind = is_compatible(&ty_trait_item); let mut trait_item = ty_trait_item; - if !compatible_kind { + if !compatible_kind { if let Some(ty_trait_item) = items.find(is_compatible) { compatible_kind = true; trait_item = ty_trait_item; @@ -1003,7 +1001,13 @@ pub(super) fn check_impl_items_against_trait<'tcx>( impl_item, ); } else { - report_mismatch_error(tcx, ty_trait_item.def_id, impl_trait_ref, impl_item, &ty_impl_item); + report_mismatch_error( + tcx, + ty_trait_item.def_id, + impl_trait_ref, + impl_item, + &ty_impl_item, + ); } } From 99a1dea1b7727885d2660bae665cff165fb86a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 23 Jan 2021 00:00:00 +0000 Subject: [PATCH 12/26] Do not mark unit variants as used when in path pattern Record that we are processing a pattern so that code responsible for handling path resolution can correctly decide whether to mark it as used or not. --- compiler/rustc_passes/src/dead.rs | 2 +- src/test/ui/lint/dead-code/const-and-self.rs | 21 ++++++++++++++++++- .../ui/lint/dead-code/const-and-self.stderr | 20 ++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/lint/dead-code/const-and-self.stderr 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/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 + From 794880c6b564d67b75cc89eed1d839d301facadf Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 23 Jan 2021 11:11:51 +0100 Subject: [PATCH 13/26] Don't provide backend_optimization_level query for extern crates --- compiler/rustc_codegen_ssa/src/base.rs | 2 +- compiler/rustc_codegen_ssa/src/lib.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) 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` From d118021f8bfbfda2cd93277c15c607b2c66ff93c Mon Sep 17 00:00:00 2001 From: oli Date: Sun, 3 Jan 2021 18:46:20 +0000 Subject: [PATCH 14/26] Permit mutable references in all const contexts --- .../src/transform/check_consts/ops.rs | 71 ++++++++++++------- .../src/transform/check_consts/validation.rs | 29 +++++++- .../ui/check-static-immutable-mut-slices.rs | 2 +- .../check-static-immutable-mut-slices.stderr | 4 +- .../ui/consts/const-address-of-mut.stderr | 24 ++++--- .../ui/consts/const-eval/issue-65394.stderr | 9 ++- src/test/ui/consts/const-multi-ref.stderr | 10 +-- .../const-mut-refs/const_mut_address_of.rs | 3 +- .../const_mut_address_of.stderr | 15 ---- .../consts/const-mut-refs/const_mut_refs.rs | 4 +- .../const-mut-refs/const_mut_refs.stderr | 21 ------ .../consts/const-mut-refs/mut_ref_in_final.rs | 24 +++++++ .../const-mut-refs/mut_ref_in_final.stderr | 9 +++ .../const-mut-refs/mut_ref_in_final_ok.rs | 22 ++++++ .../const-mut-refs/mut_ref_in_final_ok.stderr | 13 ++++ src/test/ui/consts/const_let_assign3.stderr | 17 +++-- .../ui/consts/issue-17718-const-bad-values.rs | 3 +- .../issue-17718-const-bad-values.stderr | 12 +--- .../consts/projection_qualif.mut_refs.stderr | 11 +-- src/test/ui/consts/projection_qualif.rs | 2 +- .../ui/consts/projection_qualif.stock.stderr | 10 +-- .../ui/consts/read_from_static_mut_ref.rs | 5 +- .../ui/consts/read_from_static_mut_ref.stderr | 17 +++-- ...ic_mut_containing_mut_ref2.mut_refs.stderr | 8 +-- .../consts/static_mut_containing_mut_ref2.rs | 3 +- ...tatic_mut_containing_mut_ref2.stock.stderr | 9 ++- src/test/ui/error-codes/E0017.rs | 9 +-- src/test/ui/error-codes/E0017.stderr | 35 +++++---- src/test/ui/error-codes/E0388.rs | 7 +- src/test/ui/error-codes/E0388.stderr | 29 +++++--- src/test/ui/issues/issue-46604.rs | 2 +- src/test/ui/issues/issue-46604.stderr | 4 +- src/test/ui/never_type/issue-52443.stderr | 9 ++- src/test/ui/unsafe/ranged_ints2_const.rs | 6 ++ src/test/ui/unsafe/ranged_ints2_const.stderr | 11 ++- 35 files changed, 298 insertions(+), 171 deletions(-) delete mode 100644 src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr delete mode 100644 src/test/ui/consts/const-mut-refs/const_mut_refs.stderr create mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs create mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr create mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs create mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 99ffb0edce9e1..23abd522cf0f3 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -268,43 +268,41 @@ 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 + match ccx.const_kind() { + // Mutable statics can handle mutable references in their final value + hir::ConstContext::Static(hir::Mutability::Mut) => Status::Allowed, + _ => 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> { let raw = match self.0 { hir::BorrowKind::Raw => "raw ", 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 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 +319,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 +350,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/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..fcc18cc584c54 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 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..c85acd3b84987 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -0,0 +1,24 @@ +#![feature(const_mut_refs)] +#![feature(const_fn)] +#![feature(raw_ref_op)] +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 + +// Could be ok, but the same analysis that prevents the mutable one above will also bail out here +// Using a block with some complex content, because just `&45` would get promoted, +// which is not what we want to test here. +const C: *const i32 = &{ + let mut x = 42; + x += 3; + x +}; + +fn main() { + println!("{}", unsafe { *A }); + unsafe { *B = 4 } // Bad news +} 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..6d570052aebb1 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -0,0 +1,9 @@ +error[E0764]: mutable references are not allowed in final value of constants + --> $DIR/mut_ref_in_final.rs:10:21 + | +LL | const B: *mut i32 = &mut 4; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0764`. diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs new file mode 100644 index 0000000000000..3f2995df2d769 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs @@ -0,0 +1,22 @@ +#![feature(const_mut_refs)] +#![feature(const_fn)] +#![feature(raw_ref_op)] + +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 + +// `BAR` works, because `&42` promotes immediately instead of relying on +// "final value lifetime extension". +const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); + +fn main() { + 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_ok.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr new file mode 100644 index 0000000000000..8b51e44e16956 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr @@ -0,0 +1,13 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final_ok.rs:10: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: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. 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..7e02fa4686f2f 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 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 index fad8f011f75f5..0945a23f3b123 100644 --- a/src/test/ui/consts/projection_qualif.mut_refs.stderr +++ b/src/test/ui/consts/projection_qualif.mut_refs.stderr @@ -1,9 +1,3 @@ -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 | @@ -13,7 +7,6 @@ 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 +error: aborting due to previous error -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/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs index 5e2584a6e951a..d35df330bb8c3 100644 --- a/src/test/ui/consts/projection_qualif.rs +++ b/src/test/ui/consts/projection_qualif.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/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr index fad8f011f75f5..e451898caba43 100644 --- a/src/test/ui/consts/projection_qualif.stock.stderr +++ b/src/test/ui/consts/projection_qualif.stock.stderr @@ -1,8 +1,11 @@ -error[E0764]: mutable references are not allowed in constants +error[E0658]: 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` + | ^^^^^^ + | + = 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/projection_qualif.rs:11:18 @@ -15,5 +18,4 @@ LL | unsafe { *b = 5; } 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/read_from_static_mut_ref.rs b/src/test/ui/consts/read_from_static_mut_ref.rs index 5faa983ab09f7..665c305e9617f 100644 --- a/src/test/ui/consts/read_from_static_mut_ref.rs +++ b/src/test/ui/consts/read_from_static_mut_ref.rs @@ -1,9 +1,8 @@ -// 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 +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/read_from_static_mut_ref.stderr b/src/test/ui/consts/read_from_static_mut_ref.stderr index c936ac0b7d585..373220878ec2a 100644 --- a/src/test/ui/consts/read_from_static_mut_ref.stderr +++ b/src/test/ui/consts/read_from_static_mut_ref.stderr @@ -1,9 +1,16 @@ -error[E0764]: mutable references are not allowed in statics - --> $DIR/read_from_static_mut_ref.rs:5:26 +error[E0764]: mutable references are not allowed in final value of statics + --> $DIR/read_from_static_mut_ref.rs:4:26 | LL | static OH_NO: &mut i32 = &mut 42; - | ^^^^^^^ `&mut` is only allowed in `const fn` + | ^^^^^^^ -error: aborting due to previous error +error[E0594]: cannot assign to `*OH_NO`, as `OH_NO` is an immutable static item + --> $DIR/read_from_static_mut_ref.rs:7:5 + | +LL | *OH_NO = 43; + | ^^^^^^^^^^^ cannot assign + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0764`. +Some errors have detailed explanations: E0594, E0764. +For more information about an error, try `rustc --explain E0594`. 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/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..9b094b1975730 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 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 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 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 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..74d6a92e170d4 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 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 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 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/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..488be0e7731e6 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 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/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`. From b217fab9608f97fc99c77f4cac5909df0e59db0c Mon Sep 17 00:00:00 2001 From: oli Date: Sat, 16 Jan 2021 17:27:59 +0000 Subject: [PATCH 15/26] Rename tests to what their code actually does --- .../ui/consts/{projection_qualif.rs => write_to_mut_ref_dest.rs} | 0 ...read_from_static_mut_ref.rs => write_to_static_via_mut_ref.rs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/consts/{projection_qualif.rs => write_to_mut_ref_dest.rs} (100%) rename src/test/ui/consts/{read_from_static_mut_ref.rs => write_to_static_via_mut_ref.rs} (100%) diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/write_to_mut_ref_dest.rs similarity index 100% rename from src/test/ui/consts/projection_qualif.rs rename to src/test/ui/consts/write_to_mut_ref_dest.rs diff --git a/src/test/ui/consts/read_from_static_mut_ref.rs b/src/test/ui/consts/write_to_static_via_mut_ref.rs similarity index 100% rename from src/test/ui/consts/read_from_static_mut_ref.rs rename to src/test/ui/consts/write_to_static_via_mut_ref.rs From 3cd0b46baca1848b577f2172935a139663697643 Mon Sep 17 00:00:00 2001 From: oli Date: Sat, 16 Jan 2021 17:31:22 +0000 Subject: [PATCH 16/26] Fix a comment that only made sense in the context of a dataflow based mutability check --- src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 index c85acd3b84987..98960ec6c6e8a 100644 --- 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 @@ -9,9 +9,8 @@ const A: *const i32 = &4; // as that would be an enormous footgun in oli-obk's opinion. const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed -// Could be ok, but the same analysis that prevents the mutable one above will also bail out here -// Using a block with some complex content, because just `&45` would get promoted, -// which is not what we want to test here. +// 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; From 00e62fabf101571c337fdce24544e94b0e0fda9c Mon Sep 17 00:00:00 2001 From: oli Date: Sat, 16 Jan 2021 18:05:51 +0000 Subject: [PATCH 17/26] Adjust wording of a diagnostic --- compiler/rustc_mir/src/transform/check_consts/ops.rs | 2 +- src/test/ui/check-static-immutable-mut-slices.stderr | 2 +- src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr | 2 +- src/test/ui/consts/issue-17718-const-bad-values.stderr | 2 +- ..._refs.stderr => write_to_mut_ref_dest.mut_refs.stderr} | 2 +- ...if.stock.stderr => write_to_mut_ref_dest.stock.stderr} | 4 ++-- ..._mut_ref.stderr => write_to_static_via_mut_ref.stderr} | 6 +++--- src/test/ui/error-codes/E0017.stderr | 8 ++++---- src/test/ui/error-codes/E0388.stderr | 6 +++--- src/test/ui/issues/issue-46604.stderr | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) rename src/test/ui/consts/{projection_qualif.mut_refs.stderr => write_to_mut_ref_dest.mut_refs.stderr} (91%) rename src/test/ui/consts/{projection_qualif.stock.stderr => write_to_mut_ref_dest.stock.stderr} (90%) rename src/test/ui/consts/{read_from_static_mut_ref.stderr => write_to_static_via_mut_ref.stderr} (69%) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 23abd522cf0f3..6e7262151777f 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -298,7 +298,7 @@ impl NonConstOp for MutBorrow { ccx.tcx.sess, span, E0764, - "{}mutable references are not allowed in final value of {}s", + "{}mutable references are not allowed in the final value of {}s", raw, ccx.const_kind(), ); diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr index fcc18cc584c54..a32a94c1315ab 100644 --- a/src/test/ui/check-static-immutable-mut-slices.stderr +++ b/src/test/ui/check-static-immutable-mut-slices.stderr @@ -1,4 +1,4 @@ -error[E0764]: mutable references are not allowed in final value of 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 []; 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 index 6d570052aebb1..57bf5f7395de4 100644 --- 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 @@ -1,4 +1,4 @@ -error[E0764]: mutable references are not allowed in final value of constants +error[E0764]: mutable references are not allowed in the final value of constants --> $DIR/mut_ref_in_final.rs:10:21 | LL | const B: *mut i32 = &mut 4; 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 7e02fa4686f2f..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,4 +1,4 @@ -error[E0764]: mutable references are not allowed in final value of 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 []; diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr similarity index 91% rename from src/test/ui/consts/projection_qualif.mut_refs.stderr rename to src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr index 0945a23f3b123..3ee50907461ca 100644 --- a/src/test/ui/consts/projection_qualif.mut_refs.stderr +++ b/src/test/ui/consts/write_to_mut_ref_dest.mut_refs.stderr @@ -1,5 +1,5 @@ error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/projection_qualif.rs:11:18 + --> $DIR/write_to_mut_ref_dest.rs:11:18 | LL | unsafe { *b = 5; } | ^^^^^^ diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr similarity index 90% rename from src/test/ui/consts/projection_qualif.stock.stderr rename to src/test/ui/consts/write_to_mut_ref_dest.stock.stderr index e451898caba43..2b6d1d3267b61 100644 --- a/src/test/ui/consts/projection_qualif.stock.stderr +++ b/src/test/ui/consts/write_to_mut_ref_dest.stock.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constants - --> $DIR/projection_qualif.rs:10:27 + --> $DIR/write_to_mut_ref_dest.rs:10:27 | LL | let b: *mut u32 = &mut a; | ^^^^^^ @@ -8,7 +8,7 @@ LL | let b: *mut u32 = &mut a; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: dereferencing raw pointers in constants is unstable - --> $DIR/projection_qualif.rs:11:18 + --> $DIR/write_to_mut_ref_dest.rs:11:18 | LL | unsafe { *b = 5; } | ^^^^^^ diff --git a/src/test/ui/consts/read_from_static_mut_ref.stderr b/src/test/ui/consts/write_to_static_via_mut_ref.stderr similarity index 69% rename from src/test/ui/consts/read_from_static_mut_ref.stderr rename to src/test/ui/consts/write_to_static_via_mut_ref.stderr index 373220878ec2a..d19e998d61736 100644 --- a/src/test/ui/consts/read_from_static_mut_ref.stderr +++ b/src/test/ui/consts/write_to_static_via_mut_ref.stderr @@ -1,11 +1,11 @@ -error[E0764]: mutable references are not allowed in final value of statics - --> $DIR/read_from_static_mut_ref.rs:4:26 +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/read_from_static_mut_ref.rs:7:5 + --> $DIR/write_to_static_via_mut_ref.rs:7:5 | LL | *OH_NO = 43; | ^^^^^^^^^^^ cannot assign diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr index 9b094b1975730..7d959b6d148ed 100644 --- a/src/test/ui/error-codes/E0017.stderr +++ b/src/test/ui/error-codes/E0017.stderr @@ -13,7 +13,7 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in final value of 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; @@ -28,7 +28,7 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; = 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 final value of statics +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; @@ -54,13 +54,13 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in final value of statics +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; | ^^^^^^ -error[E0764]: mutable references are not allowed in final value of statics +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 }; diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr index 74d6a92e170d4..4886a156d2ea5 100644 --- a/src/test/ui/error-codes/E0388.stderr +++ b/src/test/ui/error-codes/E0388.stderr @@ -13,7 +13,7 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in final value of 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; @@ -28,7 +28,7 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; = 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 final value of statics +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; @@ -54,7 +54,7 @@ note: `const` item defined here LL | const C: i32 = 2; | ^^^^^^^^^^^^^^^^^ -error[E0764]: mutable references are not allowed in final value of statics +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; diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr index 488be0e7731e6..7faa2d79ba483 100644 --- a/src/test/ui/issues/issue-46604.stderr +++ b/src/test/ui/issues/issue-46604.stderr @@ -1,4 +1,4 @@ -error[E0764]: mutable references are not allowed in final value of 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]; From 14f39aa81a8e0861c5cc8227c08b60f037a87947 Mon Sep 17 00:00:00 2001 From: oli Date: Sat, 16 Jan 2021 18:06:12 +0000 Subject: [PATCH 18/26] Do not allow arbitrary mutable references in `static mut`, just keep with the existing exceptions --- compiler/rustc_mir/src/transform/check_consts/ops.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 6e7262151777f..6f98760a7b0ad 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -274,12 +274,8 @@ impl NonConstOp for CellBorrow { pub struct MutBorrow(pub hir::BorrowKind); impl NonConstOp for MutBorrow { - fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - match ccx.const_kind() { - // Mutable statics can handle mutable references in their final value - hir::ConstContext::Static(hir::Mutability::Mut) => Status::Allowed, - _ => Status::Forbidden, - } + fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status { + Status::Forbidden } fn importance(&self) -> DiagnosticImportance { From cd0987115765efdf4f834f0f0bf24c4cef063b1a Mon Sep 17 00:00:00 2001 From: oli Date: Sat, 23 Jan 2021 11:58:58 +0000 Subject: [PATCH 19/26] Cover more cases in the test suite --- .../consts/const-mut-refs/mut_ref_in_final.rs | 45 +++++++++++++++ .../const-mut-refs/mut_ref_in_final.stderr | 57 ++++++++++++++++++- .../const-mut-refs/mut_ref_in_final_ok.rs | 22 ------- .../const-mut-refs/mut_ref_in_final_ok.stderr | 13 ----- 4 files changed, 99 insertions(+), 38 deletions(-) delete mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs delete mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr 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 index 98960ec6c6e8a..b2230697037f3 100644 --- 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 @@ -1,6 +1,9 @@ #![feature(const_mut_refs)] #![feature(const_fn)] +#![feature(const_transmute)] #![feature(raw_ref_op)] +#![feature(const_raw_ptr_deref)] + const NULL: *mut i32 = std::ptr::null_mut(); const A: *const i32 = &4; @@ -9,6 +12,25 @@ const A: *const i32 = &4; // 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() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour, 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)) +} } +// Check that 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 B5/helper2 test below). +const B4: Option<&mut i32> = helper(); + +const fn helper2(x: &mut i32) -> Option<&mut i32> { Some(x) } +const B5: Option<&mut i32> = helper2(&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 = &{ @@ -17,7 +39,30 @@ const C: *const i32 = &{ 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 index 57bf5f7395de4..389b88955cec4 100644 --- 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 @@ -1,9 +1,60 @@ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:10:21 + --> $DIR/mut_ref_in_final.rs:13:21 | LL | const B: *mut i32 = &mut 4; | ^^^^^^ -error: aborting due to previous error +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:19: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:32:43 + | +LL | const B5: Option<&mut i32> = helper2(&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:47: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:50: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:53: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 -For more information about this error, try `rustc --explain E0764`. +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_ok.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs deleted file mode 100644 index 3f2995df2d769..0000000000000 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![feature(const_mut_refs)] -#![feature(const_fn)] -#![feature(raw_ref_op)] - -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 - -// `BAR` works, because `&42` promotes immediately instead of relying on -// "final value lifetime extension". -const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); - -fn main() { - 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_ok.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr deleted file mode 100644 index 8b51e44e16956..0000000000000 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final_ok.rs:10: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: aborting due to previous error - -For more information about this error, try `rustc --explain E0716`. From 819b008d8be8d154d9561bed1e4b770c741f23a2 Mon Sep 17 00:00:00 2001 From: oli Date: Sat, 23 Jan 2021 12:35:45 +0000 Subject: [PATCH 20/26] Put dynamic check tests into their own file --- .../consts/const-mut-refs/mut_ref_in_final.rs | 15 ++-------- .../const-mut-refs/mut_ref_in_final.stderr | 22 +++++++-------- .../mut_ref_in_final_dynamic_check.rs | 28 +++++++++++++++++++ .../mut_ref_in_final_dynamic_check.stderr | 23 +++++++++++++++ 4 files changed, 64 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs create mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr 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 index b2230697037f3..166ba20f124e6 100644 --- 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 @@ -1,6 +1,5 @@ #![feature(const_mut_refs)] #![feature(const_fn)] -#![feature(const_transmute)] #![feature(raw_ref_op)] #![feature(const_raw_ptr_deref)] @@ -18,18 +17,8 @@ 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() -> Option<&'static mut i32> { unsafe { - // Undefined behaviour, 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)) -} } -// Check that 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 B5/helper2 test below). -const B4: Option<&mut i32> = helper(); - -const fn helper2(x: &mut i32) -> Option<&mut i32> { Some(x) } -const B5: Option<&mut i32> = helper2(&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. 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 index 389b88955cec4..cbae74cce6f6b 100644 --- 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 @@ -1,11 +1,11 @@ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:13:21 + --> $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:19:40 + --> $DIR/mut_ref_in_final.rs:18:40 | LL | const B3: Option<&mut i32> = Some(&mut 42); | ----------^^- @@ -15,17 +15,17 @@ LL | const B3: Option<&mut i32> = Some(&mut 42); | 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:32:43 + --> $DIR/mut_ref_in_final.rs:21:42 | -LL | const B5: Option<&mut i32> = helper2(&mut 42); - | -------------^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use +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:47:65 + --> $DIR/mut_ref_in_final.rs:36:65 | LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -35,7 +35,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | 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:50:67 + --> $DIR/mut_ref_in_final.rs:39:67 | LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- @@ -45,7 +45,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | 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:53:71 + --> $DIR/mut_ref_in_final.rs:42:71 | LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | -------------------------------^^-- 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 + From 1129e8678038cfc938559b90b4155dde8b84edf3 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 23 Jan 2021 18:05:59 +0100 Subject: [PATCH 21/26] Cleanup `render_stability_since_raw` to remove code duplication --- src/librustdoc/html/render/mod.rs | 43 ++++++++++++------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 26afd705740b2..f15d43b7b1600 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2934,34 +2934,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 ver = ver.filter(|inner| !inner.is_empty()); + let const_ver = const_ver.filter(|inner| !inner.is_empty()); - let const_ver = const_ver.and_then(|inner| if !inner.is_empty() { Some(inner) } else { None }); - - 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 + ); } + _ => {} } } From 9b1d27d440d58edcb4c673798c60181c03c084c1 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Fri, 22 Jan 2021 10:54:53 +0100 Subject: [PATCH 22/26] Add option to control doctest run directory This option will allow splitting the compile-time from the run-time directory of doctest invocations and is one step to solve https://github.com/rust-lang/cargo/issues/8993#issuecomment-760088944 --- src/librustdoc/config.rs | 5 ++++ src/librustdoc/doctest.rs | 3 +++ src/librustdoc/lib.rs | 8 +++++++ .../rustdoc-ui/run-directory.correct.stdout | 6 +++++ .../rustdoc-ui/run-directory.incorrect.stdout | 6 +++++ src/test/rustdoc-ui/run-directory.rs | 23 +++++++++++++++++++ 6 files changed, 51 insertions(+) create mode 100644 src/test/rustdoc-ui/run-directory.correct.stdout create mode 100644 src/test/rustdoc-ui/run-directory.incorrect.stdout create mode 100644 src/test/rustdoc-ui/run-directory.rs diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index e43ea965c0423..508bed072e61d 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 c87ab833f7a5e..09cbd94e4ac3f 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/lib.rs b/src/librustdoc/lib.rs index 719aca612f50d..d823f789013ff 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -167,6 +167,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() {} From 20a460e1cf23262b46a7e9672a02c5f07b91eff5 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 23 Jan 2021 18:41:04 +0100 Subject: [PATCH 23/26] Fix rendering of stabilization version for trait implementors --- src/librustdoc/html/render/mod.rs | 8 ++++---- .../rustdoc/implementor-stable-version.rs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 src/test/rustdoc/implementor-stable-version.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f15d43b7b1600..bfaadc38763c3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2471,7 +2471,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], @@ -2491,11 +2491,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, 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 {} From 14aa12fcc2ebee6edfd6092a51122a6a6ba78d4d Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 22 Jan 2021 06:57:33 +0100 Subject: [PATCH 24/26] Replace version_check dependency with own version parsing code This gives compiler maintainers a better degree of control over how the version gets parsed and is a good way to ensure that there are no changes of behaviour in the future. Also, issue a warning if the version is invalid instead of erroring so that we stay forwards compatible with possible future changes of the versioning scheme. Last, this improves the present test a little. --- Cargo.lock | 1 - compiler/rustc_attr/Cargo.toml | 1 - compiler/rustc_attr/src/builtin.rs | 32 ++++- .../feature-gates/feature-gate-cfg-version.rs | 30 +++-- .../feature-gate-cfg-version.stderr | 110 +++++++++++++++--- 5 files changed, 138 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2ae22b6abd9b..ee52e34163bdd 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/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`. From f8416faaaf3a1fb6ca57ff8f0b3bdf972eed266f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sun, 24 Jan 2021 13:32:18 +0100 Subject: [PATCH 25/26] Clean up dominators_given_rpo --- .../src/graph/dominators/mod.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) 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 { From 08c01f85c3625c5864e4a132d3338d233554d285 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 19 Jan 2021 16:34:02 -0500 Subject: [PATCH 26/26] Fix flaky test Rustdoc writes to a pipe, and if the program on the other side has exited, it will exit with SIGPIPE. To avoid that happening, call `rustc` instead of `true`, which will wait to exit until it sees EOF on stdin. - Use a run-make-fulldeps test so that rustc is available in CI This is not exactly right, because the test shouldn't require building rustc twice, but it avoids having to build rustdoc for run-make tests. --- .../run-make-fulldeps/rustdoc-test-builder/Makefile | 10 ++++++++++ .../run-make-fulldeps/rustdoc-test-builder/doctest.rs | 4 ++++ src/test/rustdoc/issue-80893.rs | 6 ------ 3 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 src/test/run-make-fulldeps/rustdoc-test-builder/Makefile create mode 100644 src/test/run-make-fulldeps/rustdoc-test-builder/doctest.rs delete mode 100644 src/test/rustdoc/issue-80893.rs diff --git a/src/test/run-make-fulldeps/rustdoc-test-builder/Makefile b/src/test/run-make-fulldeps/rustdoc-test-builder/Makefile new file mode 100644 index 0000000000000..54178d440e8cc --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-test-builder/Makefile @@ -0,0 +1,10 @@ +-include ../../run-make-fulldeps/tools.mk + +# How to manually run this +# $ ./x.py test src/test/run-make/rustdoc-test-builder + +all: + # Rustc isn't available in UI tests because the only compiler available is the + # one built from source, which isn't in PATH. This needs to be a run-make + # test so rustc is available. + $(RUSTDOC) --test -Z unstable-options --test-builder $(RUSTC_ORIGINAL) doctest.rs diff --git a/src/test/run-make-fulldeps/rustdoc-test-builder/doctest.rs b/src/test/run-make-fulldeps/rustdoc-test-builder/doctest.rs new file mode 100644 index 0000000000000..d714a4afb2462 --- /dev/null +++ b/src/test/run-make-fulldeps/rustdoc-test-builder/doctest.rs @@ -0,0 +1,4 @@ +/// ```no_run +/// // This tests that `--test-builder` is accepted as a flag by rustdoc. +/// ``` +pub struct Foo; diff --git a/src/test/rustdoc/issue-80893.rs b/src/test/rustdoc/issue-80893.rs deleted file mode 100644 index 7c958a80be395..0000000000000 --- a/src/test/rustdoc/issue-80893.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags: --test -Z unstable-options --test-builder true - -/// ```no_run -/// This tests that `--test-builder` is accepted as a flag by rustdoc. -/// ``` -pub struct Foo;