From afe29e48bc4d57c1bb73228ba8d70dc8f42436fc Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 5 Oct 2022 11:23:57 +0200 Subject: [PATCH 01/36] split steps for generating the standalone docs and the shared assets Before this commit, the step to generate the standalone docs (which included the index page and other HTML files at the root of the documentation) was bundled with the code copying files needed by multiple pieces of documentation. This means it wasn't possible to avoid generating the standalone docs. This commit splits the step into two, allowing the standalone docs generation to be excluded while still building the rest of the docs. --- src/bootstrap/doc.rs | 61 ++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 819af6587484d..b286c79a30307 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -227,7 +227,7 @@ impl Step for TheBook { } // build the version info page and CSS - builder.ensure(Standalone { compiler, target }); + let shared_assets = builder.ensure(SharedAssets { target }); // build the redirect pages builder.info(&format!("Documenting book redirect pages ({})", target)); @@ -236,7 +236,7 @@ impl Step for TheBook { let path = file.path(); let path = path.to_str().unwrap(); - invoke_rustdoc(builder, compiler, target, path); + invoke_rustdoc(builder, compiler, &shared_assets, target, path); } if builder.was_invoked_explicitly::(Kind::Doc) { @@ -250,6 +250,7 @@ impl Step for TheBook { fn invoke_rustdoc( builder: &Builder<'_>, compiler: Compiler, + shared_assets: &SharedAssetsPaths, target: TargetSelection, markdown: &str, ) { @@ -259,7 +260,6 @@ fn invoke_rustdoc( let header = builder.src.join("src/doc/redirect.inc"); let footer = builder.src.join("src/doc/footer.inc"); - let version_info = out.join("version_info.html"); let mut cmd = builder.rustdoc_cmd(compiler); @@ -268,7 +268,7 @@ fn invoke_rustdoc( cmd.arg("--html-after-content") .arg(&footer) .arg("--html-before-content") - .arg(&version_info) + .arg(&shared_assets.version_info) .arg("--html-in-header") .arg(&header) .arg("--markdown-no-toc") @@ -324,21 +324,11 @@ impl Step for Standalone { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); + let version_info = builder.ensure(SharedAssets { target: self.target }).version_info; + let favicon = builder.src.join("src/doc/favicon.inc"); let footer = builder.src.join("src/doc/footer.inc"); let full_toc = builder.src.join("src/doc/full-toc.inc"); - t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); - - let version_input = builder.src.join("src/doc/version_info.html.template"); - let version_info = out.join("version_info.html"); - - if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { - let info = t!(fs::read_to_string(&version_input)) - .replace("VERSION", &builder.rust_release()) - .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) - .replace("STAMP", builder.rust_info.sha().unwrap_or("")); - t!(fs::write(&version_info, &info)); - } for file in t!(fs::read_dir(builder.src.join("src/doc"))) { let file = t!(file); @@ -400,6 +390,45 @@ impl Step for Standalone { } } +#[derive(Debug, Clone)] +pub struct SharedAssetsPaths { + pub version_info: PathBuf, +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct SharedAssets { + target: TargetSelection, +} + +impl Step for SharedAssets { + type Output = SharedAssetsPaths; + const DEFAULT: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + // Other tasks depend on this, no need to execute it on its own + run.never() + } + + // Generate shared resources used by other pieces of documentation. + fn run(self, builder: &Builder<'_>) -> Self::Output { + let out = builder.doc_out(self.target); + + let version_input = builder.src.join("src").join("doc").join("version_info.html.template"); + let version_info = out.join("version_info.html"); + if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { + let info = t!(fs::read_to_string(&version_input)) + .replace("VERSION", &builder.rust_release()) + .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) + .replace("STAMP", builder.rust_info.sha().unwrap_or("")); + t!(fs::write(&version_info, &info)); + } + + builder.copy(&builder.src.join("src").join("doc").join("rust.css"), &out.join("rust.css")); + + SharedAssetsPaths { version_info } + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub stage: u32, From 004b8b98d626a89b5d4cdc630ff337c0f4ea919f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 5 Oct 2022 12:45:52 +0200 Subject: [PATCH 02/36] add a "standalone" path for doc::Standalone to be able to exclude it Before this commit, the path for the doc::Standalone step was "src/doc", which is accurate as the standalone docs source files live at the root of the "src/doc" directory tree. Unfortunately, that caused bad interactions when trying to exclude it with `--exclude src/doc`. When an exclusion is passed to bootstrap, it will exclude all steps whose path *ends with* the exclusion, which results in the Cargo book (src/tools/cargo/src/doc) to also be excluded. To work around this problem, this commit adds the "standalone" path as an alternate path for doc::Standalone, allowing `--exclude standalone` to work without side effects. --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b286c79a30307..a8524fea1b2a0 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -299,7 +299,7 @@ impl Step for Standalone { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/doc").default_condition(builder.config.docs) + run.path("src/doc").path("standalone").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { From f134370b916b107cc2c07a563430e99d3c102188 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 18 Oct 2022 16:47:35 +0200 Subject: [PATCH 03/36] apply joshua's suggestion Co-authored-by: Joshua Nelson --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index a8524fea1b2a0..939e169ec00e5 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -299,7 +299,7 @@ impl Step for Standalone { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/doc").path("standalone").default_condition(builder.config.docs) + run.path("src/doc").alias("standalone").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { From ab36a2fe16006a34c7d19baa6ef8e23f6ec079cc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Oct 2022 18:34:01 +0000 Subject: [PATCH 04/36] Revert "Unify tcx.constness and param env constness checks" This reverts commit bef8681a1837790f2745c1f6a7f8214af2fd7f5d. This reverts commit c646c4d403d8c88cd3450f859fbdc34ec26d5bb5. --- .../src/const_eval/fn_queries.rs | 72 +++++-------------- compiler/rustc_metadata/src/rmeta/encoder.rs | 56 ++++----------- compiler/rustc_ty_utils/src/ty.rs | 69 +++++++++++++++++- 3 files changed, 99 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index cdcebb61c2e8c..f1674d04f8d15 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -25,10 +25,12 @@ pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// report whether said intrinsic has a `rustc_const_{un,}stable` attribute. Otherwise, return /// `Constness::NotConst`. fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().get(hir_id) { - hir::Node::Ctor(_) => hir::Constness::Const, + let def_id = def_id.expect_local(); + let node = tcx.hir().get_by_def_id(def_id); + match node { + hir::Node::Ctor(_) => hir::Constness::Const, + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness, hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => { // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other // foreign items cannot be evaluated at compile-time. @@ -39,62 +41,20 @@ fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { }; if is_const { hir::Constness::Const } else { hir::Constness::NotConst } } + _ => { + if let Some(fn_kind) = node.fn_kind() { + if fn_kind.constness() == hir::Constness::Const { + return hir::Constness::Const; + } - hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - if tcx.is_const_default_method(def_id) => - { - hir::Constness::Const - } - - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) - | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) - | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. }) - | hir::Node::AnonConst(_) - | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) - | hir::Node::ImplItem(hir::ImplItem { - kind: - hir::ImplItemKind::Fn( - hir::FnSig { - header: hir::FnHeader { constness: hir::Constness::Const, .. }, - .. - }, - .., - ), - .. - }) => hir::Constness::Const, - - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), - .. - }) => { - let parent_hir_id = tcx.hir().get_parent_node(hir_id); - match tcx.hir().get(parent_hir_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - _ => span_bug!( - tcx.def_span(parent_hir_id.owner), - "impl item's parent node is not an impl", - ), + // If the function itself is not annotated with `const`, it may still be a `const fn` + // if it resides in a const trait impl. + let is_const = is_parent_const_impl_raw(tcx, def_id); + if is_const { hir::Constness::Const } else { hir::Constness::NotConst } + } else { + hir::Constness::NotConst } } - - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - - _ => hir::Constness::NotConst, } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 68119598285c5..3fc10197b9129 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1059,43 +1059,6 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } -fn should_encode_constness(def_kind: DefKind) -> bool { - match def_kind { - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Trait - | DefKind::AssocTy - | DefKind::Fn - | DefKind::Const - | DefKind::Static(..) - | DefKind::Ctor(..) - | DefKind::AssocFn - | DefKind::AssocConst - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder - | DefKind::Impl - | DefKind::Closure - | DefKind::Generator - | DefKind::TyAlias => true, - DefKind::Variant - | DefKind::TraitAlias - | DefKind::ForeignTy - | DefKind::Field - | DefKind::TyParam - | DefKind::Mod - | DefKind::ForeignMod - | DefKind::ConstParam - | DefKind::Macro(..) - | DefKind::Use - | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::ExternCrate => false, - } -} - fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { if tcx.def_kind(def_id) != DefKind::AssocFn { return false; @@ -1202,9 +1165,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } - if should_encode_constness(def_kind) { - self.tables.constness.set(def_id.index, tcx.constness(def_id)); - } } let inherent_impls = tcx.crate_inherent_impls(()); for (def_id, implementations) in inherent_impls.inherent_impls.iter() { @@ -1232,6 +1192,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index @@ -1259,6 +1220,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1322,6 +1284,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.repr_options[def_id] <- adt_def.repr()); record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1357,6 +1320,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } }; self.tables.asyncness.set(def_id.index, m_sig.header.asyncness); + self.tables.constness.set(def_id.index, hir::Constness::NotConst); } ty::AssocKind::Type => { self.encode_explicit_item_bounds(def_id); @@ -1381,6 +1345,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; self.tables.asyncness.set(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); + // Can be inside `impl const Trait`, so using sig.header.constness is not reliable + let constness = if self.tcx.is_const_fn_raw(def_id) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }; + self.tables.constness.set(def_id.index, constness); } ty::AssocKind::Const | ty::AssocKind::Type => {} } @@ -1503,6 +1474,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::Fn(ref sig, .., body) => { self.tables.asyncness.set(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); + self.tables.constness.set(def_id.index, sig.header.constness); } hir::ItemKind::Macro(ref macro_def, _) => { if macro_def.macro_rules { @@ -1523,6 +1495,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::Struct(ref struct_def, _) => { let adt_def = self.tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); + self.tables.constness.set(def_id.index, hir::Constness::Const); // Encode def_ids for each field and method // for methods, write all the stuff get_trait_method @@ -1551,8 +1524,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_non_exhaustive: variant.is_field_list_non_exhaustive(), }); } - hir::ItemKind::Impl(hir::Impl { defaultness, .. }) => { + hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { self.tables.impl_defaultness.set(def_id.index, *defaultness); + self.tables.constness.set(def_id.index, *constness); let trait_ref = self.tcx.impl_trait_ref(def_id); if let Some(trait_ref) = trait_ref { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 196d70614e7c9..cd9d229640571 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -137,10 +137,77 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { let local_did = def_id.as_local(); let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); + let constness = match hir_id { + Some(hir_id) => match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) + if tcx.is_const_default_method(def_id) => + { + hir::Constness::Const + } + + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) + | hir::Node::AnonConst(_) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + header: hir::FnHeader { constness: hir::Constness::Const, .. }, + .. + }, + .., + ), + .. + }) => hir::Constness::Const, + + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), + .. + }) => { + let parent_hir_id = tcx.hir().get_parent_node(hir_id); + match tcx.hir().get(parent_hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + _ => span_bug!( + tcx.def_span(parent_hir_id.owner), + "impl item's parent node is not an impl", + ), + } + } + + hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, + .., + ), + .. + }) + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + + _ => hir::Constness::NotConst, + }, + None => hir::Constness::NotConst, + }; + let unnormalized_env = ty::ParamEnv::new( tcx.intern_predicates(&predicates), traits::Reveal::UserFacing, - tcx.constness(def_id), + constness, ); let body_id = From 43f2c37f9350b2bed0b81bf858e7478869d8c306 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Oct 2022 19:05:15 +0000 Subject: [PATCH 05/36] Note discrepancies in constness calculation --- compiler/rustc_ty_utils/src/ty.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index cd9d229640571..3eebb4ace477f 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -137,6 +137,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { let local_did = def_id.as_local(); let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); + // FIXME(consts): This is not exactly in line with the constness query. let constness = match hir_id { Some(hir_id) => match tcx.hir().get(hir_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) @@ -201,6 +202,10 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { _ => hir::Constness::NotConst, }, + // FIXME(consts): It's suspicious that a param-env for a foreign item + // will always have NotConst param-env, though we don't typically use + // that param-env for anything meaningful right now, so it's likely + // not an issue. None => hir::Constness::NotConst, }; From 751ac6ce5168b8bbefd83040fb262204072fc4df Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Oct 2022 04:19:54 +0000 Subject: [PATCH 06/36] Bless test --- .../rfc-2632-const-trait-impl/issue-102985.rs | 3 ++- .../issue-102985.stderr | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs index e0df72003844c..07d3f51edce5e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs @@ -4,7 +4,8 @@ struct Bug { inner: [(); match || 1 { n => n(), //~^ ERROR the trait bound - //~| ERROR cannot call non-const fn `Bug::inner::{constant#0}::{closure#0}` in constants + //~| ERROR the trait bound + //~| ERROR cannot call non-const closure in constants }], } diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr index 14d87e7cdc64a..b98ccbe5d03ec 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr @@ -12,15 +12,30 @@ LL | n => n(), | ^^^ = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }` -error[E0015]: cannot call non-const fn `Bug::inner::{constant#0}::{closure#0}` in constants +error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const` + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ + = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }` + +error[E0015]: cannot call non-const closure in constants --> $DIR/issue-102985.rs:5:14 | LL | n => n(), | ^^^ | + = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0277. For more information about an error, try `rustc --explain E0015`. From cfcb0a2135da6d4bdbf5f28806dea0cc70c5b6c5 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 20 Oct 2022 00:30:00 -0400 Subject: [PATCH 07/36] Use a faster allocation size check in slice::from_raw_parts --- library/core/src/intrinsics.rs | 10 ++++++++++ library/core/src/lib.rs | 1 + library/core/src/slice/raw.rs | 10 +++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 2399262c05b46..3a7a179c98be9 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2229,6 +2229,16 @@ pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { !ptr.is_null() && ptr.is_aligned() } +/// Checks whether an allocation of `len` instances of `T` exceeds +/// the maximum allowed allocation size. +pub(crate) fn is_valid_allocation_size(len: usize) -> bool { + let max_len = const { + let size = crate::mem::size_of::(); + if size == 0 { usize::MAX } else { isize::MAX as usize / size } + }; + len <= max_len +} + /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size_of::()` do *not* overlap. pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2fd8180f8b2a2..aa197c990b20b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -191,6 +191,7 @@ #![feature(extern_types)] #![feature(fundamental)] #![feature(if_let_guard)] +#![feature(inline_const)] #![feature(intra_doc_pointers)] #![feature(intrinsics)] #![feature(lang_items)] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 3c5abd215a4b7..dace748fed455 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -1,7 +1,9 @@ //! Free functions to create `&[T]` and `&mut [T]`. use crate::array; -use crate::intrinsics::{assert_unsafe_precondition, is_aligned_and_not_null}; +use crate::intrinsics::{ + assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size, +}; use crate::ops::Range; use crate::ptr; @@ -91,8 +93,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. unsafe { assert_unsafe_precondition!([T](data: *const T, len: usize) => - is_aligned_and_not_null(data) - && crate::mem::size_of::().saturating_mul(len) <= isize::MAX as usize + is_aligned_and_not_null(data) && is_valid_allocation_size::(len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -135,8 +136,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. unsafe { assert_unsafe_precondition!([T](data: *mut T, len: usize) => - is_aligned_and_not_null(data) - && crate::mem::size_of::().saturating_mul(len) <= isize::MAX as usize + is_aligned_and_not_null(data) && is_valid_allocation_size::(len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) } From 988e75bb65f688d76f4f80e0fb72ef21e831d0b0 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 6 Apr 2022 11:21:10 +1000 Subject: [PATCH 08/36] Stabilize arbitrary_enum_discriminant, take 2 --- compiler/rustc_ast_passes/src/feature_gate.rs | 62 +------------------ .../src/error_codes/E0732.md | 4 -- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 2 - .../rustc_hir_analysis/src/check/check.rs | 2 +- .../arbitrary-enum-discriminant.md | 37 ----------- src/test/ui/cast/issue-88621.rs | 2 - .../arbitrary_enum_discriminant-no-repr.rs | 1 - .../arbitrary_enum_discriminant.rs | 2 +- .../enum-discriminant/discriminant_value.rs | 2 +- ...eature-gate-arbitrary_enum_discriminant.rs | 10 --- ...re-gate-arbitrary_enum_discriminant.stderr | 36 ----------- .../issue-70453-generics-in-discr-ice-2.rs | 2 +- .../issue-70453-polymorphic-ctfe.rs | 2 +- .../issue-70509-partial_eq.rs | 2 +- .../issue-70509-partial_eq.stderr | 2 +- .../intrinsics/panic-uninitialized-zeroed.rs | 2 +- src/test/ui/macros/macros-nonfatal-errors.rs | 2 +- src/test/ui/parser/issues/issue-17383.rs | 7 --- src/test/ui/parser/issues/issue-17383.stderr | 15 ----- .../ui/parser/tag-variant-disr-non-nullary.rs | 12 ---- .../tag-variant-disr-non-nullary.stderr | 25 -------- 22 files changed, 12 insertions(+), 221 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md delete mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs delete mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr delete mode 100644 src/test/ui/parser/issues/issue-17383.rs delete mode 100644 src/test/ui/parser/issues/issue-17383.stderr delete mode 100644 src/test/ui/parser/tag-variant-disr-non-nullary.rs delete mode 100644 src/test/ui/parser/tag-variant-disr-non-nullary.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0f11c1766528a..546010135a725 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; -use rustc_ast::{PatKind, RangeEnd, VariantData}; +use rustc_ast::{PatKind, RangeEnd}; use rustc_errors::{struct_span_err, Applicability, StashKey}; use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; @@ -116,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> { } } - fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { - let has_fields = variants.iter().any(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => true, - VariantData::Unit(..) => false, - }); - - let discriminant_spans = variants - .iter() - .filter(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => false, - VariantData::Unit(..) => true, - }) - .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) - .collect::>(); - - if !discriminant_spans.is_empty() && has_fields { - let mut err = feature_err( - &self.sess.parse_sess, - sym::arbitrary_enum_discriminant, - discriminant_spans.clone(), - "custom discriminant values are not allowed in enums with tuple or struct variants", - ); - for sp in discriminant_spans { - err.span_label(sp, "disallowed custom discriminant"); - } - for variant in variants.iter() { - match &variant.data { - VariantData::Struct(..) => { - err.span_label(variant.span, "struct variant defined here"); - } - VariantData::Tuple(..) => { - err.span_label(variant.span, "tuple variant defined here"); - } - VariantData::Unit(..) => {} - } - } - err.emit(); - } - } - /// Feature gate `impl Trait` inside `type Alias = $type_expr;`. fn check_impl_trait(&self, ty: &ast::Ty) { struct ImplTraitVisitor<'a> { @@ -273,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => { - for variant in variants { - match (&variant.data, &variant.disr_expr) { - (ast::VariantData::Unit(..), _) => {} - (_, Some(disr_expr)) => gate_feature_post!( - &self, - arbitrary_enum_discriminant, - disr_expr.value.span, - "discriminants on non-unit variants are experimental" - ), - _ => {} - } - } - - let has_feature = self.features.arbitrary_enum_discriminant; - if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - self.maybe_report_invalid_custom_discriminants(&variants); - } - } - ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => { if let ast::ImplPolarity::Negative(span) = polarity { gate_feature_post!( diff --git a/compiler/rustc_error_codes/src/error_codes/E0732.md b/compiler/rustc_error_codes/src/error_codes/E0732.md index 7347e6654c5b3..9536fdbf0df87 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0732.md +++ b/compiler/rustc_error_codes/src/error_codes/E0732.md @@ -3,8 +3,6 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`. Erroneous code example: ```compile_fail,E0732 -#![feature(arbitrary_enum_discriminant)] - enum Enum { // error! Unit = 1, Tuple() = 2, @@ -20,8 +18,6 @@ is a well-defined way to extract a variant's discriminant from a value; for instance: ``` -#![feature(arbitrary_enum_discriminant)] - #[repr(u8)] enum Enum { Unit = 3, diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 54bf5a2c34b82..db289a64046a7 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -53,6 +53,8 @@ declare_features! ( (accepted, abi_sysv64, "1.24.0", Some(36167), None), /// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`. (accepted, adx_target_feature, "1.61.0", Some(44839), None), + /// Allows explicit discriminants on non-unit enum variants. + (accepted, arbitrary_enum_discriminant, "CURRENT_RUSTC_VERSION", Some(60553), None), /// Allows using `sym` operands in inline assembly. (accepted, asm_sym, "CURRENT_RUSTC_VERSION", Some(93333), None), /// Allows the definition of associated constants in `trait` or `impl` blocks. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1b8d683b13361..4facb6140a300 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -292,8 +292,6 @@ declare_features! ( (incomplete, adt_const_params, "1.56.0", Some(95174), None), /// Allows defining an `#[alloc_error_handler]`. (active, alloc_error_handler, "1.29.0", Some(51540), None), - /// Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), /// Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), /// Allows using `const` operands in inline assembly. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a1faf80251957..b302cee4816fb 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1180,7 +1180,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L } } - if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant { + if tcx.adt_def(def_id).repr().int.is_none() { let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..)); let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some(); diff --git a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md deleted file mode 100644 index e0bb782270e22..0000000000000 --- a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md +++ /dev/null @@ -1,37 +0,0 @@ -# `arbitrary_enum_discriminant` - -The tracking issue for this feature is: [#60553] - -[#60553]: https://github.com/rust-lang/rust/issues/60553 - ------------------------- - -The `arbitrary_enum_discriminant` feature permits tuple-like and -struct-like enum variants with `#[repr()]` to have explicit discriminants. - -## Examples - -```rust -#![feature(arbitrary_enum_discriminant)] - -#[allow(dead_code)] -#[repr(u8)] -enum Enum { - Unit = 3, - Tuple(u16) = 2, - Struct { - a: u8, - b: u16, - } = 1, -} - -impl Enum { - fn tag(&self) -> u8 { - unsafe { *(self as *const Self as *const u8) } - } -} - -assert_eq!(3, Enum::Unit.tag()); -assert_eq!(2, Enum::Tuple(5).tag()); -assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); -``` diff --git a/src/test/ui/cast/issue-88621.rs b/src/test/ui/cast/issue-88621.rs index 9242b80e22939..1679793ee6834 100644 --- a/src/test/ui/cast/issue-88621.rs +++ b/src/test/ui/cast/issue-88621.rs @@ -1,5 +1,3 @@ -#![feature(arbitrary_enum_discriminant)] - #[repr(u8)] enum Kind2 { Foo() = 1, diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs index 4da7b5ab24b29..a6e5f70fdefa6 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs @@ -1,5 +1,4 @@ #![crate_type="lib"] -#![feature(arbitrary_enum_discriminant)] enum Enum { //~^ ERROR `#[repr(inttype)]` must be specified diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs index ccc423e4a194c..83e74a6e685a7 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(arbitrary_enum_discriminant, test)] +#![feature(test)] extern crate test; diff --git a/src/test/ui/enum-discriminant/discriminant_value.rs b/src/test/ui/enum-discriminant/discriminant_value.rs index 65ab411dbcbe6..f3dfac298ad7b 100644 --- a/src/test/ui/enum-discriminant/discriminant_value.rs +++ b/src/test/ui/enum-discriminant/discriminant_value.rs @@ -1,6 +1,6 @@ // run-pass #![allow(stable_features)] -#![feature(arbitrary_enum_discriminant, core, core_intrinsics)] +#![feature(core, core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs deleted file mode 100644 index 3e90af4d36af3..0000000000000 --- a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![crate_type="lib"] - -enum Enum { - Unit = 1, - //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants - Tuple() = 2, - //~^ ERROR discriminants on non-unit variants are experimental - Struct{} = 3, - //~^ ERROR discriminants on non-unit variants are experimental -} diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr deleted file mode 100644 index b5f61e6e991d8..0000000000000 --- a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0658]: discriminants on non-unit variants are experimental - --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:6:13 - | -LL | Tuple() = 2, - | ^ - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error[E0658]: discriminants on non-unit variants are experimental - --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:8:14 - | -LL | Struct{} = 3, - | ^ - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants - --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:4:10 - | -LL | Unit = 1, - | ^ disallowed custom discriminant -LL | -LL | Tuple() = 2, - | ----------- tuple variant defined here -LL | -LL | Struct{} = 3, - | ------------ struct variant defined here - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs index f927dd189038a..ad9fcc25b4127 100644 --- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs +++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs @@ -1,4 +1,4 @@ -#![feature(arbitrary_enum_discriminant, core_intrinsics)] +#![feature(core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs index e62582fb5161a..42a062239d34a 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -1,4 +1,4 @@ -#![feature(arbitrary_enum_discriminant, core_intrinsics)] +#![feature(core_intrinsics)] extern crate core; use core::intrinsics::discriminant_value; diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs index ae389e1146645..3adac7b72621c 100644 --- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(repr128, arbitrary_enum_discriminant)] +#![feature(repr128)] //~^ WARN the feature `repr128` is incomplete #[derive(PartialEq, Debug)] diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr index ac93badf2156b..2eef930c39434 100644 --- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr +++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr @@ -1,7 +1,7 @@ warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-70509-partial_eq.rs:2:12 | -LL | #![feature(repr128, arbitrary_enum_discriminant)] +LL | #![feature(repr128)] | ^^^^^^^ | = note: see issue #56071 for more information diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index ae44ffd29bd56..ec3860a322fc5 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -7,7 +7,7 @@ // This test checks panic emitted from `mem::{uninitialized,zeroed}`. -#![feature(never_type, arbitrary_enum_discriminant)] +#![feature(never_type)] #![allow(deprecated, invalid_value)] use std::{ diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs index 140cc5b0fd808..ab14c35893d0a 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.rs +++ b/src/test/ui/macros/macros-nonfatal-errors.rs @@ -4,7 +4,7 @@ // immediately, so that we get more errors listed at a time. #![feature(trace_macros, concat_idents)] -#![feature(stmt_expr_attributes, arbitrary_enum_discriminant)] +#![feature(stmt_expr_attributes)] use std::arch::asm; diff --git a/src/test/ui/parser/issues/issue-17383.rs b/src/test/ui/parser/issues/issue-17383.rs deleted file mode 100644 index 7bf0e64f2c0a3..0000000000000 --- a/src/test/ui/parser/issues/issue-17383.rs +++ /dev/null @@ -1,7 +0,0 @@ -enum X { - A = 3, - //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants - B(usize) -} - -fn main() {} diff --git a/src/test/ui/parser/issues/issue-17383.stderr b/src/test/ui/parser/issues/issue-17383.stderr deleted file mode 100644 index 265d6e1486614..0000000000000 --- a/src/test/ui/parser/issues/issue-17383.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants - --> $DIR/issue-17383.rs:2:9 - | -LL | A = 3, - | ^ disallowed custom discriminant -LL | -LL | B(usize) - | -------- tuple variant defined here - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs deleted file mode 100644 index a9cfdd549c752..0000000000000 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.rs +++ /dev/null @@ -1,12 +0,0 @@ -enum Color { - Red = 0xff0000, - //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants - Green = 0x00ff00, - Blue = 0x0000ff, - Black = 0x000000, - White = 0xffffff, - Other(usize), - Other2(usize, usize), -} - -fn main() {} diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr deleted file mode 100644 index 79f044a0675b7..0000000000000 --- a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants - --> $DIR/tag-variant-disr-non-nullary.rs:2:11 - | -LL | Red = 0xff0000, - | ^^^^^^^^ disallowed custom discriminant -LL | -LL | Green = 0x00ff00, - | ^^^^^^^^ disallowed custom discriminant -LL | Blue = 0x0000ff, - | ^^^^^^^^ disallowed custom discriminant -LL | Black = 0x000000, - | ^^^^^^^^ disallowed custom discriminant -LL | White = 0xffffff, - | ^^^^^^^^ disallowed custom discriminant -LL | Other(usize), - | ------------ tuple variant defined here -LL | Other2(usize, usize), - | -------------------- tuple variant defined here - | - = note: see issue #60553 for more information - = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From b614b0e64c2990c60207aa748957728d644a5a8d Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 6 Apr 2022 13:45:30 +1000 Subject: [PATCH 09/36] Bless tests --- src/test/ui/cast/issue-88621.stderr | 2 +- .../arbitrary_enum_discriminant-no-repr.stderr | 2 +- src/test/ui/transmutability/enums/should_order_correctly.rs | 1 - .../ui/transmutability/enums/should_respect_endianness.rs | 1 - .../ui/transmutability/enums/should_respect_endianness.stderr | 4 ++-- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/ui/cast/issue-88621.stderr b/src/test/ui/cast/issue-88621.stderr index e96d866515238..886145c1bafee 100644 --- a/src/test/ui/cast/issue-88621.stderr +++ b/src/test/ui/cast/issue-88621.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `Kind2` as `u8` - --> $DIR/issue-88621.rs:11:13 + --> $DIR/issue-88621.rs:9:13 | LL | let _ = Kind2::Foo() as u8; | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr index 803bb06fcc218..8cee74696295c 100644 --- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr +++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr @@ -1,5 +1,5 @@ error[E0732]: `#[repr(inttype)]` must be specified - --> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1 + --> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1 | LL | enum Enum { | ^^^^^^^^^ diff --git a/src/test/ui/transmutability/enums/should_order_correctly.rs b/src/test/ui/transmutability/enums/should_order_correctly.rs index b753cf0e62d59..1335cc9d2b17e 100644 --- a/src/test/ui/transmutability/enums/should_order_correctly.rs +++ b/src/test/ui/transmutability/enums/should_order_correctly.rs @@ -2,7 +2,6 @@ //! The payloads of an enum variant should be ordered after its tag. #![crate_type = "lib"] -#![feature(arbitrary_enum_discriminant)] #![feature(transmutability)] #![allow(dead_code)] diff --git a/src/test/ui/transmutability/enums/should_respect_endianness.rs b/src/test/ui/transmutability/enums/should_respect_endianness.rs index 19ff690050031..f3567b405f404 100644 --- a/src/test/ui/transmutability/enums/should_respect_endianness.rs +++ b/src/test/ui/transmutability/enums/should_respect_endianness.rs @@ -2,7 +2,6 @@ //! an enum with a multi-byte tag. #![crate_type = "lib"] -#![feature(arbitrary_enum_discriminant)] #![feature(transmutability)] #![allow(dead_code)] diff --git a/src/test/ui/transmutability/enums/should_respect_endianness.stderr b/src/test/ui/transmutability/enums/should_respect_endianness.stderr index fcb70813bd961..0845a5edf32e5 100644 --- a/src/test/ui/transmutability/enums/should_respect_endianness.stderr +++ b/src/test/ui/transmutability/enums/should_respect_endianness.stderr @@ -1,12 +1,12 @@ error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. - --> $DIR/should_respect_endianness.rs:37:36 + --> $DIR/should_respect_endianness.rs:36:36 | LL | assert::is_transmutable::(); | ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. | = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Unexpected` note: required by a bound in `is_transmutable` - --> $DIR/should_respect_endianness.rs:15:14 + --> $DIR/should_respect_endianness.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this From 74d4eefc1346a8b9242e072df16de4f664b0873c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 23 Oct 2022 09:22:19 +0000 Subject: [PATCH 10/36] Workaround unstable stmt_expr_attributes for method receiver expressions. --- compiler/rustc_ast/src/mut_visit.rs | 14 ++++- compiler/rustc_ast/src/visit.rs | 5 ++ compiler/rustc_builtin_macros/src/cfg_eval.rs | 9 ++- compiler/rustc_expand/src/config.rs | 10 ++- compiler/rustc_expand/src/expand.rs | 63 +++++++++++++++++++ compiler/rustc_expand/src/placeholders.rs | 8 +++ src/test/ui/cfg/cfg-method-receiver-ok.rs | 14 +++++ src/test/ui/cfg/cfg-method-receiver.rs | 3 +- src/test/ui/cfg/cfg-method-receiver.stderr | 14 +---- 9 files changed, 121 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/cfg/cfg-method-receiver-ok.rs diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 25022a02f4bb7..b970e57e0173c 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -152,6 +152,12 @@ pub trait MutVisitor: Sized { noop_visit_expr(e, self); } + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &mut P) { + self.visit_expr(ex) + } + fn filter_map_expr(&mut self, e: P) -> Option> { noop_filter_map_expr(e, self) } @@ -1301,7 +1307,7 @@ pub fn noop_visit_expr( vis.visit_ident(ident); vis.visit_id(id); visit_opt(args, |args| vis.visit_generic_args(args)); - vis.visit_expr(receiver); + vis.visit_method_receiver_expr(receiver); visit_exprs(exprs, vis); vis.visit_span(span); } @@ -1589,3 +1595,9 @@ impl DummyAstNode for Crate { } } } + +impl DummyAstNode for crate::ast_traits::AstNodeWrapper { + fn dummy() -> Self { + crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy()) + } +} diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e752cc7dc2dcd..6f56c1ef0e8da 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized { fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) { + self.visit_expr(ex) + } fn visit_expr_post(&mut self, _ex: &'ast Expr) {} fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 009f3c783d4c8..750f1fe121f6d 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -210,8 +210,15 @@ impl CfgEval<'_, '_> { } impl MutVisitor for CfgEval<'_, '_> { + #[instrument(level = "trace", skip(self))] fn visit_expr(&mut self, expr: &mut P) { - self.cfg.configure_expr(expr); + self.cfg.configure_expr(expr, false); + mut_visit::noop_visit_expr(expr, self); + } + + #[instrument(level = "trace", skip(self))] + fn visit_method_receiver_expr(&mut self, expr: &mut P) { + self.cfg.configure_expr(expr, true); mut_visit::noop_visit_expr(expr, self); } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 8d4e364074863..1d2b1298a68f6 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -469,6 +469,7 @@ impl<'a> StripUnconfigured<'a> { } /// If attributes are not allowed on expressions, emit an error for `attr` + #[instrument(level = "trace", skip(self))] pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { if !self.features.map_or(true, |features| features.stmt_expr_attributes) { let mut err = feature_err( @@ -486,9 +487,12 @@ impl<'a> StripUnconfigured<'a> { } } - pub fn configure_expr(&self, expr: &mut P) { - for attr in expr.attrs.iter() { - self.maybe_emit_expr_attr_err(attr); + #[instrument(level = "trace", skip(self))] + pub fn configure_expr(&self, expr: &mut P, method_receiver: bool) { + if !method_receiver { + for attr in expr.attrs.iter() { + self.maybe_emit_expr_attr_err(attr); + } } // If an expr is valid to cfg away it will have been removed by the diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 15e9a8db3c602..57713fb3cd61d 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -50,6 +50,7 @@ macro_rules! ast_fragments { /// Can also serve as an input and intermediate result for macro expansion operations. pub enum AstFragment { OptExpr(Option>), + MethodReceiverExpr(P), $($Kind($AstTy),)* } @@ -57,6 +58,7 @@ macro_rules! ast_fragments { #[derive(Copy, Clone, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, + MethodReceiverExpr, $($Kind,)* } @@ -64,6 +66,7 @@ macro_rules! ast_fragments { pub fn name(self) -> &'static str { match self { AstFragmentKind::OptExpr => "expression", + AstFragmentKind::MethodReceiverExpr => "expression", $(AstFragmentKind::$Kind => $kind_name,)* } } @@ -72,6 +75,8 @@ macro_rules! ast_fragments { match self { AstFragmentKind::OptExpr => result.make_expr().map(Some).map(AstFragment::OptExpr), + AstFragmentKind::MethodReceiverExpr => + result.make_expr().map(AstFragment::MethodReceiverExpr), $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* } } @@ -98,6 +103,13 @@ macro_rules! ast_fragments { } } + pub fn make_method_receiver_expr(self) -> P { + match self { + AstFragment::MethodReceiverExpr(expr) => expr, + _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), + } + } + $(pub fn $make_ast(self) -> $AstTy { match self { AstFragment::$Kind(ast) => ast, @@ -120,6 +132,7 @@ macro_rules! ast_fragments { } }); } + AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)* $($(AstFragment::$Kind(ast) => ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)* @@ -130,6 +143,7 @@ macro_rules! ast_fragments { match *self { AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr), AstFragment::OptExpr(None) => {} + AstFragment::MethodReceiverExpr(ref expr) => visitor.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)* $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] { visitor.$visit_ast_elt(ast_elt, $($args)*); @@ -222,6 +236,7 @@ impl AstFragmentKind { match self { AstFragmentKind::OptExpr | AstFragmentKind::Expr + | AstFragmentKind::MethodReceiverExpr | AstFragmentKind::Stmts | AstFragmentKind::Ty | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false }, @@ -285,6 +300,9 @@ impl AstFragmentKind { AstFragmentKind::Expr => AstFragment::Expr( items.next().expect("expected exactly one expression").expect_expr(), ), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr( + items.next().expect("expected exactly one expression").expect_expr(), + ), AstFragmentKind::OptExpr => { AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)) } @@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>( AstFragment::Stmts(stmts) } AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?), AstFragmentKind::OptExpr => { if this.token != token::Eof { AstFragment::OptExpr(Some(this.parse_expr()?)) @@ -1477,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper, OptExprTag> { } } +/// This struct is a hack to workaround unstable of `stmt_expr_attributes`. +/// It can be removed once that feature is stabilized. +struct MethodReceiverTag; +impl DummyAstNode for MethodReceiverTag { + fn dummy() -> MethodReceiverTag { + MethodReceiverTag + } +} +impl InvocationCollectorNode for AstNodeWrapper, MethodReceiverTag> { + type OutputTy = Self; + type AttrsTy = ast::AttrVec; + const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr; + fn descr() -> &'static str { + "an expression" + } + fn to_annotatable(self) -> Annotatable { + Annotatable::Expr(self.wrapped) + } + fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { + AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag) + } + fn noop_visit(&mut self, visitor: &mut V) { + noop_visit_expr(&mut self.wrapped, visitor) + } + fn is_mac_call(&self) -> bool { + matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) + } + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { + let node = self.wrapped.into_inner(); + match node.kind { + ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), + _ => unreachable!(), + } + } +} + struct InvocationCollector<'a, 'b> { cx: &'a mut ExtCtxt<'b>, invocations: Vec<(Invocation, Option>)>, @@ -1840,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.visit_node(node) } + fn visit_method_receiver_expr(&mut self, node: &mut P) { + visit_clobber(node, |node| { + let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag); + self.visit_node(&mut wrapper); + wrapper.wrapped + }) + } + fn filter_map_expr(&mut self, node: P) -> Option> { self.flat_map_node(AstNodeWrapper::new(node, OptExprTag)) } diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 3b0d5ddb97b4e..faaf3b3fea589 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -55,6 +55,7 @@ pub fn placeholder( }), AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()), AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { id, span, @@ -296,6 +297,13 @@ impl MutVisitor for PlaceholderExpander { } } + fn visit_method_receiver_expr(&mut self, expr: &mut P) { + match expr.kind { + ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(), + _ => noop_visit_expr(expr, self), + } + } + fn filter_map_expr(&mut self, expr: P) -> Option> { match expr.kind { ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(), diff --git a/src/test/ui/cfg/cfg-method-receiver-ok.rs b/src/test/ui/cfg/cfg-method-receiver-ok.rs new file mode 100644 index 0000000000000..61ad3b8c17ab2 --- /dev/null +++ b/src/test/ui/cfg/cfg-method-receiver-ok.rs @@ -0,0 +1,14 @@ +// check-pass + +macro_rules! foo { + () => { + #[allow(unreachable_patterns)] + { + 123i32 + } + }; +} + +fn main() { + let _ = foo!().abs(); +} diff --git a/src/test/ui/cfg/cfg-method-receiver.rs b/src/test/ui/cfg/cfg-method-receiver.rs index 78a072f503fab..71134ff17b527 100644 --- a/src/test/ui/cfg/cfg-method-receiver.rs +++ b/src/test/ui/cfg/cfg-method-receiver.rs @@ -7,6 +7,5 @@ macro_rules! cbor_map { fn main() { cbor_map! { #[cfg(test)] 4}; - //~^ ERROR attributes on expressions are experimental - //~| ERROR removing an expression is not supported in this position + //~^ ERROR removing an expression is not supported in this position } diff --git a/src/test/ui/cfg/cfg-method-receiver.stderr b/src/test/ui/cfg/cfg-method-receiver.stderr index 517fc8168e72d..5767a7c1b4b1c 100644 --- a/src/test/ui/cfg/cfg-method-receiver.stderr +++ b/src/test/ui/cfg/cfg-method-receiver.stderr @@ -1,12 +1,3 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/cfg-method-receiver.rs:9:17 - | -LL | cbor_map! { #[cfg(test)] 4}; - | ^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - error: removing an expression is not supported in this position --> $DIR/cfg-method-receiver.rs:9:17 | @@ -28,7 +19,6 @@ help: you must specify a concrete type for this numeric value, like `i32` LL | cbor_map! { #[cfg(test)] 4_i32}; | ~~~~~ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0689. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0689`. From 8bc43f99e91a94868fe08bb72b7ce66d7656d0b5 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Mon, 17 Oct 2022 19:41:49 +0200 Subject: [PATCH 11/36] Allow specifying multiple alternative suggestions This allows porting uses of span_suggestions() to diagnostic structs. Doesn't work for multipart_suggestions() because the rank would be reversed - the struct would specify multiple spans, each of which has multiple possible replacements, while multipart_suggestions() creates multiple possible replacements, each with multiple spans. --- compiler/rustc_errors/src/diagnostic.rs | 26 ++++- .../src/diagnostics/diagnostic_builder.rs | 2 +- .../src/diagnostics/subdiagnostic.rs | 21 ++-- .../rustc_macros/src/diagnostics/utils.rs | 105 ++++++++++++++++-- .../session-diagnostic/diagnostic-derive.rs | 38 +++++++ .../diagnostic-derive.stderr | 20 +++- .../subdiagnostic-derive.rs | 45 ++++++++ .../subdiagnostic-derive.stderr | 32 +++++- 8 files changed, 263 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a63fc0ca285da..23f29a24fe79f 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -690,6 +690,24 @@ impl Diagnostic { msg: impl Into, suggestions: impl Iterator, applicability: Applicability, + ) -> &mut Self { + self.span_suggestions_with_style( + sp, + msg, + suggestions, + applicability, + SuggestionStyle::ShowCode, + ) + } + + /// [`Diagnostic::span_suggestions()`] but you can set the [`SuggestionStyle`]. + pub fn span_suggestions_with_style( + &mut self, + sp: Span, + msg: impl Into, + suggestions: impl Iterator, + applicability: Applicability, + style: SuggestionStyle, ) -> &mut Self { let mut suggestions: Vec<_> = suggestions.collect(); suggestions.sort(); @@ -706,14 +724,15 @@ impl Diagnostic { self.push_suggestion(CodeSuggestion { substitutions, msg: self.subdiagnostic_message_to_diagnostic_message(msg), - style: SuggestionStyle::ShowCode, + style, applicability, }); self } - /// Prints out a message with multiple suggested edits of the code. - /// See also [`Diagnostic::span_suggestion()`]. + /// Prints out a message with multiple suggested edits of the code, where each edit consists of + /// multiple parts. + /// See also [`Diagnostic::multipart_suggestion()`]. pub fn multipart_suggestions( &mut self, msg: impl Into, @@ -745,6 +764,7 @@ impl Diagnostic { }); self } + /// Prints out a message with a suggested edit of the code. If the suggestion is presented /// inline, it will only show the message and not the suggestion. /// diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 9f7d2661a3e8b..3ea83fd09c794 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -454,7 +454,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { self.formatting_init.extend(code_init); Ok(quote! { - #diag.span_suggestion_with_style( + #diag.span_suggestions_with_style( #span_field, rustc_errors::fluent::#slug, #code_field, diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index d1acb71384220..fa0ca5a52423a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -11,9 +11,11 @@ use crate::diagnostics::utils::{ }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; +use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; +use super::utils::{build_suggestion_code, AllowMultipleAlternatives}; + /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct. pub(crate) struct SubdiagnosticDeriveBuilder { diag: syn::Ident, @@ -414,15 +416,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let nested_name = meta.path().segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else { - throw_invalid_nested_attr!(attr, &nested_attr); - }; - match nested_name { "code" => { - let formatted_str = self.build_format(&value.value(), value.span()); let code_field = new_code_ident(); - code.set_once((code_field, formatted_str), span); + let formatting_init = build_suggestion_code( + &code_field, + meta, + self, + AllowMultipleAlternatives::No, + ); + code.set_once((code_field, formatting_init), span); } _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("`code` is the only valid nested attribute") @@ -430,14 +433,14 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - let Some((code_field, formatted_str)) = code.value() else { + let Some((code_field, formatting_init)) = code.value() else { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); return Ok(quote! {}); }; let binding = info.binding; - self.formatting_init.extend(quote! { let #code_field = #formatted_str; }); + self.formatting_init.extend(formatting_init); let code_field = if clone_suggestion_code { quote! { #code_field.clone() } } else { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 61d5007fc30f0..374c795d0a638 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -2,7 +2,7 @@ use crate::diagnostics::error::{ span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, }; use proc_macro::Span; -use proc_macro2::TokenStream; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote, ToTokens}; use std::cell::RefCell; use std::collections::{BTreeSet, HashMap}; @@ -395,6 +395,82 @@ pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap TokenStream { + let values = match meta { + // `code = "foo"` + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s], + // `code("foo", "bar")` + Meta::List(MetaList { nested, .. }) => { + if let AllowMultipleAlternatives::No = allow_multiple { + span_err( + meta.span().unwrap(), + "expected exactly one string literal for `code = ...`", + ) + .emit(); + vec![] + } else if nested.is_empty() { + span_err( + meta.span().unwrap(), + "expected at least one string literal for `code(...)`", + ) + .emit(); + vec![] + } else { + nested + .into_iter() + .filter_map(|item| { + if let NestedMeta::Lit(syn::Lit::Str(s)) = item { + Some(s) + } else { + span_err( + item.span().unwrap(), + "`code(...)` must contain only string literals", + ) + .emit(); + None + } + }) + .collect() + } + } + _ => { + span_err( + meta.span().unwrap(), + r#"`code = "..."`/`code(...)` must contain only string literals"#, + ) + .emit(); + vec![] + } + }; + + if let AllowMultipleAlternatives::Yes = allow_multiple { + let formatted_strings: Vec<_> = values + .into_iter() + .map(|value| fields.build_format(&value.value(), value.span())) + .collect(); + quote! { let #code_field = [#(#formatted_strings),*].into_iter(); } + } else if let [value] = values.as_slice() { + let formatted_str = fields.build_format(&value.value(), value.span()); + quote! { let #code_field = #formatted_str; } + } else { + // error handled previously + quote! { let #code_field = String::new(); } + } +} + /// Possible styles for suggestion subdiagnostics. #[derive(Clone, Copy)] pub(super) enum SuggestionKind { @@ -571,21 +647,23 @@ impl SubdiagnosticKind { let nested_name = meta.path().segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let value = match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, + let string_value = match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value), + Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("a diagnostic slug must be the first argument to the attribute") }), - _ => { - invalid_nested_attr(attr, &nested_attr).emit(); - continue; - } + _ => None, }; match (nested_name, &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { - let formatted_str = fields.build_format(&value.value(), value.span()); - let code_init = quote! { let #code_field = #formatted_str; }; + let code_init = build_suggestion_code( + code_field, + meta, + fields, + AllowMultipleAlternatives::Yes, + ); code.set_once(code_init, span); } ( @@ -593,6 +671,11 @@ impl SubdiagnosticKind { SubdiagnosticKind::Suggestion { ref mut applicability, .. } | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, ) => { + let Some(value) = string_value else { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + }; + let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { span_err(span, "invalid applicability").emit(); Applicability::Unspecified @@ -623,7 +706,7 @@ impl SubdiagnosticKind { init } else { span_err(span, "suggestion without `code = \"...\"`").emit(); - quote! { let #code_field: String = unreachable!(); } + quote! { let #code_field = std::iter::empty(); } }; } SubdiagnosticKind::Label @@ -644,7 +727,7 @@ impl quote::IdentFragment for SubdiagnosticKind { SubdiagnosticKind::Note => write!(f, "note"), SubdiagnosticKind::Help => write!(f, "help"), SubdiagnosticKind::Warn => write!(f, "warn"), - SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), + SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"), SubdiagnosticKind::MultipartSuggestion { .. } => { write!(f, "multipart_suggestion_with_style") } diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 46164d573b0bd..ca77e483d6ff8 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -758,3 +758,41 @@ struct WithDocComment { #[primary_span] span: Span, } + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsGood { + #[suggestion(code("foo", "bar"))] + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsSingleItem { + #[suggestion(code("foo"))] + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsNoItem { + #[suggestion(code())] + //~^ ERROR expected at least one string literal for `code(...)` + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsInvalidItem { + #[suggestion(code(foo))] + //~^ ERROR `code(...)` must contain only string literals + sub: Span, +} + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionsInvalidLiteral { + #[suggestion(code = 3)] + //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + sub: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 0a1c4bddb06a0..859c272b6ba9c 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -573,6 +573,24 @@ LL | #[subdiagnostic(eager)] | = help: eager subdiagnostics are not supported on lints +error: expected at least one string literal for `code(...)` + --> $DIR/diagnostic-derive.rs:779:18 + | +LL | #[suggestion(code())] + | ^^^^^^ + +error: `code(...)` must contain only string literals + --> $DIR/diagnostic-derive.rs:787:23 + | +LL | #[suggestion(code(foo))] + | ^^^ + +error: `code = "..."`/`code(...)` must contain only string literals + --> $DIR/diagnostic-derive.rs:795:18 + | +LL | #[suggestion(code = 3)] + | ^^^^^^^^ + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:55:3 | @@ -647,7 +665,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 80 previous errors +error: aborting due to 83 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 9088ca6ce462b..efec85eb52c2e 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -661,3 +661,48 @@ enum BL { span: Span, } } + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BM { + #[suggestion_part(code("foo"))] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BN { + #[suggestion_part(code("foo", "bar"))] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BO { + #[suggestion_part(code(3))] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BP { + #[suggestion_part(code())] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser_add_paren)] +struct BQ { + #[suggestion_part(code = 3)] + //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + span: Span, + r#type: String, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index b21f9cc94a98c..a85a8711eaca4 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -415,6 +415,36 @@ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_sugg LL | #[applicability] | ^^^^^^^^^^^^^^^^ +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:668:23 + | +LL | #[suggestion_part(code("foo"))] + | ^^^^^^^^^^^ + +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:677:23 + | +LL | #[suggestion_part(code("foo", "bar"))] + | ^^^^^^^^^^^^^^^^^^ + +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:686:23 + | +LL | #[suggestion_part(code(3))] + | ^^^^^^^ + +error: expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive.rs:695:23 + | +LL | #[suggestion_part(code())] + | ^^^^^^ + +error: `code = "..."`/`code(...)` must contain only string literals + --> $DIR/subdiagnostic-derive.rs:704:23 + | +LL | #[suggestion_part(code = 3)] + | ^^^^^^^^ + error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 | @@ -475,6 +505,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 67 previous errors +error: aborting due to 72 previous errors For more information about this error, try `rustc --explain E0425`. From dd51b36fb261513a0886d98c16be7fcc43c66272 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Oct 2022 01:52:23 +0000 Subject: [PATCH 12/36] Add normalize hack back --- compiler/rustc_middle/src/ty/relate.rs | 15 ++++++++-- src/test/ui/consts/unnormalized-param-env.rs | 31 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/unnormalized-param-env.rs diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index cdb618e030afe..b25b4bd4fe363 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -574,8 +574,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( /// it. pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, + mut a: ty::Const<'tcx>, + mut b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); let tcx = relation.tcx(); @@ -596,6 +596,17 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( ); } + // HACK(const_generics): We still need to eagerly evaluate consts when + // relating them because during `normalize_param_env_or_error`, + // we may relate an evaluated constant in a obligation against + // an unnormalized (i.e. unevaluated) const in the param-env. + // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants + // these `eval` calls can be removed. + if !relation.tcx().features().generic_const_exprs { + a = a.eval(tcx, relation.param_env()); + b = b.eval(tcx, relation.param_env()); + } + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. diff --git a/src/test/ui/consts/unnormalized-param-env.rs b/src/test/ui/consts/unnormalized-param-env.rs new file mode 100644 index 0000000000000..a7bbe4db99290 --- /dev/null +++ b/src/test/ui/consts/unnormalized-param-env.rs @@ -0,0 +1,31 @@ +// check-pass + +pub trait CSpace { + type Traj; +} + +pub struct Const; + +pub trait Obstacle { + fn trajectory_free(&self, t: &FT) + where + CS::Traj: Sized, + CS: CSpace; +} + +// ----- + +const N: usize = 4; + +struct ObstacleSpace2df32; + +impl Obstacle for ObstacleSpace2df32 { + fn trajectory_free(&self, t: &TF) + where + CS::Traj: Sized, + CS: CSpace, + { + } +} + +fn main() {} From 6e6fe30d0f7e3dcbbf3988650311cee179992e5d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Oct 2022 17:53:29 +0000 Subject: [PATCH 13/36] Comment why normalization is needed for debug assertions --- compiler/rustc_const_eval/src/interpret/operand.rs | 9 ++++++++- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 719588a936ce3..0c212cf59e17f 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -554,6 +554,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { val: &mir::ConstantKind<'tcx>, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + // FIXME(const_prop): normalization needed b/c const prop lint in + // `mir_drops_elaborated_and_const_checked`, which happens before + // optimized MIR. Only after optimizing the MIR can we guarantee + // that the `RevealAll` pass has happened and that the body's consts + // are normalized, so any call to resolve before that needs to be + // manually normalized. + let val = self.tcx.normalize_erasing_regions(self.param_env, *val); match val { mir::ConstantKind::Ty(ct) => { match ct.kind() { @@ -585,7 +592,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } } - mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout), + mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout), mir::ConstantKind::Unevaluated(uv, _) => { let instance = self.resolve(uv.def, uv.substs)?; Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 895af80bd7f33..2526522a25c8c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -483,7 +483,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Use `Reveal::All` here because patterns are always monomorphic even if their function // isn't. let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx); - let substs = self.typeck_results.node_substs(id); + // N.B. There is no guarantee that substs collected in typeck results are fully normalized, + // so they need to be normalized in order to pass to `Instance::resolve`, which will ICE + // if given unnormalized types. + let substs = self + .tcx + .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id)); let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { Ok(Some(i)) => i, Ok(None) => { From f54c336c8019432803dd9a67b575053ffc03c372 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 22 Oct 2022 07:56:26 +0800 Subject: [PATCH 14/36] fix #103425, remove extra type error after missing semicolon error --- compiler/rustc_parse/src/parser/stmt.rs | 65 ++++++++++++++----------- src/test/ui/parser/issue-103425.rs | 15 ++++++ src/test/ui/parser/issue-103425.stderr | 29 +++++++++++ 3 files changed, 80 insertions(+), 29 deletions(-) create mode 100644 src/test/ui/parser/issue-103425.rs create mode 100644 src/test/ui/parser/issue-103425.stderr diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index a61e77b7c3bfb..12753c6785c9a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -553,39 +553,46 @@ impl<'a> Parser<'a> { match stmt.kind { // Expression without semicolon. StmtKind::Expr(ref mut expr) - if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => - { + if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => { // Just check for errors and recover; do not eat semicolon yet. - if let Err(mut e) = - self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) - { - if let TokenKind::DocComment(..) = self.token.kind { - if let Ok(snippet) = self.span_to_snippet(self.token.span) { - let sp = self.token.span; - let marker = &snippet[..3]; - let (comment_marker, doc_comment_marker) = marker.split_at(2); - - e.span_suggestion( - sp.with_hi(sp.lo() + BytePos(marker.len() as u32)), - &format!( - "add a space before `{}` to use a regular comment", - doc_comment_marker, - ), - format!("{} {}", comment_marker, doc_comment_marker), - Applicability::MaybeIncorrect, - ); + // `expect_one_of` returns PResult<'a, bool /* recovered */> + let replace_with_err = + match self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) { + // Recover from parser, skip type error to avoid extra errors. + Ok(true) => true, + Err(mut e) => { + if let TokenKind::DocComment(..) = self.token.kind && + let Ok(snippet) = self.span_to_snippet(self.token.span) { + let sp = self.token.span; + let marker = &snippet[..3]; + let (comment_marker, doc_comment_marker) = marker.split_at(2); + + e.span_suggestion( + sp.with_hi(sp.lo() + BytePos(marker.len() as u32)), + &format!( + "add a space before `{}` to use a regular comment", + doc_comment_marker, + ), + format!("{} {}", comment_marker, doc_comment_marker), + Applicability::MaybeIncorrect, + ); } - } - if let Err(mut e) = - self.check_mistyped_turbofish_with_multiple_type_params(e, expr) - { - if recover.no() { - return Err(e); + + if let Err(mut e) = + self.check_mistyped_turbofish_with_multiple_type_params(e, expr) + { + if recover.no() { + return Err(e); + } + e.emit(); + self.recover_stmt(); } - e.emit(); - self.recover_stmt(); + true } - // Don't complain about type errors in body tail after parse error (#57383). + _ => false + }; + if replace_with_err { + // We already emitted an error, so don't emit another type error let sp = expr.span.to(self.prev_token.span); *expr = self.mk_expr_err(sp); } diff --git a/src/test/ui/parser/issue-103425.rs b/src/test/ui/parser/issue-103425.rs new file mode 100644 index 0000000000000..c2f8123ca4e67 --- /dev/null +++ b/src/test/ui/parser/issue-103425.rs @@ -0,0 +1,15 @@ +fn f() -> f32 { + 3 + //~^ ERROR expected `;` + 5.0 +} + +fn k() -> f32 { + 2_u32 + //~^ ERROR expected `;` + 3_i8 + //~^ ERROR expected `;` + 5.0 +} + +fn main() {} diff --git a/src/test/ui/parser/issue-103425.stderr b/src/test/ui/parser/issue-103425.stderr new file mode 100644 index 0000000000000..0efe3e3ca7117 --- /dev/null +++ b/src/test/ui/parser/issue-103425.stderr @@ -0,0 +1,29 @@ +error: expected `;`, found `5.0` + --> $DIR/issue-103425.rs:2:6 + | +LL | 3 + | ^ help: add `;` here +LL | +LL | 5.0 + | --- unexpected token + +error: expected `;`, found `3_i8` + --> $DIR/issue-103425.rs:8:10 + | +LL | 2_u32 + | ^ help: add `;` here +LL | +LL | 3_i8 + | ---- unexpected token + +error: expected `;`, found `5.0` + --> $DIR/issue-103425.rs:10:9 + | +LL | 3_i8 + | ^ help: add `;` here +LL | +LL | 5.0 + | --- unexpected token + +error: aborting due to 3 previous errors + From 0fca075ce8a2247b6d59cd8eaf2fd1d6b89855d8 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 12 Oct 2022 17:07:30 +0800 Subject: [PATCH 15/36] suggest type annotation for local statement initialed by ref expression --- compiler/rustc_hir_typeck/src/demand.rs | 19 ++++++- .../src/fn_ctxt/suggestions.rs | 47 ++++++++++++++- src/test/ui/suggestions/format-borrow.stderr | 16 ++++++ src/test/ui/suggestions/issue-102892.rs | 25 ++++++++ src/test/ui/suggestions/issue-102892.stderr | 57 +++++++++++++++++++ 5 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/suggestions/issue-102892.rs create mode 100644 src/test/ui/suggestions/issue-102892.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 2974ac97f2368..be14234afe28d 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -714,7 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, - ) -> Option<(Span, String, String, Applicability, bool /* verbose */)> { + ) -> Option<( + Span, + String, + String, + Applicability, + bool, /* verbose */ + bool, /* suggest `&` or `&mut` type annotation */ + )> { let sess = self.sess(); let sp = expr.span; @@ -746,6 +753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + false, )); } } @@ -760,6 +768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "b".to_string(), Applicability::MachineApplicable, true, + false, )); } } @@ -817,6 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg.2, Applicability::MachineApplicable, false, + false, )); } @@ -844,6 +854,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&mut {sugg_expr}"), Applicability::MachineApplicable, false, + false, ), hir::Mutability::Not => ( sp, @@ -851,6 +862,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&{sugg_expr}"), Applicability::MachineApplicable, false, + false, ), }); } @@ -880,6 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true )); } return None; @@ -893,6 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true, )); } } @@ -959,6 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { src, applicability, true, + false, )); } } @@ -999,6 +1014,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable }, true, + false, )); } @@ -1050,6 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggestion, Applicability::MachineApplicable, true, + false, )); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index cd2e41aff0f12..4db9c56f98fee 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -327,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> bool { let expr = expr.peel_blocks(); - if let Some((sp, msg, suggestion, applicability, verbose)) = + if let Some((sp, msg, suggestion, applicability, verbose, annotation)) = self.check_ref(expr, found, expected) { if verbose { @@ -335,9 +335,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { err.span_suggestion(sp, &msg, suggestion, applicability); } + if annotation { + let suggest_annotation = match expr.peel_drop_temps().kind { + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&", + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ", + _ => return true, + }; + let mut tuple_indexes = Vec::new(); + let mut expr_id = expr.hir_id; + for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) { + match node { + Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => { + tuple_indexes.push( + subs.iter() + .enumerate() + .find(|(_, sub_expr)| sub_expr.hir_id == expr_id) + .unwrap() + .0, + ); + expr_id = parent_id; + } + Node::Local(local) => { + if let Some(mut ty) = local.ty { + while let Some(index) = tuple_indexes.pop() { + match ty.kind { + TyKind::Tup(tys) => ty = &tys[index], + _ => return true, + } + } + let annotation_span = ty.span; + err.span_suggestion( + annotation_span.with_hi(annotation_span.lo()), + format!("alternatively, consider changing the type annotation"), + suggest_annotation, + Applicability::MaybeIncorrect, + ); + } + break; + } + _ => break, + } + } + } return true; - } else if self.suggest_else_fn_with_closure(err, expr, found, expected) - { + } else if self.suggest_else_fn_with_closure(err, expr, found, expected) { return true; } else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected)) && let ty::FnDef(def_id, ..) = &found.kind() diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr index fac6a5a5f48cb..8ed2b9c9a6330 100644 --- a/src/test/ui/suggestions/format-borrow.stderr +++ b/src/test/ui/suggestions/format-borrow.stderr @@ -11,6 +11,10 @@ help: consider removing the borrow LL - let a: String = &String::from("a"); LL + let a: String = String::from("a"); | +help: alternatively, consider changing the type annotation + | +LL | let a: &String = &String::from("a"); + | + error[E0308]: mismatched types --> $DIR/format-borrow.rs:4:21 @@ -25,6 +29,10 @@ help: consider removing the borrow LL - let b: String = &format!("b"); LL + let b: String = format!("b"); | +help: alternatively, consider changing the type annotation + | +LL | let b: &String = &format!("b"); + | + error[E0308]: mismatched types --> $DIR/format-borrow.rs:6:21 @@ -39,6 +47,10 @@ help: consider removing the borrow LL - let c: String = &mut format!("c"); LL + let c: String = format!("c"); | +help: alternatively, consider changing the type annotation + | +LL | let c: &mut String = &mut format!("c"); + | ++++ error[E0308]: mismatched types --> $DIR/format-borrow.rs:8:21 @@ -53,6 +65,10 @@ help: consider removing the borrow LL - let d: String = &mut (format!("d")); LL + let d: String = format!("d")); | +help: alternatively, consider changing the type annotation + | +LL | let d: &mut String = &mut (format!("d")); + | ++++ error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/issue-102892.rs b/src/test/ui/suggestions/issue-102892.rs new file mode 100644 index 0000000000000..c1a791d8d857a --- /dev/null +++ b/src/test/ui/suggestions/issue-102892.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, unused_variables)] + +use std::sync::Arc; + +#[derive(Debug)] +struct A; +#[derive(Debug)] +struct B; + +fn process_without_annot(arc: &Arc<(A, B)>) { + let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +} + +fn process_with_annot(arc: &Arc<(A, B)>) { + let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too + //~^ ERROR mismatched types +} + +fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) { + let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-102892.stderr b/src/test/ui/suggestions/issue-102892.stderr new file mode 100644 index 0000000000000..a3dbc7cb861ff --- /dev/null +++ b/src/test/ui/suggestions/issue-102892.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:15:26 + | +LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too + | ------ ^^^^^^ expected tuple, found `&(A, B)` + | | + | expected due to this + | + = note: expected tuple `(A, B)` + found reference `&(A, B)` +help: consider removing the borrow + | +LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too +LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too + | + + +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:20:32 + | +LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)` + | + = note: expected tuple `(A, B)` + found mutable reference `&mut (A, B)` +help: consider removing the borrow + | +LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too +LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ++++ + +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:20:48 + | +LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ^^^^^^^^^^ expected struct `A`, found `&A` + | +help: consider removing the borrow + | +LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too +LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From 7b83059146b6cfb367bbee7cd97370fc271e8979 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 24 Oct 2022 12:00:35 +0200 Subject: [PATCH 16/36] rustup --- src/tools/miri/rust-version | 2 +- src/tools/miri/src/shims/windows/foreign_items.rs | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index eb0301bee2ac6..768658b1a1224 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -b1ab3b738ac718da74cd4aa0bb7f362d0adbdf84 +56f132565eb31eeb9ec7e1800a6ab2ca354e710e diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 184ba997fc861..2a34a3a47bbb5 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -418,13 +418,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Indicate an error. this.write_null(dest)?; } - "GetFileInformationByHandleEx" if this.frame_in_std() => { - #[allow(non_snake_case)] - let [_hFile, _FileInformationClass, _lpFileInformation, _dwBufferSize] = - this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - // Just make it fail. - this.write_null(dest)?; - } "GetFileType" if this.frame_in_std() => { #[allow(non_snake_case)] let [_hFile] = From 91c09d44f60c22e0874bcef393e2fa67e1875c01 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 24 Oct 2022 13:01:07 +0200 Subject: [PATCH 17/36] use the shared assets step for building std too --- src/bootstrap/doc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 939e169ec00e5..5c624bd4eb442 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -457,7 +457,8 @@ impl Step for Std { let target = self.target; let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); + + builder.ensure(SharedAssets { target: self.target }); let index_page = builder.src.join("src/doc/index.md").into_os_string(); let mut extra_args = vec![ From 1727c00f1a810cae447e12bb564110527450219c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 10 Oct 2022 22:39:41 +0000 Subject: [PATCH 18/36] Assert if inference vars are leaking from fully_resolve --- compiler/rustc_infer/src/infer/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2732c92ecd38b..7e2ea6c0e269c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1469,7 +1469,12 @@ impl<'tcx> InferCtxt<'tcx> { * except during the writeback phase. */ - resolve::fully_resolve(self, value) + let value = resolve::fully_resolve(self, value); + assert!( + value.as_ref().map_or(true, |value| !value.needs_infer()), + "`{value:?}` is not fully resolved" + ); + value } pub fn replace_bound_vars_with_fresh_vars( From eaa1b8b10e50ae618904314e0fd2ce266ed3590d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 24 Oct 2022 09:16:45 -0700 Subject: [PATCH 19/36] Migrate from highfive to triagebot --- triagebot.toml | 159 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 04c2a0507acc8..fb6287c5526c0 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -20,8 +20,6 @@ allow-unauthenticated = [ "AsyncAwait-OnDeck", ] -[assign] - [glacier] [ping.icebreakers-llvm] @@ -246,6 +244,9 @@ trigger_files = [ "src/version" ] +[autolabel."S-waiting-on-review"] +new_pr = true + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts topic = "#{number} {title}" @@ -420,3 +421,157 @@ cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] [mentions."compiler/rustc_macros/src/diagnostics"] message = "`rustc_macros::diagnostics` was changed" cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] + +[assign] +warn_non_default_branch = true +contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html" + +[assign.adhoc_groups] +compiler-team = [ + "@cjgillot", + "@estebank", + "@petrochenkov", + "@davidtwco", + "@oli-obk", + "@lcnr", + "@nagisa", + "@wesleywiser", +] +compiler-team-contributors = [ + "@compiler-errors", + "@eholk", + "@jackh726", + "@fee1-dead", + "@TaKO8Ki", +] +compiler = [ + "compiler-team", + "compiler-team-contributors", +] +libs = [ + "@joshtriplett", + "@Mark-Simulacrum", + "@m-ou-se", + "@thomcc", +] +bootstrap = [ + "@Mark-Simulacrum", + "@jyn514", +] +infra-ci = [ + "@Mark-Simulacrum", + "@pietroalbini", + "@jyn514", +] +rustdoc = [ + "@jsha", + "@GuillaumeGomez", + "@CraftSpider", + "@notriddle", +] +docs = [ + "@ehuss", + "@GuillaumeGomez", + "@JohnTitor", +] +query-system = [ + "@cjgillot", +] +incremental = [ + "@michaelwoerister", + "@wesleywiser", +] +diagnostics = [ + "@compiler-errors", + "@davidtwco", + "@estebank", + "@oli-obk", + "@TaKO8Ki", +] +parser = [ + "@davidtwco", + "@estebank", + "@nnethercote", + "@petrochenkov", +] +lexer = [ + "@nnethercote", + "@petrochenkov", +] +mir = [ + "@davidtwco", + "@oli-obk", +] +mir-opt = [ + "@nagisa", + "@oli-obk", + "@wesleywiser", +] +types = [ + "@compiler-errors", + "@jackh726", + "@lcnr", + "@oli-obk", + "@spastorino", +] +borrowck = [ + "@davidtwco", + "@pnkfelix", +] +ast_lowering = [ + "@spastorino", +] +fallback = [ + "@Mark-Simulacrum" +] + +[assign.owners] +"/.github/workflows" = ["infra-ci"] +"/Cargo.lock" = ["@Mark-Simulacrum"] +"/Cargo.toml" = ["@Mark-Simulacrum"] +"/compiler" = ["compiler"] +"/compiler/rustc_apfloat" = ["@eddyb"] +"/compiler/rustc_ast" = ["compiler", "parser"] +"/compiler/rustc_ast_lowering" = ["compiler", "ast_lowering"] +"/compiler/rustc_hir_analysis" = ["compiler", "types"] +"/compiler/rustc_lexer" = ["compiler", "lexer"] +"/compiler/rustc_llvm" = ["@cuviper"] +"/compiler/rustc_middle/src/mir" = ["compiler", "mir"] +"/compiler/rustc_middle/src/traits" = ["compiler", "types"] +"/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"] +"/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"] +"/compiler/rustc_mir_build/src/build" = ["compiler", "mir"] +"/compiler/rustc_parse" = ["compiler", "parser"] +"/compiler/rustc_parse/src/lexer" = ["compiler", "lexer"] +"/compiler/rustc_query_impl" = ["compiler", "query-system"] +"/compiler/rustc_query_system" = ["compiler", "query-system"] +"/compiler/rustc_trait_selection" = ["compiler", "types"] +"/compiler/rustc_traits" = ["compiler", "types"] +"/compiler/rustc_type_ir" = ["compiler", "types"] +"/library/alloc" = ["libs"] +"/library/core" = ["libs", "@scottmcm"] +"/library/panic_abort" = ["libs"] +"/library/panic_unwind" = ["libs"] +"/library/proc_macro" = ["@petrochenkov"] +"/library/std" = ["libs"] +"/library/std/src/sys/windows" = ["@ChrisDenton", "@thomcc"] +"/library/stdarch" = ["libs"] +"/library/test" = ["libs"] +"/src/bootstrap" = ["bootstrap"] +"/src/ci" = ["infra-ci"] +"/src/doc" = ["docs"] +"/src/doc/rustdoc" = ["rustdoc"] +"/src/etc" = ["@Mark-Simulacrum"] +"/src/librustdoc" = ["rustdoc"] +"/src/llvm-project" = ["@cuviper"] +"/src/rustdoc-json-types" = ["rustdoc"] +"/src/stage0.json" = ["bootstrap"] +"/src/tools/cargo" = ["@ehuss", "@joshtriplett"] +"/src/tools/compiletest" = ["bootstrap"] +"/src/tools/linkchecker" = ["@ehuss"] +"/src/tools/rust-installer" = ["bootstrap"] +"/src/tools/rustbook" = ["@ehuss"] +"/src/tools/rustdoc" = ["rustdoc"] +"/src/tools/rustdoc-js" = ["rustdoc"] +"/src/tools/rustdoc-themes" = ["rustdoc"] +"/src/tools/tidy" = ["bootstrap"] From 5e46d8675cd924e981aac9fd6ca146d627e9d4ab Mon Sep 17 00:00:00 2001 From: Sarthak Singh Date: Sun, 23 Oct 2022 12:29:59 +0530 Subject: [PATCH 20/36] Added helper to prevent verbose printing from the `PrettyPrinter` when printing constants --- .../src/interpret/intrinsics/type_name.rs | 6 ++++-- compiler/rustc_middle/src/ty/print/pretty.rs | 10 +++++++--- src/test/ui/type/issue-94187-verbose-type-name.rs | 13 +++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/type/issue-94187-verbose-type-name.rs diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs index 7e4c5fcb031b0..ffdb8de5b6c8c 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs @@ -4,7 +4,7 @@ use rustc_hir::definitions::DisambiguatedDefPathData; use rustc_middle::mir::interpret::{Allocation, ConstAllocation}; use rustc_middle::ty::{ self, - print::{PrettyPrinter, Print, Printer}, + print::{with_no_verbose_constants, PrettyPrinter, Print, Printer}, subst::{GenericArg, GenericArgKind}, Ty, TyCtxt, }; @@ -190,7 +190,9 @@ impl Write for AbsolutePathPrinter<'_> { /// Directly returns an `Allocation` containing an absolute path representation of the given type. pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { - let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path; + let path = with_no_verbose_constants!( + AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path + ); let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); tcx.intern_const_alloc(alloc) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b8ee2b994b1e4..c1c2e162f2839 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -63,6 +63,7 @@ thread_local! { static NO_TRIMMED_PATH: Cell = const { Cell::new(false) }; static NO_QUERIES: Cell = const { Cell::new(false) }; static NO_VISIBLE_PATH: Cell = const { Cell::new(false) }; + static NO_VERBOSE_CONSTANTS: Cell = const { Cell::new(false) }; } macro_rules! define_helper { @@ -117,6 +118,9 @@ define_helper!( /// Prevent selection of visible paths. `Display` impl of DefId will prefer /// visible (public) reexports of types as paths. fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); + /// Prevent verbose printing of constants. Verbose printing of constants is + /// never desirable in some contexts like `std::any::type_name`. + fn with_no_verbose_constants(NoVerboseConstantsGuard, NO_VERBOSE_CONSTANTS); ); /// The "region highlights" are used to control region printing during @@ -759,7 +763,7 @@ pub trait PrettyPrinter<'tcx>: } ty::Array(ty, sz) => { p!("[", print(ty), "; "); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("{:?}", sz)); } else if let ty::ConstKind::Unevaluated(..) = sz.kind() { // Do not try to evaluate unevaluated constants. If we are const evaluating an @@ -1181,7 +1185,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("Const({:?}: {:?})", ct.kind(), ct.ty())); return Ok(self); } @@ -1416,7 +1420,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("ValTree({:?}: ", valtree), print(ty), ")"); return Ok(self); } diff --git a/src/test/ui/type/issue-94187-verbose-type-name.rs b/src/test/ui/type/issue-94187-verbose-type-name.rs new file mode 100644 index 0000000000000..902ef5ade2b0e --- /dev/null +++ b/src/test/ui/type/issue-94187-verbose-type-name.rs @@ -0,0 +1,13 @@ +// Check to insure that the output of `std::any::type_name` does not change based on -Zverbose +// when printing constants +// run-pass +// edition: 2018 +// revisions: normal verbose +// [verbose]compile-flags:-Zverbose + +struct Wrapper; + +fn main() { + assert_eq!(std::any::type_name::<[u32; 0]>(), "[u32; 0]"); + assert_eq!(std::any::type_name::>(), "issue_94187_verbose_type_name::Wrapper<0>"); +} From 919673ea03e2c376931161a9301a9d6f089f8984 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 25 Oct 2022 14:45:02 +0400 Subject: [PATCH 21/36] rustc_middle: Rearrange resolver outputs structures slightly --- compiler/rustc_interface/src/passes.rs | 14 ++------- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 41 +++++++++++++------------ compiler/rustc_middle/src/ty/mod.rs | 11 ++++++- compiler/rustc_resolve/src/lib.rs | 27 ++++++++-------- 5 files changed, 48 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a47c3e3253ecd..9d2325e8265e7 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -16,7 +16,6 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::{ErrorGuaranteed, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::StableCrateId; -use rustc_hir::definitions::Definitions; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; @@ -30,7 +29,7 @@ use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn}; +use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -135,10 +134,7 @@ mod boxed_resolver { f((&mut *resolver).as_mut().unwrap()) } - pub fn to_resolver_outputs( - resolver: Rc>, - ) -> (Definitions, Box, ty::ResolverOutputs, ty::ResolverAstLowering) - { + pub fn to_resolver_outputs(resolver: Rc>) -> ty::ResolverOutputs { match Rc::try_unwrap(resolver) { Ok(resolver) => { let mut resolver = resolver.into_inner(); @@ -788,8 +784,7 @@ pub fn create_global_ctxt<'tcx>( // incr. comp. yet. dep_graph.assert_ignored(); - let (definitions, cstore, resolver_outputs, resolver_for_lowering) = - BoxedResolver::to_resolver_outputs(resolver); + let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver); let sess = &compiler.session(); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -816,10 +811,7 @@ pub fn create_global_ctxt<'tcx>( lint_store, arena, hir_arena, - definitions, - cstore, resolver_outputs, - resolver_for_lowering, krate, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2ab3b0d27c88a..67c85ef0d3b50 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -23,7 +23,7 @@ rustc_queries! { desc { "triggering a delay span bug" } } - query resolutions(_: ()) -> &'tcx ty::ResolverOutputs { + query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { eval_always no_hash desc { "getting the resolver outputs" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0816a5cb8f16e..94e3f3b63c813 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -79,7 +79,7 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; -use super::{ImplPolarity, RvalueScopes}; +use super::{ImplPolarity, ResolverOutputs, RvalueScopes}; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. @@ -1067,10 +1067,9 @@ pub struct GlobalCtxt<'tcx> { pub consts: CommonConsts<'tcx>, definitions: RwLock, - cstore: Box, /// Output of the resolver. - pub(crate) untracked_resolutions: ty::ResolverOutputs, + pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt, untracked_resolver_for_lowering: Steal, /// The entire crate as AST. This field serves as the input for the hir_crate query, /// which lowers it from AST to HIR. It must not be read or used by anything else. @@ -1233,10 +1232,7 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, - definitions: Definitions, - cstore: Box, - untracked_resolutions: ty::ResolverOutputs, - untracked_resolver_for_lowering: ty::ResolverAstLowering, + resolver_outputs: ResolverOutputs, krate: Lrc, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, @@ -1245,6 +1241,11 @@ impl<'tcx> TyCtxt<'tcx> { crate_name: &str, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { + let ResolverOutputs { + definitions, + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = resolver_outputs; let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { s.emit_fatal(err); }); @@ -1253,7 +1254,7 @@ impl<'tcx> TyCtxt<'tcx> { &interners, s, &definitions, - &*cstore, + &*untracked_resolutions.cstore, // This is only used to create a stable hashing context. &untracked_resolutions.source_span, ); @@ -1268,7 +1269,6 @@ impl<'tcx> TyCtxt<'tcx> { interners, dep_graph, definitions: RwLock::new(definitions), - cstore, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, @@ -1369,7 +1369,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_key(id) } else { - self.cstore.def_key(id) + self.untracked_resolutions.cstore.def_key(id) } } @@ -1383,7 +1383,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_path(id) } else { - self.cstore.def_path(id) + self.untracked_resolutions.cstore.def_path(id) } } @@ -1393,7 +1393,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(def_id) = def_id.as_local() { self.definitions_untracked().def_path_hash(def_id) } else { - self.cstore.def_path_hash(def_id) + self.untracked_resolutions.cstore.def_path_hash(def_id) } } @@ -1402,7 +1402,7 @@ impl<'tcx> TyCtxt<'tcx> { if crate_num == LOCAL_CRATE { self.sess.local_stable_crate_id() } else { - self.cstore.stable_crate_id(crate_num) + self.untracked_resolutions.cstore.stable_crate_id(crate_num) } } @@ -1413,7 +1413,7 @@ impl<'tcx> TyCtxt<'tcx> { if stable_crate_id == self.sess.local_stable_crate_id() { LOCAL_CRATE } else { - self.cstore.stable_crate_id_to_crate_num(stable_crate_id) + self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id) } } @@ -1432,8 +1432,9 @@ impl<'tcx> TyCtxt<'tcx> { } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. - let cnum = self.cstore.stable_crate_id_to_crate_num(stable_crate_id); - self.cstore.def_path_hash_to_def_id(cnum, hash) + let cstore = &*self.untracked_resolutions.cstore; + let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id); + cstore.def_path_hash_to_def_id(cnum, hash) } } @@ -1445,7 +1446,7 @@ impl<'tcx> TyCtxt<'tcx> { let (crate_name, stable_crate_id) = if def_id.is_local() { (self.crate_name, self.sess.local_stable_crate_id()) } else { - let cstore = &self.cstore; + let cstore = &*self.untracked_resolutions.cstore; (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; @@ -1520,7 +1521,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn { - &*self.cstore + &*self.untracked_resolutions.cstore } /// Note that this is *untracked* and should only be used within the query @@ -1546,7 +1547,7 @@ impl<'tcx> TyCtxt<'tcx> { let hcx = StableHashingContext::new( self.sess, &*definitions, - &*self.cstore, + &*self.untracked_resolutions.cstore, &self.untracked_resolutions.source_span, ); f(hcx) @@ -2364,7 +2365,7 @@ impl<'tcx> TyCtxt<'tcx> { st, self.sess, &self.definitions.read(), - &*self.cstore, + &*self.untracked_resolutions.cstore, // This is only used to create a stable hashing context. &self.untracked_resolutions.source_span, ) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c2aef8178e2c7..9671d3a32f945 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -38,11 +38,13 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; +use rustc_hir::definitions::Definitions; use rustc_hir::Node; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; +use rustc_session::cstore::CrateStoreDyn; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; @@ -142,8 +144,15 @@ mod sty; pub type RegisteredTools = FxHashSet; -#[derive(Debug)] pub struct ResolverOutputs { + pub definitions: Definitions, + pub global_ctxt: ResolverGlobalCtxt, + pub ast_lowering: ResolverAstLowering, +} + +#[derive(Debug)] +pub struct ResolverGlobalCtxt { + pub cstore: Box, pub visibilities: FxHashMap, /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. pub has_pub_restricted: bool, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1c1976af5054c..c2213e8d1e2e3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -42,9 +42,10 @@ use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::span_bug; -use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, ResolverOutputs}; +use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools}; +use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; -use rustc_session::cstore::{CrateStore, CrateStoreDyn, MetadataLoaderDyn}; +use rustc_session::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_session::lint::LintBuffer; use rustc_session::Session; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -1376,9 +1377,7 @@ impl<'a> Resolver<'a> { Default::default() } - pub fn into_outputs( - self, - ) -> (Definitions, Box, ResolverOutputs, ty::ResolverAstLowering) { + pub fn into_outputs(self) -> ResolverOutputs { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions; let cstore = Box::new(self.crate_loader.into_cstore()); @@ -1394,7 +1393,8 @@ impl<'a> Resolver<'a> { let main_def = self.main_def; let confused_type_with_std_module = self.confused_type_with_std_module; let access_levels = self.access_levels; - let resolutions = ResolverOutputs { + let global_ctxt = ResolverGlobalCtxt { + cstore, source_span, expn_that_defined, visibilities, @@ -1416,7 +1416,7 @@ impl<'a> Resolver<'a> { confused_type_with_std_module, registered_tools: self.registered_tools, }; - let resolutions_lowering = ty::ResolverAstLowering { + let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args, partial_res_map: self.partial_res_map, import_res_map: self.import_res_map, @@ -1429,16 +1429,15 @@ impl<'a> Resolver<'a> { trait_map: self.trait_map, builtin_macro_kinds: self.builtin_macro_kinds, }; - (definitions, cstore, resolutions, resolutions_lowering) + ResolverOutputs { definitions, global_ctxt, ast_lowering } } - pub fn clone_outputs( - &self, - ) -> (Definitions, Box, ResolverOutputs, ty::ResolverAstLowering) { + pub fn clone_outputs(&self) -> ResolverOutputs { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions.clone(); let cstore = Box::new(self.cstore().clone()); - let resolutions = ResolverOutputs { + let global_ctxt = ResolverGlobalCtxt { + cstore, source_span: self.source_span.clone(), expn_that_defined: self.expn_that_defined.clone(), visibilities: self.visibilities.clone(), @@ -1460,7 +1459,7 @@ impl<'a> Resolver<'a> { registered_tools: self.registered_tools.clone(), access_levels: self.access_levels.clone(), }; - let resolutions_lowering = ty::ResolverAstLowering { + let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args.clone(), partial_res_map: self.partial_res_map.clone(), import_res_map: self.import_res_map.clone(), @@ -1473,7 +1472,7 @@ impl<'a> Resolver<'a> { trait_map: self.trait_map.clone(), builtin_macro_kinds: self.builtin_macro_kinds.clone(), }; - (definitions, cstore, resolutions, resolutions_lowering) + ResolverOutputs { definitions, global_ctxt, ast_lowering } } fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { From a9447bb9d00f480d0b7f18218b632eda4d9b4f5d Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 17 Oct 2022 20:09:03 +0300 Subject: [PATCH 22/36] Perf improvements for effective visibility calculating --- compiler/rustc_middle/src/middle/privacy.rs | 68 +++++++++++---------- compiler/rustc_privacy/src/lib.rs | 8 ++- compiler/rustc_resolve/src/access_levels.rs | 22 +++---- src/test/ui/privacy/access_levels.rs | 8 +-- src/test/ui/privacy/access_levels.stderr | 4 +- 5 files changed, 57 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 556bd24d00f92..5687e5bdc4342 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -69,21 +69,7 @@ impl EffectiveVisibility { self.get(tag).is_public() } - fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool { - let mut changed = false; - for level in AccessLevel::all_levels() { - if level <= tag { - let current_effective_vis = self.get_mut(level); - if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) { - changed = true; - *current_effective_vis = vis; - } - } - } - changed - } - - fn from_vis(vis: Visibility) -> EffectiveVisibility { + pub fn from_vis(vis: Visibility) -> EffectiveVisibility { EffectiveVisibility { public: vis, exported: vis, @@ -173,33 +159,49 @@ impl> AccessLevels { parent_id: Id, tag: AccessLevel, tree: impl DefIdTree, - ) -> Result { + ) -> bool { let mut changed = false; - let mut current_effective_vis = self - .get_effective_vis(id) - .copied() - .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis())); + let mut current_effective_vis = self.get_effective_vis(id).copied().unwrap_or_else(|| { + if id.into().is_crate_root() { + EffectiveVisibility::from_vis(Visibility::Public) + } else { + EffectiveVisibility::from_vis(default_vis()) + } + }); if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) { + let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.get(tag); + let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; for level in AccessLevel::all_levels() { if tag >= level { let inherited_effective_vis_at_level = *inherited_effective_vis.get(level); - let calculated_effective_vis = - if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { - inherited_effective_vis_at_level - } else { - nominal_vis - }; - changed |= current_effective_vis.update(calculated_effective_vis, level, tree); + let current_effective_vis_at_level = current_effective_vis.get_mut(level); + // effective visibility for id shouldn't be recalculated if + // inherited from parent_id effective visibility isn't changed at next level + if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level + && tag != level) + { + calculated_effective_vis = + if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { + inherited_effective_vis_at_level + } else { + nominal_vis + }; + } + // effective visibility can't be decreased at next update call for the + // same id + if *current_effective_vis_at_level != calculated_effective_vis + && calculated_effective_vis + .is_at_least(*current_effective_vis_at_level, tree) + { + changed = true; + *current_effective_vis_at_level = calculated_effective_vis; + } + inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level; } } - } else { - if !id.into().is_crate_root() { - return Err(()); - } - changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree); } self.map.insert(id, current_effective_vis); - Ok(changed) + changed } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 2636db6dbe1a7..4db58d92bd5e3 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -922,9 +922,9 @@ pub struct TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { fn access_level_diagnostic(&mut self, def_id: LocalDefId) { if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) { + let mut error_msg = String::new(); + let span = self.tcx.def_span(def_id.to_def_id()); if let Some(effective_vis) = self.access_levels.get_effective_vis(def_id) { - let mut error_msg = String::new(); - let span = self.tcx.def_span(def_id.to_def_id()); for level in AccessLevel::all_levels() { let vis_str = match effective_vis.get(level) { ty::Visibility::Restricted(restricted_id) => { @@ -943,8 +943,10 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { } error_msg.push_str(&format!("{:?}: {}", level, vis_str)); } - self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); + } else { + error_msg.push_str("not in the table"); } + self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); } } } diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs index 257784341e3f8..c27b5b0c42007 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -96,10 +96,18 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { parent_id: LocalDefId, tag: AccessLevel, ) { + let module_id = self + .r + .get_nearest_non_block_module(def_id.to_def_id()) + .nearest_parent_mod() + .expect_local(); + if nominal_vis == Visibility::Restricted(module_id) + || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id) + { + return; + } let mut access_levels = std::mem::take(&mut self.r.access_levels); - let module_id = - self.r.get_nearest_non_block_module(def_id.to_def_id()).def_id().expect_local(); - let res = access_levels.update( + self.changed |= access_levels.update( def_id, nominal_vis, || Visibility::Restricted(module_id), @@ -107,14 +115,6 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { tag, &*self.r, ); - if let Ok(changed) = res { - self.changed |= changed; - } else { - self.r.session.delay_span_bug( - self.r.opt_span(def_id.to_def_id()).unwrap(), - "Can't update effective visibility", - ); - } self.r.access_levels = access_levels; } } diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs index 42c9975bedb70..6bca716188685 100644 --- a/src/test/ui/privacy/access_levels.rs +++ b/src/test/ui/privacy/access_levels.rs @@ -17,12 +17,12 @@ mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(c } #[rustc_effective_visibility] - struct PrivStruct; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + struct PrivStruct; //~ ERROR not in the table #[rustc_effective_visibility] pub union PubUnion { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub #[rustc_effective_visibility] - a: u8, //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + a: u8, //~ ERROR not in the table #[rustc_effective_visibility] pub b: u8, //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub } @@ -38,13 +38,13 @@ mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(c } #[rustc_effective_visibility] - macro_rules! none_macro { //~ Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) + macro_rules! none_macro { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate) () => {}; } #[macro_export] #[rustc_effective_visibility] - macro_rules! public_macro { //~ Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + macro_rules! public_macro { //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub () => {}; } diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr index 111e02bc329cc..07c4d436ff000 100644 --- a/src/test/ui/privacy/access_levels.stderr +++ b/src/test/ui/privacy/access_levels.stderr @@ -22,7 +22,7 @@ error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait LL | pub trait PubTrait { | ^^^^^^^^^^^^^^^^^^ -error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) +error: not in the table --> $DIR/access_levels.rs:20:9 | LL | struct PrivStruct; @@ -34,7 +34,7 @@ error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait LL | pub union PubUnion { | ^^^^^^^^^^^^^^^^^^ -error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) +error: not in the table --> $DIR/access_levels.rs:25:13 | LL | a: u8, From 5378c82d808f01bbb0d1c03ea03b2865f10db8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 25 Oct 2022 18:31:11 +0200 Subject: [PATCH 23/36] Use &self instead of &mut self for cast methods --- compiler/rustc_const_eval/src/interpret/cast.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index f980e606b932d..cb33c4d4c465a 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -139,7 +139,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn int_to_int_or_float( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { @@ -154,7 +154,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn float_to_float_or_int( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { @@ -176,7 +176,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts. pub fn ptr_to_ptr( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { @@ -226,7 +226,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn pointer_from_exposed_address_cast( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { From 726bf18d2d97eec43196e8ba48be5f28892b6729 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Oct 2022 21:38:05 +0000 Subject: [PATCH 24/36] Name impl trait in region bound suggestion --- .../nice_region_error/static_impl_trait.rs | 21 +++++++++---------- .../ret-impl-trait-one.stderr | 2 +- .../ui/impl-trait/hidden-lifetimes.stderr | 4 ++-- .../ordinary-bounds-unrelated.stderr | 2 +- .../ordinary-bounds-unsuited.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 14 ++++++------- .../impl-trait/region-escape-via-bound.stderr | 2 +- .../static-return-lifetime-infered.stderr | 8 +++---- .../ty-outlives/impl-trait-captures.stderr | 2 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 2 +- .../missing-lifetimes-in-signature.stderr | 2 +- .../trait-object-nested-in-impl-trait.stderr | 4 ++-- 13 files changed, 33 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 6bb736687d6e5..a74c172fa0c13 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -286,8 +286,8 @@ pub fn suggest_new_region_bound( ) { debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); // FIXME: account for the need of parens in `&(dyn Trait + '_)` - let consider = "consider changing the"; - let declare = "to declare that the"; + let consider = "consider changing"; + let declare = "to declare that"; let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); let explicit_static = arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg)); @@ -305,6 +305,10 @@ pub fn suggest_new_region_bound( return; }; + // Get the identity type for this RPIT + let did = item_id.def_id.to_def_id(); + let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); + if let Some(span) = opaque .bounds .iter() @@ -321,7 +325,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( span, - &format!("{} `impl Trait`'s {}", consider, explicit_static), + &format!("{consider} `{ty}`'s {explicit_static}"), &lifetime_name, Applicability::MaybeIncorrect, ); @@ -351,12 +355,7 @@ pub fn suggest_new_region_bound( } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - &format!( - "{declare} `impl Trait` {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), + &format!("{declare} `{ty}` {captures}, {explicit}",), &plus_lt, Applicability::MaybeIncorrect, ); @@ -367,7 +366,7 @@ pub fn suggest_new_region_bound( err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "{declare} trait object {captures}, {explicit}", + "{declare} the trait object {captures}, {explicit}", declare = declare, captures = captures, explicit = explicit, @@ -384,7 +383,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( lt.span, - &format!("{} trait object's {}", consider, explicit_static), + &format!("{} the trait object's {}", consider, explicit_static), &lifetime_name, Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 3128b4df4e2d1..ae4d0d5853ca6 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -25,7 +25,7 @@ LL | | (a, b) LL | | } | |_^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound | LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { | ++++ diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr index de06ded7acdb6..3cc47e1e89da8 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.stderr +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -6,7 +6,7 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { LL | x | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b { | ++++ @@ -19,7 +19,7 @@ LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl S LL | x | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { | ++++ diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index cb1dc0b7d50ae..ec49a61795a0c 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> im LL | if condition() { a } else { b } | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b | ++++ diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 4388e6601a6cf..c36f9bc6957c6 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, LL | if condition() { a } else { b } | ^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b | ++++ diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 16767abd72241..9c81791fbcba5 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x } | | | hidden type `&i32` captures the anonymous lifetime defined here | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ++++ @@ -19,7 +19,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | | | hidden type `&'a i32` captures the lifetime `'a` as defined here | -help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ++++ @@ -32,7 +32,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | | | let's call the lifetime of this reference `'1` | -help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` +help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ~~ @@ -47,7 +47,7 @@ error: lifetime may not live long enough LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | -help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` +help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ~~ @@ -76,7 +76,7 @@ help: to declare that the trait object captures data from argument `x`, you can | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | ++++ -help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Debug` captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } | ++++ @@ -87,7 +87,7 @@ error: lifetime may not live long enough LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | -help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` +help: consider changing `impl LifetimeTrait<'a> + 'static`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ~~ @@ -104,7 +104,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound +help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b { | ++++ diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr index fdb2fe022b4d2..44a790cb1a43a 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.stderr +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -7,7 +7,7 @@ LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> LL | x | ^ | -help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound +help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `'x` lifetime bound | LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x | ++++ diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index b868152315503..b365bd8845480 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -6,7 +6,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ++++ @@ -19,7 +19,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ++++ @@ -32,7 +32,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Iterator` captures `'a`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ++++ @@ -45,7 +45,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Iterator` captures `'a`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ++++ diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 6a8a1ad1caadd..737cb35841cf5 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -6,7 +6,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { LL | x | ^ | -help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound +help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) { | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 7e7d60d0ff90a..eb3d3e4a67a98 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -6,7 +6,7 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | | | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound | LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 30d2250c0c81d..2c0b2a0d91938 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -6,7 +6,7 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self } | | | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 171f4b333db4e..fa758bf05df5a 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -18,7 +18,7 @@ LL | | *dest = g.get(); LL | | } | |_____^ | -help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound +help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ++++ diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr index f49876bcd3f14..c77ef79e7ed18 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -10,7 +10,7 @@ LL | | remaining: self.0.iter(), LL | | } | |_________^ returning this value requires that `'1` must outlive `'static` | -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound +help: to declare that `impl Iterator>` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter(&self) -> impl Iterator> + '_ { | ++++ @@ -65,7 +65,7 @@ LL | | remaining: self.0.iter(), LL | | } | |_________^ returning this value requires that `'a` must outlive `'static` | -help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound +help: to declare that `impl Iterator>` captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { | ++++ From 43e17454e2d8f650142cb671e13ca70fcbe42fcc Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Mon, 24 Oct 2022 20:59:22 +0200 Subject: [PATCH 25/36] Remove `rustc_driver::set_sigpipe_handler()` Its usage was removed in 5e624bf4ba and 093b075d32, so we do not need to keep it around any longer. According to [preliminary input](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Find.20.60rustc_driver.60.20dependent.20projects.3F/near/304490764), we do not need to worry about any deprecation cycle for this API and can just straight up remove it. Migration instructions for remaining clients -------------------------------------------- Change from ```rust extern crate rustc_driver; fn main() { rustc_driver::set_sigpipe_handler(); // ... ``` to ```rust fn main() { // ... ``` --- compiler/rustc_driver/src/lib.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 7edbb6f757ce1..cfa734c7df39c 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -427,18 +427,6 @@ fn run_compiler( }) } -#[cfg(unix)] -pub fn set_sigpipe_handler() { - unsafe { - // Set the SIGPIPE signal handler, so that an EPIPE - // will cause rustc to terminate, as expected. - assert_ne!(libc::signal(libc::SIGPIPE, libc::SIG_DFL), libc::SIG_ERR); - } -} - -#[cfg(windows)] -pub fn set_sigpipe_handler() {} - // Extract output directory and file from matches. fn make_output(matches: &getopts::Matches) -> (Option, Option) { let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o)); From 543afa889674aa8217af251d070a31d79ec0b040 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Oct 2022 19:49:12 +0200 Subject: [PATCH 26/36] rustup --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 768658b1a1224..d0e98a8b0dba9 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -56f132565eb31eeb9ec7e1800a6ab2ca354e710e +85d089b41e2a0c0f07ab34f6c5a7c451389f25e6 From 5a5a3e4ef4b4c450991459415c0c7a963ba2d278 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Oct 2022 19:59:36 +0200 Subject: [PATCH 27/36] bless clippy --- src/tools/miri/build.rs | 2 +- src/tools/miri/cargo-miri/src/phases.rs | 10 +++++----- src/tools/miri/cargo-miri/src/util.rs | 12 ++++++------ src/tools/miri/src/bin/miri.rs | 6 +++--- src/tools/miri/src/concurrency/vector_clock.rs | 2 +- src/tools/miri/src/diagnostics.rs | 2 +- src/tools/miri/src/helpers.rs | 4 ++-- src/tools/miri/src/machine.rs | 6 +++--- src/tools/miri/src/range_map.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 2 +- src/tools/miri/src/shims/unix/fs.rs | 4 ++-- src/tools/miri/src/shims/unix/linux/foreign_items.rs | 2 +- src/tools/miri/src/stacked_borrows/diagnostics.rs | 12 ++++++------ src/tools/miri/src/stacked_borrows/mod.rs | 2 +- 14 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/tools/miri/build.rs b/src/tools/miri/build.rs index 37c626baab58a..0977c0ba016bd 100644 --- a/src/tools/miri/build.rs +++ b/src/tools/miri/build.rs @@ -4,5 +4,5 @@ fn main() { // Re-export the TARGET environment variable so it can // be accessed by miri. let target = std::env::var("TARGET").unwrap(); - println!("cargo:rustc-env=TARGET={}", target); + println!("cargo:rustc-env=TARGET={target}"); } diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 0c1f039d6cc09..22da80be90211 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -34,7 +34,7 @@ Examples: "#; fn show_help() { - println!("{}", CARGO_MIRI_HELP); + println!("{CARGO_MIRI_HELP}"); } fn show_version() { @@ -52,7 +52,7 @@ fn forward_patched_extern_arg(args: &mut impl Iterator, cmd: &mut let path = args.next().expect("`--extern` should be followed by a filename"); if let Some(lib) = path.strip_suffix(".rlib") { // If this is an rlib, make it an rmeta. - cmd.arg(format!("{}.rmeta", lib)); + cmd.arg(format!("{lib}.rmeta")); } else { // Some other extern file (e.g. a `.so`). Forward unchanged. cmd.arg(path); @@ -336,7 +336,7 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { "[cargo-miri rustc inside rustdoc] captured input:\n{}", std::str::from_utf8(&env.stdin).unwrap() ); - eprintln!("[cargo-miri rustc inside rustdoc] going to run:\n{:?}", cmd); + eprintln!("[cargo-miri rustc inside rustdoc] going to run:\n{cmd:?}"); } exec_with_pipe(cmd, &env.stdin, format!("{}.stdin", out_filename("", "").display())); @@ -374,7 +374,7 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { val.push("metadata"); } } - cmd.arg(format!("{}={}", emit_flag, val.join(","))); + cmd.arg(format!("{emit_flag}={}", val.join(","))); } else if arg == "--extern" { // Patch `--extern` filenames, since Cargo sometimes passes stub `.rlib` files: // https://github.com/rust-lang/miri/issues/1705 @@ -535,7 +535,7 @@ pub fn phase_runner(mut binary_args: impl Iterator, phase: Runner // Run it. debug_cmd("[cargo-miri runner]", verbose, &cmd); match phase { - RunnerPhase::Rustdoc => exec_with_pipe(cmd, &info.stdin, format!("{}.stdin", binary)), + RunnerPhase::Rustdoc => exec_with_pipe(cmd, &info.stdin, format!("{binary}.stdin")), RunnerPhase::Cargo => exec(cmd), } } diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs index aabe5547e5c9a..60f39cb36abaa 100644 --- a/src/tools/miri/cargo-miri/src/util.rs +++ b/src/tools/miri/cargo-miri/src/util.rs @@ -83,7 +83,7 @@ pub fn escape_for_toml(s: &str) -> String { // We want to surround this string in quotes `"`. So we first escape all quotes, // and also all backslashes (that are used to escape quotes). let s = s.replace('\\', r#"\\"#).replace('"', r#"\""#); - format!("\"{}\"", s) + format!("\"{s}\"") } /// Returns the path to the `miri` binary @@ -175,7 +175,7 @@ pub fn ask_to_run(mut cmd: Command, ask: bool, text: &str) { let is_ci = env::var_os("CI").is_some() || env::var_os("TF_BUILD").is_some(); if ask && !is_ci { let mut buf = String::new(); - print!("I will run `{:?}` to {}. Proceed? [Y/n] ", cmd, text); + print!("I will run `{cmd:?}` to {text}. Proceed? [Y/n] "); io::stdout().flush().unwrap(); io::stdin().read_line(&mut buf).unwrap(); match buf.trim().to_lowercase().as_ref() { @@ -185,10 +185,10 @@ pub fn ask_to_run(mut cmd: Command, ask: bool, text: &str) { a => show_error!("invalid answer `{}`", a), }; } else { - eprintln!("Running `{:?}` to {}.", cmd, text); + eprintln!("Running `{cmd:?}` to {text}."); } - if cmd.status().unwrap_or_else(|_| panic!("failed to execute {:?}", cmd)).success().not() { + if cmd.status().unwrap_or_else(|_| panic!("failed to execute {cmd:?}")).success().not() { show_error!("failed to {}", text); } } @@ -276,12 +276,12 @@ pub fn debug_cmd(prefix: &str, verbose: usize, cmd: &Command) { // Print only what has been changed for this `cmd`. for (var, val) in cmd.get_envs() { if let Some(val) = val { - writeln!(out, "{}={:?} \\", var.to_string_lossy(), val).unwrap(); + writeln!(out, "{}={val:?} \\", var.to_string_lossy()).unwrap(); } else { writeln!(out, "--unset={}", var.to_string_lossy()).unwrap(); } } } write!(out, "{cmd:?}").unwrap(); - eprintln!("{}", out); + eprintln!("{out}"); } diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 2e114c71d662a..bd01ea655dd70 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -192,7 +192,7 @@ fn init_late_loggers(tcx: TyCtxt<'_>) { if log::Level::from_str(&var).is_ok() { env::set_var( "RUSTC_LOG", - &format!( + format!( "rustc_middle::mir::interpret={0},rustc_const_eval::interpret={0}", var ), @@ -243,7 +243,7 @@ fn host_sysroot() -> Option { ) } } - format!("{}/toolchains/{}", home, toolchain) + format!("{home}/toolchains/{toolchain}") } _ => option_env!("RUST_SYSROOT") .unwrap_or_else(|| { @@ -330,7 +330,7 @@ fn main() { } else if crate_kind == "host" { false } else { - panic!("invalid `MIRI_BE_RUSTC` value: {:?}", crate_kind) + panic!("invalid `MIRI_BE_RUSTC` value: {crate_kind:?}") }; // We cannot use `rustc_driver::main` as we need to adjust the CLI arguments. diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index 32449f8eb1884..e7e5b35ac2cd2 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -399,7 +399,7 @@ mod tests { //Test partial_cmp let compare = l.partial_cmp(&r); - assert_eq!(compare, o, "Invalid comparison\n l: {:?}\n r: {:?}", l, r); + assert_eq!(compare, o, "Invalid comparison\n l: {l:?}\n r: {r:?}"); let alt_compare = r.partial_cmp(&l); assert_eq!( alt_compare, diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index ecfe0cd3f8a65..ec81ffd3cd5c9 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -263,7 +263,7 @@ pub fn report_error<'tcx, 'mir>( msg.insert(0, e.to_string()); report_msg( DiagLevel::Error, - &if let Some(title) = title { format!("{}: {}", title, msg[0]) } else { msg[0].clone() }, + &if let Some(title) = title { format!("{title}: {}", msg[0]) } else { msg[0].clone() }, msg, vec![], helps, diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 15833fe42adc9..4bc38d2dc3647 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -107,7 +107,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Gets an instance for a path. fn resolve_path(&self, path: &[&str]) -> ty::Instance<'tcx> { self.try_resolve_path(path) - .unwrap_or_else(|| panic!("failed to find required Rust item: {:?}", path)) + .unwrap_or_else(|| panic!("failed to find required Rust item: {path:?}")) } /// Evaluates the scalar at the specified path. Returns Some(val) @@ -505,7 +505,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { RejectOpWith::WarningWithoutBacktrace => { this.tcx .sess - .warn(&format!("{} was made to return an error due to isolation", op_name)); + .warn(format!("{op_name} was made to return an error due to isolation")); Ok(()) } RejectOpWith::Warning => { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index fc9a1170d2942..e014e2db1e1f2 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -191,12 +191,12 @@ impl interpret::Provenance for Provenance { Provenance::Concrete { alloc_id, sb } => { // Forward `alternate` flag to `alloc_id` printing. if f.alternate() { - write!(f, "[{:#?}]", alloc_id)?; + write!(f, "[{alloc_id:#?}]")?; } else { - write!(f, "[{:?}]", alloc_id)?; + write!(f, "[{alloc_id:?}]")?; } // Print Stacked Borrows tag. - write!(f, "{:?}", sb)?; + write!(f, "{sb:?}")?; } Provenance::Wildcard => { write!(f, "[wildcard]")?; diff --git a/src/tools/miri/src/range_map.rs b/src/tools/miri/src/range_map.rs index 4742a365ec38b..c8ff06a36652d 100644 --- a/src/tools/miri/src/range_map.rs +++ b/src/tools/miri/src/range_map.rs @@ -40,7 +40,7 @@ impl RangeMap { let mut left = 0usize; // inclusive let mut right = self.v.len(); // exclusive loop { - debug_assert!(left < right, "find_offset: offset {} is out-of-bounds", offset); + debug_assert!(left < right, "find_offset: offset {offset} is out-of-bounds"); let candidate = left.checked_add(right).unwrap() / 2; let elem = &self.v[candidate]; if offset < elem.range.start { diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index a49e6ba4ce386..9d0e47cd06f34 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -321,7 +321,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(Some(body)); } - this.handle_unsupported(format!("can't call foreign function: {}", link_name))?; + this.handle_unsupported(format!("can't call foreign function: {link_name}"))?; return Ok(None); } } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 0610f65db113f..b152082b4deb8 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -621,7 +621,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(-1); } - let fd = options.open(&path).map(|file| { + let fd = options.open(path).map(|file| { let fh = &mut this.machine.file_handler; fh.insert_fd(Box::new(FileHandle { file, writable })) }); @@ -1862,7 +1862,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let possibly_unique = std::env::temp_dir().join::(p.into()); - let file = fopts.open(&possibly_unique); + let file = fopts.open(possibly_unique); match file { Ok(f) => { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 5d000f9d121d4..dd382fff029cf 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -126,7 +126,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { futex(this, &args[1..], dest)?; } id => { - this.handle_unsupported(format!("can't execute syscall with ID {}", id))?; + this.handle_unsupported(format!("can't execute syscall with ID {id}"))?; return Ok(EmulateByNameResult::AlreadyJumped); } } diff --git a/src/tools/miri/src/stacked_borrows/diagnostics.rs b/src/tools/miri/src/stacked_borrows/diagnostics.rs index 2cc7a88704ea3..d3843b030347f 100644 --- a/src/tools/miri/src/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/stacked_borrows/diagnostics.rs @@ -86,12 +86,12 @@ impl Invalidation { impl fmt::Display for InvalidationCause { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - InvalidationCause::Access(kind) => write!(f, "{}", kind), + InvalidationCause::Access(kind) => write!(f, "{kind}"), InvalidationCause::Retag(perm, kind) => if *kind == RetagCause::FnEntry { - write!(f, "{:?} FnEntry retag", perm) + write!(f, "{perm:?} FnEntry retag") } else { - write!(f, "{:?} retag", perm) + write!(f, "{perm:?} retag") }, } } @@ -339,7 +339,7 @@ impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir // this allocation. if self.history.base.0.tag() == tag { Some(( - format!("{:?} was created here, as the base tag for {:?}", tag, self.history.id), + format!("{tag:?} was created here, as the base tag for {:?}", self.history.id), self.history.base.1.data() )) } else { @@ -381,7 +381,7 @@ impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir self.offset.bytes(), ); err_sb_ub( - format!("{}{}", action, error_cause(stack, op.orig_tag)), + format!("{action}{}", error_cause(stack, op.orig_tag)), Some(operation_summary(&op.cause.summary(), self.history.id, op.range)), op.orig_tag.and_then(|orig_tag| self.get_logs_relevant_to(orig_tag, None)), ) @@ -401,7 +401,7 @@ impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir offset = self.offset.bytes(), ); err_sb_ub( - format!("{}{}", action, error_cause(stack, op.tag)), + format!("{action}{}", error_cause(stack, op.tag)), Some(operation_summary("an access", self.history.id, op.range)), op.tag.and_then(|tag| self.get_logs_relevant_to(tag, None)), ) diff --git a/src/tools/miri/src/stacked_borrows/mod.rs b/src/tools/miri/src/stacked_borrows/mod.rs index 959e351d1a145..a2f003e6cc800 100644 --- a/src/tools/miri/src/stacked_borrows/mod.rs +++ b/src/tools/miri/src/stacked_borrows/mod.rs @@ -1153,7 +1153,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let alloc_extra = this.get_alloc_extra(alloc_id)?; let stacks = alloc_extra.stacked_borrows.as_ref().unwrap().borrow(); for (range, stack) in stacks.stacks.iter_all() { - print!("{:?}: [", range); + print!("{range:?}: ["); for i in 0..stack.len() { let item = stack.get(i).unwrap(); print!(" {:?}{:?}", item.perm(), item.tag()); From 5064648624c94008d54a2f1d754168d1a0d1df26 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 25 Oct 2022 12:16:25 -0700 Subject: [PATCH 28/36] Pinning tests for some macro_rules things discussed in the lang meeting --- .../ui/macros/macro_rules-unmatchable-literals.rs | 14 ++++++++++++++ .../macros/macro_rules-unmatchable-literals.stderr | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/ui/macros/macro_rules-unmatchable-literals.rs create mode 100644 src/test/ui/macros/macro_rules-unmatchable-literals.stderr diff --git a/src/test/ui/macros/macro_rules-unmatchable-literals.rs b/src/test/ui/macros/macro_rules-unmatchable-literals.rs new file mode 100644 index 0000000000000..bde0fe1a01574 --- /dev/null +++ b/src/test/ui/macros/macro_rules-unmatchable-literals.rs @@ -0,0 +1,14 @@ +// Pinning tests for things that don't work to make sure we notice if that changes + +#![crate_type = "lib"] + +macro_rules! octal_with_bad_digit { + ( 0o1238 ) => {}; //~ ERROR invalid digit +} + +macro_rules! binary_with_bad_digit { + ( 0b012 ) => {}; //~ ERROR invalid digit +} + +// This can't happen for Hex and Decimal as things like `123A` and `0xFFG` +// get treated as unknown *suffixes*, rather than digits. diff --git a/src/test/ui/macros/macro_rules-unmatchable-literals.stderr b/src/test/ui/macros/macro_rules-unmatchable-literals.stderr new file mode 100644 index 0000000000000..956a669791d0e --- /dev/null +++ b/src/test/ui/macros/macro_rules-unmatchable-literals.stderr @@ -0,0 +1,14 @@ +error: invalid digit for a base 8 literal + --> $DIR/macro_rules-unmatchable-literals.rs:6:12 + | +LL | ( 0o1238 ) => {}; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/macro_rules-unmatchable-literals.rs:10:11 + | +LL | ( 0b012 ) => {}; + | ^ + +error: aborting due to 2 previous errors + From 52fda858ddb5f4a6ce2826f7305ac83973a0ad43 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Oct 2022 22:09:35 +0200 Subject: [PATCH 29/36] interpret: a bit of cast cleanup --- .../rustc_const_eval/src/interpret/cast.rs | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index f980e606b932d..9742dca01debc 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -138,21 +138,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + /// Handles 'IntToInt' and 'IntToFloat' casts. pub fn int_to_int_or_float( &mut self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { - if (src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool()) - && (cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char()) - { - let scalar = src.to_scalar(); - Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) - } else { - bug!("Unexpected cast from type {:?}", src.layout.ty) - } + assert!(src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool()); + assert!(cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char()); + + Ok(self.cast_from_int_like(src.to_scalar(), src.layout, cast_ty)?.into()) } + /// Handles 'FloatToFloat' and 'FloatToInt' casts. pub fn float_to_float_or_int( &mut self, src: &ImmTy<'tcx, M::Provenance>, @@ -180,31 +178,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate> { + assert!(src.layout.ty.is_any_ptr()); + assert!(cast_ty.is_unsafe_ptr()); // Handle casting any ptr to raw ptr (might be a fat ptr). - if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() { - let dest_layout = self.layout_of(cast_ty)?; - if dest_layout.size == src.layout.size { - // Thin or fat pointer that just hast the ptr kind of target type changed. - return Ok(**src); - } else { - // Casting the metadata away from a fat ptr. - assert_eq!(src.layout.size, 2 * self.pointer_size()); - assert_eq!(dest_layout.size, self.pointer_size()); - assert!(src.layout.ty.is_unsafe_ptr()); - return match **src { - Immediate::ScalarPair(data, _) => Ok(data.into()), - Immediate::Scalar(..) => span_bug!( - self.cur_span(), - "{:?} input to a fat-to-thin cast ({:?} -> {:?})", - *src, - src.layout.ty, - cast_ty - ), - Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), - }; - } + let dest_layout = self.layout_of(cast_ty)?; + if dest_layout.size == src.layout.size { + // Thin or fat pointer that just hast the ptr kind of target type changed. + return Ok(**src); } else { - bug!("Can't cast 'Ptr' or 'FnPtr' into {:?}", cast_ty); + // Casting the metadata away from a fat ptr. + assert_eq!(src.layout.size, 2 * self.pointer_size()); + assert_eq!(dest_layout.size, self.pointer_size()); + assert!(src.layout.ty.is_unsafe_ptr()); + return match **src { + Immediate::ScalarPair(data, _) => Ok(data.into()), + Immediate::Scalar(..) => span_bug!( + self.cur_span(), + "{:?} input to a fat-to-thin cast ({:?} -> {:?})", + *src, + src.layout.ty, + cast_ty + ), + Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), + }; } } @@ -243,6 +239,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Scalar::from_maybe_pointer(ptr, self).into()) } + /// Low-level cast helper function. This works directly on scalars and can take 'int-like' input + /// type (basically everything with a scalar layout) to int/float/char types. pub fn cast_from_int_like( &self, scalar: Scalar, // input value (there is no ScalarTy so we separate data+layout) @@ -282,6 +280,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) } + /// Low-level cast helper function. Converts an apfloat `f` into int or float types. fn cast_from_float(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar where F: Float + Into> + FloatConvert + FloatConvert, From d86bbd5094badaf55ade2073fbb41835ffc641b6 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 23 Oct 2022 12:32:45 -0400 Subject: [PATCH 30/36] Rename, improve docs, fail better --- src/tools/miri/README.md | 15 ++++++--- src/tools/miri/src/shims/foreign_items.rs | 8 +++-- src/tools/miri/src/stacked_borrows/mod.rs | 3 ++ .../pass/stacked-borrows/stack-printing.rs | 31 ++++++++++++++----- .../stacked-borrows/stack-printing.stdout | 1 + 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 81c4f5ffef4ec..bd175b46b7a68 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -538,15 +538,20 @@ extern "Rust" { fn miri_start_panic(payload: *mut u8) -> !; /// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer - /// points to. This is only useful as an input to `miri_print_stacks`, and it is a separate call because + /// points to. This is only useful as an input to `miri_print_borrow_stacks`, and it is a separate call because /// getting a pointer to an allocation at runtime can change the borrow stacks in the allocation. + /// This function should be considered unstable. It exists only to support `miri_print_borrow_stacks` and so + /// inherits all of its instability. fn miri_get_alloc_id(ptr: *const ()) -> u64; /// Miri-provided extern function to print (from the interpreter, not the program) the contents of all - /// borrow stacks in an allocation. The format of what this emits is unstable and may change at any time. - /// In particular, users should be aware that Miri will periodically attempt to garbage collect the - /// contents of all stacks. Callers of this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC. - fn miri_print_stacks(alloc_id: u64); + /// borrow stacks in an allocation. The leftmost tag is the bottom of the stack. + /// The format of what this emits is unstable and may change at any time. In particular, users should be + /// aware that Miri will periodically attempt to garbage collect the contents of all stacks. Callers of + /// this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC. + /// This function is extremely unstable. At any time the format of its output may change, its signature may + /// change, or it may be removed entirely. + fn miri_print_borrow_stacks(alloc_id: u64); /// Miri-provided extern function to print (from the interpreter, not the /// program) the contents of a section of program memory, as bytes. Bytes diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 9d0e47cd06f34..1b3205aabc99d 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -420,10 +420,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "miri_get_alloc_id" => { let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; - let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr)?; + let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr).map_err(|_e| { + err_machine_stop!(TerminationInfo::Abort( + format!("pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}") + )) + })?; this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?; } - "miri_print_stacks" => { + "miri_print_borrow_stacks" => { let [id] = this.check_shim(abi, Abi::Rust, link_name, args)?; let id = this.read_scalar(id)?.to_u64()?; if let Some(id) = std::num::NonZeroU64::new(id) { diff --git a/src/tools/miri/src/stacked_borrows/mod.rs b/src/tools/miri/src/stacked_borrows/mod.rs index a2f003e6cc800..cc27b71eb5604 100644 --- a/src/tools/miri/src/stacked_borrows/mod.rs +++ b/src/tools/miri/src/stacked_borrows/mod.rs @@ -1154,6 +1154,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let stacks = alloc_extra.stacked_borrows.as_ref().unwrap().borrow(); for (range, stack) in stacks.stacks.iter_all() { print!("{range:?}: ["); + if let Some(bottom) = stack.unknown_bottom() { + print!(" unknown-bottom(..{bottom:?})"); + } for i in 0..stack.len() { let item = stack.get(i).unwrap(); print!(" {:?}{:?}", item.perm(), item.tag()); diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs index 8d96a2e1ca991..3ca937ae13db8 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zmiri-permissive-provenance +#![feature(strict_provenance)] use std::{ alloc::{self, Layout}, mem::ManuallyDrop, @@ -5,25 +7,40 @@ use std::{ extern "Rust" { fn miri_get_alloc_id(ptr: *const u8) -> u64; - fn miri_print_stacks(alloc_id: u64); + fn miri_print_borrow_stacks(alloc_id: u64); +} + +fn get_alloc_id(ptr: *const u8) -> u64 { + unsafe { miri_get_alloc_id(ptr) } +} + +fn print_borrow_stacks(alloc_id: u64) { + unsafe { miri_print_borrow_stacks(alloc_id) } } fn main() { let ptr = unsafe { alloc::alloc(Layout::new::()) }; - let alloc_id = unsafe { miri_get_alloc_id(ptr) }; - unsafe { miri_print_stacks(alloc_id) }; + let alloc_id = get_alloc_id(ptr); + print_borrow_stacks(alloc_id); assert!(!ptr.is_null()); - unsafe { miri_print_stacks(alloc_id) }; + print_borrow_stacks(alloc_id); unsafe { *ptr = 42 }; - unsafe { miri_print_stacks(alloc_id) }; + print_borrow_stacks(alloc_id); let _b = unsafe { ManuallyDrop::new(Box::from_raw(ptr)) }; - unsafe { miri_print_stacks(alloc_id) }; + print_borrow_stacks(alloc_id); let _ptr = unsafe { &*ptr }; - unsafe { miri_print_stacks(alloc_id) }; + print_borrow_stacks(alloc_id); + + // Create an unknown bottom, and print it + let ptr = ptr as usize as *mut u8; + unsafe { + *ptr = 5; + } + print_borrow_stacks(alloc_id); unsafe { alloc::dealloc(ptr, Layout::new::()) }; } diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout index 660ee71e6f58b..838733078209d 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.stdout @@ -3,3 +3,4 @@ 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite Unique Unique Unique Unique Unique ] 0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] +0..1: [ unknown-bottom(..) ] From 952585c1eb43ae456c1413d6c609d5a9d31fb5a5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 25 Oct 2022 12:34:05 -0700 Subject: [PATCH 31/36] Update books --- src/doc/book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index f1e5ad844d0c6..aa5ee485bd6bd 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit f1e5ad844d0c61738006cdef26227beeb136948e +Subproject commit aa5ee485bd6bd80d205da7c82fcdd776f92fdd51 diff --git a/src/doc/reference b/src/doc/reference index f6ed74f582bdd..4ea7c5def38ac 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit f6ed74f582bddcec73f753eafaab3749c4f7df61 +Subproject commit 4ea7c5def38ac81df33a9e48e5637a82a5ac404d diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 5e7b296d6c345..03491f33375c5 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 5e7b296d6c345addbd748f242aae28c42555c015 +Subproject commit 03491f33375c5a2a1661c7fa4be671fe95ce1249 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 7518c3445dc02..51a37ad19a157 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 7518c3445dc02df0d196f5f84e568d633c5141fb +Subproject commit 51a37ad19a15709d0601afbac6581f5aea6a45da From 60b5f6dc9190c1fa10c2ca22d472d32f9689253e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 25 Oct 2022 16:52:50 -0700 Subject: [PATCH 32/36] rustdoc: add visible focus outline to rustdoc-toggle The change in opacity is inconsistent with most of rustdoc, which uses default browser styles for the focus outline. Unfortunately, just using the default focus outline here won't work, because it gets applied to the summary itself instead of the pseudo-element "real button." --- src/librustdoc/html/static/css/rustdoc.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 173553ed47749..84a1fa2e28ece 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1585,6 +1585,14 @@ details.rustdoc-toggle > summary:hover::before { opacity: 1; } +details.rustdoc-toggle > summary:focus-visible::before { + /* The SVG is black, and gets turned white using a filter. + Do the same with the outline. + */ + outline: 1px dotted #000; + outline-offset: 1px; +} + details.rustdoc-toggle.top-doc > summary, details.rustdoc-toggle.top-doc > summary::before, details.rustdoc-toggle.non-exhaustive > summary, From 71e6815885f54631a2035e0c4d180a6de25ebccf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Oct 2022 09:58:21 +0200 Subject: [PATCH 33/36] tweak docs --- src/tools/miri/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index bd175b46b7a68..5803a88c0e757 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -538,7 +538,9 @@ extern "Rust" { fn miri_start_panic(payload: *mut u8) -> !; /// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer - /// points to. This is only useful as an input to `miri_print_borrow_stacks`, and it is a separate call because + /// points to. If this pointer is invalid (not pointing to an allocation), interpretation will abort. + /// + /// This is only useful as an input to `miri_print_borrow_stacks`, and it is a separate call because /// getting a pointer to an allocation at runtime can change the borrow stacks in the allocation. /// This function should be considered unstable. It exists only to support `miri_print_borrow_stacks` and so /// inherits all of its instability. @@ -549,6 +551,7 @@ extern "Rust" { /// The format of what this emits is unstable and may change at any time. In particular, users should be /// aware that Miri will periodically attempt to garbage collect the contents of all stacks. Callers of /// this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC. + /// /// This function is extremely unstable. At any time the format of its output may change, its signature may /// change, or it may be removed entirely. fn miri_print_borrow_stacks(alloc_id: u64); From 70087eaa35c66e99dd428c55edef9a43a4873fac Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Oct 2022 10:42:43 +0200 Subject: [PATCH 34/36] add pthread_getname_np --- src/tools/miri/src/concurrency/thread.rs | 1 + src/tools/miri/src/helpers.rs | 59 +++++++++++++++++++ src/tools/miri/src/shims/os_str.rs | 33 +---------- .../src/shims/unix/linux/foreign_items.rs | 10 ++++ .../src/shims/unix/macos/foreign_items.rs | 10 ++++ src/tools/miri/src/shims/unix/thread.rs | 24 ++++++++ .../miri/tests/pass-dep/shims/pthreads.rs | 25 ++++++++ 7 files changed, 131 insertions(+), 31 deletions(-) diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 3432f10f7a925..ac5dcbf0f4f2f 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -870,6 +870,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.machine.threads.active_thread_stack_mut() } + /// Set the name of the current thread. The buffer must not include the null terminator. #[inline] fn set_thread_name(&mut self, thread: ThreadId, new_thread_name: Vec) { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 4bc38d2dc3647..f98727186c48d 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1,6 +1,7 @@ pub mod convert; use std::cmp; +use std::iter; use std::mem; use std::num::NonZeroUsize; use std::time::Duration; @@ -735,6 +736,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }) } + /// Read a sequence of bytes until the first null terminator. fn read_c_str<'a>(&'a self, ptr: Pointer>) -> InterpResult<'tcx, &'a [u8]> where 'tcx: 'a, @@ -761,6 +763,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.read_bytes_ptr_strip_provenance(ptr, len) } + /// Helper function to write a sequence of bytes with an added null-terminator, which is what + /// the Unix APIs usually handle. This function returns `Ok((false, length))` without trying + /// to write if `size` is not large enough to fit the contents of `c_str` plus a null + /// terminator. It returns `Ok((true, length))` if the writing process was successful. The + /// string length returned does include the null terminator. + fn write_c_str( + &mut self, + c_str: &[u8], + ptr: Pointer>, + size: u64, + ) -> InterpResult<'tcx, (bool, u64)> { + // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null + // terminator to memory using the `ptr` pointer would cause an out-of-bounds access. + let string_length = u64::try_from(c_str.len()).unwrap(); + let string_length = string_length.checked_add(1).unwrap(); + if size < string_length { + return Ok((false, string_length)); + } + self.eval_context_mut() + .write_bytes_ptr(ptr, c_str.iter().copied().chain(iter::once(0u8)))?; + Ok((true, string_length)) + } + + /// Read a sequence of u16 until the first null terminator. fn read_wide_str(&self, mut ptr: Pointer>) -> InterpResult<'tcx, Vec> { let this = self.eval_context_ref(); let size2 = Size::from_bytes(2); @@ -783,6 +809,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(wchars) } + /// Helper function to write a sequence of u16 with an added 0x0000-terminator, which is what + /// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying + /// to write if `size` is not large enough to fit the contents of `os_string` plus a null + /// terminator. It returns `Ok((true, length))` if the writing process was successful. The + /// string length returned does include the null terminator. Length is measured in units of + /// `u16.` + fn write_wide_str( + &mut self, + wide_str: &[u16], + ptr: Pointer>, + size: u64, + ) -> InterpResult<'tcx, (bool, u64)> { + // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required + // 0x0000 terminator to memory would cause an out-of-bounds access. + let string_length = u64::try_from(wide_str.len()).unwrap(); + let string_length = string_length.checked_add(1).unwrap(); + if size < string_length { + return Ok((false, string_length)); + } + + // Store the UTF-16 string. + let size2 = Size::from_bytes(2); + let this = self.eval_context_mut(); + let mut alloc = this + .get_ptr_alloc_mut(ptr, size2 * string_length, Align::from_bytes(2).unwrap())? + .unwrap(); // not a ZST, so we will get a result + for (offset, wchar) in wide_str.iter().copied().chain(iter::once(0x0000)).enumerate() { + let offset = u64::try_from(offset).unwrap(); + alloc.write_scalar(alloc_range(size2 * offset, size2), Scalar::from_u16(wchar))?; + } + Ok((true, string_length)) + } + /// Check that the ABI is what we expect. fn check_abi<'a>(&self, abi: Abi, exp_abi: Abi) -> InterpResult<'a, ()> { if self.eval_context_ref().machine.enforce_abi && abi != exp_abi { diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs index 407dab970ad7d..99b3605c60175 100644 --- a/src/tools/miri/src/shims/os_str.rs +++ b/src/tools/miri/src/shims/os_str.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; use std::ffi::{OsStr, OsString}; -use std::iter; use std::path::{Path, PathBuf}; #[cfg(unix)] @@ -9,7 +8,6 @@ use std::os::unix::ffi::{OsStrExt, OsStringExt}; use std::os::windows::ffi::{OsStrExt, OsStringExt}; use rustc_middle::ty::layout::LayoutOf; -use rustc_target::abi::{Align, Size}; use crate::*; @@ -100,16 +98,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { size: u64, ) -> InterpResult<'tcx, (bool, u64)> { let bytes = os_str_to_bytes(os_str)?; - // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null - // terminator to memory using the `ptr` pointer would cause an out-of-bounds access. - let string_length = u64::try_from(bytes.len()).unwrap(); - let string_length = string_length.checked_add(1).unwrap(); - if size < string_length { - return Ok((false, string_length)); - } - self.eval_context_mut() - .write_bytes_ptr(ptr, bytes.iter().copied().chain(iter::once(0u8)))?; - Ok((true, string_length)) + self.eval_context_mut().write_c_str(bytes, ptr, size) } /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what @@ -140,25 +129,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } let u16_vec = os_str_to_u16vec(os_str)?; - // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required - // 0x0000 terminator to memory would cause an out-of-bounds access. - let string_length = u64::try_from(u16_vec.len()).unwrap(); - let string_length = string_length.checked_add(1).unwrap(); - if size < string_length { - return Ok((false, string_length)); - } - - // Store the UTF-16 string. - let size2 = Size::from_bytes(2); - let this = self.eval_context_mut(); - let mut alloc = this - .get_ptr_alloc_mut(ptr, size2 * string_length, Align::from_bytes(2).unwrap())? - .unwrap(); // not a ZST, so we will get a result - for (offset, wchar) in u16_vec.into_iter().chain(iter::once(0x0000)).enumerate() { - let offset = u64::try_from(offset).unwrap(); - alloc.write_scalar(alloc_range(size2 * offset, size2), Scalar::from_u16(wchar))?; - } - Ok((true, string_length)) + self.eval_context_mut().write_wide_str(&u16_vec, ptr, size) } /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes. diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index dd382fff029cf..c004e2292a93a 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -72,6 +72,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.pthread_setname_np(this.read_scalar(thread)?, this.read_scalar(name)?)?; this.write_scalar(res, dest)?; } + "pthread_getname_np" => { + let [thread, name, len] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let res = this.pthread_getname_np( + this.read_scalar(thread)?, + this.read_scalar(name)?, + this.read_scalar(len)?, + )?; + this.write_scalar(res, dest)?; + } // Dynamically invoked syscalls "syscall" => { diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 38d791fba98a4..0e931023e6c1c 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -178,6 +178,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let thread = this.pthread_self()?; this.pthread_setname_np(thread, this.read_scalar(name)?)?; } + "pthread_getname_np" => { + let [thread, name, len] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let res = this.pthread_getname_np( + this.read_scalar(thread)?, + this.read_scalar(name)?, + this.read_scalar(len)?, + )?; + this.write_scalar(res, dest)?; + } // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 59474d8d10ad7..4320ecd389e5b 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -78,11 +78,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let name = name.to_pointer(this)?; let name = this.read_c_str(name)?.to_owned(); + + if name.len() > 15 { + // Thread names are limited to 16 characaters, including the null terminator. + return this.eval_libc("ERANGE"); + } + this.set_thread_name(thread, name); Ok(Scalar::from_u32(0)) } + fn pthread_getname_np( + &mut self, + thread: Scalar, + name_out: Scalar, + len: Scalar, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let thread = ThreadId::try_from(thread.to_machine_usize(this)?).unwrap(); + let name_out = name_out.to_pointer(this)?; + let len = len.to_machine_usize(this)?; + + let name = this.get_thread_name(thread).to_owned(); + let (success, _written) = this.write_c_str(&name, name_out, len)?; + + if success { Ok(Scalar::from_u32(0)) } else { this.eval_libc("ERANGE") } + } + fn sched_yield(&mut self) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/tests/pass-dep/shims/pthreads.rs b/src/tools/miri/tests/pass-dep/shims/pthreads.rs index d062eda7e90c8..bbddca74754c5 100644 --- a/src/tools/miri/tests/pass-dep/shims/pthreads.rs +++ b/src/tools/miri/tests/pass-dep/shims/pthreads.rs @@ -1,10 +1,14 @@ //@ignore-target-windows: No libc on Windows +#![feature(cstr_from_bytes_until_nul)] +use std::ffi::CStr; +use std::thread; fn main() { test_mutex_libc_init_recursive(); test_mutex_libc_init_normal(); test_mutex_libc_init_errorcheck(); test_rwlock_libc_static_initializer(); + test_named_thread_truncation(); #[cfg(any(target_os = "linux"))] test_mutex_libc_static_initializer_recursive(); @@ -125,3 +129,24 @@ fn test_rwlock_libc_static_initializer() { assert_eq!(libc::pthread_rwlock_destroy(rw.get()), 0); } } + +fn test_named_thread_truncation() { + let long_name = std::iter::once("test_named_thread_truncation") + .chain(std::iter::repeat(" yada").take(100)) + .collect::(); + + let result = thread::Builder::new().name(long_name.clone()).spawn(move || { + // Rust remembers the full thread name itself. + assert_eq!(thread::current().name(), Some(long_name.as_str())); + + // But the system is limited -- make sure we successfully set a truncation. + let mut buf = vec![0u8; long_name.len() + 1]; + unsafe { + libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len()); + } + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert!(cstr.to_bytes().len() >= 15); // POSIX seems to promise at least 15 chars + assert!(long_name.as_bytes().starts_with(cstr.to_bytes())); + }); + result.unwrap().join().unwrap(); +} From dac24128908bd542d5ab7660d1995859e8c2d858 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Oct 2022 10:50:11 +0200 Subject: [PATCH 35/36] account for different max thread name lengths on different platforms --- src/tools/miri/src/shims/unix/freebsd/foreign_items.rs | 8 ++++++-- src/tools/miri/src/shims/unix/linux/foreign_items.rs | 8 ++++++-- src/tools/miri/src/shims/unix/macos/foreign_items.rs | 7 ++++++- src/tools/miri/src/shims/unix/thread.rs | 7 +++++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 70798f9817453..d755e5f10bae8 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -26,8 +26,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "pthread_set_name_np" => { let [thread, name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let res = - this.pthread_setname_np(this.read_scalar(thread)?, this.read_scalar(name)?)?; + let max_len = usize::MAX; // freebsd does not seem to have a limit. + let res = this.pthread_setname_np( + this.read_scalar(thread)?, + this.read_scalar(name)?, + max_len, + )?; this.write_scalar(res, dest)?; } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index c004e2292a93a..2b53152688bb7 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -68,8 +68,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "pthread_setname_np" => { let [thread, name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let res = - this.pthread_setname_np(this.read_scalar(thread)?, this.read_scalar(name)?)?; + let max_len = 16; + let res = this.pthread_setname_np( + this.read_scalar(thread)?, + this.read_scalar(name)?, + max_len, + )?; this.write_scalar(res, dest)?; } "pthread_getname_np" => { diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 0e931023e6c1c..371f56ca35550 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -176,7 +176,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "pthread_setname_np" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let thread = this.pthread_self()?; - this.pthread_setname_np(thread, this.read_scalar(name)?)?; + let max_len = this.eval_libc("MAXTHREADNAMESIZE")?.to_machine_usize(this)?; + this.pthread_setname_np( + thread, + this.read_scalar(name)?, + max_len.try_into().unwrap(), + )?; } "pthread_getname_np" => { let [thread, name, len] = diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 4320ecd389e5b..b43682710bbe5 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -67,10 +67,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(Scalar::from_machine_usize(thread_id.into(), this)) } + /// Set the name of the current thread. `max_name_len` is the maximal length of the name + /// including the null terminator. fn pthread_setname_np( &mut self, thread: Scalar, name: Scalar, + max_name_len: usize, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); @@ -79,8 +82,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let name = this.read_c_str(name)?.to_owned(); - if name.len() > 15 { - // Thread names are limited to 16 characaters, including the null terminator. + // Comparing with `>=` to account for null terminator. + if name.len() >= max_name_len { return this.eval_libc("ERANGE"); } From b857138d3bad1372618cb925963a9e1fb512fd8e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 26 Oct 2022 02:41:34 -0700 Subject: [PATCH 36/36] Update src/librustdoc/html/static/css/rustdoc.css Co-authored-by: Jacob Hoffman-Andrews --- src/librustdoc/html/static/css/rustdoc.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 84a1fa2e28ece..8424b2c4e2932 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1586,8 +1586,9 @@ details.rustdoc-toggle > summary:hover::before { } details.rustdoc-toggle > summary:focus-visible::before { - /* The SVG is black, and gets turned white using a filter. + /* The SVG is black, and gets turned white using a filter in the dark themes. Do the same with the outline. + The dotted 1px style is copied from Firefox's focus ring style. */ outline: 1px dotted #000; outline-offset: 1px;